dominds 1.9.1 → 1.9.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.
Files changed (105) hide show
  1. package/dist/llm/kernel-driver/subdialog.d.ts +2 -0
  2. package/dist/llm/kernel-driver/subdialog.js +9 -4
  3. package/dist/llm/kernel-driver/tellask-special.js +1 -0
  4. package/dist/persistence.js +31 -16
  5. package/dist/priming.js +32 -12
  6. package/dist/server/api-routes.js +212 -89
  7. package/dist/server/auth.d.ts +1 -0
  8. package/dist/server/auth.js +21 -0
  9. package/dist/server/server-core.js +15 -0
  10. package/package.json +1 -1
  11. package/webapp/dist/assets/{_basePickBy-BCSeQ8Mb.js → _basePickBy-9Z1lbVTN.js} +3 -3
  12. package/webapp/dist/assets/{_basePickBy-BCSeQ8Mb.js.map → _basePickBy-9Z1lbVTN.js.map} +1 -1
  13. package/webapp/dist/assets/{_baseUniq-B5WIJgde.js → _baseUniq-C3pRnD57.js} +2 -2
  14. package/webapp/dist/assets/{_baseUniq-B5WIJgde.js.map → _baseUniq-C3pRnD57.js.map} +1 -1
  15. package/webapp/dist/assets/{arc-CWDgoT74.js → arc-BvNng3O_.js} +2 -2
  16. package/webapp/dist/assets/{arc-CWDgoT74.js.map → arc-BvNng3O_.js.map} +1 -1
  17. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-DFdZI4Uu.js → architectureDiagram-2XIMDMQ5-BF8vwQ4e.js} +7 -7
  18. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-DFdZI4Uu.js.map → architectureDiagram-2XIMDMQ5-BF8vwQ4e.js.map} +1 -1
  19. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-DRcKQf9Q.js → blockDiagram-WCTKOSBZ-C7kfjZhf.js} +7 -7
  20. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-DRcKQf9Q.js.map → blockDiagram-WCTKOSBZ-C7kfjZhf.js.map} +1 -1
  21. package/webapp/dist/assets/{c4Diagram-IC4MRINW-B0AMlCwV.js → c4Diagram-IC4MRINW-CaJ6bX75.js} +3 -3
  22. package/webapp/dist/assets/{c4Diagram-IC4MRINW-B0AMlCwV.js.map → c4Diagram-IC4MRINW-CaJ6bX75.js.map} +1 -1
  23. package/webapp/dist/assets/{channel-B0ljx2su.js → channel-DDuIUO0R.js} +2 -2
  24. package/webapp/dist/assets/{channel-B0ljx2su.js.map → channel-DDuIUO0R.js.map} +1 -1
  25. package/webapp/dist/assets/{chunk-4BX2VUAB-DbKTqY07.js → chunk-4BX2VUAB-BQPkQh6v.js} +2 -2
  26. package/webapp/dist/assets/{chunk-4BX2VUAB-DbKTqY07.js.map → chunk-4BX2VUAB-BQPkQh6v.js.map} +1 -1
  27. package/webapp/dist/assets/{chunk-55IACEB6-DwJgszOl.js → chunk-55IACEB6-C2eZTkZ1.js} +2 -2
  28. package/webapp/dist/assets/{chunk-55IACEB6-DwJgszOl.js.map → chunk-55IACEB6-C2eZTkZ1.js.map} +1 -1
  29. package/webapp/dist/assets/{chunk-FMBD7UC4-BzUcOjMH.js → chunk-FMBD7UC4-aXp5zApD.js} +2 -2
  30. package/webapp/dist/assets/{chunk-FMBD7UC4-BzUcOjMH.js.map → chunk-FMBD7UC4-aXp5zApD.js.map} +1 -1
  31. package/webapp/dist/assets/{chunk-JSJVCQXG-B-adw7iw.js → chunk-JSJVCQXG-DXyaccrz.js} +2 -2
  32. package/webapp/dist/assets/{chunk-JSJVCQXG-B-adw7iw.js.map → chunk-JSJVCQXG-DXyaccrz.js.map} +1 -1
  33. package/webapp/dist/assets/{chunk-KX2RTZJC-a1S8VCMi.js → chunk-KX2RTZJC-C-u000c0.js} +2 -2
  34. package/webapp/dist/assets/{chunk-KX2RTZJC-a1S8VCMi.js.map → chunk-KX2RTZJC-C-u000c0.js.map} +1 -1
  35. package/webapp/dist/assets/{chunk-NQ4KR5QH-BkpgGRb2.js → chunk-NQ4KR5QH-BoYRoo4A.js} +4 -4
  36. package/webapp/dist/assets/{chunk-NQ4KR5QH-BkpgGRb2.js.map → chunk-NQ4KR5QH-BoYRoo4A.js.map} +1 -1
  37. package/webapp/dist/assets/{chunk-QZHKN3VN-BzG0M8E7.js → chunk-QZHKN3VN-BAc_2ceG.js} +2 -2
  38. package/webapp/dist/assets/{chunk-QZHKN3VN-BzG0M8E7.js.map → chunk-QZHKN3VN-BAc_2ceG.js.map} +1 -1
  39. package/webapp/dist/assets/{chunk-WL4C6EOR-Jdr3sqWq.js → chunk-WL4C6EOR-D6ws69Jx.js} +6 -6
  40. package/webapp/dist/assets/{chunk-WL4C6EOR-Jdr3sqWq.js.map → chunk-WL4C6EOR-D6ws69Jx.js.map} +1 -1
  41. package/webapp/dist/assets/{classDiagram-VBA2DB6C-Bgs-IGF1.js → classDiagram-VBA2DB6C-BIRrKhqs.js} +7 -7
  42. package/webapp/dist/assets/{classDiagram-VBA2DB6C-Bgs-IGF1.js.map → classDiagram-VBA2DB6C-BIRrKhqs.js.map} +1 -1
  43. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-Bgs-IGF1.js → classDiagram-v2-RAHNMMFH-BIRrKhqs.js} +7 -7
  44. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-Bgs-IGF1.js.map → classDiagram-v2-RAHNMMFH-BIRrKhqs.js.map} +1 -1
  45. package/webapp/dist/assets/{clone-8W6qtrsz.js → clone-DweFyVW6.js} +2 -2
  46. package/webapp/dist/assets/{clone-8W6qtrsz.js.map → clone-DweFyVW6.js.map} +1 -1
  47. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-gwXVRMa3.js → cose-bilkent-S5V4N54A-vgovmGKM.js} +2 -2
  48. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-gwXVRMa3.js.map → cose-bilkent-S5V4N54A-vgovmGKM.js.map} +1 -1
  49. package/webapp/dist/assets/{dagre-KLK3FWXG-CgLK6cUW.js → dagre-KLK3FWXG-B-Ax3qBf.js} +7 -7
  50. package/webapp/dist/assets/{dagre-KLK3FWXG-CgLK6cUW.js.map → dagre-KLK3FWXG-B-Ax3qBf.js.map} +1 -1
  51. package/webapp/dist/assets/{diagram-E7M64L7V-BUDea9FM.js → diagram-E7M64L7V-B1sUlvtn.js} +8 -8
  52. package/webapp/dist/assets/{diagram-E7M64L7V-BUDea9FM.js.map → diagram-E7M64L7V-B1sUlvtn.js.map} +1 -1
  53. package/webapp/dist/assets/{diagram-IFDJBPK2-CiVS6fbK.js → diagram-IFDJBPK2-3IlyK_xp.js} +7 -7
  54. package/webapp/dist/assets/{diagram-IFDJBPK2-CiVS6fbK.js.map → diagram-IFDJBPK2-3IlyK_xp.js.map} +1 -1
  55. package/webapp/dist/assets/{diagram-P4PSJMXO-DpYGO4Wi.js → diagram-P4PSJMXO-C3x0JkgF.js} +7 -7
  56. package/webapp/dist/assets/{diagram-P4PSJMXO-DpYGO4Wi.js.map → diagram-P4PSJMXO-C3x0JkgF.js.map} +1 -1
  57. package/webapp/dist/assets/{erDiagram-INFDFZHY-Cz1TI05E.js → erDiagram-INFDFZHY-mEp6kC6i.js} +5 -5
  58. package/webapp/dist/assets/{erDiagram-INFDFZHY-Cz1TI05E.js.map → erDiagram-INFDFZHY-mEp6kC6i.js.map} +1 -1
  59. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CxjVowsG.js → flowDiagram-PKNHOUZH-AsG_wdLN.js} +7 -7
  60. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CxjVowsG.js.map → flowDiagram-PKNHOUZH-AsG_wdLN.js.map} +1 -1
  61. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-C3t2AHs5.js → ganttDiagram-A5KZAMGK-zv3UhEAO.js} +3 -3
  62. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-C3t2AHs5.js.map → ganttDiagram-A5KZAMGK-zv3UhEAO.js.map} +1 -1
  63. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-D3Fz3qNA.js → gitGraphDiagram-K3NZZRJ6-C1yyISy7.js} +8 -8
  64. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-D3Fz3qNA.js.map → gitGraphDiagram-K3NZZRJ6-C1yyISy7.js.map} +1 -1
  65. package/webapp/dist/assets/{graph-DEeBvsT_.js → graph-CkQycYq_.js} +3 -3
  66. package/webapp/dist/assets/{graph-DEeBvsT_.js.map → graph-CkQycYq_.js.map} +1 -1
  67. package/webapp/dist/assets/{index-D-SgXZTb.js → index-CCGi5dDE.js} +969 -260
  68. package/webapp/dist/assets/{index-D-SgXZTb.js.map → index-CCGi5dDE.js.map} +1 -1
  69. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-CcsQeBG4.js → infoDiagram-LFFYTUFH-Dw1wAgpl.js} +6 -6
  70. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-CcsQeBG4.js.map → infoDiagram-LFFYTUFH-Dw1wAgpl.js.map} +1 -1
  71. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-CAV8iv45.js → ishikawaDiagram-PHBUUO56-DY9fHLYz.js} +2 -2
  72. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-CAV8iv45.js.map → ishikawaDiagram-PHBUUO56-DY9fHLYz.js.map} +1 -1
  73. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-C_mKL3Wf.js → journeyDiagram-4ABVD52K-CSGjRykr.js} +5 -5
  74. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-C_mKL3Wf.js.map → journeyDiagram-4ABVD52K-CSGjRykr.js.map} +1 -1
  75. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Ptg6jh3y.js → kanban-definition-K7BYSVSG-DDCQetMc.js} +3 -3
  76. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Ptg6jh3y.js.map → kanban-definition-K7BYSVSG-DDCQetMc.js.map} +1 -1
  77. package/webapp/dist/assets/{layout-vY-lESK1.js → layout-DpuTr6cl.js} +5 -5
  78. package/webapp/dist/assets/{layout-vY-lESK1.js.map → layout-DpuTr6cl.js.map} +1 -1
  79. package/webapp/dist/assets/{linear-Cw12N-49.js → linear-BQv5LuhW.js} +2 -2
  80. package/webapp/dist/assets/{linear-Cw12N-49.js.map → linear-BQv5LuhW.js.map} +1 -1
  81. package/webapp/dist/assets/{mindmap-definition-YRQLILUH--gGSoZfe.js → mindmap-definition-YRQLILUH-C5ajM9Hr.js} +4 -4
  82. package/webapp/dist/assets/{mindmap-definition-YRQLILUH--gGSoZfe.js.map → mindmap-definition-YRQLILUH-C5ajM9Hr.js.map} +1 -1
  83. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-DBQkeFNk.js → pieDiagram-SKSYHLDU-Daqms3DT.js} +8 -8
  84. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-DBQkeFNk.js.map → pieDiagram-SKSYHLDU-Daqms3DT.js.map} +1 -1
  85. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-BRqQEQ5R.js → quadrantDiagram-337W2JSQ-BMNWp18J.js} +3 -3
  86. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-BRqQEQ5R.js.map → quadrantDiagram-337W2JSQ-BMNWp18J.js.map} +1 -1
  87. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-Bg-ZQVHw.js → requirementDiagram-Z7DCOOCP-C1Mc4MX-.js} +4 -4
  88. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-Bg-ZQVHw.js.map → requirementDiagram-Z7DCOOCP-C1Mc4MX-.js.map} +1 -1
  89. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-ADkSZ215.js → sankeyDiagram-WA2Y5GQK-DTHGhOsp.js} +2 -2
  90. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-ADkSZ215.js.map → sankeyDiagram-WA2Y5GQK-DTHGhOsp.js.map} +1 -1
  91. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-D4N6ze3Y.js → sequenceDiagram-2WXFIKYE-C6cA5ncc.js} +4 -4
  92. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-D4N6ze3Y.js.map → sequenceDiagram-2WXFIKYE-C6cA5ncc.js.map} +1 -1
  93. package/webapp/dist/assets/{stateDiagram-RAJIS63D-vNdpo2RN.js → stateDiagram-RAJIS63D-DRDqVPKY.js} +9 -9
  94. package/webapp/dist/assets/{stateDiagram-RAJIS63D-vNdpo2RN.js.map → stateDiagram-RAJIS63D-DRDqVPKY.js.map} +1 -1
  95. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-DklmFziq.js → stateDiagram-v2-FVOUBMTO-B-pby7Ke.js} +5 -5
  96. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-DklmFziq.js.map → stateDiagram-v2-FVOUBMTO-B-pby7Ke.js.map} +1 -1
  97. package/webapp/dist/assets/{timeline-definition-YZTLITO2-BrGjv8Mt.js → timeline-definition-YZTLITO2-C-m1bG_Z.js} +3 -3
  98. package/webapp/dist/assets/{timeline-definition-YZTLITO2-BrGjv8Mt.js.map → timeline-definition-YZTLITO2-C-m1bG_Z.js.map} +1 -1
  99. package/webapp/dist/assets/{treemap-KZPCXAKY-CuF9Fl6a.js → treemap-KZPCXAKY-BWvLuAyU.js} +5 -5
  100. package/webapp/dist/assets/{treemap-KZPCXAKY-CuF9Fl6a.js.map → treemap-KZPCXAKY-BWvLuAyU.js.map} +1 -1
  101. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-BsWMgmkQ.js → vennDiagram-LZ73GAT5-C8gZYuUq.js} +2 -2
  102. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-BsWMgmkQ.js.map → vennDiagram-LZ73GAT5-C8gZYuUq.js.map} +1 -1
  103. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-MwmjJKc5.js → xychartDiagram-JWTSCODW-Bb3azvDM.js} +3 -3
  104. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-MwmjJKc5.js.map → xychartDiagram-JWTSCODW-Bb3azvDM.js.map} +1 -1
  105. package/webapp/dist/index.html +1 -1
@@ -1,3 +1,4 @@
1
+ import { type CallerCourseNumber } from '@longrun-ai/kernel/types/storage';
1
2
  import { Dialog, DialogID, SubDialog } from '../../dialog';
2
3
  import type { KernelDriverDriveCallOptions, KernelDriverSubdialogReplyTarget } from './types';
3
4
  export type SubdialogReplyTarget = KernelDriverSubdialogReplyTarget;
@@ -13,6 +14,7 @@ export declare function supplyResponseToSupdialog(args: {
13
14
  course: number;
14
15
  genseq: number;
15
16
  };
17
+ callerCourseOverride?: CallerCourseNumber;
16
18
  scheduleDrive: ScheduleDriveFn;
17
19
  subdialog?: SubDialog;
18
20
  }): Promise<void>;
@@ -148,7 +148,7 @@ async function resolveLatestAssignmentAnchorRef(args) {
148
148
  return undefined;
149
149
  }
150
150
  async function supplyResponseToSupdialog(args) {
151
- const { parentDialog, subdialogId, responseText, callType, callId, status = 'completed', calleeResponseRef, scheduleDrive, subdialog: maybeSubdialog, } = args;
151
+ const { parentDialog, subdialogId, responseText, callType, callId, status = 'completed', calleeResponseRef, callerCourseOverride, scheduleDrive, subdialog: maybeSubdialog, } = args;
152
152
  try {
153
153
  const result = await (0, subdialog_txn_1.withSubdialogTxnLock)(parentDialog.id, async () => {
154
154
  const pendingSubdialogs = await persistence_1.DialogPersistence.loadPendingSubdialogs(parentDialog.id, parentDialog.status);
@@ -231,6 +231,9 @@ async function supplyResponseToSupdialog(args) {
231
231
  sessionSlug,
232
232
  callId: pendingRecord?.callId,
233
233
  callingCourse: pendingRecord?.callingCourse,
234
+ callerCourse: pendingRecord?.callingCourse !== undefined
235
+ ? (0, storage_1.toCallerCourseNumber)(pendingRecord.callingCourse)
236
+ : callerCourseOverride,
234
237
  shouldRevive,
235
238
  };
236
239
  });
@@ -271,6 +274,10 @@ async function supplyResponseToSupdialog(args) {
271
274
  })
272
275
  : undefined;
273
276
  if (resolvedCallId !== '' && calleeResponseRef) {
277
+ if (result.callerCourse === undefined) {
278
+ throw new Error(`tellask response anchor invariant violation: missing callerCourse ` +
279
+ `(parentId=${parentDialog.id.selfId}, subdialogId=${subdialogId.selfId}, callId=${resolvedCallId})`);
280
+ }
274
281
  const assignmentRef = await resolveLatestAssignmentAnchorRef({
275
282
  calleeDialogId: subdialogId,
276
283
  callId: resolvedCallId,
@@ -308,9 +315,7 @@ async function supplyResponseToSupdialog(args) {
308
315
  ? (0, storage_1.toAssignmentGenerationSeqNumber)(assignmentRef.genseq)
309
316
  : undefined,
310
317
  callerDialogId: parentDialog.id.selfId,
311
- callerCourse: result.callingCourse !== undefined
312
- ? (0, storage_1.toCallerCourseNumber)(result.callingCourse)
313
- : undefined,
318
+ callerCourse: result.callerCourse,
314
319
  };
315
320
  await persistence_1.DialogPersistence.appendEvent(subdialogId, calleeResponseRef.course, anchorRecord, parentDialog.status);
316
321
  }
@@ -800,6 +800,7 @@ async function executeTellaskCall(dlg, mentionList, body, callId, callbacks, opt
800
800
  course: sub.currentCourse,
801
801
  genseq: finalized.responseGenseq,
802
802
  },
803
+ callerCourseOverride: callingCourse !== undefined ? (0, storage_1.toCallerCourseNumber)(callingCourse) : undefined,
803
804
  scheduleDrive: callbacks.scheduleDrive,
804
805
  });
805
806
  sub.setFbrConclusionToolsEnabled(false);
@@ -2260,22 +2260,37 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
2260
2260
  break;
2261
2261
  }
2262
2262
  case 'tellask_call_anchor_record': {
2263
- const anchorEvent = {
2264
- type: 'tellask_call_anchor_evt',
2265
- course,
2266
- genseq: event.genseq,
2267
- anchorRole: event.anchorRole ?? 'response',
2268
- callId: event.callId,
2269
- assignmentCourse: event.assignmentCourse,
2270
- assignmentGenseq: event.assignmentGenseq,
2271
- callerDialogId: event.callerDialogId,
2272
- callerCourse: event.callerCourse,
2273
- dialog: {
2274
- selfId: dialog.id.selfId,
2275
- rootId: dialog.id.rootId,
2276
- },
2277
- timestamp: event.ts,
2278
- };
2263
+ const anchorEvent = event.anchorRole === 'assignment'
2264
+ ? {
2265
+ type: 'tellask_call_anchor_evt',
2266
+ course,
2267
+ genseq: event.genseq,
2268
+ anchorRole: 'assignment',
2269
+ callId: event.callId,
2270
+ assignmentCourse: event.assignmentCourse,
2271
+ assignmentGenseq: event.assignmentGenseq,
2272
+ dialog: {
2273
+ selfId: dialog.id.selfId,
2274
+ rootId: dialog.id.rootId,
2275
+ },
2276
+ timestamp: event.ts,
2277
+ }
2278
+ : {
2279
+ type: 'tellask_call_anchor_evt',
2280
+ course,
2281
+ genseq: event.genseq,
2282
+ anchorRole: 'response',
2283
+ callId: event.callId,
2284
+ assignmentCourse: event.assignmentCourse,
2285
+ assignmentGenseq: event.assignmentGenseq,
2286
+ callerDialogId: event.callerDialogId,
2287
+ callerCourse: event.callerCourse,
2288
+ dialog: {
2289
+ selfId: dialog.id.selfId,
2290
+ rootId: dialog.id.rootId,
2291
+ },
2292
+ timestamp: event.ts,
2293
+ };
2279
2294
  if (ws.readyState === 1) {
2280
2295
  ws.send(JSON.stringify(anchorEvent));
2281
2296
  }
package/dist/priming.js CHANGED
@@ -746,27 +746,47 @@ function normalizePrimingRecordFromJson(raw) {
746
746
  if (callerDialogId !== undefined && typeof callerDialogId !== 'string') {
747
747
  throw new Error(`${context}.callerDialogId must be a string when provided`);
748
748
  }
749
- const record = {
749
+ const baseRecord = {
750
750
  ts: '',
751
751
  type,
752
752
  ...(0, storage_1.toRootGenerationAnchor)({
753
753
  rootCourse: expectIntegerField(raw, 'rootCourse', context),
754
754
  rootGenseq: expectIntegerField(raw, 'rootGenseq', context),
755
755
  }),
756
- anchorRole,
757
756
  callId: expectStringField(raw, 'callId', context),
758
757
  genseq: expectIntegerField(raw, 'genseq', context),
758
+ ...(assignmentCourse !== undefined
759
+ ? { assignmentCourse: (0, storage_1.toAssignmentCourseNumber)(assignmentCourse) }
760
+ : {}),
761
+ ...(assignmentGenseq !== undefined
762
+ ? { assignmentGenseq: (0, storage_1.toAssignmentGenerationSeqNumber)(assignmentGenseq) }
763
+ : {}),
759
764
  };
760
- if (assignmentCourse !== undefined) {
761
- record.assignmentCourse = (0, storage_1.toAssignmentCourseNumber)(assignmentCourse);
762
- }
763
- if (assignmentGenseq !== undefined) {
764
- record.assignmentGenseq = (0, storage_1.toAssignmentGenerationSeqNumber)(assignmentGenseq);
765
- }
766
- if (callerDialogId !== undefined)
767
- record.callerDialogId = callerDialogId;
768
- if (callerCourse !== undefined) {
769
- record.callerCourse = (0, storage_1.toCallerCourseNumber)(callerCourse);
765
+ let record;
766
+ switch (anchorRole) {
767
+ case 'assignment':
768
+ if (callerDialogId !== undefined || callerCourse !== undefined) {
769
+ throw new Error(`${context} assignment anchor must not provide callerDialogId/callerCourse`);
770
+ }
771
+ record = {
772
+ ...baseRecord,
773
+ anchorRole: 'assignment',
774
+ };
775
+ break;
776
+ case 'response':
777
+ if (typeof callerDialogId !== 'string' || callerDialogId.trim() === '') {
778
+ throw new Error(`${context}.callerDialogId must be a non-empty string for response`);
779
+ }
780
+ if (callerCourse === undefined) {
781
+ throw new Error(`${context}.callerCourse is required for response`);
782
+ }
783
+ record = {
784
+ ...baseRecord,
785
+ anchorRole: 'response',
786
+ callerDialogId,
787
+ callerCourse: (0, storage_1.toCallerCourseNumber)(callerCourse),
788
+ };
789
+ break;
770
790
  }
771
791
  if (sourceTag)
772
792
  record.sourceTag = sourceTag;
@@ -320,6 +320,22 @@ async function handleSaveCurrentCoursePriming(req, res) {
320
320
  }
321
321
  }
322
322
  async function handleWorkspaceFilePreviewPage(req, res, pathname) {
323
+ const pseudoPathRel = parseWorkspacePseudoPreviewPathname(pathname);
324
+ if (pseudoPathRel !== null) {
325
+ if (req.method !== 'GET') {
326
+ res.writeHead(405, { 'Content-Type': 'text/plain; charset=utf-8', Allow: 'GET' });
327
+ res.end('Method Not Allowed');
328
+ return true;
329
+ }
330
+ const urlObj = new URL(req.url ?? '', 'http://127.0.0.1');
331
+ const location = `${buildWorkspacePreviewRoutePath(pseudoPathRel)}${urlObj.search}`;
332
+ res.writeHead(307, {
333
+ Location: location,
334
+ 'Cache-Control': 'no-store',
335
+ });
336
+ res.end();
337
+ return true;
338
+ }
323
339
  if (!(pathname === '/f' || pathname === '/f/' || pathname.startsWith('/f/'))) {
324
340
  return false;
325
341
  }
@@ -359,6 +375,8 @@ async function handleWorkspaceFilePreviewPage(req, res, pathname) {
359
375
  }
360
376
  }
361
377
  }
378
+ const initialPreviewPayload = await buildWorkspacePreviewPagePayload(pathRel);
379
+ const initialPreviewPayloadJson = serializeJsonForInlineScript(initialPreviewPayload);
362
380
  const html = `<!doctype html>
363
381
  <html lang="en">
364
382
  <head>
@@ -539,7 +557,7 @@ async function handleWorkspaceFilePreviewPage(req, res, pathname) {
539
557
  <div id="preview-meta" class="meta"></div>
540
558
  </div>
541
559
  <div class="body">
542
- <div id="status" class="status">Loading workspace entry...</div>
560
+ <div id="status" class="status">Loading preview...</div>
543
561
  <div id="code-wrap" class="code-wrap" style="display:none;">
544
562
  <div id="code-view" class="code-view"></div>
545
563
  </div>
@@ -874,15 +892,10 @@ async function handleWorkspaceFilePreviewPage(req, res, pathname) {
874
892
  return;
875
893
  }
876
894
 
895
+ var initialPayload = ${initialPreviewPayloadJson};
877
896
  var search = new URLSearchParams(window.location.search);
878
897
  var line = parsePositiveInt(search.get('line'));
879
898
  var column = parsePositiveInt(search.get('column'));
880
- var authFromUrl = search.get('auth');
881
- var authFromStorage = null;
882
- try { authFromStorage = window.localStorage.getItem('dominds.authKey'); } catch {}
883
- var token =
884
- (typeof authFromUrl === 'string' && authFromUrl.trim() !== '' ? authFromUrl.trim() : null) ||
885
- (typeof authFromStorage === 'string' && authFromStorage.trim() !== '' ? authFromStorage.trim() : null);
886
899
 
887
900
  pathEl.textContent = previewPath.length > 0 ? previewPath : '.';
888
901
  if (line !== null) {
@@ -891,64 +904,44 @@ async function handleWorkspaceFilePreviewPage(req, res, pathname) {
891
904
  metaEl.textContent = '';
892
905
  }
893
906
 
894
- var headers = { Accept: 'application/json' };
895
- if (token !== null) {
896
- headers['Authorization'] = 'Bearer ' + token;
897
- }
898
-
899
907
  resetViews();
900
- fetch('/api/workspace/entry?path=' + encodeURIComponent(previewPath), {
901
- method: 'GET',
902
- headers: headers,
903
- cache: 'no-store'
904
- })
905
- .then(function (resp) {
906
- return resp.json().catch(function () { return {}; }).then(function (payload) {
907
- return { ok: resp.ok, status: resp.status, payload: payload };
908
- });
909
- })
910
- .then(function (result) {
911
- if (!result.ok || !result.payload || result.payload.success !== true || typeof result.payload.kind !== 'string') {
912
- var msg = result.payload && typeof result.payload.error === 'string' && result.payload.error !== ''
913
- ? result.payload.error
914
- : ('Request failed: HTTP ' + String(result.status));
915
- setError(msg);
916
- return;
917
- }
908
+ if (!initialPayload || initialPayload.success !== true || typeof initialPayload.kind !== 'string') {
909
+ var errorMessage =
910
+ initialPayload && typeof initialPayload.error === 'string' && initialPayload.error !== ''
911
+ ? initialPayload.error
912
+ : 'Failed to load preview';
913
+ setError(errorMessage);
914
+ return;
915
+ }
918
916
 
919
- showReady();
920
- pathEl.textContent =
921
- typeof result.payload.path === 'string' && result.payload.path.length > 0
922
- ? result.payload.path
923
- : '.';
917
+ showReady();
918
+ pathEl.textContent =
919
+ typeof initialPayload.path === 'string' && initialPayload.path.length > 0
920
+ ? initialPayload.path
921
+ : '.';
924
922
 
925
- if (result.payload.kind === 'file' && typeof result.payload.raw === 'string') {
926
- var lang = detectLang(typeof result.payload.path === 'string' ? result.payload.path : previewPath);
927
- var sizeText = formatBytes(result.payload.size);
928
- var metaItems = [];
929
- if (line !== null) metaItems.push('Line ' + String(line) + (column !== null ? ':' + String(column) : ''));
930
- metaItems.push(lang);
931
- if (sizeText) metaItems.push(sizeText);
932
- metaEl.textContent = metaItems.join(' | ');
933
- renderFile(result.payload.raw, lang, line, column);
934
- return;
935
- }
923
+ if (initialPayload.kind === 'file' && typeof initialPayload.raw === 'string') {
924
+ var lang = detectLang(typeof initialPayload.path === 'string' ? initialPayload.path : previewPath);
925
+ var sizeText = formatBytes(initialPayload.size);
926
+ var metaItems = [];
927
+ if (line !== null) metaItems.push('Line ' + String(line) + (column !== null ? ':' + String(column) : ''));
928
+ metaItems.push(lang);
929
+ if (sizeText) metaItems.push(sizeText);
930
+ metaEl.textContent = metaItems.join(' | ');
931
+ renderFile(initialPayload.raw, lang, line, column);
932
+ return;
933
+ }
936
934
 
937
- if (result.payload.kind === 'directory' && Array.isArray(result.payload.entries)) {
938
- metaEl.textContent = 'directory | ' + String(result.payload.entries.length) + ' entries';
939
- renderDirectory(
940
- typeof result.payload.path === 'string' ? result.payload.path : previewPath,
941
- result.payload.entries,
942
- );
943
- return;
944
- }
935
+ if (initialPayload.kind === 'directory' && Array.isArray(initialPayload.entries)) {
936
+ metaEl.textContent = 'directory | ' + String(initialPayload.entries.length) + ' entries';
937
+ renderDirectory(
938
+ typeof initialPayload.path === 'string' ? initialPayload.path : previewPath,
939
+ initialPayload.entries,
940
+ );
941
+ return;
942
+ }
945
943
 
946
- setError('Invalid preview payload');
947
- })
948
- .catch(function (err) {
949
- var msg = err && typeof err.message === 'string' ? err.message : 'Failed to load workspace entry';
950
- setError(msg);
951
- });
944
+ setError('Invalid preview payload');
952
945
  })();
953
946
  </script>
954
947
  </body>
@@ -1192,9 +1185,8 @@ async function handleApiRoute(req, res, pathname, context) {
1192
1185
  if (pathname === '/api/docs/read' && req.method === 'GET') {
1193
1186
  return await handleReadDocsMarkdown(req, res);
1194
1187
  }
1195
- // Read workspace file or directory content for markdown preview links.
1196
- if (pathname === '/api/workspace/entry' && req.method === 'GET') {
1197
- return await handleReadWorkspaceEntry(req, res);
1188
+ if (pathname === '/api/markdown-links/resolve' && req.method === 'POST') {
1189
+ return await handleResolveMarkdownLinks(req, res);
1198
1190
  }
1199
1191
  if (pathname === '/api/snippets/builtin' && req.method === 'GET') {
1200
1192
  const payload = await (0, snippets_routes_1.handleGetBuiltinSnippets)();
@@ -1437,6 +1429,7 @@ async function handleReadDocsMarkdown(req, res) {
1437
1429
  return true;
1438
1430
  }
1439
1431
  const WORKSPACE_FILE_PREVIEW_MAX_BYTES = 2 * 1024 * 1024;
1432
+ const RTWS_PSEUDO_ROUTE_SEGMENTS = ['workspace', 'rtws'];
1440
1433
  function ensurePathSuffixSeparator(input) {
1441
1434
  if (input.endsWith(path.sep))
1442
1435
  return input;
@@ -1473,6 +1466,25 @@ function normalizeRtwsRelativePath(input, options) {
1473
1466
  }
1474
1467
  return normalized;
1475
1468
  }
1469
+ function normalizeWorkspacePseudoRelativePath(input) {
1470
+ const trimmed = input.trim();
1471
+ for (const prefix of RTWS_PSEUDO_ROUTE_SEGMENTS) {
1472
+ let tail = null;
1473
+ if (trimmed === prefix || trimmed === `/${prefix}`) {
1474
+ tail = '';
1475
+ }
1476
+ else if (trimmed.startsWith(`/${prefix}/`)) {
1477
+ tail = trimmed.slice(prefix.length + 2);
1478
+ }
1479
+ else if (trimmed.startsWith(`${prefix}/`)) {
1480
+ tail = trimmed.slice(prefix.length + 1);
1481
+ }
1482
+ if (tail !== null) {
1483
+ return normalizeRtwsRelativePath(tail, { allowRoot: true });
1484
+ }
1485
+ }
1486
+ return null;
1487
+ }
1476
1488
  function parseWorkspacePreviewPathname(pathname) {
1477
1489
  if (pathname === '/f' || pathname === '/f/')
1478
1490
  return '';
@@ -1502,6 +1514,47 @@ function parseWorkspacePreviewPathname(pathname) {
1502
1514
  }
1503
1515
  return normalizeRtwsRelativePath(decodedParts.join('/'), { allowRoot: true });
1504
1516
  }
1517
+ function parseWorkspacePseudoPreviewPathname(pathname) {
1518
+ for (const prefixSegment of RTWS_PSEUDO_ROUTE_SEGMENTS) {
1519
+ const prefix = `/${prefixSegment}`;
1520
+ if (pathname === prefix || pathname === `${prefix}/`)
1521
+ return '';
1522
+ if (!pathname.startsWith(`${prefix}/`))
1523
+ continue;
1524
+ const tail = pathname.slice(prefix.length + 1);
1525
+ if (tail.length < 1)
1526
+ return '';
1527
+ const rawParts = tail.split('/');
1528
+ const decodedParts = [];
1529
+ for (const rawPart of rawParts) {
1530
+ if (rawPart.length < 1)
1531
+ continue;
1532
+ let decoded;
1533
+ try {
1534
+ decoded = decodeURIComponent(rawPart);
1535
+ }
1536
+ catch {
1537
+ return null;
1538
+ }
1539
+ if (decoded.length < 1)
1540
+ continue;
1541
+ if (decoded.includes('/') || decoded.includes('\\') || decoded.includes('\0')) {
1542
+ return null;
1543
+ }
1544
+ decodedParts.push(decoded);
1545
+ }
1546
+ return normalizeWorkspacePseudoRelativePath(decodedParts.join('/'));
1547
+ }
1548
+ return null;
1549
+ }
1550
+ function buildWorkspacePreviewRoutePath(pathRel) {
1551
+ if (pathRel.length < 1)
1552
+ return '/f';
1553
+ return `/f/${pathRel
1554
+ .split('/')
1555
+ .map((segment) => encodeURIComponent(segment))
1556
+ .join('/')}`;
1557
+ }
1505
1558
  async function getWorkspaceRootRealAbs() {
1506
1559
  const workspaceRootAbs = path.resolve(process.cwd());
1507
1560
  try {
@@ -1620,13 +1673,13 @@ async function readFileHead(fileAbsPath, maxBytes) {
1620
1673
  await file.close();
1621
1674
  }
1622
1675
  }
1623
- async function handleReadWorkspaceEntry(req, res) {
1624
- const urlObj = new URL(req.url ?? '', 'http://127.0.0.1');
1625
- const pathRaw = urlObj.searchParams.get('path');
1626
- const pathRel = typeof pathRaw === 'string' ? normalizeRtwsRelativePath(pathRaw, { allowRoot: true }) : '';
1676
+ async function buildWorkspacePreviewPagePayload(pathRel) {
1627
1677
  if (pathRel === null) {
1628
- respondJson(res, 400, { success: false, error: 'Invalid workspace path' });
1629
- return true;
1678
+ return {
1679
+ success: false,
1680
+ error: 'Invalid preview path. Expected /f/<rtws-relative-path> and no ..',
1681
+ status: 400,
1682
+ };
1630
1683
  }
1631
1684
  try {
1632
1685
  const resolved = await resolveWorkspacePreviewPath(pathRel);
@@ -1637,59 +1690,129 @@ async function handleReadWorkspaceEntry(req, res) {
1637
1690
  dirAbsPath: resolved.resolvedAbsPath,
1638
1691
  workspaceRootRealAbs: resolved.workspaceRootRealAbs,
1639
1692
  });
1640
- respondJson(res, 200, {
1693
+ return {
1641
1694
  success: true,
1642
1695
  kind: 'directory',
1643
1696
  path: pathRel,
1644
1697
  entries,
1645
- });
1646
- return true;
1698
+ };
1647
1699
  }
1648
1700
  if (!stat.isFile()) {
1649
- respondJson(res, 400, {
1701
+ return {
1650
1702
  success: false,
1651
1703
  error: 'Path must resolve to a file or directory',
1652
1704
  path: pathRel,
1653
- });
1654
- return true;
1705
+ status: 400,
1706
+ };
1655
1707
  }
1656
1708
  if (stat.size > WORKSPACE_FILE_PREVIEW_MAX_BYTES) {
1657
- respondJson(res, 413, {
1709
+ return {
1658
1710
  success: false,
1659
1711
  error: `File too large for preview (max ${WORKSPACE_FILE_PREVIEW_MAX_BYTES} bytes)`,
1660
1712
  path: pathRel,
1661
- size: stat.size,
1662
- });
1663
- return true;
1713
+ status: 413,
1714
+ };
1664
1715
  }
1665
1716
  const raw = await promises_1.default.readFile(resolved.candidateAbsPath, 'utf-8');
1666
- respondJson(res, 200, {
1717
+ return {
1667
1718
  success: true,
1668
1719
  kind: 'file',
1669
1720
  path: pathRel,
1670
1721
  raw,
1671
1722
  size: stat.size,
1672
- });
1673
- return true;
1723
+ };
1674
1724
  }
1675
1725
  catch (error) {
1676
1726
  const code = getErrorCode(error);
1677
1727
  if (code === 'ENOENT') {
1678
- respondJson(res, 404, { success: false, error: 'Path not found', path: pathRel });
1679
- return true;
1728
+ return {
1729
+ success: false,
1730
+ error: 'Path not found',
1731
+ path: pathRel,
1732
+ status: 404,
1733
+ };
1680
1734
  }
1681
1735
  if (code === 'OUTSIDE_RTWS') {
1682
- respondJson(res, 403, {
1736
+ return {
1683
1737
  success: false,
1684
1738
  error: 'Path resolves outside rtws',
1685
1739
  path: pathRel,
1686
- });
1687
- return true;
1740
+ status: 403,
1741
+ };
1688
1742
  }
1689
- log.error('Failed to read workspace entry', error, { path: pathRel });
1690
- respondJson(res, 500, { success: false, error: 'Failed to read workspace entry' });
1743
+ log.error('Failed to build workspace preview payload', error, { path: pathRel });
1744
+ return {
1745
+ success: false,
1746
+ error: 'Failed to load preview',
1747
+ path: pathRel,
1748
+ status: 500,
1749
+ };
1750
+ }
1751
+ }
1752
+ function serializeJsonForInlineScript(value) {
1753
+ return JSON.stringify(value)
1754
+ .replace(/</g, '\\u003c')
1755
+ .replace(/>/g, '\\u003e')
1756
+ .replace(/&/g, '\\u0026')
1757
+ .replace(/\u2028/g, '\\u2028')
1758
+ .replace(/\u2029/g, '\\u2029');
1759
+ }
1760
+ async function resolveWorkspaceEntryExists(pathRel) {
1761
+ const resolved = await resolveWorkspacePreviewPath(pathRel);
1762
+ const stat = await promises_1.default.stat(resolved.candidateAbsPath);
1763
+ return stat.isFile() || stat.isDirectory();
1764
+ }
1765
+ async function handleResolveMarkdownLinks(req, res) {
1766
+ let parsed;
1767
+ try {
1768
+ const body = await readRequestBody(req);
1769
+ parsed = body.length > 0 ? JSON.parse(body) : {};
1770
+ }
1771
+ catch {
1772
+ respondJson(res, 400, { success: false, error: 'Invalid JSON body' });
1773
+ return true;
1774
+ }
1775
+ if (!isRecord(parsed)) {
1776
+ respondJson(res, 400, { success: false, error: 'Invalid JSON body' });
1691
1777
  return true;
1692
1778
  }
1779
+ const pathsRaw = parsed['paths'];
1780
+ if (!Array.isArray(pathsRaw)) {
1781
+ respondJson(res, 400, { success: false, error: '`paths` must be an array' });
1782
+ return true;
1783
+ }
1784
+ const normalizedPaths = [];
1785
+ for (const entry of pathsRaw) {
1786
+ if (typeof entry !== 'string') {
1787
+ respondJson(res, 400, { success: false, error: '`paths` entries must be strings' });
1788
+ return true;
1789
+ }
1790
+ const normalized = normalizeRtwsRelativePath(entry, { allowRoot: true });
1791
+ if (normalized === null) {
1792
+ respondJson(res, 400, { success: false, error: `Invalid workspace path: ${entry}` });
1793
+ return true;
1794
+ }
1795
+ normalizedPaths.push(normalized);
1796
+ }
1797
+ const uniquePaths = Array.from(new Set(normalizedPaths));
1798
+ const results = await Promise.all(uniquePaths.map(async (pathRel) => {
1799
+ try {
1800
+ const exists = await resolveWorkspaceEntryExists(pathRel);
1801
+ return { path: pathRel, exists };
1802
+ }
1803
+ catch (error) {
1804
+ const code = getErrorCode(error);
1805
+ if (code === 'ENOENT' || code === 'OUTSIDE_RTWS') {
1806
+ return { path: pathRel, exists: false };
1807
+ }
1808
+ throw error;
1809
+ }
1810
+ }));
1811
+ respondJson(res, 200, {
1812
+ success: true,
1813
+ results,
1814
+ });
1815
+ return true;
1693
1816
  }
1694
1817
  async function handleGetToolsRegistry(req, res) {
1695
1818
  try {
@@ -35,6 +35,7 @@ export declare function isAuthEnabled(auth: AuthConfig): auth is Extract<AuthCon
35
35
  kind: 'enabled';
36
36
  }>;
37
37
  export declare function getHttpAuthCheck(req: IncomingMessage, auth: AuthConfig): AuthCheckResult;
38
+ export declare function getHttpAuthCheckAllowUrlParam(req: IncomingMessage, auth: AuthConfig, requestUrl: URL): AuthCheckResult;
38
39
  export declare function getWebSocketAuthCheck(req: IncomingMessage, auth: AuthConfig): AuthCheckResult;
39
40
  export declare function formatAutoAuthUrl(params: {
40
41
  host: string;
@@ -51,6 +51,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
51
51
  exports.computeAuthConfig = computeAuthConfig;
52
52
  exports.isAuthEnabled = isAuthEnabled;
53
53
  exports.getHttpAuthCheck = getHttpAuthCheck;
54
+ exports.getHttpAuthCheckAllowUrlParam = getHttpAuthCheckAllowUrlParam;
54
55
  exports.getWebSocketAuthCheck = getWebSocketAuthCheck;
55
56
  exports.formatAutoAuthUrl = formatAutoAuthUrl;
56
57
  const crypto = __importStar(require("crypto"));
@@ -86,6 +87,26 @@ function getHttpAuthCheck(req, auth) {
86
87
  ? { kind: 'ok' }
87
88
  : { kind: 'unauthorized', reason: 'invalid' };
88
89
  }
90
+ function getHttpAuthCheckAllowUrlParam(req, auth, requestUrl) {
91
+ if (auth.kind === 'disabled')
92
+ return { kind: 'ok' };
93
+ const header = getSingleHeaderValue(req.headers.authorization);
94
+ if (header) {
95
+ const parsed = parseBearerAuthHeader(header);
96
+ if (!parsed)
97
+ return { kind: 'unauthorized', reason: 'invalid' };
98
+ return constantTimeEqual(parsed.token, auth.key)
99
+ ? { kind: 'ok' }
100
+ : { kind: 'unauthorized', reason: 'invalid' };
101
+ }
102
+ const queryToken = requestUrl.searchParams.get('auth');
103
+ if (typeof queryToken !== 'string' || queryToken === '') {
104
+ return { kind: 'unauthorized', reason: 'missing' };
105
+ }
106
+ return constantTimeEqual(queryToken, auth.key)
107
+ ? { kind: 'ok' }
108
+ : { kind: 'unauthorized', reason: 'invalid' };
109
+ }
89
110
  function getWebSocketAuthCheck(req, auth) {
90
111
  if (auth.kind === 'disabled')
91
112
  return { kind: 'ok' };
@@ -105,6 +105,21 @@ class HttpServerCore {
105
105
  return;
106
106
  }
107
107
  }
108
+ if (pathname === '/f' ||
109
+ pathname === '/f/' ||
110
+ pathname.startsWith('/f/') ||
111
+ pathname === '/workspace' ||
112
+ pathname === '/workspace/' ||
113
+ pathname.startsWith('/workspace/') ||
114
+ pathname === '/rtws' ||
115
+ pathname === '/rtws/' ||
116
+ pathname.startsWith('/rtws/')) {
117
+ const authCheck = (0, auth_1.getHttpAuthCheckAllowUrlParam)(req, this.config.auth ?? { kind: 'disabled' }, requestUrl);
118
+ if (authCheck.kind !== 'ok') {
119
+ this.sendUnauthorized(res);
120
+ return;
121
+ }
122
+ }
108
123
  // Backend-direct workspace file preview page.
109
124
  if (await (0, api_routes_1.handleWorkspaceFilePreviewPage)(req, res, pathname)) {
110
125
  return;