dominds 1.2.5 → 1.2.7

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 (149) hide show
  1. package/dist/agent-priming.js +2051 -0
  2. package/dist/apps/app-lock-file.js +228 -0
  3. package/dist/apps/assigned-port.js +124 -0
  4. package/dist/apps/enabled-apps.js +472 -7
  5. package/dist/apps/manifest.js +37 -0
  6. package/dist/apps/override-paths.js +19 -6
  7. package/dist/apps/problems.js +43 -0
  8. package/dist/apps/resolution-file.js +370 -0
  9. package/dist/apps/runtime.js +5 -17
  10. package/dist/apps/teammates.js +102 -1
  11. package/dist/cli/disable.js +10 -6
  12. package/dist/cli/enable.js +21 -19
  13. package/dist/cli/install.js +40 -18
  14. package/dist/cli/uninstall.js +6 -6
  15. package/dist/cli/update.js +38 -13
  16. package/dist/dialog.js +5 -0
  17. package/dist/docs/app-constitution.md +85 -18
  18. package/dist/docs/app-constitution.zh.md +86 -21
  19. package/dist/docs/dialog-system.md +1 -1
  20. package/dist/docs/dialog-system.zh.md +1 -1
  21. package/dist/docs/dominds-agent-priming.md +218 -0
  22. package/dist/docs/dominds-agent-priming.zh.md +196 -0
  23. package/dist/docs/drive-logic-context-refactor-plan.zh.md +338 -0
  24. package/dist/docs/keep-going.md +176 -0
  25. package/dist/docs/keep-going.zh.md +162 -0
  26. package/dist/docs/showing-by-doing.md +208 -0
  27. package/dist/docs/showing-by-doing.zh.md +177 -0
  28. package/dist/docs/team-mgmt-toolset.md +482 -0
  29. package/dist/docs/team-mgmt-toolset.zh.md +426 -0
  30. package/dist/llm/defaults.yaml +1 -1
  31. package/dist/llm/driver.js +4093 -0
  32. package/dist/llm/kernel-driver/drive.js +5 -2
  33. package/dist/llm/kernel-driver/flow.js +3 -0
  34. package/dist/minds/promptdocs.js +263 -0
  35. package/dist/problems.js +67 -16
  36. package/dist/server/api-routes.js +333 -0
  37. package/dist/server/prompts-routes.js +545 -0
  38. package/dist/server/server-core.js +4 -0
  39. package/dist/server/websocket-handler.js +17 -0
  40. package/dist/shared/team-mgmt-manual.js +120 -0
  41. package/dist/shared/types/prompts.js +2 -0
  42. package/dist/shared/types/tellask.js +8 -0
  43. package/dist/showing-by-doing.js +1091 -0
  44. package/dist/snippets/README.en.md +3 -0
  45. package/dist/snippets/README.md +4 -0
  46. package/dist/static/assets/{_basePickBy-CF9r08iy.js → _basePickBy-BMCtwrV7.js} +3 -3
  47. package/dist/static/assets/{_basePickBy-CF9r08iy.js.map → _basePickBy-BMCtwrV7.js.map} +1 -1
  48. package/dist/static/assets/{_baseUniq-CxKv0cd4.js → _baseUniq-BuyCgJiA.js} +2 -2
  49. package/dist/static/assets/{_baseUniq-CxKv0cd4.js.map → _baseUniq-BuyCgJiA.js.map} +1 -1
  50. package/dist/static/assets/{arc-C9JyvnlB.js → arc-BDuN8lwA.js} +2 -2
  51. package/dist/static/assets/{arc-C9JyvnlB.js.map → arc-BDuN8lwA.js.map} +1 -1
  52. package/dist/static/assets/{architectureDiagram-VXUJARFQ-CpcUgjHf.js → architectureDiagram-VXUJARFQ-C-ekqGAD.js} +7 -7
  53. package/dist/static/assets/{architectureDiagram-VXUJARFQ-CpcUgjHf.js.map → architectureDiagram-VXUJARFQ-C-ekqGAD.js.map} +1 -1
  54. package/dist/static/assets/{blockDiagram-VD42YOAC-BA9vtmm7.js → blockDiagram-VD42YOAC-CgQiNuuQ.js} +7 -7
  55. package/dist/static/assets/{blockDiagram-VD42YOAC-BA9vtmm7.js.map → blockDiagram-VD42YOAC-CgQiNuuQ.js.map} +1 -1
  56. package/dist/static/assets/{c4Diagram-YG6GDRKO-D49MGNdF.js → c4Diagram-YG6GDRKO-DONC39q-.js} +3 -3
  57. package/dist/static/assets/{c4Diagram-YG6GDRKO-D49MGNdF.js.map → c4Diagram-YG6GDRKO-DONC39q-.js.map} +1 -1
  58. package/dist/static/assets/{channel-B4KzL0Kg.js → channel-CJTFwXIG.js} +2 -2
  59. package/dist/static/assets/{channel-B4KzL0Kg.js.map → channel-CJTFwXIG.js.map} +1 -1
  60. package/dist/static/assets/{chunk-4BX2VUAB-0F-1ayl0.js → chunk-4BX2VUAB-NaIy4uLJ.js} +2 -2
  61. package/dist/static/assets/{chunk-4BX2VUAB-0F-1ayl0.js.map → chunk-4BX2VUAB-NaIy4uLJ.js.map} +1 -1
  62. package/dist/static/assets/{chunk-55IACEB6-Dnl2HDTZ.js → chunk-55IACEB6-JUKI_Ayx.js} +2 -2
  63. package/dist/static/assets/{chunk-55IACEB6-Dnl2HDTZ.js.map → chunk-55IACEB6-JUKI_Ayx.js.map} +1 -1
  64. package/dist/static/assets/{chunk-B4BG7PRW-Bhx5RbkQ.js → chunk-B4BG7PRW-dIswFJDn.js} +5 -5
  65. package/dist/static/assets/{chunk-B4BG7PRW-Bhx5RbkQ.js.map → chunk-B4BG7PRW-dIswFJDn.js.map} +1 -1
  66. package/dist/static/assets/{chunk-DI55MBZ5-EYd1wL3E.js → chunk-DI55MBZ5-DU2b_N30.js} +4 -4
  67. package/dist/static/assets/{chunk-DI55MBZ5-EYd1wL3E.js.map → chunk-DI55MBZ5-DU2b_N30.js.map} +1 -1
  68. package/dist/static/assets/{chunk-FMBD7UC4-DAjkhhUU.js → chunk-FMBD7UC4-BgExcScw.js} +2 -2
  69. package/dist/static/assets/{chunk-FMBD7UC4-DAjkhhUU.js.map → chunk-FMBD7UC4-BgExcScw.js.map} +1 -1
  70. package/dist/static/assets/{chunk-QN33PNHL-CK6TY7IE.js → chunk-QN33PNHL-bitxyqh7.js} +2 -2
  71. package/dist/static/assets/{chunk-QN33PNHL-CK6TY7IE.js.map → chunk-QN33PNHL-bitxyqh7.js.map} +1 -1
  72. package/dist/static/assets/{chunk-QZHKN3VN-CketngiE.js → chunk-QZHKN3VN-Cor8u7DT.js} +2 -2
  73. package/dist/static/assets/{chunk-QZHKN3VN-CketngiE.js.map → chunk-QZHKN3VN-Cor8u7DT.js.map} +1 -1
  74. package/dist/static/assets/{chunk-TZMSLE5B-Bcuvqo45.js → chunk-TZMSLE5B-Aceoxav_.js} +2 -2
  75. package/dist/static/assets/{chunk-TZMSLE5B-Bcuvqo45.js.map → chunk-TZMSLE5B-Aceoxav_.js.map} +1 -1
  76. package/dist/static/assets/{classDiagram-2ON5EDUG-CaP4T3r4.js → classDiagram-2ON5EDUG-D1Q6a8Hg.js} +6 -6
  77. package/dist/static/assets/{classDiagram-2ON5EDUG-CaP4T3r4.js.map → classDiagram-2ON5EDUG-D1Q6a8Hg.js.map} +1 -1
  78. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-CaP4T3r4.js → classDiagram-v2-WZHVMYZB-D1Q6a8Hg.js} +6 -6
  79. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-CaP4T3r4.js.map → classDiagram-v2-WZHVMYZB-D1Q6a8Hg.js.map} +1 -1
  80. package/dist/static/assets/{clone-C-JULvnG.js → clone-MlWbv1V0.js} +2 -2
  81. package/dist/static/assets/{clone-C-JULvnG.js.map → clone-MlWbv1V0.js.map} +1 -1
  82. package/dist/static/assets/{cose-bilkent-S5V4N54A-vXCmi_eC.js → cose-bilkent-S5V4N54A-DWPCXSrn.js} +2 -2
  83. package/dist/static/assets/{cose-bilkent-S5V4N54A-vXCmi_eC.js.map → cose-bilkent-S5V4N54A-DWPCXSrn.js.map} +1 -1
  84. package/dist/static/assets/{dagre-6UL2VRFP-bhGzX6kO.js → dagre-6UL2VRFP-C8ptQ9V3.js} +7 -7
  85. package/dist/static/assets/{dagre-6UL2VRFP-bhGzX6kO.js.map → dagre-6UL2VRFP-C8ptQ9V3.js.map} +1 -1
  86. package/dist/static/assets/{diagram-PSM6KHXK-BUKfmfGk.js → diagram-PSM6KHXK-Bgf1FqkE.js} +8 -8
  87. package/dist/static/assets/{diagram-PSM6KHXK-BUKfmfGk.js.map → diagram-PSM6KHXK-Bgf1FqkE.js.map} +1 -1
  88. package/dist/static/assets/{diagram-QEK2KX5R-DYlq3uFq.js → diagram-QEK2KX5R-BZ5xzofU.js} +7 -7
  89. package/dist/static/assets/{diagram-QEK2KX5R-DYlq3uFq.js.map → diagram-QEK2KX5R-BZ5xzofU.js.map} +1 -1
  90. package/dist/static/assets/{diagram-S2PKOQOG-CjxkLHWG.js → diagram-S2PKOQOG-Dwp47T9I.js} +7 -7
  91. package/dist/static/assets/{diagram-S2PKOQOG-CjxkLHWG.js.map → diagram-S2PKOQOG-Dwp47T9I.js.map} +1 -1
  92. package/dist/static/assets/{erDiagram-Q2GNP2WA-S3hR85On.js → erDiagram-Q2GNP2WA-Cx4weIHl.js} +5 -5
  93. package/dist/static/assets/{erDiagram-Q2GNP2WA-S3hR85On.js.map → erDiagram-Q2GNP2WA-Cx4weIHl.js.map} +1 -1
  94. package/dist/static/assets/{flowDiagram-NV44I4VS-aBmNMuQ0.js → flowDiagram-NV44I4VS-vNUuIeRk.js} +6 -6
  95. package/dist/static/assets/{flowDiagram-NV44I4VS-aBmNMuQ0.js.map → flowDiagram-NV44I4VS-vNUuIeRk.js.map} +1 -1
  96. package/dist/static/assets/{ganttDiagram-JELNMOA3-DJxXaiW1.js → ganttDiagram-JELNMOA3-BEfozJAr.js} +3 -3
  97. package/dist/static/assets/{ganttDiagram-JELNMOA3-DJxXaiW1.js.map → ganttDiagram-JELNMOA3-BEfozJAr.js.map} +1 -1
  98. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-DEOBCM0G.js → gitGraphDiagram-V2S2FVAM-eHxwc3d9.js} +8 -8
  99. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-DEOBCM0G.js.map → gitGraphDiagram-V2S2FVAM-eHxwc3d9.js.map} +1 -1
  100. package/dist/static/assets/{graph-DwrKSIE7.js → graph-C6a6uAok.js} +3 -3
  101. package/dist/static/assets/{graph-DwrKSIE7.js.map → graph-C6a6uAok.js.map} +1 -1
  102. package/dist/static/assets/{index-HWTRvE2k.js → index-D3TQbAKh.js} +383 -59
  103. package/dist/static/assets/index-D3TQbAKh.js.map +1 -0
  104. package/dist/static/assets/{infoDiagram-HS3SLOUP-BH9kVuYd.js → infoDiagram-HS3SLOUP-CX0NiId3.js} +6 -6
  105. package/dist/static/assets/{infoDiagram-HS3SLOUP-BH9kVuYd.js.map → infoDiagram-HS3SLOUP-CX0NiId3.js.map} +1 -1
  106. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Dap7AcjR.js → journeyDiagram-XKPGCS4Q-C1IepPZ-.js} +5 -5
  107. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Dap7AcjR.js.map → journeyDiagram-XKPGCS4Q-C1IepPZ-.js.map} +1 -1
  108. package/dist/static/assets/{kanban-definition-3W4ZIXB7-4NOl8MEj.js → kanban-definition-3W4ZIXB7-uMNX4Z1W.js} +3 -3
  109. package/dist/static/assets/{kanban-definition-3W4ZIXB7-4NOl8MEj.js.map → kanban-definition-3W4ZIXB7-uMNX4Z1W.js.map} +1 -1
  110. package/dist/static/assets/{layout-D6uIxu1E.js → layout-CpE3kk5z.js} +5 -5
  111. package/dist/static/assets/{layout-D6uIxu1E.js.map → layout-CpE3kk5z.js.map} +1 -1
  112. package/dist/static/assets/{linear-CvBOGQA2.js → linear-DV8laXr9.js} +2 -2
  113. package/dist/static/assets/{linear-CvBOGQA2.js.map → linear-DV8laXr9.js.map} +1 -1
  114. package/dist/static/assets/{mindmap-definition-VGOIOE7T-ugsrLNY5.js → mindmap-definition-VGOIOE7T-CKjgVM9S.js} +4 -4
  115. package/dist/static/assets/{mindmap-definition-VGOIOE7T-ugsrLNY5.js.map → mindmap-definition-VGOIOE7T-CKjgVM9S.js.map} +1 -1
  116. package/dist/static/assets/{pieDiagram-ADFJNKIX-CdVZjM8g.js → pieDiagram-ADFJNKIX-BBonlNyT.js} +8 -8
  117. package/dist/static/assets/{pieDiagram-ADFJNKIX-CdVZjM8g.js.map → pieDiagram-ADFJNKIX-BBonlNyT.js.map} +1 -1
  118. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-A6m5lZKd.js → quadrantDiagram-AYHSOK5B-BTI8HbBu.js} +3 -3
  119. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-A6m5lZKd.js.map → quadrantDiagram-AYHSOK5B-BTI8HbBu.js.map} +1 -1
  120. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-Cac3zSJH.js → requirementDiagram-UZGBJVZJ-ZtSr9Q5R.js} +4 -4
  121. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-Cac3zSJH.js.map → requirementDiagram-UZGBJVZJ-ZtSr9Q5R.js.map} +1 -1
  122. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DXDdUUl1.js → sankeyDiagram-TZEHDZUN-DibLVGzg.js} +2 -2
  123. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DXDdUUl1.js.map → sankeyDiagram-TZEHDZUN-DibLVGzg.js.map} +1 -1
  124. package/dist/static/assets/{sequenceDiagram-WL72ISMW-Domsjl5Y.js → sequenceDiagram-WL72ISMW-qXatfzVt.js} +4 -4
  125. package/dist/static/assets/{sequenceDiagram-WL72ISMW-Domsjl5Y.js.map → sequenceDiagram-WL72ISMW-qXatfzVt.js.map} +1 -1
  126. package/dist/static/assets/{stateDiagram-FKZM4ZOC-Bu0lRQK1.js → stateDiagram-FKZM4ZOC-7fgxCQHo.js} +9 -9
  127. package/dist/static/assets/{stateDiagram-FKZM4ZOC-Bu0lRQK1.js.map → stateDiagram-FKZM4ZOC-7fgxCQHo.js.map} +1 -1
  128. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-D0K-n3ic.js → stateDiagram-v2-4FDKWEC3-DcWlOAnF.js} +5 -5
  129. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-D0K-n3ic.js.map → stateDiagram-v2-4FDKWEC3-DcWlOAnF.js.map} +1 -1
  130. package/dist/static/assets/{timeline-definition-IT6M3QCI-BGvpddwR.js → timeline-definition-IT6M3QCI-iX2MRdpY.js} +3 -3
  131. package/dist/static/assets/{timeline-definition-IT6M3QCI-BGvpddwR.js.map → timeline-definition-IT6M3QCI-iX2MRdpY.js.map} +1 -1
  132. package/dist/static/assets/{treemap-GDKQZRPO-BoOzOm2j.js → treemap-GDKQZRPO-AVRnyXu1.js} +5 -5
  133. package/dist/static/assets/{treemap-GDKQZRPO-BoOzOm2j.js.map → treemap-GDKQZRPO-AVRnyXu1.js.map} +1 -1
  134. package/dist/static/assets/{xychartDiagram-PRI3JC2R-C_h3_ICR.js → xychartDiagram-PRI3JC2R-DVYEo5aJ.js} +3 -3
  135. package/dist/static/assets/{xychartDiagram-PRI3JC2R-C_h3_ICR.js.map → xychartDiagram-PRI3JC2R-DVYEo5aJ.js.map} +1 -1
  136. package/dist/static/index.html +1 -1
  137. package/dist/team.js +52 -48
  138. package/dist/tellask.js +439 -0
  139. package/dist/tools/context-health.js +177 -0
  140. package/dist/tools/diag.js +583 -0
  141. package/dist/tools/fs.js +194 -68
  142. package/dist/tools/prompts/memory/en/principles.md +13 -5
  143. package/dist/tools/prompts/memory/en/tools.md +11 -36
  144. package/dist/tools/prompts/memory/zh/principles.md +18 -8
  145. package/dist/tools/prompts/memory/zh/tools.md +11 -36
  146. package/dist/tools/team-mgmt.js +3487 -0
  147. package/dist/utils/task-doc.js +236 -0
  148. package/package.json +1 -1
  149. package/dist/static/assets/index-HWTRvE2k.js.map +0 -1
@@ -1,19 +1,484 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.loadEnabledAppsSnapshot = loadEnabledAppsSnapshot;
4
- const installed_file_1 = require("./installed-file");
5
- async function loadEnabledAppsSnapshot(params) {
6
- const loaded = await (0, installed_file_1.loadInstalledAppsFile)({ rtwsRootAbs: params.rtwsRootAbs });
7
+ const promises_1 = __importDefault(require("node:fs/promises"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const assigned_port_1 = require("./assigned-port");
10
+ const manifest_1 = require("./manifest");
11
+ const package_info_1 = require("./package-info");
12
+ const resolution_file_1 = require("./resolution-file");
13
+ const run_app_json_1 = require("./run-app-json");
14
+ async function fileExists(filePathAbs) {
15
+ try {
16
+ await promises_1.default.access(filePathAbs);
17
+ return true;
18
+ }
19
+ catch (err) {
20
+ const isEnoent = typeof err === 'object' &&
21
+ err !== null &&
22
+ 'code' in err &&
23
+ err.code === 'ENOENT';
24
+ if (isEnoent)
25
+ return false;
26
+ throw err;
27
+ }
28
+ }
29
+ async function dirExists(dirPathAbs) {
30
+ try {
31
+ const st = await promises_1.default.stat(dirPathAbs);
32
+ return st.isDirectory();
33
+ }
34
+ catch (err) {
35
+ const isEnoent = typeof err === 'object' &&
36
+ err !== null &&
37
+ 'code' in err &&
38
+ err.code === 'ENOENT';
39
+ if (isEnoent)
40
+ return false;
41
+ throw err;
42
+ }
43
+ }
44
+ async function tryLoadRtwsAppManifestDeps(params) {
45
+ const filePathAbs = node_path_1.default.resolve(params.rtwsRootAbs, '.minds', 'app.yaml');
46
+ if (!(await fileExists(filePathAbs)))
47
+ return [];
48
+ const loaded = await (0, manifest_1.loadDomindsAppManifest)({
49
+ packageRootAbs: params.rtwsRootAbs,
50
+ manifestRelPath: '.minds/app.yaml',
51
+ });
7
52
  if (loaded.kind === 'error') {
8
- throw new Error(`Failed to load installed apps file: ${loaded.errorText} (${loaded.filePathAbs})`);
53
+ throw new Error(`Failed to load rtws app manifest: ${loaded.errorText} (${loaded.filePathAbs})`);
9
54
  }
10
- const enabledApps = loaded.file.apps
55
+ return loaded.manifest.dependencies ?? [];
56
+ }
57
+ function indexOverlayApps(params) {
58
+ const byId = new Map();
59
+ const extras = [];
60
+ for (const e of params.overlayApps) {
61
+ if (byId.has(e.id)) {
62
+ // Loud: duplicate IDs means non-deterministic overrides.
63
+ throw new Error(`Invalid apps resolution overlay: duplicate app id '${e.id}'`);
64
+ }
65
+ byId.set(e.id, e);
66
+ extras.push(e);
67
+ }
68
+ return { byId, extras };
69
+ }
70
+ function normalizeStrategy(raw) {
71
+ const order = raw?.order ??
72
+ resolution_file_1.DEFAULT_APPS_RESOLUTION_STRATEGY.order ??
73
+ ['local'];
74
+ const localRoots = raw?.localRoots ??
75
+ resolution_file_1.DEFAULT_APPS_RESOLUTION_STRATEGY.localRoots ?? ['dominds-apps'];
76
+ if (order.length === 0) {
77
+ throw new Error(`Invalid ${resolution_file_1.APPS_RESOLUTION_REL_PATH}: resolutionStrategy.order must not be empty`);
78
+ }
79
+ if (localRoots.length === 0) {
80
+ throw new Error(`Invalid ${resolution_file_1.APPS_RESOLUTION_REL_PATH}: resolutionStrategy.localRoots must not be empty`);
81
+ }
82
+ const orderSet = new Set(order);
83
+ if (orderSet.size !== order.length) {
84
+ throw new Error(`Invalid ${resolution_file_1.APPS_RESOLUTION_REL_PATH}: resolutionStrategy.order has duplicates`);
85
+ }
86
+ const localRootsSet = new Set(localRoots);
87
+ if (localRootsSet.size !== localRoots.length) {
88
+ throw new Error(`Invalid ${resolution_file_1.APPS_RESOLUTION_REL_PATH}: resolutionStrategy.localRoots has duplicates`);
89
+ }
90
+ return { order, localRoots };
91
+ }
92
+ function getResolutionHint(params) {
93
+ const filePathAbs = node_path_1.default.resolve(params.rtwsRootAbs, resolution_file_1.APPS_RESOLUTION_REL_PATH);
94
+ const action = params.hasResolutionFile ? 'Edit' : 'Create';
95
+ return (`${action} ${filePathAbs} to configure 'resolutionStrategy'. ` +
96
+ `Default local root is 'dominds-apps' (rtws-relative) and expects local apps at '<root>/<appId>/'.`);
97
+ }
98
+ async function resolveLocalAppPackageRootAbs(params) {
99
+ for (const root of params.localRoots) {
100
+ const rootAbs = node_path_1.default.isAbsolute(root) ? root : node_path_1.default.resolve(params.rtwsRootAbs, root);
101
+ const candidateAbs = node_path_1.default.resolve(rootAbs, params.appId);
102
+ if (await dirExists(candidateAbs))
103
+ return candidateAbs;
104
+ }
105
+ return null;
106
+ }
107
+ async function resolveAppManifestDepsFromInstalledApp(params) {
108
+ const pkgInfo = await (0, package_info_1.readPackageInfo)({ packageRootAbs: params.packageRootAbs });
109
+ const loaded = await (0, manifest_1.loadDomindsAppManifest)({
110
+ packageRootAbs: params.packageRootAbs,
111
+ manifestRelPath: pkgInfo.manifestRelPath,
112
+ });
113
+ if (loaded.kind === 'error') {
114
+ throw new Error(`Failed to load app manifest for '${params.appId}': ${loaded.errorText} (${loaded.filePathAbs})`);
115
+ }
116
+ return loaded.manifest.dependencies ?? [];
117
+ }
118
+ async function resolveAppsFromRtwsHierarchy(params) {
119
+ const issues = [];
120
+ const pushIssue = (issue) => {
121
+ issues.push(issue);
122
+ };
123
+ const resolvedById = new Map();
124
+ const depsByAppId = new Map();
125
+ const requiredById = new Map();
126
+ const requiredByParents = new Map();
127
+ const missingRequired = new Set();
128
+ const fatalApps = new Set();
129
+ const addRequiredByParent = (depId, parentId) => {
130
+ const existing = requiredByParents.get(depId);
131
+ if (existing) {
132
+ existing.add(parentId);
133
+ return;
134
+ }
135
+ requiredByParents.set(depId, new Set([parentId]));
136
+ };
137
+ const mergeRequiredFlag = (id, required) => {
138
+ const prev = requiredById.get(id);
139
+ if (prev === undefined) {
140
+ requiredById.set(id, required);
141
+ return true;
142
+ }
143
+ if (prev === true)
144
+ return false;
145
+ if (required === true) {
146
+ requiredById.set(id, true);
147
+ return true;
148
+ }
149
+ return false;
150
+ };
151
+ const queue = [];
152
+ const enqueue = (id, required, parentId) => {
153
+ const changed = mergeRequiredFlag(id, required);
154
+ if (parentId && required)
155
+ addRequiredByParent(id, parentId);
156
+ if (changed)
157
+ queue.push(id);
158
+ };
159
+ try {
160
+ const rootDeps = await tryLoadRtwsAppManifestDeps({ rtwsRootAbs: params.rtwsRootAbs });
161
+ for (const dep of rootDeps) {
162
+ enqueue(dep.id, dep.optional !== true, 'rtws');
163
+ }
164
+ }
165
+ catch (err) {
166
+ pushIssue({
167
+ kind: 'app_manifest_load_failed',
168
+ severity: 'error',
169
+ message: 'Failed to load rtws app manifest (.minds/app.yaml); app dependencies will not be resolved.',
170
+ detail: {
171
+ appId: 'rtws',
172
+ manifestRelPath: '.minds/app.yaml',
173
+ errorText: err instanceof Error ? err.message : String(err),
174
+ },
175
+ });
176
+ }
177
+ // Also treat explicitly enabled overlay apps as roots so their own transitive dependencies
178
+ // are resolved and missing-required issues can be surfaced.
179
+ for (const e of params.overlay.extras) {
180
+ if (!e.userEnabled)
181
+ continue;
182
+ enqueue(e.id, true, 'resolution_overlay');
183
+ }
184
+ const resolveMissingApp = async (appId) => {
185
+ for (const item of params.strategy.order) {
186
+ if (item === 'local') {
187
+ const packageRootAbs = await resolveLocalAppPackageRootAbs({
188
+ rtwsRootAbs: params.rtwsRootAbs,
189
+ appId,
190
+ localRoots: params.strategy.localRoots,
191
+ });
192
+ if (!packageRootAbs) {
193
+ continue;
194
+ }
195
+ const installJson = await (0, run_app_json_1.runDomindsAppJsonViaLocalPackage)({ packageRootAbs });
196
+ if (installJson.appId !== appId) {
197
+ throw new Error(`App id mismatch for local package '${packageRootAbs}': expected '${appId}', got '${installJson.appId}'`);
198
+ }
199
+ const source = { kind: 'local', pathAbs: packageRootAbs };
200
+ return {
201
+ id: appId,
202
+ enabled: true,
203
+ userEnabled: true,
204
+ source,
205
+ assignedPort: null,
206
+ installJson,
207
+ };
208
+ }
209
+ if (item === 'npx') {
210
+ throw new Error(`Apps resolution strategy 'npx' is not supported yet for missing app '${appId}'. ` +
211
+ `Install it explicitly so it appears in ${resolution_file_1.APPS_RESOLUTION_REL_PATH}.`);
212
+ }
213
+ const _exhaustive = item;
214
+ throw new Error(`Unreachable: unknown resolution strategy item: ${String(_exhaustive)}`);
215
+ }
216
+ return null;
217
+ };
218
+ while (queue.length > 0) {
219
+ const appId = queue.shift();
220
+ if (!appId)
221
+ break;
222
+ if (resolvedById.has(appId) || missingRequired.has(appId) || fatalApps.has(appId)) {
223
+ continue;
224
+ }
225
+ const required = requiredById.get(appId) ?? true;
226
+ const overlayEntry = params.overlay.byId.get(appId) ?? null;
227
+ let entry = overlayEntry;
228
+ if (!entry) {
229
+ try {
230
+ entry = await resolveMissingApp(appId);
231
+ }
232
+ catch (err) {
233
+ if (required) {
234
+ const roots = params.strategy.localRoots
235
+ .map((r) => (node_path_1.default.isAbsolute(r) ? r : node_path_1.default.resolve(params.rtwsRootAbs, r)))
236
+ .join(', ');
237
+ pushIssue({
238
+ kind: 'required_dependency_missing',
239
+ severity: 'error',
240
+ message: `Required app dependency '${appId}' failed to resolve.`,
241
+ detail: {
242
+ appId,
243
+ searchedLocalRootsAbs: roots,
244
+ hint: getResolutionHint({
245
+ rtwsRootAbs: params.rtwsRootAbs,
246
+ hasResolutionFile: params.hasResolutionFile,
247
+ }),
248
+ errorText: err instanceof Error ? err.message : String(err),
249
+ requiredBy: [...(requiredByParents.get(appId) ?? new Set())].sort(),
250
+ },
251
+ });
252
+ missingRequired.add(appId);
253
+ }
254
+ continue;
255
+ }
256
+ }
257
+ if (!entry) {
258
+ if (required) {
259
+ const roots = params.strategy.localRoots
260
+ .map((r) => (node_path_1.default.isAbsolute(r) ? r : node_path_1.default.resolve(params.rtwsRootAbs, r)))
261
+ .join(', ');
262
+ pushIssue({
263
+ kind: 'required_dependency_missing',
264
+ severity: 'error',
265
+ message: `Required app dependency '${appId}' is missing.`,
266
+ detail: {
267
+ appId,
268
+ searchedLocalRootsAbs: roots,
269
+ hint: getResolutionHint({
270
+ rtwsRootAbs: params.rtwsRootAbs,
271
+ hasResolutionFile: params.hasResolutionFile,
272
+ }),
273
+ requiredBy: [...(requiredByParents.get(appId) ?? new Set())].sort(),
274
+ },
275
+ });
276
+ missingRequired.add(appId);
277
+ }
278
+ continue;
279
+ }
280
+ resolvedById.set(appId, entry);
281
+ if (!entry.userEnabled) {
282
+ if (required) {
283
+ pushIssue({
284
+ kind: 'required_dependency_disabled',
285
+ severity: 'error',
286
+ message: `Required app dependency '${appId}' is disabled.`,
287
+ detail: {
288
+ appId,
289
+ resolutionFileRelPath: resolution_file_1.APPS_RESOLUTION_REL_PATH,
290
+ requiredBy: [...(requiredByParents.get(appId) ?? new Set())].sort(),
291
+ hint: getResolutionHint({
292
+ rtwsRootAbs: params.rtwsRootAbs,
293
+ hasResolutionFile: params.hasResolutionFile,
294
+ }),
295
+ },
296
+ });
297
+ }
298
+ continue;
299
+ }
300
+ let manifestDeps;
301
+ try {
302
+ manifestDeps = await resolveAppManifestDepsFromInstalledApp({
303
+ appId,
304
+ packageRootAbs: entry.installJson.package.rootAbs,
305
+ });
306
+ }
307
+ catch (err) {
308
+ pushIssue({
309
+ kind: 'app_manifest_load_failed',
310
+ severity: 'error',
311
+ message: `Failed to load app manifest for '${appId}'.`,
312
+ detail: {
313
+ appId,
314
+ packageRootAbs: entry.installJson.package.rootAbs,
315
+ errorText: err instanceof Error ? err.message : String(err),
316
+ },
317
+ });
318
+ fatalApps.add(appId);
319
+ continue;
320
+ }
321
+ const edges = manifestDeps.map((d) => ({
322
+ depId: d.id,
323
+ required: d.optional !== true,
324
+ }));
325
+ depsByAppId.set(appId, edges);
326
+ for (const e of edges) {
327
+ enqueue(e.depId, e.required, appId);
328
+ }
329
+ }
330
+ const effectiveEnabledById = new Map();
331
+ for (const [id, entry] of resolvedById.entries()) {
332
+ effectiveEnabledById.set(id, entry.userEnabled && !fatalApps.has(id));
333
+ }
334
+ // Fixed-point disable propagation: if an enabled app has a required dependency that is missing
335
+ // or effectively disabled, the app becomes effectively disabled.
336
+ let changed = true;
337
+ while (changed) {
338
+ changed = false;
339
+ for (const [appId, entry] of resolvedById.entries()) {
340
+ if (!effectiveEnabledById.get(appId))
341
+ continue;
342
+ if (!entry.userEnabled)
343
+ continue;
344
+ const edges = depsByAppId.get(appId) ?? [];
345
+ for (const edge of edges) {
346
+ if (!edge.required)
347
+ continue;
348
+ const depId = edge.depId;
349
+ const depResolved = resolvedById.get(depId) ?? null;
350
+ const depEnabled = depResolved ? (effectiveEnabledById.get(depId) ?? false) : false;
351
+ const depMissing = !depResolved && missingRequired.has(depId);
352
+ if (depMissing || !depEnabled) {
353
+ effectiveEnabledById.set(appId, false);
354
+ pushIssue({
355
+ kind: 'app_effectively_disabled_due_to_required_dependency',
356
+ severity: 'error',
357
+ message: `App '${appId}' is effectively disabled due to missing/disabled required dependency '${depId}'.`,
358
+ detail: {
359
+ appId,
360
+ dependencyId: depId,
361
+ dependencyState: depMissing
362
+ ? 'missing'
363
+ : depResolved && depResolved.userEnabled === false
364
+ ? 'disabled'
365
+ : 'effectively_disabled',
366
+ },
367
+ });
368
+ changed = true;
369
+ break;
370
+ }
371
+ }
372
+ }
373
+ }
374
+ const assignedPortById = new Map();
375
+ const resolvedEntriesForPort = [...resolvedById.values()];
376
+ for (const [appId, entry] of resolvedById.entries()) {
377
+ if (!effectiveEnabledById.get(appId))
378
+ continue;
379
+ const assigned = await (0, assigned_port_1.resolveStableAssignedPortWithReason)({
380
+ appId,
381
+ installJson: entry.installJson,
382
+ existingApps: resolvedEntriesForPort,
383
+ existingAssignedPort: entry.assignedPort,
384
+ });
385
+ assignedPortById.set(appId, assigned.assignedPort);
386
+ if (assigned.assignedPort !== entry.assignedPort) {
387
+ const nextEntry = { ...entry, assignedPort: assigned.assignedPort };
388
+ resolvedById.set(appId, nextEntry);
389
+ const idx = resolvedEntriesForPort.findIndex((a) => a.id === appId);
390
+ if (idx >= 0) {
391
+ resolvedEntriesForPort[idx] = nextEntry;
392
+ }
393
+ }
394
+ if (assigned.reason === 'reassigned_from_existing_conflict' ||
395
+ assigned.reason === 'reassigned_from_existing_unbindable') {
396
+ pushIssue({
397
+ kind: 'assigned_port_reassigned',
398
+ severity: 'warning',
399
+ message: `App '${appId}' assignedPort was reassigned due to runtime port conflict.`,
400
+ detail: {
401
+ appId,
402
+ previousAssignedPort: entry.assignedPort,
403
+ reassignedToPort: assigned.assignedPort,
404
+ reason: assigned.reason,
405
+ resolutionFileRelPath: resolution_file_1.APPS_RESOLUTION_REL_PATH,
406
+ },
407
+ });
408
+ }
409
+ }
410
+ const out = [];
411
+ for (const [appId, entry] of resolvedById.entries()) {
412
+ if (!effectiveEnabledById.get(appId))
413
+ continue;
414
+ out.push(entry.enabled ? entry : { ...entry, enabled: true });
415
+ }
416
+ return { apps: out, issues, effectiveEnabledById, assignedPortById };
417
+ }
418
+ async function loadAppsResolutionOverlay(params) {
419
+ const filePathAbs = node_path_1.default.resolve(params.rtwsRootAbs, resolution_file_1.APPS_RESOLUTION_REL_PATH);
420
+ const hasResolutionFile = await fileExists(filePathAbs);
421
+ if (!hasResolutionFile) {
422
+ const emptyFile = { schemaVersion: 1, apps: [] };
423
+ return {
424
+ overlay: indexOverlayApps({ overlayApps: [] }),
425
+ resolutionFile: emptyFile,
426
+ strategy: normalizeStrategy(undefined),
427
+ hasResolutionFile,
428
+ };
429
+ }
430
+ const loaded = await (0, resolution_file_1.loadAppsResolutionFile)({ rtwsRootAbs: params.rtwsRootAbs });
431
+ if (loaded.kind === 'error') {
432
+ throw new Error(`Failed to load apps resolution file overlay: ${loaded.errorText} (${loaded.filePathAbs})`);
433
+ }
434
+ return {
435
+ overlay: indexOverlayApps({ overlayApps: loaded.file.apps }),
436
+ resolutionFile: loaded.file,
437
+ strategy: normalizeStrategy(loaded.file.resolutionStrategy),
438
+ hasResolutionFile,
439
+ };
440
+ }
441
+ async function loadEffectiveAppsResolution(params) {
442
+ const loaded = await loadAppsResolutionOverlay({ rtwsRootAbs: params.rtwsRootAbs });
443
+ const resolved = await resolveAppsFromRtwsHierarchy({
444
+ rtwsRootAbs: params.rtwsRootAbs,
445
+ overlay: loaded.overlay,
446
+ strategy: loaded.strategy,
447
+ hasResolutionFile: loaded.hasResolutionFile,
448
+ });
449
+ if (loaded.hasResolutionFile) {
450
+ const withEffectiveEnabled = (0, resolution_file_1.applyEffectiveEnabledToResolvedApps)({
451
+ existing: loaded.resolutionFile,
452
+ effectiveEnabledById: resolved.effectiveEnabledById,
453
+ });
454
+ const nextResolutionFile = (0, resolution_file_1.applyAssignedPortToResolvedApps)({
455
+ existing: withEffectiveEnabled,
456
+ assignedPortById: resolved.assignedPortById,
457
+ });
458
+ if (nextResolutionFile !== loaded.resolutionFile) {
459
+ await (0, resolution_file_1.writeAppsResolutionFileIfChanged)({
460
+ rtwsRootAbs: params.rtwsRootAbs,
461
+ file: nextResolutionFile,
462
+ });
463
+ }
464
+ }
465
+ return { apps: resolved.apps, issues: resolved.issues };
466
+ }
467
+ async function loadEnabledAppsSnapshot(params) {
468
+ const loaded = await loadEffectiveAppsResolution({ rtwsRootAbs: params.rtwsRootAbs });
469
+ const enabledApps = loaded.apps
11
470
  .filter((a) => a.enabled)
12
471
  .map((a) => ({
472
+ // Note: installJson.frontend.defaultPort may be 0 (meaning "runtime decides"); do not pass 0 as runtimePort.
13
473
  id: a.id,
14
- runtimePort: a.runtime.port,
474
+ runtimePort: a.assignedPort ??
475
+ (a.installJson.frontend &&
476
+ a.installJson.frontend.defaultPort &&
477
+ a.installJson.frontend.defaultPort > 0
478
+ ? a.installJson.frontend.defaultPort
479
+ : null),
15
480
  installJson: a.installJson,
16
481
  source: a.source,
17
482
  }));
18
- return { enabledApps };
483
+ return { enabledApps, issues: loaded.issues };
19
484
  }
@@ -15,6 +15,29 @@ function isRecord(v) {
15
15
  function asOptionalString(v) {
16
16
  return typeof v === 'string' ? v : undefined;
17
17
  }
18
+ function asOptionalBool(v) {
19
+ return typeof v === 'boolean' ? v : undefined;
20
+ }
21
+ function parseDependencies(raw, at, filePathAbs) {
22
+ if (!Array.isArray(raw)) {
23
+ return { ok: false, errorText: `Invalid ${at}: expected array (${filePathAbs})` };
24
+ }
25
+ const deps = [];
26
+ for (let i = 0; i < raw.length; i += 1) {
27
+ const item = raw[i];
28
+ const itemAt = `${at}[${i}]`;
29
+ if (!isRecord(item)) {
30
+ return { ok: false, errorText: `Invalid ${itemAt}: expected object (${filePathAbs})` };
31
+ }
32
+ const id = typeof item['id'] === 'string' ? item['id'].trim() : '';
33
+ if (id === '') {
34
+ return { ok: false, errorText: `Invalid ${itemAt}.id: required (${filePathAbs})` };
35
+ }
36
+ const optional = asOptionalBool(item['optional']);
37
+ deps.push({ id, optional });
38
+ }
39
+ return { ok: true, value: deps };
40
+ }
18
41
  function normalizeMountPath(raw) {
19
42
  const trimmed = raw.trim();
20
43
  if (trimmed === '' || trimmed === '/')
@@ -48,6 +71,19 @@ function parseDomindsAppManifest(parsed, filePathAbs) {
48
71
  errorText: `Invalid manifest id: non-empty string required (${filePathAbs})`,
49
72
  };
50
73
  }
74
+ // dependencies
75
+ const depsRaw = parsed['dependencies'];
76
+ const dependencies = (() => {
77
+ if (depsRaw === undefined)
78
+ return undefined;
79
+ const parsedDeps = parseDependencies(depsRaw, 'dependencies', filePathAbs);
80
+ if (!parsedDeps.ok)
81
+ return parsedDeps;
82
+ return { ok: true, value: parsedDeps.value };
83
+ })();
84
+ if (dependencies && !dependencies.ok) {
85
+ return { ok: false, errorText: dependencies.errorText };
86
+ }
51
87
  const contributesRaw = parsed['contributes'];
52
88
  const contributes = (() => {
53
89
  if (contributesRaw === undefined)
@@ -200,6 +236,7 @@ function parseDomindsAppManifest(parsed, filePathAbs) {
200
236
  apiVersion,
201
237
  kind,
202
238
  id,
239
+ dependencies: dependencies ? dependencies.value : undefined,
203
240
  name,
204
241
  description,
205
242
  contributes: contributes ? contributes.value : undefined,
@@ -24,11 +24,11 @@ async function isRegularFile(filePathAbs) {
24
24
  }
25
25
  }
26
26
  /**
27
- * Resolve a workspace override file path for a given app-relative file path.
27
+ * Resolve an app asset override file path for a given app-relative file path.
28
28
  *
29
29
  * Priority order (read-time):
30
30
  * 1) `<rtws>/.apps/override/<app-id>/<rel>`
31
- * 2) `<rtws>/.apps/<app-id>/<rel>` (legacy)
31
+ * 2) `<integrator-app-root>/.apps/override/<app-id>/<rel>` (in provided order)
32
32
  */
33
33
  async function resolveAppOverrideFileAbs(params) {
34
34
  const normalized = normalizeRelNoTraversal(params.appRelPath);
@@ -36,11 +36,24 @@ async function resolveAppOverrideFileAbs(params) {
36
36
  return { kind: 'none' };
37
37
  const preferredAbs = path_1.default.resolve(params.rtwsRootAbs, '.apps', 'override', params.appId, normalized);
38
38
  if (await isRegularFile(preferredAbs)) {
39
- return { kind: 'found', filePathAbs: preferredAbs, source: 'override' };
39
+ return {
40
+ kind: 'found',
41
+ filePathAbs: preferredAbs,
42
+ source: 'rtws_override',
43
+ ownerAppId: null,
44
+ };
40
45
  }
41
- const legacyAbs = path_1.default.resolve(params.rtwsRootAbs, '.apps', params.appId, normalized);
42
- if (await isRegularFile(legacyAbs)) {
43
- return { kind: 'found', filePathAbs: legacyAbs, source: 'legacy_override' };
46
+ const owners = params.appOverrideOwners ?? [];
47
+ for (const owner of owners) {
48
+ const candidateAbs = path_1.default.resolve(owner.packageRootAbs, '.apps', 'override', params.appId, normalized);
49
+ if (await isRegularFile(candidateAbs)) {
50
+ return {
51
+ kind: 'found',
52
+ filePathAbs: candidateAbs,
53
+ source: 'app_override',
54
+ ownerAppId: owner.appId,
55
+ };
56
+ }
44
57
  }
45
58
  return { kind: 'none' };
46
59
  }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reconcileAppsResolutionIssuesToProblems = reconcileAppsResolutionIssuesToProblems;
4
+ const problems_1 = require("../problems");
5
+ const time_1 = require("../shared/utils/time");
6
+ const APPS_PROBLEM_PREFIX = 'apps/apps_resolution/';
7
+ function sanitizeProblemIdSegment(segment) {
8
+ return segment.replace(/[^a-zA-Z0-9_-]/g, '_');
9
+ }
10
+ function asNonEmptyString(v) {
11
+ if (typeof v !== 'string')
12
+ return null;
13
+ const trimmed = v.trim();
14
+ return trimmed === '' ? null : trimmed;
15
+ }
16
+ function buildAppsIssueProblemId(issue) {
17
+ const kindSeg = sanitizeProblemIdSegment(issue.kind);
18
+ const appId = asNonEmptyString(issue.detail['appId']);
19
+ const depId = asNonEmptyString(issue.detail['dependencyId']);
20
+ if (appId && depId) {
21
+ return `${APPS_PROBLEM_PREFIX}${kindSeg}/${sanitizeProblemIdSegment(appId)}/${sanitizeProblemIdSegment(depId)}`;
22
+ }
23
+ if (appId) {
24
+ return `${APPS_PROBLEM_PREFIX}${kindSeg}/${sanitizeProblemIdSegment(appId)}`;
25
+ }
26
+ return `${APPS_PROBLEM_PREFIX}${kindSeg}`;
27
+ }
28
+ function reconcileAppsResolutionIssuesToProblems(params) {
29
+ const now = (0, time_1.formatUnifiedTimestamp)(new Date());
30
+ const desired = [];
31
+ for (const issue of params.issues) {
32
+ desired.push({
33
+ kind: 'generic_problem',
34
+ source: 'system',
35
+ id: buildAppsIssueProblemId(issue),
36
+ severity: issue.severity,
37
+ timestamp: now,
38
+ message: issue.message,
39
+ detail: { text: JSON.stringify(issue.detail, null, 2) },
40
+ });
41
+ }
42
+ (0, problems_1.reconcileProblemsByPrefix)(APPS_PROBLEM_PREFIX, desired);
43
+ }