dominds 1.4.2 → 1.5.1
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 +24 -0
- package/README.zh.md +24 -0
- package/dist/apps/app-json.js +38 -3
- package/dist/apps/dialog-run-controls.js +4 -0
- package/dist/apps/enabled-apps.js +8 -1
- package/dist/apps/installed-file.js +207 -0
- package/dist/apps/run-app-json.js +6 -6
- package/dist/apps/runtime-port.js +91 -0
- package/dist/apps/runtime.js +316 -68
- package/dist/apps-host/client.js +153 -3
- package/dist/apps-host/host.js +339 -2
- package/dist/apps-host/ipc-types.js +215 -30
- package/dist/cli/install.js +21 -1
- package/dist/dialog-fork.js +608 -0
- package/dist/dialog.js +2 -2
- package/dist/docs/app-constitution.md +153 -2
- package/dist/docs/app-constitution.zh.md +153 -2
- package/dist/docs/dialog-persistence.md +31 -0
- package/dist/docs/dialog-persistence.zh.md +31 -0
- package/dist/docs/dialog-system.md +29 -0
- package/dist/docs/dialog-system.zh.md +29 -0
- package/dist/docs/kernel-app-architecture.md +286 -0
- package/dist/docs/kernel-app-architecture.zh.md +285 -0
- package/dist/llm/defaults.yaml +16 -0
- package/dist/llm/driver-entry.js +28 -0
- package/dist/llm/driver-v2/context-health.js +121 -0
- package/dist/llm/driver-v2/context.js +56 -0
- package/dist/llm/driver-v2/core.js +1545 -0
- package/dist/llm/driver-v2/index.js +26 -0
- package/dist/llm/driver-v2/orchestrator.js +158 -0
- package/dist/llm/driver-v2/policy.js +129 -0
- package/dist/llm/driver-v2/restore-dialog-hierarchy.js +73 -0
- package/dist/llm/driver-v2/round.js +366 -0
- package/dist/llm/driver-v2/runtime-utils.js +365 -0
- package/dist/llm/driver-v2/saying-events.js +20 -0
- package/dist/llm/driver-v2/subdialog-txn.js +42 -0
- package/dist/llm/driver-v2/supdialog-response.js +400 -0
- package/dist/llm/driver-v2/tellask-bridge.js +1148 -0
- package/dist/llm/driver-v2/types.js +10 -0
- package/dist/llm/driver-v2-ref-only/context-health.js +121 -0
- package/dist/llm/driver-v2-ref-only/context.js +17 -0
- package/dist/llm/driver-v2-ref-only/core.js +1710 -0
- package/dist/llm/driver-v2-ref-only/index.js +26 -0
- package/dist/llm/driver-v2-ref-only/orchestrator.js +158 -0
- package/dist/llm/driver-v2-ref-only/policy.js +129 -0
- package/dist/llm/driver-v2-ref-only/restore-dialog-hierarchy.js +73 -0
- package/dist/llm/driver-v2-ref-only/round.js +366 -0
- package/dist/llm/driver-v2-ref-only/runtime-utils.js +473 -0
- package/dist/llm/driver-v2-ref-only/saying-events.js +18 -0
- package/dist/llm/driver-v2-ref-only/subdialog-txn.js +42 -0
- package/dist/llm/driver-v2-ref-only/supdialog-response.js +453 -0
- package/dist/llm/driver-v2-ref-only/tellask-bridge.js +1178 -0
- package/dist/llm/driver-v2-ref-only/types.js +10 -0
- package/dist/llm/gen/anthropic.js +68 -15
- package/dist/llm/gen/codex.js +59 -10
- package/dist/llm/gen/openai-compatible.js +38 -9
- package/dist/llm/gen/openai.js +58 -11
- package/dist/llm/gen/tool-output-limit.js +50 -0
- package/dist/llm/kernel-driver/subdialog.js +8 -1
- package/dist/llm/kernel-driver/tellask-special.js +18 -3
- package/dist/minds/load.js +7 -0
- package/dist/persistence.js +190 -28
- package/dist/priming.js +20 -1
- package/dist/server/api-routes.js +82 -0
- package/dist/server/setup-routes.js +15 -0
- package/dist/static/assets/{_basePickBy-B2o4z1Hf.js → _basePickBy-C-nynT9f.js} +3 -3
- package/dist/static/assets/{_basePickBy-B2o4z1Hf.js.map → _basePickBy-C-nynT9f.js.map} +1 -1
- package/dist/static/assets/{_baseUniq-CLmcxjdl.js → _baseUniq-CiHd-eVT.js} +2 -2
- package/dist/static/assets/{_baseUniq-CLmcxjdl.js.map → _baseUniq-CiHd-eVT.js.map} +1 -1
- package/dist/static/assets/{arc-CymD_KN7.js → arc-_OJzDWy1.js} +2 -2
- package/dist/static/assets/{arc-CymD_KN7.js.map → arc-_OJzDWy1.js.map} +1 -1
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-DJQfSJUH.js → architectureDiagram-VXUJARFQ-CDEG85ub.js} +7 -7
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-DJQfSJUH.js.map → architectureDiagram-VXUJARFQ-CDEG85ub.js.map} +1 -1
- package/dist/static/assets/{blockDiagram-VD42YOAC-pHVz60D0.js → blockDiagram-VD42YOAC-1LzKVc5t.js} +7 -7
- package/dist/static/assets/{blockDiagram-VD42YOAC-pHVz60D0.js.map → blockDiagram-VD42YOAC-1LzKVc5t.js.map} +1 -1
- package/dist/static/assets/{c4Diagram-YG6GDRKO-B0WnCfAT.js → c4Diagram-YG6GDRKO-BzYnVyvY.js} +3 -3
- package/dist/static/assets/{c4Diagram-YG6GDRKO-B0WnCfAT.js.map → c4Diagram-YG6GDRKO-BzYnVyvY.js.map} +1 -1
- package/dist/static/assets/{channel-CX9BlKil.js → channel-VAEDAk9T.js} +2 -2
- package/dist/static/assets/{channel-CX9BlKil.js.map → channel-VAEDAk9T.js.map} +1 -1
- package/dist/static/assets/{chunk-4BX2VUAB-lXArRj3o.js → chunk-4BX2VUAB-D0r2u3mX.js} +2 -2
- package/dist/static/assets/{chunk-4BX2VUAB-lXArRj3o.js.map → chunk-4BX2VUAB-D0r2u3mX.js.map} +1 -1
- package/dist/static/assets/{chunk-55IACEB6-CdqwynH9.js → chunk-55IACEB6-Dkl8Xw7i.js} +2 -2
- package/dist/static/assets/{chunk-55IACEB6-CdqwynH9.js.map → chunk-55IACEB6-Dkl8Xw7i.js.map} +1 -1
- package/dist/static/assets/{chunk-B4BG7PRW-Y-uXcJst.js → chunk-B4BG7PRW-9sxsI8ns.js} +5 -5
- package/dist/static/assets/{chunk-B4BG7PRW-Y-uXcJst.js.map → chunk-B4BG7PRW-9sxsI8ns.js.map} +1 -1
- package/dist/static/assets/{chunk-DI55MBZ5-C5xSbRST.js → chunk-DI55MBZ5-AHaqkaLl.js} +4 -4
- package/dist/static/assets/{chunk-DI55MBZ5-C5xSbRST.js.map → chunk-DI55MBZ5-AHaqkaLl.js.map} +1 -1
- package/dist/static/assets/{chunk-FMBD7UC4-5uefwCjI.js → chunk-FMBD7UC4-NWDLDixD.js} +2 -2
- package/dist/static/assets/{chunk-FMBD7UC4-5uefwCjI.js.map → chunk-FMBD7UC4-NWDLDixD.js.map} +1 -1
- package/dist/static/assets/{chunk-QN33PNHL-DzWVcvpI.js → chunk-QN33PNHL-C2KeUqle.js} +2 -2
- package/dist/static/assets/{chunk-QN33PNHL-DzWVcvpI.js.map → chunk-QN33PNHL-C2KeUqle.js.map} +1 -1
- package/dist/static/assets/{chunk-QZHKN3VN-BrrvAZdP.js → chunk-QZHKN3VN-B6Eoxo5L.js} +2 -2
- package/dist/static/assets/{chunk-QZHKN3VN-BrrvAZdP.js.map → chunk-QZHKN3VN-B6Eoxo5L.js.map} +1 -1
- package/dist/static/assets/{chunk-TZMSLE5B-DyKOlPTY.js → chunk-TZMSLE5B-Bc-VyQon.js} +2 -2
- package/dist/static/assets/{chunk-TZMSLE5B-DyKOlPTY.js.map → chunk-TZMSLE5B-Bc-VyQon.js.map} +1 -1
- package/dist/static/assets/{classDiagram-2ON5EDUG-FCrnlCWC.js → classDiagram-2ON5EDUG-DmPfsN1H.js} +6 -6
- package/dist/static/assets/{classDiagram-2ON5EDUG-FCrnlCWC.js.map → classDiagram-2ON5EDUG-DmPfsN1H.js.map} +1 -1
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-FCrnlCWC.js → classDiagram-v2-WZHVMYZB-DmPfsN1H.js} +6 -6
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-FCrnlCWC.js.map → classDiagram-v2-WZHVMYZB-DmPfsN1H.js.map} +1 -1
- package/dist/static/assets/{clone-BlI81KqZ.js → clone-B1R4pLTW.js} +2 -2
- package/dist/static/assets/{clone-BlI81KqZ.js.map → clone-B1R4pLTW.js.map} +1 -1
- package/dist/static/assets/{cose-bilkent-S5V4N54A-yM7S2atz.js → cose-bilkent-S5V4N54A-CxY__sKv.js} +2 -2
- package/dist/static/assets/{cose-bilkent-S5V4N54A-yM7S2atz.js.map → cose-bilkent-S5V4N54A-CxY__sKv.js.map} +1 -1
- package/dist/static/assets/{dagre-6UL2VRFP-BcweuZHt.js → dagre-6UL2VRFP-CPkB5tQ0.js} +7 -7
- package/dist/static/assets/{dagre-6UL2VRFP-BcweuZHt.js.map → dagre-6UL2VRFP-CPkB5tQ0.js.map} +1 -1
- package/dist/static/assets/{diagram-PSM6KHXK-D4-QwLW1.js → diagram-PSM6KHXK-C6kCVpCz.js} +8 -8
- package/dist/static/assets/{diagram-PSM6KHXK-D4-QwLW1.js.map → diagram-PSM6KHXK-C6kCVpCz.js.map} +1 -1
- package/dist/static/assets/{diagram-QEK2KX5R-BVbuejJn.js → diagram-QEK2KX5R-BWF6htf1.js} +7 -7
- package/dist/static/assets/{diagram-QEK2KX5R-BVbuejJn.js.map → diagram-QEK2KX5R-BWF6htf1.js.map} +1 -1
- package/dist/static/assets/{diagram-S2PKOQOG-pB6N6Tq_.js → diagram-S2PKOQOG-lKGJH6O9.js} +7 -7
- package/dist/static/assets/{diagram-S2PKOQOG-pB6N6Tq_.js.map → diagram-S2PKOQOG-lKGJH6O9.js.map} +1 -1
- package/dist/static/assets/{erDiagram-Q2GNP2WA-DLKmthuw.js → erDiagram-Q2GNP2WA-DJ3YaFob.js} +5 -5
- package/dist/static/assets/{erDiagram-Q2GNP2WA-DLKmthuw.js.map → erDiagram-Q2GNP2WA-DJ3YaFob.js.map} +1 -1
- package/dist/static/assets/{flowDiagram-NV44I4VS-BsBhWukh.js → flowDiagram-NV44I4VS-h3eQwA3O.js} +6 -6
- package/dist/static/assets/{flowDiagram-NV44I4VS-BsBhWukh.js.map → flowDiagram-NV44I4VS-h3eQwA3O.js.map} +1 -1
- package/dist/static/assets/{ganttDiagram-JELNMOA3-Debz-J-C.js → ganttDiagram-JELNMOA3-BCbsDOF_.js} +3 -3
- package/dist/static/assets/{ganttDiagram-JELNMOA3-Debz-J-C.js.map → ganttDiagram-JELNMOA3-BCbsDOF_.js.map} +1 -1
- package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-BnAPFBGR.js → gitGraphDiagram-V2S2FVAM-D0kX6h-T.js} +8 -8
- package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-BnAPFBGR.js.map → gitGraphDiagram-V2S2FVAM-D0kX6h-T.js.map} +1 -1
- package/dist/static/assets/{graph-DbzWiBNK.js → graph-CZIEXp3A.js} +3 -3
- package/dist/static/assets/{graph-DbzWiBNK.js.map → graph-CZIEXp3A.js.map} +1 -1
- package/dist/static/assets/{index-B-8J28g7.js → index-vIzCTZQE.js} +156 -35
- package/dist/static/assets/index-vIzCTZQE.js.map +1 -0
- package/dist/static/assets/{infoDiagram-HS3SLOUP-CZ5hWoxV.js → infoDiagram-HS3SLOUP-DUNbcXxv.js} +6 -6
- package/dist/static/assets/{infoDiagram-HS3SLOUP-CZ5hWoxV.js.map → infoDiagram-HS3SLOUP-DUNbcXxv.js.map} +1 -1
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CKN3oSxk.js → journeyDiagram-XKPGCS4Q-Cg_VhiqB.js} +5 -5
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CKN3oSxk.js.map → journeyDiagram-XKPGCS4Q-Cg_VhiqB.js.map} +1 -1
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-BQCMklfJ.js → kanban-definition-3W4ZIXB7-DMVCZVFE.js} +3 -3
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-BQCMklfJ.js.map → kanban-definition-3W4ZIXB7-DMVCZVFE.js.map} +1 -1
- package/dist/static/assets/{layout-C5B58szc.js → layout-DoKTmwlM.js} +5 -5
- package/dist/static/assets/{layout-C5B58szc.js.map → layout-DoKTmwlM.js.map} +1 -1
- package/dist/static/assets/{linear-_32fut6G.js → linear-DFVlPfX6.js} +2 -2
- package/dist/static/assets/{linear-_32fut6G.js.map → linear-DFVlPfX6.js.map} +1 -1
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-C_goMzjx.js → mindmap-definition-VGOIOE7T-l5K7agVV.js} +4 -4
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-C_goMzjx.js.map → mindmap-definition-VGOIOE7T-l5K7agVV.js.map} +1 -1
- package/dist/static/assets/{pieDiagram-ADFJNKIX-BQ2n0cOB.js → pieDiagram-ADFJNKIX-BfQzSE-A.js} +8 -8
- package/dist/static/assets/{pieDiagram-ADFJNKIX-BQ2n0cOB.js.map → pieDiagram-ADFJNKIX-BfQzSE-A.js.map} +1 -1
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-BLg7_neg.js → quadrantDiagram-AYHSOK5B-CJWvA5jc.js} +3 -3
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-BLg7_neg.js.map → quadrantDiagram-AYHSOK5B-CJWvA5jc.js.map} +1 -1
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DwkJt0zi.js → requirementDiagram-UZGBJVZJ-CeBbmqBK.js} +4 -4
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DwkJt0zi.js.map → requirementDiagram-UZGBJVZJ-CeBbmqBK.js.map} +1 -1
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DmxmatUB.js → sankeyDiagram-TZEHDZUN-JeUBTDxx.js} +2 -2
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DmxmatUB.js.map → sankeyDiagram-TZEHDZUN-JeUBTDxx.js.map} +1 -1
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-KHU_eApU.js → sequenceDiagram-WL72ISMW-Bd_7Pgc5.js} +4 -4
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-KHU_eApU.js.map → sequenceDiagram-WL72ISMW-Bd_7Pgc5.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-B3DBCxAL.js → stateDiagram-FKZM4ZOC-D_WyM3K1.js} +9 -9
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-B3DBCxAL.js.map → stateDiagram-FKZM4ZOC-D_WyM3K1.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-C-uIk7gh.js → stateDiagram-v2-4FDKWEC3-Q_yh26yx.js} +5 -5
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-C-uIk7gh.js.map → stateDiagram-v2-4FDKWEC3-Q_yh26yx.js.map} +1 -1
- package/dist/static/assets/{timeline-definition-IT6M3QCI-SysEcQCC.js → timeline-definition-IT6M3QCI-Ca8mCFDg.js} +3 -3
- package/dist/static/assets/{timeline-definition-IT6M3QCI-SysEcQCC.js.map → timeline-definition-IT6M3QCI-Ca8mCFDg.js.map} +1 -1
- package/dist/static/assets/{treemap-GDKQZRPO-d0AbKEc4.js → treemap-GDKQZRPO-CyBvKC8o.js} +5 -5
- package/dist/static/assets/{treemap-GDKQZRPO-d0AbKEc4.js.map → treemap-GDKQZRPO-CyBvKC8o.js.map} +1 -1
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-CmSQMxUh.js → xychartDiagram-PRI3JC2R-DY0BLEdj.js} +3 -3
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-CmSQMxUh.js.map → xychartDiagram-PRI3JC2R-DY0BLEdj.js.map} +1 -1
- package/dist/static/index.html +1 -1
- package/dist/team.js +33 -4
- package/dist/tools/app-reminders.js +280 -0
- package/dist/tools/prompts/memory/en/errors.md +155 -0
- package/dist/tools/prompts/memory/en/index.md +47 -0
- package/dist/tools/prompts/memory/en/principles.md +79 -0
- package/dist/tools/prompts/memory/en/scenarios.md +174 -0
- package/dist/tools/prompts/memory/en/tools.md +154 -0
- package/dist/tools/prompts/memory/zh/errors.md +155 -0
- package/dist/tools/prompts/memory/zh/index.md +47 -0
- package/dist/tools/prompts/memory/zh/principles.md +79 -0
- package/dist/tools/prompts/memory/zh/scenarios.md +174 -0
- package/dist/tools/prompts/memory/zh/tools.md +154 -0
- package/dist/tools/ripgrep.js +197 -63
- package/package.json +2 -2
- package/dist/static/assets/index-B-8J28g7.js.map +0 -1
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.forkRootDialogTreeAtGeneration = forkRootDialogTreeAtGeneration;
|
|
7
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const dialog_1 = require("./dialog");
|
|
10
|
+
const persistence_1 = require("./persistence");
|
|
11
|
+
const time_1 = require("./shared/utils/time");
|
|
12
|
+
const id_1 = require("./utils/id");
|
|
13
|
+
const FORK_BASELINE_ANCHOR = {
|
|
14
|
+
rootCourse: 1,
|
|
15
|
+
rootGenseq: 0,
|
|
16
|
+
};
|
|
17
|
+
function compareRootAnchor(left, right) {
|
|
18
|
+
if (left.rootCourse < right.rootCourse)
|
|
19
|
+
return -1;
|
|
20
|
+
if (left.rootCourse > right.rootCourse)
|
|
21
|
+
return 1;
|
|
22
|
+
if (left.rootGenseq < right.rootGenseq)
|
|
23
|
+
return -1;
|
|
24
|
+
if (left.rootGenseq > right.rootGenseq)
|
|
25
|
+
return 1;
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
function anchorAtOrBefore(candidate, cutoff) {
|
|
29
|
+
return compareRootAnchor(candidate, cutoff) <= 0;
|
|
30
|
+
}
|
|
31
|
+
function cloneReminderSnapshot(snapshot) {
|
|
32
|
+
return {
|
|
33
|
+
content: snapshot.content,
|
|
34
|
+
owner: undefined,
|
|
35
|
+
meta: snapshot.meta,
|
|
36
|
+
echoback: snapshot.echoback,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function cloneQuestions(questions) {
|
|
40
|
+
return questions.map((question) => ({
|
|
41
|
+
...question,
|
|
42
|
+
remainingCallIds: question.remainingCallIds ? [...question.remainingCallIds] : undefined,
|
|
43
|
+
callSiteRef: { ...question.callSiteRef },
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
function clonePendingSubdialogs(pendingSubdialogs) {
|
|
47
|
+
return pendingSubdialogs.map((entry) => ({
|
|
48
|
+
...entry,
|
|
49
|
+
mentionList: entry.mentionList ? [...entry.mentionList] : undefined,
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
function cloneRegistryEntries(entries) {
|
|
53
|
+
return entries.map((entry) => ({ ...entry }));
|
|
54
|
+
}
|
|
55
|
+
function cloneSubdialogResponses(responses) {
|
|
56
|
+
return responses.map((response) => ({
|
|
57
|
+
...response,
|
|
58
|
+
mentionList: response.mentionList ? [...response.mentionList] : undefined,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
function rewriteForkTreeDialogSelfId(sourceDialogSelfId, sourceRootId, targetRootId) {
|
|
62
|
+
return sourceDialogSelfId === sourceRootId ? targetRootId : sourceDialogSelfId;
|
|
63
|
+
}
|
|
64
|
+
function rewriteAssignmentFromSupForFork(assignmentFromSup, sourceRootId, targetRootId) {
|
|
65
|
+
return {
|
|
66
|
+
...assignmentFromSup,
|
|
67
|
+
callerDialogId: rewriteForkTreeDialogSelfId(assignmentFromSup.callerDialogId, sourceRootId, targetRootId),
|
|
68
|
+
mentionList: assignmentFromSup.mentionList ? [...assignmentFromSup.mentionList] : undefined,
|
|
69
|
+
collectiveTargets: assignmentFromSup.collectiveTargets
|
|
70
|
+
? [...assignmentFromSup.collectiveTargets]
|
|
71
|
+
: undefined,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function rewriteSubdialogMetadataForFork(metadata, sourceRootId, targetRootId) {
|
|
75
|
+
return {
|
|
76
|
+
...metadata,
|
|
77
|
+
supdialogId: rewriteForkTreeDialogSelfId(metadata.supdialogId, sourceRootId, targetRootId),
|
|
78
|
+
assignmentFromSup: rewriteAssignmentFromSupForFork(metadata.assignmentFromSup, sourceRootId, targetRootId),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function isForkStateRecord(record) {
|
|
82
|
+
switch (record.type) {
|
|
83
|
+
case 'subdialog_created_record':
|
|
84
|
+
case 'reminders_reconciled_record':
|
|
85
|
+
case 'questions4human_reconciled_record':
|
|
86
|
+
case 'pending_subdialogs_reconciled_record':
|
|
87
|
+
case 'subdialog_registry_reconciled_record':
|
|
88
|
+
case 'subdialog_responses_reconciled_record':
|
|
89
|
+
return record;
|
|
90
|
+
default:
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function isPersistedMessageRecord(record) {
|
|
95
|
+
switch (record.type) {
|
|
96
|
+
case 'agent_thought_record':
|
|
97
|
+
case 'agent_words_record':
|
|
98
|
+
case 'ui_only_markdown_record':
|
|
99
|
+
case 'human_text_record':
|
|
100
|
+
case 'func_call_record':
|
|
101
|
+
case 'func_result_record':
|
|
102
|
+
case 'teammate_call_result_record':
|
|
103
|
+
case 'teammate_response_record':
|
|
104
|
+
return true;
|
|
105
|
+
case 'web_search_call_record':
|
|
106
|
+
case 'quest_for_sup_record':
|
|
107
|
+
case 'teammate_call_anchor_record':
|
|
108
|
+
case 'gen_start_record':
|
|
109
|
+
case 'gen_finish_record':
|
|
110
|
+
case 'subdialog_created_record':
|
|
111
|
+
case 'reminders_reconciled_record':
|
|
112
|
+
case 'questions4human_reconciled_record':
|
|
113
|
+
case 'pending_subdialogs_reconciled_record':
|
|
114
|
+
case 'subdialog_registry_reconciled_record':
|
|
115
|
+
case 'subdialog_responses_reconciled_record':
|
|
116
|
+
return false;
|
|
117
|
+
default: {
|
|
118
|
+
const _exhaustive = record;
|
|
119
|
+
throw new Error(`Unhandled persisted record while counting messages: ${String(_exhaustive)}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function getRecordRootAnchor(record) {
|
|
124
|
+
const rootCourse = 'rootCourse' in record && typeof record.rootCourse === 'number' ? record.rootCourse : null;
|
|
125
|
+
const rootGenseq = 'rootGenseq' in record && typeof record.rootGenseq === 'number' ? record.rootGenseq : null;
|
|
126
|
+
if (rootCourse === null || rootGenseq === null) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
rootCourse,
|
|
131
|
+
rootGenseq,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function normalizeDraftUserText(events, targetGenseq) {
|
|
135
|
+
const texts = events
|
|
136
|
+
.filter((event) => event.type === 'human_text_record' && event.genseq === targetGenseq)
|
|
137
|
+
.map((event) => event.content.trim())
|
|
138
|
+
.filter((value) => value !== '');
|
|
139
|
+
if (texts.length === 0)
|
|
140
|
+
return null;
|
|
141
|
+
return texts.join('\n\n');
|
|
142
|
+
}
|
|
143
|
+
function rewriteFuncResultContentItems(items, newRootId) {
|
|
144
|
+
if (!items)
|
|
145
|
+
return undefined;
|
|
146
|
+
return items.map((item) => {
|
|
147
|
+
switch (item.type) {
|
|
148
|
+
case 'input_text':
|
|
149
|
+
return item;
|
|
150
|
+
case 'input_image':
|
|
151
|
+
return {
|
|
152
|
+
...item,
|
|
153
|
+
artifact: {
|
|
154
|
+
...item.artifact,
|
|
155
|
+
rootId: newRootId,
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
default: {
|
|
159
|
+
const _exhaustive = item;
|
|
160
|
+
return _exhaustive;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
function rewriteRecordForFork(record, newRootId) {
|
|
166
|
+
switch (record.type) {
|
|
167
|
+
case 'agent_thought_record':
|
|
168
|
+
case 'agent_words_record':
|
|
169
|
+
case 'ui_only_markdown_record':
|
|
170
|
+
case 'func_call_record':
|
|
171
|
+
case 'web_search_call_record':
|
|
172
|
+
case 'human_text_record':
|
|
173
|
+
case 'quest_for_sup_record':
|
|
174
|
+
case 'teammate_call_result_record':
|
|
175
|
+
case 'teammate_call_anchor_record':
|
|
176
|
+
case 'teammate_response_record':
|
|
177
|
+
case 'gen_start_record':
|
|
178
|
+
case 'gen_finish_record':
|
|
179
|
+
return record;
|
|
180
|
+
case 'func_result_record':
|
|
181
|
+
return {
|
|
182
|
+
...record,
|
|
183
|
+
contentItems: rewriteFuncResultContentItems(record.contentItems, newRootId),
|
|
184
|
+
};
|
|
185
|
+
case 'subdialog_created_record':
|
|
186
|
+
case 'reminders_reconciled_record':
|
|
187
|
+
case 'questions4human_reconciled_record':
|
|
188
|
+
case 'pending_subdialogs_reconciled_record':
|
|
189
|
+
case 'subdialog_registry_reconciled_record':
|
|
190
|
+
case 'subdialog_responses_reconciled_record':
|
|
191
|
+
throw new Error(`Fork transcript copy must not include state record ${record.type}`);
|
|
192
|
+
default: {
|
|
193
|
+
const _exhaustive = record;
|
|
194
|
+
return _exhaustive;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function countMessages(events) {
|
|
199
|
+
let count = 0;
|
|
200
|
+
for (const event of events) {
|
|
201
|
+
if (isPersistedMessageRecord(event)) {
|
|
202
|
+
count += 1;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return count;
|
|
206
|
+
}
|
|
207
|
+
function countFunctionCalls(events) {
|
|
208
|
+
let count = 0;
|
|
209
|
+
for (const event of events) {
|
|
210
|
+
if (event.type === 'func_call_record') {
|
|
211
|
+
count += 1;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return count;
|
|
215
|
+
}
|
|
216
|
+
function computeRootForkRunState(args) {
|
|
217
|
+
if (args.action.kind === 'draft_user_text') {
|
|
218
|
+
return { kind: 'idle_waiting_user' };
|
|
219
|
+
}
|
|
220
|
+
const hasQ4H = args.questions.length > 0;
|
|
221
|
+
const hasSubdialogs = args.pendingSubdialogs.length > 0;
|
|
222
|
+
if (hasQ4H && hasSubdialogs) {
|
|
223
|
+
return { kind: 'blocked', reason: { kind: 'needs_human_input_and_subdialogs' } };
|
|
224
|
+
}
|
|
225
|
+
if (hasQ4H) {
|
|
226
|
+
return { kind: 'blocked', reason: { kind: 'needs_human_input' } };
|
|
227
|
+
}
|
|
228
|
+
if (hasSubdialogs) {
|
|
229
|
+
return { kind: 'blocked', reason: { kind: 'waiting_for_subdialogs' } };
|
|
230
|
+
}
|
|
231
|
+
return { kind: 'interrupted', reason: { kind: 'system_stop', detail: 'fork_dialog_continue' } };
|
|
232
|
+
}
|
|
233
|
+
async function copyArtifactsIfPresent(sourceId, targetId, sourceStatus) {
|
|
234
|
+
const sourceDir = node_path_1.default.join(persistence_1.DialogPersistence.getDialogEventsPath(sourceId, sourceStatus), 'artifacts');
|
|
235
|
+
const targetDir = node_path_1.default.join(persistence_1.DialogPersistence.getDialogEventsPath(targetId, 'running'), 'artifacts');
|
|
236
|
+
try {
|
|
237
|
+
await promises_1.default.access(sourceDir);
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
const code = typeof error === 'object' && error !== null ? error.code : undefined;
|
|
241
|
+
if (code === 'ENOENT')
|
|
242
|
+
return;
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(targetDir), { recursive: true });
|
|
246
|
+
await promises_1.default.cp(sourceDir, targetDir, { recursive: true });
|
|
247
|
+
}
|
|
248
|
+
async function listDialogCourseNumbers(dialogId, status) {
|
|
249
|
+
const dialogDir = persistence_1.DialogPersistence.getDialogEventsPath(dialogId, status);
|
|
250
|
+
let entries = [];
|
|
251
|
+
try {
|
|
252
|
+
entries = (await promises_1.default.readdir(dialogDir, { withFileTypes: true }));
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
const code = typeof error === 'object' && error !== null ? error.code : undefined;
|
|
256
|
+
if (code === 'ENOENT')
|
|
257
|
+
return [];
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
const courses = [];
|
|
261
|
+
for (const entry of entries) {
|
|
262
|
+
if (!entry.isFile())
|
|
263
|
+
continue;
|
|
264
|
+
if (!/^course-\d+\.jsonl$/.test(entry.name))
|
|
265
|
+
continue;
|
|
266
|
+
courses.push(persistence_1.DialogPersistence.getCourseFromFilename(entry.name));
|
|
267
|
+
}
|
|
268
|
+
courses.sort((a, b) => a - b);
|
|
269
|
+
return courses;
|
|
270
|
+
}
|
|
271
|
+
async function collectForkSnapshot(dialogId, status, cutoffAnchor) {
|
|
272
|
+
const courseNumbers = await listDialogCourseNumbers(dialogId, status);
|
|
273
|
+
let latestReminders = null;
|
|
274
|
+
let latestQuestions = null;
|
|
275
|
+
let latestPending = null;
|
|
276
|
+
let latestRegistry = null;
|
|
277
|
+
let latestResponses = null;
|
|
278
|
+
for (const course of courseNumbers) {
|
|
279
|
+
const events = await persistence_1.DialogPersistence.readCourseEvents(dialogId, course, status);
|
|
280
|
+
for (const event of events) {
|
|
281
|
+
const stateRecord = isForkStateRecord(event);
|
|
282
|
+
if (!stateRecord)
|
|
283
|
+
continue;
|
|
284
|
+
if (!anchorAtOrBefore(stateRecord, cutoffAnchor))
|
|
285
|
+
continue;
|
|
286
|
+
switch (stateRecord.type) {
|
|
287
|
+
case 'reminders_reconciled_record':
|
|
288
|
+
latestReminders = stateRecord.reminders.map((item) => ({ ...item }));
|
|
289
|
+
break;
|
|
290
|
+
case 'questions4human_reconciled_record':
|
|
291
|
+
latestQuestions = cloneQuestions(stateRecord.questions);
|
|
292
|
+
break;
|
|
293
|
+
case 'pending_subdialogs_reconciled_record':
|
|
294
|
+
latestPending = clonePendingSubdialogs(stateRecord.pendingSubdialogs);
|
|
295
|
+
break;
|
|
296
|
+
case 'subdialog_registry_reconciled_record':
|
|
297
|
+
latestRegistry = cloneRegistryEntries(stateRecord.entries);
|
|
298
|
+
break;
|
|
299
|
+
case 'subdialog_responses_reconciled_record':
|
|
300
|
+
latestResponses = cloneSubdialogResponses(stateRecord.responses);
|
|
301
|
+
break;
|
|
302
|
+
case 'subdialog_created_record':
|
|
303
|
+
break;
|
|
304
|
+
default: {
|
|
305
|
+
const _exhaustive = stateRecord;
|
|
306
|
+
throw new Error(`Unhandled fork snapshot record ${String(_exhaustive)}`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
reminders: latestReminders !== null ? latestReminders.map((item) => cloneReminderSnapshot(item)) : [],
|
|
313
|
+
questions: latestQuestions ?? [],
|
|
314
|
+
pendingSubdialogs: latestPending ?? [],
|
|
315
|
+
registryEntries: latestRegistry ?? [],
|
|
316
|
+
subdialogResponses: latestResponses ?? [],
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
async function collectIncludedSubdialogs(args) {
|
|
320
|
+
const sourceRootDialogId = new dialog_1.DialogID(args.sourceRootId);
|
|
321
|
+
const courseNumbers = await listDialogCourseNumbers(sourceRootDialogId, args.sourceStatus);
|
|
322
|
+
const includedSelfIds = new Set();
|
|
323
|
+
for (const course of courseNumbers) {
|
|
324
|
+
const events = await persistence_1.DialogPersistence.readCourseEvents(sourceRootDialogId, course, args.sourceStatus);
|
|
325
|
+
for (const event of events) {
|
|
326
|
+
if (event.type !== 'subdialog_created_record')
|
|
327
|
+
continue;
|
|
328
|
+
if (!anchorAtOrBefore(event, args.cutoffAnchor))
|
|
329
|
+
continue;
|
|
330
|
+
includedSelfIds.add(event.subdialogId);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const included = [];
|
|
334
|
+
const orderedSelfIds = Array.from(includedSelfIds).sort();
|
|
335
|
+
for (const selfId of orderedSelfIds) {
|
|
336
|
+
const sourceId = new dialog_1.DialogID(selfId, args.sourceRootId);
|
|
337
|
+
const metadata = await persistence_1.DialogPersistence.loadDialogMetadata(sourceId, args.sourceStatus);
|
|
338
|
+
if (!metadata || metadata.supdialogId === undefined) {
|
|
339
|
+
throw new Error(`Missing included subdialog metadata for ${sourceId.valueOf()}`);
|
|
340
|
+
}
|
|
341
|
+
included.push({
|
|
342
|
+
sourceId,
|
|
343
|
+
targetId: new dialog_1.DialogID(selfId, args.targetRootId),
|
|
344
|
+
metadata,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
return included;
|
|
348
|
+
}
|
|
349
|
+
async function buildDialogForkPlan(args) {
|
|
350
|
+
const courseNumbers = await listDialogCourseNumbers(args.sourceId, args.sourceStatus);
|
|
351
|
+
const retainedCourses = [];
|
|
352
|
+
for (const course of courseNumbers) {
|
|
353
|
+
const events = await persistence_1.DialogPersistence.readCourseEvents(args.sourceId, course, args.sourceStatus);
|
|
354
|
+
const isRootDialog = args.sourceId.selfId === args.sourceId.rootId;
|
|
355
|
+
const retained = events.filter((event, index) => {
|
|
356
|
+
if (isForkStateRecord(event)) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
if (args.truncateRootCourse && course === args.truncateRootCourse.course && isRootDialog) {
|
|
360
|
+
return index < args.truncateRootCourse.keepCount;
|
|
361
|
+
}
|
|
362
|
+
if (!isRootDialog) {
|
|
363
|
+
const recordAnchor = getRecordRootAnchor(event);
|
|
364
|
+
if (recordAnchor === null) {
|
|
365
|
+
throw new Error(`fork dialog requires root anchor on subdialog transcript record: dialog=${args.sourceId.valueOf()} course=${String(course)} type=${event.type}`);
|
|
366
|
+
}
|
|
367
|
+
return anchorAtOrBefore(recordAnchor, args.cutoffAnchor);
|
|
368
|
+
}
|
|
369
|
+
return true;
|
|
370
|
+
});
|
|
371
|
+
if (retained.length > 0) {
|
|
372
|
+
retainedCourses.push({ course, events: retained });
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const snapshot = await collectForkSnapshot(args.sourceId, args.sourceStatus, args.cutoffAnchor);
|
|
376
|
+
const retainedCurrentCourse = retainedCourses.length > 0 ? retainedCourses[retainedCourses.length - 1].course : 1;
|
|
377
|
+
return {
|
|
378
|
+
sourceId: args.sourceId,
|
|
379
|
+
targetId: args.targetId,
|
|
380
|
+
metadata: args.sourceMetadata,
|
|
381
|
+
retainedCourses,
|
|
382
|
+
currentCourse: retainedCurrentCourse,
|
|
383
|
+
reminders: snapshot.reminders,
|
|
384
|
+
questions: snapshot.questions,
|
|
385
|
+
pendingSubdialogs: snapshot.pendingSubdialogs,
|
|
386
|
+
registryEntries: snapshot.registryEntries,
|
|
387
|
+
subdialogResponses: snapshot.subdialogResponses,
|
|
388
|
+
childCount: args.childCount,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
async function appendForkBaselineState(plan, rootBaselineRecords) {
|
|
392
|
+
const baselineTs = (0, time_1.formatUnifiedTimestamp)(new Date());
|
|
393
|
+
for (const record of rootBaselineRecords) {
|
|
394
|
+
await persistence_1.DialogPersistence.appendEvent(plan.targetId, 1, record, 'running');
|
|
395
|
+
}
|
|
396
|
+
const remindersRecord = {
|
|
397
|
+
ts: baselineTs,
|
|
398
|
+
type: 'reminders_reconciled_record',
|
|
399
|
+
...FORK_BASELINE_ANCHOR,
|
|
400
|
+
reminders: plan.reminders.map((reminder) => ({
|
|
401
|
+
content: reminder.content,
|
|
402
|
+
ownerName: reminder.owner?.name,
|
|
403
|
+
meta: reminder.meta,
|
|
404
|
+
echoback: reminder.echoback,
|
|
405
|
+
createdAt: reminder.createdAt ?? baselineTs,
|
|
406
|
+
priority: reminder.priority ?? 'medium',
|
|
407
|
+
})),
|
|
408
|
+
};
|
|
409
|
+
const q4hRecord = {
|
|
410
|
+
ts: baselineTs,
|
|
411
|
+
type: 'questions4human_reconciled_record',
|
|
412
|
+
...FORK_BASELINE_ANCHOR,
|
|
413
|
+
questions: cloneQuestions(plan.questions),
|
|
414
|
+
};
|
|
415
|
+
const pendingRecord = {
|
|
416
|
+
ts: baselineTs,
|
|
417
|
+
type: 'pending_subdialogs_reconciled_record',
|
|
418
|
+
...FORK_BASELINE_ANCHOR,
|
|
419
|
+
pendingSubdialogs: clonePendingSubdialogs(plan.pendingSubdialogs),
|
|
420
|
+
};
|
|
421
|
+
const registryRecord = {
|
|
422
|
+
ts: baselineTs,
|
|
423
|
+
type: 'subdialog_registry_reconciled_record',
|
|
424
|
+
...FORK_BASELINE_ANCHOR,
|
|
425
|
+
entries: cloneRegistryEntries(plan.registryEntries),
|
|
426
|
+
};
|
|
427
|
+
const responsesRecord = {
|
|
428
|
+
ts: baselineTs,
|
|
429
|
+
type: 'subdialog_responses_reconciled_record',
|
|
430
|
+
...FORK_BASELINE_ANCHOR,
|
|
431
|
+
responses: cloneSubdialogResponses(plan.subdialogResponses),
|
|
432
|
+
};
|
|
433
|
+
await persistence_1.DialogPersistence.appendEvent(plan.targetId, 1, remindersRecord, 'running');
|
|
434
|
+
await persistence_1.DialogPersistence.appendEvent(plan.targetId, 1, q4hRecord, 'running');
|
|
435
|
+
await persistence_1.DialogPersistence.appendEvent(plan.targetId, 1, pendingRecord, 'running');
|
|
436
|
+
await persistence_1.DialogPersistence.appendEvent(plan.targetId, 1, registryRecord, 'running');
|
|
437
|
+
await persistence_1.DialogPersistence.appendEvent(plan.targetId, 1, responsesRecord, 'running');
|
|
438
|
+
}
|
|
439
|
+
async function persistForkPlan(args) {
|
|
440
|
+
const { plan } = args;
|
|
441
|
+
let rewrittenMetadata;
|
|
442
|
+
if (plan.targetId.selfId === plan.targetId.rootId) {
|
|
443
|
+
rewrittenMetadata = {
|
|
444
|
+
...plan.metadata,
|
|
445
|
+
id: plan.targetId.selfId,
|
|
446
|
+
createdAt: args.now,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
if (plan.metadata.supdialogId === undefined) {
|
|
451
|
+
throw new Error(`fork subdialog plan missing supdialog metadata: ${plan.targetId.valueOf()}`);
|
|
452
|
+
}
|
|
453
|
+
rewrittenMetadata = rewriteSubdialogMetadataForFork(plan.metadata, plan.sourceId.rootId, plan.targetId.rootId);
|
|
454
|
+
}
|
|
455
|
+
await persistence_1.DialogPersistence.saveDialogMetadata(plan.targetId, rewrittenMetadata, 'running');
|
|
456
|
+
for (const course of plan.retainedCourses) {
|
|
457
|
+
for (const event of course.events) {
|
|
458
|
+
await persistence_1.DialogPersistence.appendEvent(plan.targetId, course.course, rewriteRecordForFork(event, plan.targetId.rootId), 'running');
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
await appendForkBaselineState(plan, plan.targetId.selfId === plan.targetId.rootId ? args.rootBaselineRecords : []);
|
|
462
|
+
await persistence_1.DialogPersistence._saveReminderState(plan.targetId, [...plan.reminders], 'running');
|
|
463
|
+
await persistence_1.DialogPersistence._saveQuestions4HumanState(plan.targetId, [...plan.questions], 'running');
|
|
464
|
+
await persistence_1.DialogPersistence.savePendingSubdialogs(plan.targetId, [...plan.pendingSubdialogs], undefined, 'running');
|
|
465
|
+
await persistence_1.DialogPersistence.saveSubdialogRegistry(plan.targetId, plan.registryEntries.map((entry) => ({
|
|
466
|
+
key: entry.key,
|
|
467
|
+
subdialogId: new dialog_1.DialogID(entry.subdialogId, plan.targetId.rootId),
|
|
468
|
+
agentId: entry.agentId,
|
|
469
|
+
sessionSlug: entry.sessionSlug,
|
|
470
|
+
})), 'running');
|
|
471
|
+
await persistence_1.DialogPersistence.saveSubdialogResponses(plan.targetId, [...plan.subdialogResponses], undefined, 'running');
|
|
472
|
+
await copyArtifactsIfPresent(plan.sourceId, plan.targetId, args.sourceStatus);
|
|
473
|
+
const currentCourseEvents = plan.retainedCourses.find((item) => item.course === plan.currentCourse)?.events ?? [];
|
|
474
|
+
const runState = plan.targetId.selfId === plan.targetId.rootId
|
|
475
|
+
? computeRootForkRunState({
|
|
476
|
+
action: args.action,
|
|
477
|
+
questions: plan.questions,
|
|
478
|
+
pendingSubdialogs: plan.pendingSubdialogs,
|
|
479
|
+
})
|
|
480
|
+
: { kind: 'idle_waiting_user' };
|
|
481
|
+
await persistence_1.DialogPersistence.mutateDialogLatest(plan.targetId, () => ({
|
|
482
|
+
kind: 'replace',
|
|
483
|
+
next: {
|
|
484
|
+
currentCourse: plan.currentCourse,
|
|
485
|
+
lastModified: args.now,
|
|
486
|
+
status: 'active',
|
|
487
|
+
messageCount: countMessages(currentCourseEvents),
|
|
488
|
+
functionCallCount: countFunctionCalls(currentCourseEvents),
|
|
489
|
+
subdialogCount: plan.childCount,
|
|
490
|
+
generating: false,
|
|
491
|
+
needsDrive: false,
|
|
492
|
+
runState,
|
|
493
|
+
disableDiligencePush: plan.targetId.selfId === plan.targetId.rootId ? args.latestDisableDiligencePush : false,
|
|
494
|
+
diligencePushRemainingBudget: plan.targetId.selfId === plan.targetId.rootId
|
|
495
|
+
? args.latestDiligencePushRemainingBudget
|
|
496
|
+
: undefined,
|
|
497
|
+
},
|
|
498
|
+
}));
|
|
499
|
+
}
|
|
500
|
+
async function forkRootDialogTreeAtGeneration(args) {
|
|
501
|
+
const sourceRootId = args.sourceRootId.trim();
|
|
502
|
+
if (sourceRootId === '') {
|
|
503
|
+
throw new Error('sourceRootId is required');
|
|
504
|
+
}
|
|
505
|
+
if (!Number.isFinite(args.course) || args.course <= 0) {
|
|
506
|
+
throw new Error('course must be a positive integer');
|
|
507
|
+
}
|
|
508
|
+
if (!Number.isFinite(args.genseq) || args.genseq <= 0) {
|
|
509
|
+
throw new Error('genseq must be a positive integer');
|
|
510
|
+
}
|
|
511
|
+
const sourceRootDialogId = new dialog_1.DialogID(sourceRootId);
|
|
512
|
+
const sourceMetadata = await persistence_1.DialogPersistence.loadDialogMetadata(sourceRootDialogId, args.sourceStatus);
|
|
513
|
+
if (!sourceMetadata) {
|
|
514
|
+
throw new Error(`Root dialog not found: ${sourceRootId} (${args.sourceStatus})`);
|
|
515
|
+
}
|
|
516
|
+
if (sourceMetadata.supdialogId !== undefined) {
|
|
517
|
+
throw new Error(`fork dialog only supports root dialogs: ${sourceRootId}`);
|
|
518
|
+
}
|
|
519
|
+
const targetCourse = Math.floor(args.course);
|
|
520
|
+
const targetGenseq = Math.floor(args.genseq);
|
|
521
|
+
const rootEvents = await persistence_1.DialogPersistence.readCourseEvents(sourceRootDialogId, targetCourse, args.sourceStatus);
|
|
522
|
+
const targetStartIndex = rootEvents.findIndex((event) => 'genseq' in event && typeof event.genseq === 'number' && event.genseq === targetGenseq);
|
|
523
|
+
if (targetStartIndex < 0) {
|
|
524
|
+
throw new Error(`Target genseq ${String(targetGenseq)} not found in dialog ${sourceRootId} course ${String(targetCourse)}`);
|
|
525
|
+
}
|
|
526
|
+
const targetStartEvent = rootEvents[targetStartIndex];
|
|
527
|
+
if (!targetStartEvent) {
|
|
528
|
+
throw new Error(`Target genseq ${String(targetGenseq)} missing start event in dialog ${sourceRootId} course ${String(targetCourse)}`);
|
|
529
|
+
}
|
|
530
|
+
const cutoffAnchor = {
|
|
531
|
+
rootCourse: targetCourse,
|
|
532
|
+
rootGenseq: targetGenseq - 1,
|
|
533
|
+
};
|
|
534
|
+
const draftUserText = normalizeDraftUserText(rootEvents, targetGenseq);
|
|
535
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(sourceRootDialogId, args.sourceStatus);
|
|
536
|
+
const targetRootId = (0, id_1.generateDialogID)();
|
|
537
|
+
const now = (0, time_1.formatUnifiedTimestamp)(new Date());
|
|
538
|
+
const includedSubdialogs = await collectIncludedSubdialogs({
|
|
539
|
+
sourceRootId,
|
|
540
|
+
sourceStatus: args.sourceStatus,
|
|
541
|
+
cutoffAnchor,
|
|
542
|
+
targetRootId,
|
|
543
|
+
});
|
|
544
|
+
const childCountByParentSelfId = new Map();
|
|
545
|
+
for (const subdialog of includedSubdialogs) {
|
|
546
|
+
childCountByParentSelfId.set(subdialog.metadata.supdialogId, (childCountByParentSelfId.get(subdialog.metadata.supdialogId) ?? 0) + 1);
|
|
547
|
+
}
|
|
548
|
+
const rootPlan = await buildDialogForkPlan({
|
|
549
|
+
sourceId: sourceRootDialogId,
|
|
550
|
+
targetId: new dialog_1.DialogID(targetRootId),
|
|
551
|
+
sourceStatus: args.sourceStatus,
|
|
552
|
+
sourceMetadata,
|
|
553
|
+
cutoffAnchor,
|
|
554
|
+
truncateRootCourse: { course: targetCourse, keepCount: targetStartIndex },
|
|
555
|
+
childCount: childCountByParentSelfId.get(sourceRootId) ?? 0,
|
|
556
|
+
});
|
|
557
|
+
const action = draftUserText !== null
|
|
558
|
+
? { kind: 'draft_user_text', userText: draftUserText }
|
|
559
|
+
: rootPlan.questions.length > 0 || rootPlan.pendingSubdialogs.length > 0
|
|
560
|
+
? {
|
|
561
|
+
kind: 'restore_pending',
|
|
562
|
+
pendingQ4H: rootPlan.questions.length > 0,
|
|
563
|
+
pendingSubdialogs: rootPlan.pendingSubdialogs.length > 0,
|
|
564
|
+
}
|
|
565
|
+
: { kind: 'auto_continue' };
|
|
566
|
+
const subdialogPlans = [];
|
|
567
|
+
for (const subdialog of includedSubdialogs) {
|
|
568
|
+
subdialogPlans.push(await buildDialogForkPlan({
|
|
569
|
+
sourceId: subdialog.sourceId,
|
|
570
|
+
targetId: subdialog.targetId,
|
|
571
|
+
sourceStatus: args.sourceStatus,
|
|
572
|
+
sourceMetadata: subdialog.metadata,
|
|
573
|
+
cutoffAnchor,
|
|
574
|
+
childCount: childCountByParentSelfId.get(subdialog.sourceId.selfId) ?? 0,
|
|
575
|
+
}));
|
|
576
|
+
}
|
|
577
|
+
const rootBaselineRecords = includedSubdialogs.map((subdialog) => ({
|
|
578
|
+
ts: now,
|
|
579
|
+
type: 'subdialog_created_record',
|
|
580
|
+
...FORK_BASELINE_ANCHOR,
|
|
581
|
+
subdialogId: subdialog.targetId.selfId,
|
|
582
|
+
supdialogId: rewriteForkTreeDialogSelfId(subdialog.metadata.supdialogId, sourceRootId, targetRootId),
|
|
583
|
+
agentId: subdialog.metadata.agentId,
|
|
584
|
+
taskDocPath: subdialog.metadata.taskDocPath,
|
|
585
|
+
createdAt: subdialog.metadata.createdAt,
|
|
586
|
+
sessionSlug: subdialog.metadata.sessionSlug,
|
|
587
|
+
assignmentFromSup: rewriteAssignmentFromSupForFork(subdialog.metadata.assignmentFromSup, sourceRootId, targetRootId),
|
|
588
|
+
}));
|
|
589
|
+
const allPlans = [rootPlan, ...subdialogPlans];
|
|
590
|
+
for (const plan of allPlans) {
|
|
591
|
+
await persistForkPlan({
|
|
592
|
+
plan,
|
|
593
|
+
sourceStatus: args.sourceStatus,
|
|
594
|
+
now,
|
|
595
|
+
action,
|
|
596
|
+
rootBaselineRecords,
|
|
597
|
+
latestDisableDiligencePush: latest?.disableDiligencePush,
|
|
598
|
+
latestDiligencePushRemainingBudget: latest?.diligencePushRemainingBudget,
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
rootId: targetRootId,
|
|
603
|
+
selfId: targetRootId,
|
|
604
|
+
agentId: sourceMetadata.agentId,
|
|
605
|
+
taskDocPath: sourceMetadata.taskDocPath,
|
|
606
|
+
action,
|
|
607
|
+
};
|
|
608
|
+
}
|
package/dist/dialog.js
CHANGED
|
@@ -1041,7 +1041,7 @@ class RootDialog extends Dialog {
|
|
|
1041
1041
|
agentId: subdialog.agentId,
|
|
1042
1042
|
sessionSlug: subdialog.sessionSlug,
|
|
1043
1043
|
}));
|
|
1044
|
-
await this.dlgStore.saveSubdialogRegistry(this.id, entries, this.status);
|
|
1044
|
+
await this.dlgStore.saveSubdialogRegistry(this, this.id, entries, this.status);
|
|
1045
1045
|
}
|
|
1046
1046
|
/**
|
|
1047
1047
|
* Load subdialog registry from disk (registry.yaml).
|
|
@@ -1124,7 +1124,7 @@ class DialogStore {
|
|
|
1124
1124
|
async loadPendingSubdialogs(_dialogId, _status) {
|
|
1125
1125
|
return [];
|
|
1126
1126
|
}
|
|
1127
|
-
async saveSubdialogRegistry(_rootDialogId, _entries, _status) { }
|
|
1127
|
+
async saveSubdialogRegistry(_dialog, _rootDialogId, _entries, _status) { }
|
|
1128
1128
|
async loadSubdialogRegistry(_rootDialog, _status) { }
|
|
1129
1129
|
/**
|
|
1130
1130
|
* Clear Questions for Human state in storage
|