dominds 0.7.0 → 0.7.2
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/agent-priming.js +162 -24
- package/dist/docs/dialog-system.md +18 -16
- package/dist/docs/dialog-system.zh.md +20 -19
- package/dist/llm/driver-v2/core.js +101 -1
- package/dist/llm/driver-v2/orchestrator.js +7 -0
- package/dist/llm/driver-v2/round.js +114 -4
- package/dist/llm/driver-v2/tellask-bridge.js +29 -2
- package/dist/llm/driver.js +54 -2
- package/dist/persistence.js +20 -0
- package/dist/server/websocket-handler.js +99 -7
- package/dist/shared/diligence.js +8 -2
- package/dist/static/assets/{_baseUniq-BxKNVs_E.js → _baseUniq-C04fddeD.js} +2 -2
- package/dist/static/assets/{_baseUniq-BxKNVs_E.js.map → _baseUniq-C04fddeD.js.map} +1 -1
- package/dist/static/assets/{arc-SobL0GO-.js → arc-qmZerooe.js} +2 -2
- package/dist/static/assets/{arc-SobL0GO-.js.map → arc-qmZerooe.js.map} +1 -1
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-MMDS1QOC.js → architectureDiagram-VXUJARFQ-DPAwJ19g.js} +6 -6
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-MMDS1QOC.js.map → architectureDiagram-VXUJARFQ-DPAwJ19g.js.map} +1 -1
- package/dist/static/assets/{blockDiagram-VD42YOAC-BOsSirNK.js → blockDiagram-VD42YOAC-M0jbEJ-1.js} +7 -7
- package/dist/static/assets/{blockDiagram-VD42YOAC-BOsSirNK.js.map → blockDiagram-VD42YOAC-M0jbEJ-1.js.map} +1 -1
- package/dist/static/assets/{c4Diagram-YG6GDRKO-D4jQkzwx.js → c4Diagram-YG6GDRKO-DlF8gwFw.js} +3 -3
- package/dist/static/assets/{c4Diagram-YG6GDRKO-D4jQkzwx.js.map → c4Diagram-YG6GDRKO-DlF8gwFw.js.map} +1 -1
- package/dist/static/assets/{channel-CNJ5IKbI.js → channel-B2Ph7be3.js} +2 -2
- package/dist/static/assets/{channel-CNJ5IKbI.js.map → channel-B2Ph7be3.js.map} +1 -1
- package/dist/static/assets/{chunk-4BX2VUAB-Dzp3xxyo.js → chunk-4BX2VUAB-BZ2L6PK1.js} +2 -2
- package/dist/static/assets/{chunk-4BX2VUAB-Dzp3xxyo.js.map → chunk-4BX2VUAB-BZ2L6PK1.js.map} +1 -1
- package/dist/static/assets/{chunk-55IACEB6-CbmixuSI.js → chunk-55IACEB6-COXFmnJW.js} +2 -2
- package/dist/static/assets/{chunk-55IACEB6-CbmixuSI.js.map → chunk-55IACEB6-COXFmnJW.js.map} +1 -1
- package/dist/static/assets/{chunk-B4BG7PRW-CdpmYjdb.js → chunk-B4BG7PRW-B1HiWlBq.js} +5 -5
- package/dist/static/assets/{chunk-B4BG7PRW-CdpmYjdb.js.map → chunk-B4BG7PRW-B1HiWlBq.js.map} +1 -1
- package/dist/static/assets/{chunk-DI55MBZ5-wBUIgR3h.js → chunk-DI55MBZ5-BO3wQRnL.js} +4 -4
- package/dist/static/assets/{chunk-DI55MBZ5-wBUIgR3h.js.map → chunk-DI55MBZ5-BO3wQRnL.js.map} +1 -1
- package/dist/static/assets/{chunk-FMBD7UC4-l62jcBz-.js → chunk-FMBD7UC4-BdavRHSy.js} +2 -2
- package/dist/static/assets/{chunk-FMBD7UC4-l62jcBz-.js.map → chunk-FMBD7UC4-BdavRHSy.js.map} +1 -1
- package/dist/static/assets/{chunk-QN33PNHL-BXfKZUpE.js → chunk-QN33PNHL-DchoUNF7.js} +2 -2
- package/dist/static/assets/{chunk-QN33PNHL-BXfKZUpE.js.map → chunk-QN33PNHL-DchoUNF7.js.map} +1 -1
- package/dist/static/assets/{chunk-QZHKN3VN-BYB4VxWj.js → chunk-QZHKN3VN-Dr3uVTtK.js} +2 -2
- package/dist/static/assets/{chunk-QZHKN3VN-BYB4VxWj.js.map → chunk-QZHKN3VN-Dr3uVTtK.js.map} +1 -1
- package/dist/static/assets/{chunk-TZMSLE5B-CvlWEnXl.js → chunk-TZMSLE5B-BhOcHZNs.js} +2 -2
- package/dist/static/assets/{chunk-TZMSLE5B-CvlWEnXl.js.map → chunk-TZMSLE5B-BhOcHZNs.js.map} +1 -1
- package/dist/static/assets/{classDiagram-2ON5EDUG-x2kw_AQY.js → classDiagram-2ON5EDUG-Dep-MR6W.js} +6 -6
- package/dist/static/assets/{classDiagram-2ON5EDUG-x2kw_AQY.js.map → classDiagram-2ON5EDUG-Dep-MR6W.js.map} +1 -1
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-x2kw_AQY.js → classDiagram-v2-WZHVMYZB-Dep-MR6W.js} +6 -6
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-x2kw_AQY.js.map → classDiagram-v2-WZHVMYZB-Dep-MR6W.js.map} +1 -1
- package/dist/static/assets/{clone-CfBpi3MU.js → clone-DzoL-dSX.js} +2 -2
- package/dist/static/assets/{clone-CfBpi3MU.js.map → clone-DzoL-dSX.js.map} +1 -1
- package/dist/static/assets/{cose-bilkent-S5V4N54A-DQSzPb7y.js → cose-bilkent-S5V4N54A-Bqu_DqDB.js} +2 -2
- package/dist/static/assets/{cose-bilkent-S5V4N54A-DQSzPb7y.js.map → cose-bilkent-S5V4N54A-Bqu_DqDB.js.map} +1 -1
- package/dist/static/assets/{dagre-6UL2VRFP-BuBo_U3J.js → dagre-6UL2VRFP-49InNTzs.js} +7 -7
- package/dist/static/assets/{dagre-6UL2VRFP-BuBo_U3J.js.map → dagre-6UL2VRFP-49InNTzs.js.map} +1 -1
- package/dist/static/assets/{diagram-PSM6KHXK-J2z13Z5A.js → diagram-PSM6KHXK-C1IsQq8m.js} +7 -7
- package/dist/static/assets/{diagram-PSM6KHXK-J2z13Z5A.js.map → diagram-PSM6KHXK-C1IsQq8m.js.map} +1 -1
- package/dist/static/assets/{diagram-QEK2KX5R-x8XUGykE.js → diagram-QEK2KX5R-DyJeSg_Y.js} +6 -6
- package/dist/static/assets/{diagram-QEK2KX5R-x8XUGykE.js.map → diagram-QEK2KX5R-DyJeSg_Y.js.map} +1 -1
- package/dist/static/assets/{diagram-S2PKOQOG-BE6Nr1BM.js → diagram-S2PKOQOG-aeLjjldp.js} +6 -6
- package/dist/static/assets/{diagram-S2PKOQOG-BE6Nr1BM.js.map → diagram-S2PKOQOG-aeLjjldp.js.map} +1 -1
- package/dist/static/assets/{erDiagram-Q2GNP2WA-D3qVnFAh.js → erDiagram-Q2GNP2WA-BUcv4AUq.js} +5 -5
- package/dist/static/assets/{erDiagram-Q2GNP2WA-D3qVnFAh.js.map → erDiagram-Q2GNP2WA-BUcv4AUq.js.map} +1 -1
- package/dist/static/assets/{flowDiagram-NV44I4VS-Cjp9Rt9t.js → flowDiagram-NV44I4VS-DfmTKlf_.js} +6 -6
- package/dist/static/assets/{flowDiagram-NV44I4VS-Cjp9Rt9t.js.map → flowDiagram-NV44I4VS-DfmTKlf_.js.map} +1 -1
- package/dist/static/assets/{ganttDiagram-JELNMOA3-D_hc66FC.js → ganttDiagram-JELNMOA3-BpJE8Lhp.js} +3 -3
- package/dist/static/assets/{ganttDiagram-JELNMOA3-D_hc66FC.js.map → ganttDiagram-JELNMOA3-BpJE8Lhp.js.map} +1 -1
- package/dist/static/assets/{gitGraphDiagram-NY62KEGX-1I_zaTtz.js → gitGraphDiagram-NY62KEGX-DmznjSYb.js} +7 -7
- package/dist/static/assets/{gitGraphDiagram-NY62KEGX-1I_zaTtz.js.map → gitGraphDiagram-NY62KEGX-DmznjSYb.js.map} +1 -1
- package/dist/static/assets/{graph-K6mmQESm.js → graph-CcKyIZaL.js} +3 -3
- package/dist/static/assets/{graph-K6mmQESm.js.map → graph-CcKyIZaL.js.map} +1 -1
- package/dist/static/assets/{index-RV1MEt3b.js → index-CQr8MdPI.js} +77 -44
- package/dist/static/assets/index-CQr8MdPI.js.map +1 -0
- package/dist/static/assets/{infoDiagram-WHAUD3N6-CqazW4ov.js → infoDiagram-WHAUD3N6-DwRPjndM.js} +5 -5
- package/dist/static/assets/{infoDiagram-WHAUD3N6-CqazW4ov.js.map → infoDiagram-WHAUD3N6-DwRPjndM.js.map} +1 -1
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CCwUViz2.js → journeyDiagram-XKPGCS4Q-BRAFSgVa.js} +5 -5
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CCwUViz2.js.map → journeyDiagram-XKPGCS4Q-BRAFSgVa.js.map} +1 -1
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-BKj9P06Z.js → kanban-definition-3W4ZIXB7-DlJ7-fgN.js} +3 -3
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-BKj9P06Z.js.map → kanban-definition-3W4ZIXB7-DlJ7-fgN.js.map} +1 -1
- package/dist/static/assets/{layout-BcrPlYah.js → layout-CcW5-Iee.js} +5 -5
- package/dist/static/assets/{layout-BcrPlYah.js.map → layout-CcW5-Iee.js.map} +1 -1
- package/dist/static/assets/{linear-DYXbzldi.js → linear-sKdPIuOH.js} +2 -2
- package/dist/static/assets/{linear-DYXbzldi.js.map → linear-sKdPIuOH.js.map} +1 -1
- package/dist/static/assets/{min-CAfJrdkg.js → min-CQ0AYqmk.js} +3 -3
- package/dist/static/assets/{min-CAfJrdkg.js.map → min-CQ0AYqmk.js.map} +1 -1
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-CXWJYrd0.js → mindmap-definition-VGOIOE7T-CTRwSlu8.js} +4 -4
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-CXWJYrd0.js.map → mindmap-definition-VGOIOE7T-CTRwSlu8.js.map} +1 -1
- package/dist/static/assets/{pieDiagram-ADFJNKIX-DjKlsPYr.js → pieDiagram-ADFJNKIX-DmD5KRKE.js} +7 -7
- package/dist/static/assets/{pieDiagram-ADFJNKIX-DjKlsPYr.js.map → pieDiagram-ADFJNKIX-DmD5KRKE.js.map} +1 -1
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-fcJtlyUO.js → quadrantDiagram-AYHSOK5B-C5sqZOBF.js} +3 -3
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-fcJtlyUO.js.map → quadrantDiagram-AYHSOK5B-C5sqZOBF.js.map} +1 -1
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DmB9Ezaa.js → requirementDiagram-UZGBJVZJ-DBAUwM-7.js} +4 -4
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DmB9Ezaa.js.map → requirementDiagram-UZGBJVZJ-DBAUwM-7.js.map} +1 -1
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-CdGDwaMo.js → sankeyDiagram-TZEHDZUN-CkaxkOo7.js} +2 -2
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-CdGDwaMo.js.map → sankeyDiagram-TZEHDZUN-CkaxkOo7.js.map} +1 -1
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-C-jiKkhi.js → sequenceDiagram-WL72ISMW-CJ6wMDXh.js} +4 -4
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-C-jiKkhi.js.map → sequenceDiagram-WL72ISMW-CJ6wMDXh.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-M9808W5W.js → stateDiagram-FKZM4ZOC-C66ZP2NW.js} +9 -9
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-M9808W5W.js.map → stateDiagram-FKZM4ZOC-C66ZP2NW.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-JE0YQyVh.js → stateDiagram-v2-4FDKWEC3-DdoOy271.js} +5 -5
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-JE0YQyVh.js.map → stateDiagram-v2-4FDKWEC3-DdoOy271.js.map} +1 -1
- package/dist/static/assets/{timeline-definition-IT6M3QCI-a2Rh8B62.js → timeline-definition-IT6M3QCI-2A2Mqedz.js} +3 -3
- package/dist/static/assets/{timeline-definition-IT6M3QCI-a2Rh8B62.js.map → timeline-definition-IT6M3QCI-2A2Mqedz.js.map} +1 -1
- package/dist/static/assets/{treemap-KMMF4GRG-D3tvybuo.js → treemap-KMMF4GRG-CTbGSr5o.js} +4 -4
- package/dist/static/assets/{treemap-KMMF4GRG-D3tvybuo.js.map → treemap-KMMF4GRG-CTbGSr5o.js.map} +1 -1
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-kmwKLP3Y.js → xychartDiagram-PRI3JC2R-C_S3XXZI.js} +3 -3
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-kmwKLP3Y.js.map → xychartDiagram-PRI3JC2R-C_S3XXZI.js.map} +1 -1
- package/dist/static/index.html +1 -1
- package/package.json +1 -1
- package/dist/static/assets/index-RV1MEt3b.js.map +0 -1
|
@@ -71,6 +71,93 @@ async function emitUserMarkdown(dlg, content) {
|
|
|
71
71
|
function resolveModelInfo(providerCfg, model) {
|
|
72
72
|
return providerCfg.models[model];
|
|
73
73
|
}
|
|
74
|
+
function resolveModelContextLimitTokens(modelInfo) {
|
|
75
|
+
if (modelInfo &&
|
|
76
|
+
typeof modelInfo.context_length === 'number' &&
|
|
77
|
+
Number.isFinite(modelInfo.context_length)) {
|
|
78
|
+
const n = Math.floor(modelInfo.context_length);
|
|
79
|
+
return n > 0 ? n : null;
|
|
80
|
+
}
|
|
81
|
+
if (modelInfo &&
|
|
82
|
+
typeof modelInfo.input_length === 'number' &&
|
|
83
|
+
Number.isFinite(modelInfo.input_length)) {
|
|
84
|
+
const n = Math.floor(modelInfo.input_length);
|
|
85
|
+
return n > 0 ? n : null;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
function resolveEffectiveOptimalMaxTokens(args) {
|
|
90
|
+
const configuredOptimal = args.modelInfo &&
|
|
91
|
+
typeof args.modelInfo.optimal_max_tokens === 'number' &&
|
|
92
|
+
Number.isFinite(args.modelInfo.optimal_max_tokens)
|
|
93
|
+
? Math.floor(args.modelInfo.optimal_max_tokens)
|
|
94
|
+
: undefined;
|
|
95
|
+
const optimalMaxTokensConfigured = configuredOptimal !== undefined && configuredOptimal > 0 ? configuredOptimal : undefined;
|
|
96
|
+
const configuredCritical = args.modelInfo &&
|
|
97
|
+
typeof args.modelInfo.critical_max_tokens === 'number' &&
|
|
98
|
+
Number.isFinite(args.modelInfo.critical_max_tokens)
|
|
99
|
+
? Math.floor(args.modelInfo.critical_max_tokens)
|
|
100
|
+
: undefined;
|
|
101
|
+
const criticalMaxTokensConfigured = configuredCritical !== undefined && configuredCritical > 0 ? configuredCritical : undefined;
|
|
102
|
+
const defaultOptimal = 100000;
|
|
103
|
+
const effectiveOptimalMaxTokens = optimalMaxTokensConfigured !== undefined ? optimalMaxTokensConfigured : defaultOptimal;
|
|
104
|
+
const defaultCritical = Math.max(1, Math.floor(args.modelContextLimitTokens * 0.9));
|
|
105
|
+
const effectiveCriticalMaxTokens = criticalMaxTokensConfigured !== undefined ? criticalMaxTokensConfigured : defaultCritical;
|
|
106
|
+
return {
|
|
107
|
+
effectiveOptimalMaxTokens,
|
|
108
|
+
optimalMaxTokensConfigured,
|
|
109
|
+
effectiveCriticalMaxTokens,
|
|
110
|
+
criticalMaxTokensConfigured,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function computeContextHealthSnapshot(args) {
|
|
114
|
+
const modelInfo = args.providerCfg.models[args.model];
|
|
115
|
+
const modelContextWindowText = modelInfo && typeof modelInfo.context_window === 'string'
|
|
116
|
+
? modelInfo.context_window
|
|
117
|
+
: undefined;
|
|
118
|
+
const modelContextLimitTokens = resolveModelContextLimitTokens(modelInfo);
|
|
119
|
+
if (modelContextLimitTokens === null) {
|
|
120
|
+
return { kind: 'unavailable', reason: 'model_limit_unavailable', modelContextWindowText };
|
|
121
|
+
}
|
|
122
|
+
const { effectiveOptimalMaxTokens, optimalMaxTokensConfigured, effectiveCriticalMaxTokens, criticalMaxTokensConfigured, } = resolveEffectiveOptimalMaxTokens({
|
|
123
|
+
modelInfo,
|
|
124
|
+
modelContextLimitTokens,
|
|
125
|
+
});
|
|
126
|
+
if (args.usage.kind !== 'available') {
|
|
127
|
+
return {
|
|
128
|
+
kind: 'unavailable',
|
|
129
|
+
reason: 'usage_unavailable',
|
|
130
|
+
modelContextWindowText,
|
|
131
|
+
modelContextLimitTokens,
|
|
132
|
+
effectiveOptimalMaxTokens,
|
|
133
|
+
optimalMaxTokensConfigured,
|
|
134
|
+
effectiveCriticalMaxTokens,
|
|
135
|
+
criticalMaxTokensConfigured,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const hardUtil = args.usage.promptTokens / modelContextLimitTokens;
|
|
139
|
+
const optimalUtil = args.usage.promptTokens / effectiveOptimalMaxTokens;
|
|
140
|
+
const level = args.usage.promptTokens > effectiveCriticalMaxTokens
|
|
141
|
+
? 'critical'
|
|
142
|
+
: args.usage.promptTokens > effectiveOptimalMaxTokens
|
|
143
|
+
? 'caution'
|
|
144
|
+
: 'healthy';
|
|
145
|
+
return {
|
|
146
|
+
kind: 'available',
|
|
147
|
+
promptTokens: args.usage.promptTokens,
|
|
148
|
+
completionTokens: args.usage.completionTokens,
|
|
149
|
+
totalTokens: args.usage.totalTokens,
|
|
150
|
+
modelContextWindowText,
|
|
151
|
+
modelContextLimitTokens,
|
|
152
|
+
effectiveOptimalMaxTokens,
|
|
153
|
+
optimalMaxTokensConfigured,
|
|
154
|
+
effectiveCriticalMaxTokens,
|
|
155
|
+
criticalMaxTokensConfigured,
|
|
156
|
+
hardUtil,
|
|
157
|
+
optimalUtil,
|
|
158
|
+
level,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
74
161
|
async function buildProviderContext(args) {
|
|
75
162
|
const provider = args.agent.provider ?? args.team.memberDefaults.provider;
|
|
76
163
|
const model = args.agent.model ?? args.team.memberDefaults.model;
|
|
@@ -372,6 +459,7 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
|
|
|
372
459
|
const funcTools = projected.tools;
|
|
373
460
|
let suspendForHuman = false;
|
|
374
461
|
let llmGenModelForGen = model;
|
|
462
|
+
let contextHealthForGen;
|
|
375
463
|
await dlg.notifyGeneratingStart();
|
|
376
464
|
try {
|
|
377
465
|
const currentPrompt = pendingPrompt;
|
|
@@ -553,6 +641,12 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
|
|
|
553
641
|
nonStreamResult.llmGenModel.trim() !== '') {
|
|
554
642
|
llmGenModelForGen = nonStreamResult.llmGenModel.trim();
|
|
555
643
|
}
|
|
644
|
+
contextHealthForGen = computeContextHealthSnapshot({
|
|
645
|
+
providerCfg,
|
|
646
|
+
model,
|
|
647
|
+
usage: nonStreamResult.usage,
|
|
648
|
+
});
|
|
649
|
+
dlg.setLastContextHealth(contextHealthForGen);
|
|
556
650
|
const nonStreamMsgs = nonStreamResult.messages;
|
|
557
651
|
const assistantMsgs = nonStreamMsgs.filter((m) => m.type === 'saying_msg' || m.type === 'thinking_msg');
|
|
558
652
|
const collectedAssistantCalls = [];
|
|
@@ -802,6 +896,12 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
|
|
|
802
896
|
streamResult.llmGenModel.trim() !== '') {
|
|
803
897
|
llmGenModelForGen = streamResult.llmGenModel.trim();
|
|
804
898
|
}
|
|
899
|
+
contextHealthForGen = computeContextHealthSnapshot({
|
|
900
|
+
providerCfg,
|
|
901
|
+
model,
|
|
902
|
+
usage: streamResult.usage,
|
|
903
|
+
});
|
|
904
|
+
dlg.setLastContextHealth(contextHealthForGen);
|
|
805
905
|
const collectedCalls = parser.getCollectedCalls();
|
|
806
906
|
const policyViolation = (0, policy_1.resolveDriverV2PolicyViolationKind)({
|
|
807
907
|
policy,
|
|
@@ -887,7 +987,7 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
|
|
|
887
987
|
}
|
|
888
988
|
}
|
|
889
989
|
finally {
|
|
890
|
-
await dlg.notifyGeneratingFinish(
|
|
990
|
+
await dlg.notifyGeneratingFinish(contextHealthForGen, llmGenModelForGen);
|
|
891
991
|
}
|
|
892
992
|
}
|
|
893
993
|
finalRunState = await (0, dialog_run_state_1.computeIdleRunState)(dlg);
|
|
@@ -49,6 +49,13 @@ function runBackendDriver() {
|
|
|
49
49
|
const dialogsToDrive = dialog_global_registry_1.globalDialogRegistry.getDialogsNeedingDrive();
|
|
50
50
|
for (const rootDialog of dialogsToDrive) {
|
|
51
51
|
try {
|
|
52
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(rootDialog.id, 'running');
|
|
53
|
+
const runStateKind = latest?.runState?.kind;
|
|
54
|
+
if (runStateKind === 'interrupted' || runStateKind === 'proceeding_stop_requested') {
|
|
55
|
+
dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId);
|
|
56
|
+
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
52
59
|
if (!(await rootDialog.canDrive())) {
|
|
53
60
|
continue;
|
|
54
61
|
}
|
|
@@ -6,11 +6,65 @@ const dialog_run_state_1 = require("../../dialog-run-state");
|
|
|
6
6
|
const log_1 = require("../../log");
|
|
7
7
|
const load_1 = require("../../minds/load");
|
|
8
8
|
const persistence_1 = require("../../persistence");
|
|
9
|
+
const driver_messages_1 = require("../../shared/i18n/driver-messages");
|
|
9
10
|
const runtime_language_1 = require("../../shared/runtime-language");
|
|
11
|
+
const id_1 = require("../../shared/utils/id");
|
|
10
12
|
const context_health_1 = require("./context-health");
|
|
11
13
|
const core_1 = require("./core");
|
|
12
14
|
const policy_1 = require("./policy");
|
|
13
15
|
const supdialog_response_1 = require("./supdialog-response");
|
|
16
|
+
const defaultCriticalCountdownGenerations = 5;
|
|
17
|
+
const contextHealthRoundStateByDialogKey = new Map();
|
|
18
|
+
function getContextHealthRoundState(dialog) {
|
|
19
|
+
const key = dialog.id.key();
|
|
20
|
+
const existing = contextHealthRoundStateByDialogKey.get(key);
|
|
21
|
+
if (existing) {
|
|
22
|
+
return existing;
|
|
23
|
+
}
|
|
24
|
+
const created = {};
|
|
25
|
+
contextHealthRoundStateByDialogKey.set(key, created);
|
|
26
|
+
return created;
|
|
27
|
+
}
|
|
28
|
+
function resetContextHealthRoundState(dialog) {
|
|
29
|
+
contextHealthRoundStateByDialogKey.delete(dialog.id.key());
|
|
30
|
+
}
|
|
31
|
+
function resolveCriticalCountdownRemaining(dialog, snapshot) {
|
|
32
|
+
if (!snapshot || snapshot.kind !== 'available') {
|
|
33
|
+
resetContextHealthRoundState(dialog);
|
|
34
|
+
return defaultCriticalCountdownGenerations;
|
|
35
|
+
}
|
|
36
|
+
if (snapshot.level !== 'critical') {
|
|
37
|
+
if (snapshot.level === 'healthy') {
|
|
38
|
+
resetContextHealthRoundState(dialog);
|
|
39
|
+
return defaultCriticalCountdownGenerations;
|
|
40
|
+
}
|
|
41
|
+
const state = getContextHealthRoundState(dialog);
|
|
42
|
+
state.lastSeenLevel = snapshot.level;
|
|
43
|
+
state.criticalCountdownRemaining = undefined;
|
|
44
|
+
return defaultCriticalCountdownGenerations;
|
|
45
|
+
}
|
|
46
|
+
const state = getContextHealthRoundState(dialog);
|
|
47
|
+
if (state.lastSeenLevel !== 'critical' ||
|
|
48
|
+
typeof state.criticalCountdownRemaining !== 'number' ||
|
|
49
|
+
!Number.isFinite(state.criticalCountdownRemaining)) {
|
|
50
|
+
state.lastSeenLevel = 'critical';
|
|
51
|
+
state.criticalCountdownRemaining = defaultCriticalCountdownGenerations;
|
|
52
|
+
}
|
|
53
|
+
const remaining = Math.floor(state.criticalCountdownRemaining);
|
|
54
|
+
return remaining > 0 ? remaining : 0;
|
|
55
|
+
}
|
|
56
|
+
function consumeCriticalCountdown(dialog) {
|
|
57
|
+
const state = getContextHealthRoundState(dialog);
|
|
58
|
+
const currentRaw = typeof state.criticalCountdownRemaining === 'number' &&
|
|
59
|
+
Number.isFinite(state.criticalCountdownRemaining)
|
|
60
|
+
? Math.floor(state.criticalCountdownRemaining)
|
|
61
|
+
: defaultCriticalCountdownGenerations;
|
|
62
|
+
const current = currentRaw > 0 ? currentRaw : 0;
|
|
63
|
+
const next = Math.max(0, current - 1);
|
|
64
|
+
state.lastSeenLevel = 'critical';
|
|
65
|
+
state.criticalCountdownRemaining = next;
|
|
66
|
+
return next;
|
|
67
|
+
}
|
|
14
68
|
function resolveEffectivePrompt(dialog, humanPrompt) {
|
|
15
69
|
if (humanPrompt) {
|
|
16
70
|
return humanPrompt;
|
|
@@ -39,6 +93,7 @@ async function executeDriveRound(args) {
|
|
|
39
93
|
let followUp;
|
|
40
94
|
let driveResult;
|
|
41
95
|
let subdialogReplyTarget;
|
|
96
|
+
const allowResumeFromInterrupted = driveOptions?.allowResumeFromInterrupted === true || humanPrompt?.origin === 'user';
|
|
42
97
|
try {
|
|
43
98
|
// Prime active-run registration right after acquiring dialog lock so user stop can
|
|
44
99
|
// reliably interrupt queued auto-revive drives during preflight.
|
|
@@ -53,6 +108,23 @@ async function executeDriveRound(args) {
|
|
|
53
108
|
latest.runState.kind === 'dead') {
|
|
54
109
|
return;
|
|
55
110
|
}
|
|
111
|
+
if (latest && latest.runState && latest.runState.kind === 'proceeding_stop_requested') {
|
|
112
|
+
log_1.log.info('driver-v2 skip drive while stop request is still being processed', undefined, {
|
|
113
|
+
dialogId: dialog.id.valueOf(),
|
|
114
|
+
reason: latest.runState.reason,
|
|
115
|
+
});
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (latest &&
|
|
119
|
+
latest.runState &&
|
|
120
|
+
latest.runState.kind === 'interrupted' &&
|
|
121
|
+
!allowResumeFromInterrupted) {
|
|
122
|
+
log_1.log.info('driver-v2 skip drive for interrupted dialog without explicit resume/user prompt', undefined, {
|
|
123
|
+
dialogId: dialog.id.valueOf(),
|
|
124
|
+
reason: latest.runState.reason,
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
56
128
|
}
|
|
57
129
|
catch (err) {
|
|
58
130
|
log_1.log.warn('driver-v2 failed to check runState before drive; proceeding best-effort', err, {
|
|
@@ -71,18 +143,56 @@ async function executeDriveRound(args) {
|
|
|
71
143
|
if (!validation.ok) {
|
|
72
144
|
throw new Error(`driver-v2 policy invariant violation: ${validation.detail}`);
|
|
73
145
|
}
|
|
146
|
+
const snapshot = dialog.getLastContextHealth();
|
|
147
|
+
const hasQueuedUpNext = dialog.hasUpNext();
|
|
148
|
+
const criticalCountdownRemaining = resolveCriticalCountdownRemaining(dialog, snapshot);
|
|
74
149
|
const healthDecision = (0, context_health_1.decideDriverV2ContextHealth)({
|
|
75
|
-
snapshot
|
|
76
|
-
hadUserPromptThisGen:
|
|
77
|
-
criticalCountdownRemaining
|
|
150
|
+
snapshot,
|
|
151
|
+
hadUserPromptThisGen: humanPrompt !== undefined,
|
|
152
|
+
criticalCountdownRemaining,
|
|
78
153
|
});
|
|
79
154
|
if (healthDecision.kind === 'suspend') {
|
|
80
155
|
return;
|
|
81
156
|
}
|
|
157
|
+
let healthPrompt;
|
|
158
|
+
if (healthDecision.kind === 'continue') {
|
|
159
|
+
if (healthDecision.reason === 'critical_force_new_course') {
|
|
160
|
+
const language = (0, runtime_language_1.getWorkLanguage)();
|
|
161
|
+
const newCoursePrompt = language === 'zh'
|
|
162
|
+
? '系统因上下文已告急(critical)而自动开启新一程对话,请继续推进任务。'
|
|
163
|
+
: 'System auto-started a new dialog course because context health is critical. Please continue the task.';
|
|
164
|
+
await dialog.startNewCourse(newCoursePrompt);
|
|
165
|
+
dialog.setLastContextHealth({ kind: 'unavailable', reason: 'usage_unavailable' });
|
|
166
|
+
resetContextHealthRoundState(dialog);
|
|
167
|
+
}
|
|
168
|
+
else if (!hasQueuedUpNext) {
|
|
169
|
+
const language = (0, runtime_language_1.getWorkLanguage)();
|
|
170
|
+
const guideText = healthDecision.reason === 'caution_soft_remediation'
|
|
171
|
+
? (0, driver_messages_1.formatUserFacingContextHealthV3RemediationGuide)(language, {
|
|
172
|
+
kind: 'caution',
|
|
173
|
+
mode: 'soft',
|
|
174
|
+
})
|
|
175
|
+
: (0, driver_messages_1.formatUserFacingContextHealthV3RemediationGuide)(language, {
|
|
176
|
+
kind: 'critical',
|
|
177
|
+
mode: 'countdown',
|
|
178
|
+
promptsRemainingAfterThis: consumeCriticalCountdown(dialog),
|
|
179
|
+
promptsTotal: defaultCriticalCountdownGenerations,
|
|
180
|
+
});
|
|
181
|
+
healthPrompt = {
|
|
182
|
+
content: guideText,
|
|
183
|
+
msgId: (0, id_1.generateShortId)(),
|
|
184
|
+
grammar: 'markdown',
|
|
185
|
+
userLanguageCode: language,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
82
189
|
args.runtime.driveCount += 1;
|
|
83
190
|
args.runtime.totalGenIterations += 1;
|
|
84
191
|
args.runtime.usedLegacyDriveCore = false;
|
|
85
|
-
const
|
|
192
|
+
const promptForCore = healthDecision.kind === 'continue' && healthDecision.reason === 'critical_force_new_course'
|
|
193
|
+
? undefined
|
|
194
|
+
: (healthPrompt ?? humanPrompt);
|
|
195
|
+
const effectivePrompt = resolveEffectivePrompt(dialog, promptForCore);
|
|
86
196
|
subdialogReplyTarget = effectivePrompt?.subdialogReplyTarget;
|
|
87
197
|
if (effectivePrompt && effectivePrompt.userLanguageCode) {
|
|
88
198
|
dialog.setLastUserLanguageCode(effectivePrompt.userLanguageCode);
|
|
@@ -193,6 +193,33 @@ async function updateSubdialogAssignment(subdialog, assignment) {
|
|
|
193
193
|
subdialog.assignmentFromSup = assignment;
|
|
194
194
|
await persistence_1.DialogPersistence.updateSubdialogAssignment(subdialog.id, assignment);
|
|
195
195
|
}
|
|
196
|
+
async function lookupLiveRegisteredSubdialog(rootDialog, agentId, tellaskSession) {
|
|
197
|
+
const existing = rootDialog.lookupSubdialog(agentId, tellaskSession);
|
|
198
|
+
if (!existing) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
const existingSession = existing.tellaskSession;
|
|
202
|
+
if (!existingSession) {
|
|
203
|
+
throw new Error(`Type B registry invariant violation: lookupSubdialog returned entry without tellaskSession (root=${rootDialog.id.valueOf()} sub=${existing.id.valueOf()})`);
|
|
204
|
+
}
|
|
205
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(existing.id, rootDialog.status);
|
|
206
|
+
const runState = latest?.runState;
|
|
207
|
+
if (!runState || runState.kind !== 'dead') {
|
|
208
|
+
return existing;
|
|
209
|
+
}
|
|
210
|
+
const removed = rootDialog.unregisterSubdialog(existing.agentId, existingSession);
|
|
211
|
+
if (!removed) {
|
|
212
|
+
throw new Error(`Failed to unregister dead registered subdialog: root=${rootDialog.id.valueOf()} sub=${existing.id.valueOf()} session=${existingSession}`);
|
|
213
|
+
}
|
|
214
|
+
await rootDialog.saveSubdialogRegistry();
|
|
215
|
+
log_1.log.info('Pruned dead registered subdialog from Type B registry', undefined, {
|
|
216
|
+
rootId: rootDialog.id.rootId,
|
|
217
|
+
subdialogId: existing.id.selfId,
|
|
218
|
+
agentId: existing.agentId,
|
|
219
|
+
tellaskSession: existingSession,
|
|
220
|
+
});
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
196
223
|
function extractLastAssistantResponse(messages, defaultMessage) {
|
|
197
224
|
let responseText = '';
|
|
198
225
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -662,7 +689,7 @@ async function executeTellaskCall(dlg, agent, firstMention, tellaskHead, body, c
|
|
|
662
689
|
callId,
|
|
663
690
|
collectiveTargets: options?.collectiveTargets ?? [parseResult.agentId],
|
|
664
691
|
};
|
|
665
|
-
const existing = rootDialog
|
|
692
|
+
const existing = await lookupLiveRegisteredSubdialog(rootDialog, parseResult.agentId, derivedSession);
|
|
666
693
|
if (existing) {
|
|
667
694
|
try {
|
|
668
695
|
await updateSubdialogAssignment(existing, assignment);
|
|
@@ -902,7 +929,7 @@ async function executeTellaskCall(dlg, agent, firstMention, tellaskHead, body, c
|
|
|
902
929
|
};
|
|
903
930
|
const pendingOwner = callerDialog;
|
|
904
931
|
const result = await (0, subdialog_txn_1.withSubdialogTxnLock)(rootDialog.id, async () => {
|
|
905
|
-
const existing = rootDialog
|
|
932
|
+
const existing = await lookupLiveRegisteredSubdialog(rootDialog, parseResult.agentId, parseResult.tellaskSession);
|
|
906
933
|
if (existing) {
|
|
907
934
|
try {
|
|
908
935
|
await updateSubdialogAssignment(existing, assignment);
|
package/dist/llm/driver.js
CHANGED
|
@@ -915,6 +915,7 @@ async function driveDialogStream(dlg, humanPrompt, waitInQue = false, driveOptio
|
|
|
915
915
|
if (!waitInQue && dlg.isLocked()) {
|
|
916
916
|
throw new Error(`Dialog busy driven, see how it proceeded and try again.`);
|
|
917
917
|
}
|
|
918
|
+
const allowResumeFromInterrupted = driveOptions?.allowResumeFromInterrupted === true || humanPrompt?.origin === 'user';
|
|
918
919
|
const release = await dlg.acquire();
|
|
919
920
|
let followUp;
|
|
920
921
|
let driveResult;
|
|
@@ -930,6 +931,23 @@ async function driveDialogStream(dlg, humanPrompt, waitInQue = false, driveOptio
|
|
|
930
931
|
latest.runState.kind === 'dead') {
|
|
931
932
|
return;
|
|
932
933
|
}
|
|
934
|
+
if (latest && latest.runState && latest.runState.kind === 'proceeding_stop_requested') {
|
|
935
|
+
log_1.log.info('Skip drive while stop request is still being processed', undefined, {
|
|
936
|
+
dialogId: dlg.id.valueOf(),
|
|
937
|
+
reason: latest.runState.reason,
|
|
938
|
+
});
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
if (latest &&
|
|
942
|
+
latest.runState &&
|
|
943
|
+
latest.runState.kind === 'interrupted' &&
|
|
944
|
+
!allowResumeFromInterrupted) {
|
|
945
|
+
log_1.log.info('Skip drive for interrupted dialog without explicit resume/user prompt', undefined, {
|
|
946
|
+
dialogId: dlg.id.valueOf(),
|
|
947
|
+
reason: latest.runState.reason,
|
|
948
|
+
});
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
933
951
|
}
|
|
934
952
|
catch (err) {
|
|
935
953
|
log_1.log.warn('Failed to check runState before drive; proceeding best-effort', err, {
|
|
@@ -991,6 +1009,13 @@ async function runBackendDriver() {
|
|
|
991
1009
|
const dialogsToDrive = dialog_global_registry_1.globalDialogRegistry.getDialogsNeedingDrive();
|
|
992
1010
|
for (const rootDialog of dialogsToDrive) {
|
|
993
1011
|
try {
|
|
1012
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(rootDialog.id, 'running');
|
|
1013
|
+
const runStateKind = latest?.runState?.kind;
|
|
1014
|
+
if (runStateKind === 'interrupted' || runStateKind === 'proceeding_stop_requested') {
|
|
1015
|
+
dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId);
|
|
1016
|
+
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
|
|
1017
|
+
continue;
|
|
1018
|
+
}
|
|
994
1019
|
if (!(await rootDialog.canDrive())) {
|
|
995
1020
|
continue;
|
|
996
1021
|
}
|
|
@@ -2757,6 +2782,33 @@ async function updateSubdialogAssignment(subdialog, assignment) {
|
|
|
2757
2782
|
subdialog.assignmentFromSup = assignment;
|
|
2758
2783
|
await persistence_1.DialogPersistence.updateSubdialogAssignment(subdialog.id, assignment);
|
|
2759
2784
|
}
|
|
2785
|
+
async function lookupLiveRegisteredSubdialog(rootDialog, agentId, tellaskSession) {
|
|
2786
|
+
const existing = rootDialog.lookupSubdialog(agentId, tellaskSession);
|
|
2787
|
+
if (!existing) {
|
|
2788
|
+
return undefined;
|
|
2789
|
+
}
|
|
2790
|
+
const existingSession = existing.tellaskSession;
|
|
2791
|
+
if (!existingSession) {
|
|
2792
|
+
throw new Error(`Type B registry invariant violation: lookupSubdialog returned entry without tellaskSession (root=${rootDialog.id.valueOf()} sub=${existing.id.valueOf()})`);
|
|
2793
|
+
}
|
|
2794
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(existing.id, rootDialog.status);
|
|
2795
|
+
const runState = latest?.runState;
|
|
2796
|
+
if (!runState || runState.kind !== 'dead') {
|
|
2797
|
+
return existing;
|
|
2798
|
+
}
|
|
2799
|
+
const removed = rootDialog.unregisterSubdialog(existing.agentId, existingSession);
|
|
2800
|
+
if (!removed) {
|
|
2801
|
+
throw new Error(`Failed to unregister dead registered subdialog: root=${rootDialog.id.valueOf()} sub=${existing.id.valueOf()} session=${existingSession}`);
|
|
2802
|
+
}
|
|
2803
|
+
await rootDialog.saveSubdialogRegistry();
|
|
2804
|
+
log_1.log.info('Pruned dead registered subdialog from Type B registry', undefined, {
|
|
2805
|
+
rootId: rootDialog.id.rootId,
|
|
2806
|
+
subdialogId: existing.id.selfId,
|
|
2807
|
+
agentId: existing.agentId,
|
|
2808
|
+
tellaskSession: existingSession,
|
|
2809
|
+
});
|
|
2810
|
+
return undefined;
|
|
2811
|
+
}
|
|
2760
2812
|
let agentPrimingModulePromise = null;
|
|
2761
2813
|
async function scheduleInheritedAgentPrimingForSubdialog(callerDialog, subdialog) {
|
|
2762
2814
|
const rootDialog = callerDialog instanceof dialog_1.RootDialog
|
|
@@ -3550,7 +3602,7 @@ async function executeTellaskCall(dlg, agent, firstMention, tellaskHead, body, c
|
|
|
3550
3602
|
callId,
|
|
3551
3603
|
collectiveTargets: options?.collectiveTargets ?? [parseResult.agentId],
|
|
3552
3604
|
};
|
|
3553
|
-
const existing = rootDialog
|
|
3605
|
+
const existing = await lookupLiveRegisteredSubdialog(rootDialog, parseResult.agentId, derivedSession);
|
|
3554
3606
|
if (existing) {
|
|
3555
3607
|
try {
|
|
3556
3608
|
await updateSubdialogAssignment(existing, assignment);
|
|
@@ -3822,7 +3874,7 @@ async function executeTellaskCall(dlg, agent, firstMention, tellaskHead, body, c
|
|
|
3822
3874
|
};
|
|
3823
3875
|
const pendingOwner = callerDialog;
|
|
3824
3876
|
const result = await withSuspensionStateLock(rootDialog.id, async () => {
|
|
3825
|
-
const existing = rootDialog
|
|
3877
|
+
const existing = await lookupLiveRegisteredSubdialog(rootDialog, parseResult.agentId, parseResult.tellaskSession);
|
|
3826
3878
|
if (existing) {
|
|
3827
3879
|
try {
|
|
3828
3880
|
await updateSubdialogAssignment(existing, assignment);
|
package/dist/persistence.js
CHANGED
|
@@ -941,9 +941,26 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
941
941
|
}
|
|
942
942
|
async loadSubdialogRegistry(rootDialog, status) {
|
|
943
943
|
const entries = await DialogPersistence.loadSubdialogRegistry(rootDialog.id, status);
|
|
944
|
+
const shouldPruneDead = status === 'running';
|
|
945
|
+
let prunedDeadRegistryEntries = false;
|
|
944
946
|
for (const entry of entries) {
|
|
945
947
|
if (!entry.tellaskSession)
|
|
946
948
|
continue;
|
|
949
|
+
if (shouldPruneDead) {
|
|
950
|
+
const latest = await DialogPersistence.loadDialogLatest(entry.subdialogId, status);
|
|
951
|
+
const runState = latest?.runState;
|
|
952
|
+
if (runState && runState.kind === 'dead') {
|
|
953
|
+
prunedDeadRegistryEntries = true;
|
|
954
|
+
rootDialog.unregisterSubdialog(entry.agentId, entry.tellaskSession);
|
|
955
|
+
log_1.log.info('Skip dead subdialog while loading Type B registry', undefined, {
|
|
956
|
+
rootId: rootDialog.id.rootId,
|
|
957
|
+
subdialogId: entry.subdialogId.selfId,
|
|
958
|
+
agentId: entry.agentId,
|
|
959
|
+
tellaskSession: entry.tellaskSession,
|
|
960
|
+
});
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
947
964
|
const existing = rootDialog.lookupDialog(entry.subdialogId.selfId);
|
|
948
965
|
if (existing) {
|
|
949
966
|
if (existing instanceof dialog_1.SubDialog && existing.tellaskSession) {
|
|
@@ -965,6 +982,9 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
965
982
|
});
|
|
966
983
|
rootDialog.registerSubdialog(subdialog);
|
|
967
984
|
}
|
|
985
|
+
if (prunedDeadRegistryEntries) {
|
|
986
|
+
await rootDialog.saveSubdialogRegistry();
|
|
987
|
+
}
|
|
968
988
|
}
|
|
969
989
|
/**
|
|
970
990
|
* Clear Questions for Human state in storage
|