dominds 0.7.2 → 0.7.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.
Files changed (105) hide show
  1. package/dist/dialog-global-registry.js +58 -3
  2. package/dist/dialog.js +17 -0
  3. package/dist/evt-registry.js +53 -14
  4. package/dist/llm/driver-v2/context.js +2 -1
  5. package/dist/llm/driver-v2/core.js +1 -118
  6. package/dist/llm/driver-v2/orchestrator.js +65 -38
  7. package/dist/llm/driver-v2/round.js +117 -31
  8. package/dist/llm/driver-v2/runtime-utils.js +1 -0
  9. package/dist/llm/driver-v2/supdialog-response.js +5 -18
  10. package/dist/llm/driver-v2/tellask-bridge.js +66 -4
  11. package/dist/persistence.js +80 -9
  12. package/dist/server/websocket-handler.js +48 -29
  13. package/dist/static/assets/{_baseUniq-C04fddeD.js → _baseUniq-C_6DmNp6.js} +2 -2
  14. package/dist/static/assets/{_baseUniq-C04fddeD.js.map → _baseUniq-C_6DmNp6.js.map} +1 -1
  15. package/dist/static/assets/{arc-qmZerooe.js → arc-CbWoOhl1.js} +2 -2
  16. package/dist/static/assets/{arc-qmZerooe.js.map → arc-CbWoOhl1.js.map} +1 -1
  17. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DPAwJ19g.js → architectureDiagram-VXUJARFQ-CTckhB9O.js} +6 -6
  18. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DPAwJ19g.js.map → architectureDiagram-VXUJARFQ-CTckhB9O.js.map} +1 -1
  19. package/dist/static/assets/{blockDiagram-VD42YOAC-M0jbEJ-1.js → blockDiagram-VD42YOAC-mX558EDN.js} +7 -7
  20. package/dist/static/assets/{blockDiagram-VD42YOAC-M0jbEJ-1.js.map → blockDiagram-VD42YOAC-mX558EDN.js.map} +1 -1
  21. package/dist/static/assets/{c4Diagram-YG6GDRKO-DlF8gwFw.js → c4Diagram-YG6GDRKO-Bti3To3b.js} +3 -3
  22. package/dist/static/assets/{c4Diagram-YG6GDRKO-DlF8gwFw.js.map → c4Diagram-YG6GDRKO-Bti3To3b.js.map} +1 -1
  23. package/dist/static/assets/{channel-B2Ph7be3.js → channel-Dxi4rUwG.js} +2 -2
  24. package/dist/static/assets/{channel-B2Ph7be3.js.map → channel-Dxi4rUwG.js.map} +1 -1
  25. package/dist/static/assets/{chunk-4BX2VUAB-BZ2L6PK1.js → chunk-4BX2VUAB-CAbdAd2-.js} +2 -2
  26. package/dist/static/assets/{chunk-4BX2VUAB-BZ2L6PK1.js.map → chunk-4BX2VUAB-CAbdAd2-.js.map} +1 -1
  27. package/dist/static/assets/{chunk-55IACEB6-COXFmnJW.js → chunk-55IACEB6-D4r4rpB1.js} +2 -2
  28. package/dist/static/assets/{chunk-55IACEB6-COXFmnJW.js.map → chunk-55IACEB6-D4r4rpB1.js.map} +1 -1
  29. package/dist/static/assets/{chunk-B4BG7PRW-B1HiWlBq.js → chunk-B4BG7PRW-sNmEhJCQ.js} +5 -5
  30. package/dist/static/assets/{chunk-B4BG7PRW-B1HiWlBq.js.map → chunk-B4BG7PRW-sNmEhJCQ.js.map} +1 -1
  31. package/dist/static/assets/{chunk-DI55MBZ5-BO3wQRnL.js → chunk-DI55MBZ5-BSutc2-e.js} +4 -4
  32. package/dist/static/assets/{chunk-DI55MBZ5-BO3wQRnL.js.map → chunk-DI55MBZ5-BSutc2-e.js.map} +1 -1
  33. package/dist/static/assets/{chunk-FMBD7UC4-BdavRHSy.js → chunk-FMBD7UC4-DafIeMhA.js} +2 -2
  34. package/dist/static/assets/{chunk-FMBD7UC4-BdavRHSy.js.map → chunk-FMBD7UC4-DafIeMhA.js.map} +1 -1
  35. package/dist/static/assets/{chunk-QN33PNHL-DchoUNF7.js → chunk-QN33PNHL-1EobqGS_.js} +2 -2
  36. package/dist/static/assets/{chunk-QN33PNHL-DchoUNF7.js.map → chunk-QN33PNHL-1EobqGS_.js.map} +1 -1
  37. package/dist/static/assets/{chunk-QZHKN3VN-Dr3uVTtK.js → chunk-QZHKN3VN-C4U4YGsG.js} +2 -2
  38. package/dist/static/assets/{chunk-QZHKN3VN-Dr3uVTtK.js.map → chunk-QZHKN3VN-C4U4YGsG.js.map} +1 -1
  39. package/dist/static/assets/{chunk-TZMSLE5B-BhOcHZNs.js → chunk-TZMSLE5B-BAuDx0ol.js} +2 -2
  40. package/dist/static/assets/{chunk-TZMSLE5B-BhOcHZNs.js.map → chunk-TZMSLE5B-BAuDx0ol.js.map} +1 -1
  41. package/dist/static/assets/{classDiagram-2ON5EDUG-Dep-MR6W.js → classDiagram-2ON5EDUG-B0n34y1v.js} +6 -6
  42. package/dist/static/assets/{classDiagram-2ON5EDUG-Dep-MR6W.js.map → classDiagram-2ON5EDUG-B0n34y1v.js.map} +1 -1
  43. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-Dep-MR6W.js → classDiagram-v2-WZHVMYZB-B0n34y1v.js} +6 -6
  44. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-Dep-MR6W.js.map → classDiagram-v2-WZHVMYZB-B0n34y1v.js.map} +1 -1
  45. package/dist/static/assets/{clone-DzoL-dSX.js → clone-DMVEoZzo.js} +2 -2
  46. package/dist/static/assets/{clone-DzoL-dSX.js.map → clone-DMVEoZzo.js.map} +1 -1
  47. package/dist/static/assets/{cose-bilkent-S5V4N54A-Bqu_DqDB.js → cose-bilkent-S5V4N54A-BM7Q-IjT.js} +2 -2
  48. package/dist/static/assets/{cose-bilkent-S5V4N54A-Bqu_DqDB.js.map → cose-bilkent-S5V4N54A-BM7Q-IjT.js.map} +1 -1
  49. package/dist/static/assets/{dagre-6UL2VRFP-49InNTzs.js → dagre-6UL2VRFP-DsBBLjwD.js} +7 -7
  50. package/dist/static/assets/{dagre-6UL2VRFP-49InNTzs.js.map → dagre-6UL2VRFP-DsBBLjwD.js.map} +1 -1
  51. package/dist/static/assets/{diagram-PSM6KHXK-C1IsQq8m.js → diagram-PSM6KHXK-uinTtuhJ.js} +7 -7
  52. package/dist/static/assets/{diagram-PSM6KHXK-C1IsQq8m.js.map → diagram-PSM6KHXK-uinTtuhJ.js.map} +1 -1
  53. package/dist/static/assets/{diagram-QEK2KX5R-DyJeSg_Y.js → diagram-QEK2KX5R-ChxmtmD8.js} +6 -6
  54. package/dist/static/assets/{diagram-QEK2KX5R-DyJeSg_Y.js.map → diagram-QEK2KX5R-ChxmtmD8.js.map} +1 -1
  55. package/dist/static/assets/{diagram-S2PKOQOG-aeLjjldp.js → diagram-S2PKOQOG-2cukzOFZ.js} +6 -6
  56. package/dist/static/assets/{diagram-S2PKOQOG-aeLjjldp.js.map → diagram-S2PKOQOG-2cukzOFZ.js.map} +1 -1
  57. package/dist/static/assets/{erDiagram-Q2GNP2WA-BUcv4AUq.js → erDiagram-Q2GNP2WA-CwIFDwop.js} +5 -5
  58. package/dist/static/assets/{erDiagram-Q2GNP2WA-BUcv4AUq.js.map → erDiagram-Q2GNP2WA-CwIFDwop.js.map} +1 -1
  59. package/dist/static/assets/{flowDiagram-NV44I4VS-DfmTKlf_.js → flowDiagram-NV44I4VS-jKMMhPpA.js} +6 -6
  60. package/dist/static/assets/{flowDiagram-NV44I4VS-DfmTKlf_.js.map → flowDiagram-NV44I4VS-jKMMhPpA.js.map} +1 -1
  61. package/dist/static/assets/{ganttDiagram-JELNMOA3-BpJE8Lhp.js → ganttDiagram-JELNMOA3-0onO7ppU.js} +3 -3
  62. package/dist/static/assets/{ganttDiagram-JELNMOA3-BpJE8Lhp.js.map → ganttDiagram-JELNMOA3-0onO7ppU.js.map} +1 -1
  63. package/dist/static/assets/{gitGraphDiagram-NY62KEGX-DmznjSYb.js → gitGraphDiagram-NY62KEGX-CxBFzFla.js} +7 -7
  64. package/dist/static/assets/{gitGraphDiagram-NY62KEGX-DmznjSYb.js.map → gitGraphDiagram-NY62KEGX-CxBFzFla.js.map} +1 -1
  65. package/dist/static/assets/{graph-CcKyIZaL.js → graph-DuuInXXc.js} +3 -3
  66. package/dist/static/assets/{graph-CcKyIZaL.js.map → graph-DuuInXXc.js.map} +1 -1
  67. package/dist/static/assets/{index-CQr8MdPI.js → index-CIEJ2QXv.js} +311 -228
  68. package/dist/static/assets/index-CIEJ2QXv.js.map +1 -0
  69. package/dist/static/assets/{infoDiagram-WHAUD3N6-DwRPjndM.js → infoDiagram-WHAUD3N6-TznEGa7r.js} +5 -5
  70. package/dist/static/assets/{infoDiagram-WHAUD3N6-DwRPjndM.js.map → infoDiagram-WHAUD3N6-TznEGa7r.js.map} +1 -1
  71. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-BRAFSgVa.js → journeyDiagram-XKPGCS4Q-BHyegEi7.js} +5 -5
  72. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-BRAFSgVa.js.map → journeyDiagram-XKPGCS4Q-BHyegEi7.js.map} +1 -1
  73. package/dist/static/assets/{kanban-definition-3W4ZIXB7-DlJ7-fgN.js → kanban-definition-3W4ZIXB7-Cb42cM0l.js} +3 -3
  74. package/dist/static/assets/{kanban-definition-3W4ZIXB7-DlJ7-fgN.js.map → kanban-definition-3W4ZIXB7-Cb42cM0l.js.map} +1 -1
  75. package/dist/static/assets/{layout-CcW5-Iee.js → layout-BmWDm7l3.js} +5 -5
  76. package/dist/static/assets/{layout-CcW5-Iee.js.map → layout-BmWDm7l3.js.map} +1 -1
  77. package/dist/static/assets/{linear-sKdPIuOH.js → linear-CnzPs1-w.js} +2 -2
  78. package/dist/static/assets/{linear-sKdPIuOH.js.map → linear-CnzPs1-w.js.map} +1 -1
  79. package/dist/static/assets/{min-CQ0AYqmk.js → min-B10Xh5Ux.js} +3 -3
  80. package/dist/static/assets/{min-CQ0AYqmk.js.map → min-B10Xh5Ux.js.map} +1 -1
  81. package/dist/static/assets/{mindmap-definition-VGOIOE7T-CTRwSlu8.js → mindmap-definition-VGOIOE7T-CrN1eydc.js} +4 -4
  82. package/dist/static/assets/{mindmap-definition-VGOIOE7T-CTRwSlu8.js.map → mindmap-definition-VGOIOE7T-CrN1eydc.js.map} +1 -1
  83. package/dist/static/assets/{pieDiagram-ADFJNKIX-DmD5KRKE.js → pieDiagram-ADFJNKIX-B30qa_F6.js} +7 -7
  84. package/dist/static/assets/{pieDiagram-ADFJNKIX-DmD5KRKE.js.map → pieDiagram-ADFJNKIX-B30qa_F6.js.map} +1 -1
  85. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-C5sqZOBF.js → quadrantDiagram-AYHSOK5B-CqcwrOFK.js} +3 -3
  86. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-C5sqZOBF.js.map → quadrantDiagram-AYHSOK5B-CqcwrOFK.js.map} +1 -1
  87. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DBAUwM-7.js → requirementDiagram-UZGBJVZJ-D_pK_WHp.js} +4 -4
  88. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DBAUwM-7.js.map → requirementDiagram-UZGBJVZJ-D_pK_WHp.js.map} +1 -1
  89. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-CkaxkOo7.js → sankeyDiagram-TZEHDZUN-DCWsFfhe.js} +2 -2
  90. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-CkaxkOo7.js.map → sankeyDiagram-TZEHDZUN-DCWsFfhe.js.map} +1 -1
  91. package/dist/static/assets/{sequenceDiagram-WL72ISMW-CJ6wMDXh.js → sequenceDiagram-WL72ISMW-bYELxg0L.js} +4 -4
  92. package/dist/static/assets/{sequenceDiagram-WL72ISMW-CJ6wMDXh.js.map → sequenceDiagram-WL72ISMW-bYELxg0L.js.map} +1 -1
  93. package/dist/static/assets/{stateDiagram-FKZM4ZOC-C66ZP2NW.js → stateDiagram-FKZM4ZOC-DETJEZs6.js} +9 -9
  94. package/dist/static/assets/{stateDiagram-FKZM4ZOC-C66ZP2NW.js.map → stateDiagram-FKZM4ZOC-DETJEZs6.js.map} +1 -1
  95. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-DdoOy271.js → stateDiagram-v2-4FDKWEC3-DEfNRBx4.js} +5 -5
  96. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-DdoOy271.js.map → stateDiagram-v2-4FDKWEC3-DEfNRBx4.js.map} +1 -1
  97. package/dist/static/assets/{timeline-definition-IT6M3QCI-2A2Mqedz.js → timeline-definition-IT6M3QCI-BRvufh0i.js} +3 -3
  98. package/dist/static/assets/{timeline-definition-IT6M3QCI-2A2Mqedz.js.map → timeline-definition-IT6M3QCI-BRvufh0i.js.map} +1 -1
  99. package/dist/static/assets/{treemap-KMMF4GRG-CTbGSr5o.js → treemap-KMMF4GRG-D4s4uF2T.js} +4 -4
  100. package/dist/static/assets/{treemap-KMMF4GRG-CTbGSr5o.js.map → treemap-KMMF4GRG-D4s4uF2T.js.map} +1 -1
  101. package/dist/static/assets/{xychartDiagram-PRI3JC2R-C_S3XXZI.js → xychartDiagram-PRI3JC2R-eBEH5utX.js} +3 -3
  102. package/dist/static/assets/{xychartDiagram-PRI3JC2R-C_S3XXZI.js.map → xychartDiagram-PRI3JC2R-eBEH5utX.js.map} +1 -1
  103. package/dist/static/index.html +1 -1
  104. package/package.json +1 -1
  105. package/dist/static/assets/index-CQr8MdPI.js.map +0 -1
@@ -2,9 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.globalDialogRegistry = void 0;
4
4
  const persistence_1 = require("./persistence");
5
+ const evt_1 = require("./shared/evt");
5
6
  class GlobalDialogRegistry {
6
7
  constructor() {
7
8
  this.entries = new Map();
9
+ this.driveTriggerPubChan = (0, evt_1.createPubChan)();
10
+ this.driveTriggerSubChan = (0, evt_1.createSubChan)(this.driveTriggerPubChan);
8
11
  }
9
12
  static getInstance() {
10
13
  if (!GlobalDialogRegistry.instance) {
@@ -30,7 +33,10 @@ class GlobalDialogRegistry {
30
33
  try {
31
34
  const needsDrive = await persistence_1.DialogPersistence.getNeedsDrive(rootDialog.id);
32
35
  if (needsDrive) {
33
- this.markNeedsDrive(rootDialog.id.rootId);
36
+ this.markNeedsDrive(rootDialog.id.rootId, {
37
+ source: 'dialog_registry_hydration',
38
+ reason: 'persisted_needs_drive_true',
39
+ });
34
40
  }
35
41
  }
36
42
  catch {
@@ -41,17 +47,66 @@ class GlobalDialogRegistry {
41
47
  unregister(rootId) {
42
48
  this.entries.delete(rootId);
43
49
  }
44
- markNeedsDrive(rootId) {
50
+ publishDriveTrigger(args) {
51
+ this.driveTriggerPubChan.write({
52
+ type: 'drive_trigger_evt',
53
+ action: args.action,
54
+ rootId: args.rootId,
55
+ entryFound: args.entryFound,
56
+ previousNeedsDrive: args.previousNeedsDrive,
57
+ nextNeedsDrive: args.nextNeedsDrive,
58
+ source: args.meta.source,
59
+ reason: args.meta.reason,
60
+ emittedAtMs: Date.now(),
61
+ });
62
+ }
63
+ async waitForDriveTrigger() {
64
+ for (;;) {
65
+ const trigger = await this.driveTriggerSubChan.read();
66
+ if (trigger !== evt_1.EndOfStream) {
67
+ return trigger;
68
+ }
69
+ // Recreate subscription if EOS is ever observed (should not happen in normal runtime).
70
+ this.driveTriggerSubChan = (0, evt_1.createSubChan)(this.driveTriggerPubChan);
71
+ }
72
+ }
73
+ markNeedsDrive(rootId, meta) {
74
+ const triggerMeta = meta ?? {
75
+ source: 'unknown',
76
+ reason: 'unspecified',
77
+ };
45
78
  const entry = this.entries.get(rootId);
79
+ const previousNeedsDrive = entry ? entry.needsDrive : null;
46
80
  if (entry) {
47
81
  entry.needsDrive = true;
48
82
  }
83
+ this.publishDriveTrigger({
84
+ action: 'mark_needs_drive',
85
+ rootId,
86
+ entryFound: entry !== undefined,
87
+ previousNeedsDrive,
88
+ nextNeedsDrive: true,
89
+ meta: triggerMeta,
90
+ });
49
91
  }
50
- markNotNeedingDrive(rootId) {
92
+ markNotNeedingDrive(rootId, meta) {
93
+ const triggerMeta = meta ?? {
94
+ source: 'unknown',
95
+ reason: 'unspecified',
96
+ };
51
97
  const entry = this.entries.get(rootId);
98
+ const previousNeedsDrive = entry ? entry.needsDrive : null;
52
99
  if (entry) {
53
100
  entry.needsDrive = false;
54
101
  }
102
+ this.publishDriveTrigger({
103
+ action: 'mark_not_needing_drive',
104
+ rootId,
105
+ entryFound: entry !== undefined,
106
+ previousNeedsDrive,
107
+ nextNeedsDrive: false,
108
+ meta: triggerMeta,
109
+ });
55
110
  }
56
111
  getDialogsNeedingDrive() {
57
112
  return Array.from(this.entries.values())
package/dist/dialog.js CHANGED
@@ -502,9 +502,26 @@ class Dialog {
502
502
  this._upNext = {
503
503
  prompt: trimmed,
504
504
  msgId: (0, id_1.generateShortId)(),
505
+ grammar: 'markdown',
505
506
  userLanguageCode: this._lastUserLanguageCode,
506
507
  };
507
508
  }
509
+ queueUpNextPrompt(options) {
510
+ if (this._upNext !== undefined) {
511
+ throw new Error(`UpNext prompt overwrite violation: dialog=${this.id.valueOf()} existingMsgId=${this._upNext.msgId} incomingMsgId=${options.msgId}`);
512
+ }
513
+ const trimmed = options.prompt.trim();
514
+ if (!trimmed) {
515
+ throw new Error('Prompt is required to queue upNext');
516
+ }
517
+ this._upNext = {
518
+ prompt: trimmed,
519
+ msgId: options.msgId,
520
+ grammar: options.grammar,
521
+ userLanguageCode: options.userLanguageCode ?? this._lastUserLanguageCode,
522
+ };
523
+ this._updatedAt = (0, time_1.formatUnifiedTimestamp)(new Date());
524
+ }
508
525
  hasUpNext() {
509
526
  return this._upNext !== undefined;
510
527
  }
@@ -7,6 +7,7 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.dialogEventRegistry = void 0;
10
+ exports.setGlobalDialogEventBroadcaster = setGlobalDialogEventBroadcaster;
10
11
  exports.setQ4HBroadcaster = setQ4HBroadcaster;
11
12
  exports.postDialogEvent = postDialogEvent;
12
13
  exports.postDialogEventById = postDialogEventById;
@@ -18,20 +19,48 @@ class DialogEventRegistryImpl {
18
19
  constructor() {
19
20
  this.pubChans = new Map();
20
21
  this.log = (0, log_1.createLogger)('evt-registry');
21
- // Q4H (Questions for Human) is globally visible in the WebUI.
22
- // These events must reach ALL connected clients, not only those subscribed to a specific dialog stream.
23
- this.q4hBroadcaster = null;
22
+ // Some dialog events are global UI state updates. They must reach ALL connected clients,
23
+ // not only those subscribed to a specific dialog stream.
24
+ this.globalDialogEventBroadcaster = null;
24
25
  }
25
- setQ4HBroadcaster(fn) {
26
- this.q4hBroadcaster = fn;
26
+ setGlobalDialogEventBroadcaster(fn) {
27
+ this.globalDialogEventBroadcaster = fn;
27
28
  }
28
- broadcastIfQ4H(evt) {
29
- // Only broadcast Q4H events; all other dialog events remain dialog-scoped streams.
30
- if (evt.type !== 'new_q4h_asked' && evt.type !== 'q4h_answered')
29
+ broadcastGlobalEvent(evt) {
30
+ const fn = this.globalDialogEventBroadcaster;
31
+ if (!fn)
31
32
  return;
32
- const fn = this.q4hBroadcaster;
33
- if (fn)
34
- fn(evt);
33
+ fn(evt);
34
+ }
35
+ emitDialogTouched(source) {
36
+ if (source.type === 'dlg_touched_evt')
37
+ return;
38
+ const touchedEvt = {
39
+ dialog: source.dialog,
40
+ timestamp: source.timestamp,
41
+ type: 'dlg_touched_evt',
42
+ sourceType: source.type,
43
+ };
44
+ this.broadcastGlobalEvent(touchedEvt);
45
+ }
46
+ dispatchGloballyIfNeeded(evt) {
47
+ // Global-only delivery prevents duplicate deliveries from two independent paths
48
+ // (global broadcaster + dialog-scoped stream).
49
+ switch (evt.type) {
50
+ case 'new_q4h_asked':
51
+ case 'q4h_answered':
52
+ case 'subdialog_created_evt':
53
+ case 'dlg_touched_evt':
54
+ break;
55
+ default:
56
+ return false;
57
+ }
58
+ const fn = this.globalDialogEventBroadcaster;
59
+ if (!fn) {
60
+ throw new Error(`Global dialog event broadcaster missing: cannot publish ${evt.type} for dialog=${evt.dialog.selfId}`);
61
+ }
62
+ fn(evt);
63
+ return true;
35
64
  }
36
65
  /**
37
66
  * Get or create a PubChan for a specific dialog ID
@@ -75,13 +104,19 @@ class DialogEventRegistryImpl {
75
104
  */
76
105
  postEvent(dlg, event) {
77
106
  const typedEvent = this.createTypedEvent(dlg.id, event);
78
- this.broadcastIfQ4H(typedEvent);
107
+ this.emitDialogTouched(typedEvent);
108
+ if (this.dispatchGloballyIfNeeded(typedEvent)) {
109
+ return;
110
+ }
79
111
  const chan = this.getPubChan(dlg.id);
80
112
  chan.write(typedEvent);
81
113
  }
82
114
  postEventById(dialogId, event) {
83
115
  const typedEvent = this.createTypedEvent(dialogId, event);
84
- this.broadcastIfQ4H(typedEvent);
116
+ this.emitDialogTouched(typedEvent);
117
+ if (this.dispatchGloballyIfNeeded(typedEvent)) {
118
+ return;
119
+ }
85
120
  const chan = this.getPubChan(dialogId);
86
121
  chan.write(typedEvent);
87
122
  }
@@ -106,8 +141,12 @@ class DialogEventRegistryImpl {
106
141
  }
107
142
  // Export singleton instance
108
143
  exports.dialogEventRegistry = new DialogEventRegistryImpl();
144
+ function setGlobalDialogEventBroadcaster(fn) {
145
+ exports.dialogEventRegistry.setGlobalDialogEventBroadcaster(fn);
146
+ }
147
+ // Backward-compatible alias used by existing tests/callers.
109
148
  function setQ4HBroadcaster(fn) {
110
- exports.dialogEventRegistry.setQ4HBroadcaster(fn);
149
+ setGlobalDialogEventBroadcaster(fn);
111
150
  }
112
151
  // Export helper function to import in other modules
113
152
  function postDialogEvent(dlg, event) {
@@ -39,7 +39,8 @@ function buildDriveBaseContextMessages(parts) {
39
39
  }
40
40
  function appendDriveEphemeralContext(base, parts) {
41
41
  const next = [...base];
42
- if (parts.subdialogResponseContextMsgs.length > 0) {
42
+ if (Array.isArray(parts.subdialogResponseContextMsgs) &&
43
+ parts.subdialogResponseContextMsgs.length > 0) {
43
44
  next.push(...parts.subdialogResponseContextMsgs);
44
45
  }
45
46
  if (parts.internalDrivePromptMsg) {
@@ -10,7 +10,6 @@ const persistence_1 = require("../../persistence");
10
10
  const diligence_1 = require("../../shared/diligence");
11
11
  const driver_messages_1 = require("../../shared/i18n/driver-messages");
12
12
  const runtime_language_1 = require("../../shared/runtime-language");
13
- const inter_dialog_format_1 = require("../../shared/utils/inter-dialog-format");
14
13
  const tellask_1 = require("../../tellask");
15
14
  const taskdoc_1 = require("../../utils/taskdoc");
16
15
  const client_1 = require("../client");
@@ -20,7 +19,6 @@ const context_1 = require("./context");
20
19
  const policy_1 = require("./policy");
21
20
  const runtime_utils_1 = require("./runtime-utils");
22
21
  const saying_events_1 = require("./saying-events");
23
- const subdialog_txn_1 = require("./subdialog-txn");
24
22
  const tellask_bridge_1 = require("./tellask-bridge");
25
23
  class DialogInterruptedError extends Error {
26
24
  constructor(reason) {
@@ -56,7 +54,7 @@ function resolveUpNextPrompt(dlg) {
56
54
  return {
57
55
  content: upNext.prompt,
58
56
  msgId: upNext.msgId,
59
- grammar: 'markdown',
57
+ grammar: upNext.grammar ?? 'markdown',
60
58
  userLanguageCode: upNext.userLanguageCode,
61
59
  };
62
60
  }
@@ -210,21 +208,6 @@ async function buildProviderContext(args) {
210
208
  }
211
209
  return { provider, model, providerCfg };
212
210
  }
213
- async function hasQueuedSubdialogResponses(dialog) {
214
- try {
215
- const queued = await (0, subdialog_txn_1.withSubdialogTxnLock)(dialog.id, async () => {
216
- return await persistence_1.DialogPersistence.loadSubdialogResponsesQueue(dialog.id);
217
- });
218
- return queued.length > 0;
219
- }
220
- catch (err) {
221
- log_1.log.warn('driver-v2 failed to check queued subdialog responses; suppressing diligence as safe default', {
222
- dialogId: dialog.id.valueOf(),
223
- error: err,
224
- });
225
- return true;
226
- }
227
- }
228
211
  async function executeFunctionCalls(args) {
229
212
  const { dialog, agent, agentTools, funcCalls, abortSignal } = args;
230
213
  const functionPromises = funcCalls.map(async (func) => {
@@ -357,13 +340,6 @@ async function maybeContinueWithDiligencePrompt(args) {
357
340
  }
358
341
  return { kind: 'break' };
359
342
  }
360
- const queuedResponses = await hasQueuedSubdialogResponses(dlg);
361
- if (queuedResponses) {
362
- log_1.log.info('driver-v2 skip diligence prompt while subdialog responses remain queued', {
363
- dialogId: dlg.id.valueOf(),
364
- });
365
- return { kind: 'break' };
366
- }
367
343
  const prepared = await (0, runtime_utils_1.maybePrepareDiligenceAutoContinuePrompt)({
368
344
  dlg,
369
345
  isRootDialog: true,
@@ -415,12 +391,7 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
415
391
  await (0, dialog_run_state_1.setDialogRunState)(dlg.id, { kind: 'proceeding' });
416
392
  let pubRemindersVer = dlg.remindersVer;
417
393
  let lastAssistantSayingContent = null;
418
- let generationHadError = false;
419
- let tookSubdialogResponses = false;
420
- let takenSubdialogResponses = [];
421
- let subdialogResponseContextMsgs = [];
422
394
  let internalDrivePromptMsg;
423
- let committedTakenSubdialogResponses = false;
424
395
  let genIterNo = 0;
425
396
  let pendingPrompt = humanPrompt;
426
397
  let skipTaskdocForThisDrive = humanPrompt?.skipTaskdoc === true;
@@ -548,20 +519,6 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
548
519
  await resetDiligenceBudgetAfterQ4H(dlg, team);
549
520
  break;
550
521
  }
551
- if (genIterNo === 1 && !tookSubdialogResponses) {
552
- tookSubdialogResponses = true;
553
- try {
554
- takenSubdialogResponses = await (0, subdialog_txn_1.takeSubdialogResponses)(dlg.id);
555
- }
556
- catch (err) {
557
- log_1.log.warn('driver-v2 failed to take subdialog responses for injection', {
558
- dialogId: dlg.id.selfId,
559
- error: err,
560
- });
561
- generationHadError = true;
562
- takenSubdialogResponses = [];
563
- }
564
- }
565
522
  const taskDocMsg = dlg.taskDocPath && !skipTaskdocForThisDrive ? await (0, taskdoc_1.formatTaskDocContent)(dlg) : undefined;
566
523
  const coursePrefixMsgs = (() => {
567
524
  const msgs = dlg.getCoursePrefixMsgs();
@@ -574,19 +531,6 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
574
531
  return false;
575
532
  return true;
576
533
  });
577
- if (genIterNo === 1 && takenSubdialogResponses.length > 0) {
578
- subdialogResponseContextMsgs = takenSubdialogResponses.map((response) => ({
579
- type: 'environment_msg',
580
- role: 'user',
581
- content: (0, inter_dialog_format_1.formatTeammateResponseContent)({
582
- responderId: response.responderId,
583
- requesterId: response.originMemberId,
584
- originalCallHeadLine: response.tellaskHead,
585
- responseBody: response.response,
586
- language: (0, runtime_language_1.getWorkLanguage)(),
587
- }),
588
- }));
589
- }
590
534
  await dlg.processReminderUpdates();
591
535
  const renderedReminders = dlg.reminders.length > 0
592
536
  ? await Promise.all(dlg.reminders.map(async (reminder, index) => {
@@ -618,7 +562,6 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
618
562
  dialogMsgsForContext,
619
563
  },
620
564
  ephemeral: {
621
- subdialogResponseContextMsgs,
622
565
  internalDrivePromptMsg,
623
566
  },
624
567
  tail: {
@@ -1005,12 +948,10 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
1005
948
  : { kind: 'system_stop', detail: 'Aborted.' }
1006
949
  : undefined;
1007
950
  if (interruptedReason) {
1008
- generationHadError = true;
1009
951
  finalRunState = { kind: 'interrupted', reason: interruptedReason };
1010
952
  (0, dialog_run_state_1.broadcastRunStateMarker)(dlg.id, { kind: 'interrupted', reason: interruptedReason });
1011
953
  return { lastAssistantSayingContent, interrupted: true };
1012
954
  }
1013
- generationHadError = true;
1014
955
  const errText = (0, log_1.extractErrorDetails)(err).message;
1015
956
  try {
1016
957
  await dlg.streamError(errText);
@@ -1053,63 +994,5 @@ async function driveDialogStreamCoreV2(dlg, humanPrompt, driveOptions, callbacks
1053
994
  });
1054
995
  }
1055
996
  await (0, dialog_run_state_1.setDialogRunState)(dlg.id, finalRunState);
1056
- if (tookSubdialogResponses) {
1057
- try {
1058
- if (generationHadError) {
1059
- await (0, subdialog_txn_1.rollbackTakenSubdialogResponses)(dlg.id);
1060
- }
1061
- else {
1062
- await (0, subdialog_txn_1.commitTakenSubdialogResponses)(dlg.id);
1063
- committedTakenSubdialogResponses = true;
1064
- }
1065
- }
1066
- catch (err2) {
1067
- log_1.log.warn('driver-v2 failed to finalize subdialog response queue after drive', {
1068
- dialogId: dlg.id.selfId,
1069
- error: err2,
1070
- });
1071
- }
1072
- }
1073
- if (committedTakenSubdialogResponses && takenSubdialogResponses.length > 0) {
1074
- try {
1075
- const mirroredMsgs = [];
1076
- for (const response of takenSubdialogResponses) {
1077
- const content = (0, inter_dialog_format_1.formatTeammateResponseContent)({
1078
- responderId: response.responderId,
1079
- requesterId: response.originMemberId,
1080
- originalCallHeadLine: response.tellaskHead,
1081
- responseBody: response.response,
1082
- language: (0, runtime_language_1.getWorkLanguage)(),
1083
- });
1084
- const status = response.status ?? 'completed';
1085
- const alreadyMirrored = dlg.msgs.some((msg) => msg.type === 'tellask_result_msg' &&
1086
- msg.role === 'tool' &&
1087
- msg.responderId === response.responderId &&
1088
- msg.tellaskHead === response.tellaskHead &&
1089
- msg.status === status &&
1090
- msg.content === content);
1091
- if (alreadyMirrored) {
1092
- continue;
1093
- }
1094
- mirroredMsgs.push({
1095
- type: 'tellask_result_msg',
1096
- role: 'tool',
1097
- responderId: response.responderId,
1098
- tellaskHead: response.tellaskHead,
1099
- status,
1100
- content,
1101
- });
1102
- }
1103
- if (mirroredMsgs.length > 0) {
1104
- await dlg.addChatMessages(...mirroredMsgs);
1105
- }
1106
- }
1107
- catch (err) {
1108
- log_1.log.warn('driver-v2 failed to mirror committed subdialog responses into dialog msgs', {
1109
- dialogId: dlg.id.selfId,
1110
- error: err,
1111
- });
1112
- }
1113
- }
1114
997
  }
1115
998
  }
@@ -42,48 +42,75 @@ async function supplyResponseToSupdialog(...args) {
42
42
  },
43
43
  });
44
44
  }
45
+ function formatDriveTriggerForLog(trigger) {
46
+ return {
47
+ action: trigger.action,
48
+ rootId: trigger.rootId,
49
+ entryFound: trigger.entryFound,
50
+ previousNeedsDrive: trigger.previousNeedsDrive,
51
+ nextNeedsDrive: trigger.nextNeedsDrive,
52
+ source: trigger.source,
53
+ reason: trigger.reason,
54
+ emittedAtMs: trigger.emittedAtMs,
55
+ };
56
+ }
57
+ async function driveQueuedDialogsOnce() {
58
+ const dialogsToDrive = dialog_global_registry_1.globalDialogRegistry.getDialogsNeedingDrive();
59
+ for (const rootDialog of dialogsToDrive) {
60
+ try {
61
+ const latest = await persistence_1.DialogPersistence.loadDialogLatest(rootDialog.id, 'running');
62
+ const runStateKind = latest?.runState?.kind;
63
+ if (runStateKind === 'interrupted' || runStateKind === 'proceeding_stop_requested') {
64
+ dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId, {
65
+ source: 'driver_v2_backend_loop',
66
+ reason: `run_state_blocked:${runStateKind}`,
67
+ });
68
+ await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
69
+ continue;
70
+ }
71
+ if (!(await rootDialog.canDrive())) {
72
+ continue;
73
+ }
74
+ await driveDialogStream(rootDialog, undefined, true);
75
+ const status = await rootDialog.getSuspensionStatus();
76
+ const shouldStayQueued = rootDialog.hasUpNext() || !status.canDrive;
77
+ if (shouldStayQueued) {
78
+ dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(rootDialog.id.rootId, {
79
+ source: 'driver_v2_backend_loop',
80
+ reason: rootDialog.hasUpNext() ? 'post_drive_upnext_pending' : 'post_drive_suspended',
81
+ });
82
+ await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, true, rootDialog.status);
83
+ }
84
+ else {
85
+ dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId, {
86
+ source: 'driver_v2_backend_loop',
87
+ reason: 'post_drive_idle',
88
+ });
89
+ await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
90
+ }
91
+ if (status.subdialogs) {
92
+ log_1.log.info(`Dialog ${rootDialog.id.rootId} suspended, waiting for subdialogs`);
93
+ }
94
+ if (status.q4h) {
95
+ log_1.log.info(`Dialog ${rootDialog.id.rootId} awaiting Q4H answer`);
96
+ }
97
+ }
98
+ catch (err) {
99
+ log_1.log.error(`Error driving dialog ${rootDialog.id.rootId}:`, err, undefined, {
100
+ dialogId: rootDialog.id.rootId,
101
+ });
102
+ }
103
+ }
104
+ }
45
105
  function runBackendDriver() {
46
106
  return (async () => {
47
107
  while (true) {
48
108
  try {
49
- const dialogsToDrive = dialog_global_registry_1.globalDialogRegistry.getDialogsNeedingDrive();
50
- for (const rootDialog of dialogsToDrive) {
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
- }
59
- if (!(await rootDialog.canDrive())) {
60
- continue;
61
- }
62
- await driveDialogStream(rootDialog, undefined, true);
63
- const status = await rootDialog.getSuspensionStatus();
64
- const shouldStayQueued = rootDialog.hasUpNext() || !status.canDrive;
65
- if (shouldStayQueued) {
66
- dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(rootDialog.id.rootId);
67
- await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, true, rootDialog.status);
68
- }
69
- else {
70
- dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId);
71
- await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
72
- }
73
- if (status.subdialogs) {
74
- log_1.log.info(`Dialog ${rootDialog.id.rootId} suspended, waiting for subdialogs`);
75
- }
76
- if (status.q4h) {
77
- log_1.log.info(`Dialog ${rootDialog.id.rootId} awaiting Q4H answer`);
78
- }
79
- }
80
- catch (err) {
81
- log_1.log.error(`Error driving dialog ${rootDialog.id.rootId}:`, err, undefined, {
82
- dialogId: rootDialog.id.rootId,
83
- });
84
- }
85
- }
86
- await new Promise((resolve) => setTimeout(resolve, 100));
109
+ await driveQueuedDialogsOnce();
110
+ const trigger = await dialog_global_registry_1.globalDialogRegistry.waitForDriveTrigger();
111
+ log_1.log.debug('Backend driver woke from drive trigger event', undefined, {
112
+ trigger: formatDriveTriggerForLog(trigger),
113
+ });
87
114
  }
88
115
  catch (loopErr) {
89
116
  log_1.log.error('Error in backend driver loop:', loopErr);