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.
- package/dist/agent-priming.js +2051 -0
- package/dist/apps/app-lock-file.js +228 -0
- package/dist/apps/assigned-port.js +124 -0
- package/dist/apps/enabled-apps.js +472 -7
- package/dist/apps/manifest.js +37 -0
- package/dist/apps/override-paths.js +19 -6
- package/dist/apps/problems.js +43 -0
- package/dist/apps/resolution-file.js +370 -0
- package/dist/apps/runtime.js +5 -17
- package/dist/apps/teammates.js +102 -1
- package/dist/cli/disable.js +10 -6
- package/dist/cli/enable.js +21 -19
- package/dist/cli/install.js +40 -18
- package/dist/cli/uninstall.js +6 -6
- package/dist/cli/update.js +38 -13
- package/dist/dialog.js +5 -0
- package/dist/docs/app-constitution.md +85 -18
- package/dist/docs/app-constitution.zh.md +86 -21
- package/dist/docs/dialog-system.md +1 -1
- package/dist/docs/dialog-system.zh.md +1 -1
- package/dist/docs/dominds-agent-priming.md +218 -0
- package/dist/docs/dominds-agent-priming.zh.md +196 -0
- package/dist/docs/drive-logic-context-refactor-plan.zh.md +338 -0
- package/dist/docs/keep-going.md +176 -0
- package/dist/docs/keep-going.zh.md +162 -0
- package/dist/docs/showing-by-doing.md +208 -0
- package/dist/docs/showing-by-doing.zh.md +177 -0
- package/dist/docs/team-mgmt-toolset.md +482 -0
- package/dist/docs/team-mgmt-toolset.zh.md +426 -0
- package/dist/llm/defaults.yaml +1 -1
- package/dist/llm/driver.js +4093 -0
- package/dist/llm/kernel-driver/drive.js +5 -2
- package/dist/llm/kernel-driver/flow.js +3 -0
- package/dist/minds/promptdocs.js +263 -0
- package/dist/problems.js +67 -16
- package/dist/server/api-routes.js +333 -0
- package/dist/server/prompts-routes.js +545 -0
- package/dist/server/server-core.js +4 -0
- package/dist/server/websocket-handler.js +17 -0
- package/dist/shared/team-mgmt-manual.js +120 -0
- package/dist/shared/types/prompts.js +2 -0
- package/dist/shared/types/tellask.js +8 -0
- package/dist/showing-by-doing.js +1091 -0
- package/dist/snippets/README.en.md +3 -0
- package/dist/snippets/README.md +4 -0
- package/dist/static/assets/{_basePickBy-CF9r08iy.js → _basePickBy-BMCtwrV7.js} +3 -3
- package/dist/static/assets/{_basePickBy-CF9r08iy.js.map → _basePickBy-BMCtwrV7.js.map} +1 -1
- package/dist/static/assets/{_baseUniq-CxKv0cd4.js → _baseUniq-BuyCgJiA.js} +2 -2
- package/dist/static/assets/{_baseUniq-CxKv0cd4.js.map → _baseUniq-BuyCgJiA.js.map} +1 -1
- package/dist/static/assets/{arc-C9JyvnlB.js → arc-BDuN8lwA.js} +2 -2
- package/dist/static/assets/{arc-C9JyvnlB.js.map → arc-BDuN8lwA.js.map} +1 -1
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-CpcUgjHf.js → architectureDiagram-VXUJARFQ-C-ekqGAD.js} +7 -7
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-CpcUgjHf.js.map → architectureDiagram-VXUJARFQ-C-ekqGAD.js.map} +1 -1
- package/dist/static/assets/{blockDiagram-VD42YOAC-BA9vtmm7.js → blockDiagram-VD42YOAC-CgQiNuuQ.js} +7 -7
- package/dist/static/assets/{blockDiagram-VD42YOAC-BA9vtmm7.js.map → blockDiagram-VD42YOAC-CgQiNuuQ.js.map} +1 -1
- package/dist/static/assets/{c4Diagram-YG6GDRKO-D49MGNdF.js → c4Diagram-YG6GDRKO-DONC39q-.js} +3 -3
- package/dist/static/assets/{c4Diagram-YG6GDRKO-D49MGNdF.js.map → c4Diagram-YG6GDRKO-DONC39q-.js.map} +1 -1
- package/dist/static/assets/{channel-B4KzL0Kg.js → channel-CJTFwXIG.js} +2 -2
- package/dist/static/assets/{channel-B4KzL0Kg.js.map → channel-CJTFwXIG.js.map} +1 -1
- package/dist/static/assets/{chunk-4BX2VUAB-0F-1ayl0.js → chunk-4BX2VUAB-NaIy4uLJ.js} +2 -2
- package/dist/static/assets/{chunk-4BX2VUAB-0F-1ayl0.js.map → chunk-4BX2VUAB-NaIy4uLJ.js.map} +1 -1
- package/dist/static/assets/{chunk-55IACEB6-Dnl2HDTZ.js → chunk-55IACEB6-JUKI_Ayx.js} +2 -2
- package/dist/static/assets/{chunk-55IACEB6-Dnl2HDTZ.js.map → chunk-55IACEB6-JUKI_Ayx.js.map} +1 -1
- package/dist/static/assets/{chunk-B4BG7PRW-Bhx5RbkQ.js → chunk-B4BG7PRW-dIswFJDn.js} +5 -5
- package/dist/static/assets/{chunk-B4BG7PRW-Bhx5RbkQ.js.map → chunk-B4BG7PRW-dIswFJDn.js.map} +1 -1
- package/dist/static/assets/{chunk-DI55MBZ5-EYd1wL3E.js → chunk-DI55MBZ5-DU2b_N30.js} +4 -4
- package/dist/static/assets/{chunk-DI55MBZ5-EYd1wL3E.js.map → chunk-DI55MBZ5-DU2b_N30.js.map} +1 -1
- package/dist/static/assets/{chunk-FMBD7UC4-DAjkhhUU.js → chunk-FMBD7UC4-BgExcScw.js} +2 -2
- package/dist/static/assets/{chunk-FMBD7UC4-DAjkhhUU.js.map → chunk-FMBD7UC4-BgExcScw.js.map} +1 -1
- package/dist/static/assets/{chunk-QN33PNHL-CK6TY7IE.js → chunk-QN33PNHL-bitxyqh7.js} +2 -2
- package/dist/static/assets/{chunk-QN33PNHL-CK6TY7IE.js.map → chunk-QN33PNHL-bitxyqh7.js.map} +1 -1
- package/dist/static/assets/{chunk-QZHKN3VN-CketngiE.js → chunk-QZHKN3VN-Cor8u7DT.js} +2 -2
- package/dist/static/assets/{chunk-QZHKN3VN-CketngiE.js.map → chunk-QZHKN3VN-Cor8u7DT.js.map} +1 -1
- package/dist/static/assets/{chunk-TZMSLE5B-Bcuvqo45.js → chunk-TZMSLE5B-Aceoxav_.js} +2 -2
- package/dist/static/assets/{chunk-TZMSLE5B-Bcuvqo45.js.map → chunk-TZMSLE5B-Aceoxav_.js.map} +1 -1
- package/dist/static/assets/{classDiagram-2ON5EDUG-CaP4T3r4.js → classDiagram-2ON5EDUG-D1Q6a8Hg.js} +6 -6
- package/dist/static/assets/{classDiagram-2ON5EDUG-CaP4T3r4.js.map → classDiagram-2ON5EDUG-D1Q6a8Hg.js.map} +1 -1
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-CaP4T3r4.js → classDiagram-v2-WZHVMYZB-D1Q6a8Hg.js} +6 -6
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-CaP4T3r4.js.map → classDiagram-v2-WZHVMYZB-D1Q6a8Hg.js.map} +1 -1
- package/dist/static/assets/{clone-C-JULvnG.js → clone-MlWbv1V0.js} +2 -2
- package/dist/static/assets/{clone-C-JULvnG.js.map → clone-MlWbv1V0.js.map} +1 -1
- package/dist/static/assets/{cose-bilkent-S5V4N54A-vXCmi_eC.js → cose-bilkent-S5V4N54A-DWPCXSrn.js} +2 -2
- package/dist/static/assets/{cose-bilkent-S5V4N54A-vXCmi_eC.js.map → cose-bilkent-S5V4N54A-DWPCXSrn.js.map} +1 -1
- package/dist/static/assets/{dagre-6UL2VRFP-bhGzX6kO.js → dagre-6UL2VRFP-C8ptQ9V3.js} +7 -7
- package/dist/static/assets/{dagre-6UL2VRFP-bhGzX6kO.js.map → dagre-6UL2VRFP-C8ptQ9V3.js.map} +1 -1
- package/dist/static/assets/{diagram-PSM6KHXK-BUKfmfGk.js → diagram-PSM6KHXK-Bgf1FqkE.js} +8 -8
- package/dist/static/assets/{diagram-PSM6KHXK-BUKfmfGk.js.map → diagram-PSM6KHXK-Bgf1FqkE.js.map} +1 -1
- package/dist/static/assets/{diagram-QEK2KX5R-DYlq3uFq.js → diagram-QEK2KX5R-BZ5xzofU.js} +7 -7
- package/dist/static/assets/{diagram-QEK2KX5R-DYlq3uFq.js.map → diagram-QEK2KX5R-BZ5xzofU.js.map} +1 -1
- package/dist/static/assets/{diagram-S2PKOQOG-CjxkLHWG.js → diagram-S2PKOQOG-Dwp47T9I.js} +7 -7
- package/dist/static/assets/{diagram-S2PKOQOG-CjxkLHWG.js.map → diagram-S2PKOQOG-Dwp47T9I.js.map} +1 -1
- package/dist/static/assets/{erDiagram-Q2GNP2WA-S3hR85On.js → erDiagram-Q2GNP2WA-Cx4weIHl.js} +5 -5
- package/dist/static/assets/{erDiagram-Q2GNP2WA-S3hR85On.js.map → erDiagram-Q2GNP2WA-Cx4weIHl.js.map} +1 -1
- package/dist/static/assets/{flowDiagram-NV44I4VS-aBmNMuQ0.js → flowDiagram-NV44I4VS-vNUuIeRk.js} +6 -6
- package/dist/static/assets/{flowDiagram-NV44I4VS-aBmNMuQ0.js.map → flowDiagram-NV44I4VS-vNUuIeRk.js.map} +1 -1
- package/dist/static/assets/{ganttDiagram-JELNMOA3-DJxXaiW1.js → ganttDiagram-JELNMOA3-BEfozJAr.js} +3 -3
- package/dist/static/assets/{ganttDiagram-JELNMOA3-DJxXaiW1.js.map → ganttDiagram-JELNMOA3-BEfozJAr.js.map} +1 -1
- package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-DEOBCM0G.js → gitGraphDiagram-V2S2FVAM-eHxwc3d9.js} +8 -8
- package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-DEOBCM0G.js.map → gitGraphDiagram-V2S2FVAM-eHxwc3d9.js.map} +1 -1
- package/dist/static/assets/{graph-DwrKSIE7.js → graph-C6a6uAok.js} +3 -3
- package/dist/static/assets/{graph-DwrKSIE7.js.map → graph-C6a6uAok.js.map} +1 -1
- package/dist/static/assets/{index-HWTRvE2k.js → index-D3TQbAKh.js} +383 -59
- package/dist/static/assets/index-D3TQbAKh.js.map +1 -0
- package/dist/static/assets/{infoDiagram-HS3SLOUP-BH9kVuYd.js → infoDiagram-HS3SLOUP-CX0NiId3.js} +6 -6
- package/dist/static/assets/{infoDiagram-HS3SLOUP-BH9kVuYd.js.map → infoDiagram-HS3SLOUP-CX0NiId3.js.map} +1 -1
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Dap7AcjR.js → journeyDiagram-XKPGCS4Q-C1IepPZ-.js} +5 -5
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Dap7AcjR.js.map → journeyDiagram-XKPGCS4Q-C1IepPZ-.js.map} +1 -1
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-4NOl8MEj.js → kanban-definition-3W4ZIXB7-uMNX4Z1W.js} +3 -3
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-4NOl8MEj.js.map → kanban-definition-3W4ZIXB7-uMNX4Z1W.js.map} +1 -1
- package/dist/static/assets/{layout-D6uIxu1E.js → layout-CpE3kk5z.js} +5 -5
- package/dist/static/assets/{layout-D6uIxu1E.js.map → layout-CpE3kk5z.js.map} +1 -1
- package/dist/static/assets/{linear-CvBOGQA2.js → linear-DV8laXr9.js} +2 -2
- package/dist/static/assets/{linear-CvBOGQA2.js.map → linear-DV8laXr9.js.map} +1 -1
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-ugsrLNY5.js → mindmap-definition-VGOIOE7T-CKjgVM9S.js} +4 -4
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-ugsrLNY5.js.map → mindmap-definition-VGOIOE7T-CKjgVM9S.js.map} +1 -1
- package/dist/static/assets/{pieDiagram-ADFJNKIX-CdVZjM8g.js → pieDiagram-ADFJNKIX-BBonlNyT.js} +8 -8
- package/dist/static/assets/{pieDiagram-ADFJNKIX-CdVZjM8g.js.map → pieDiagram-ADFJNKIX-BBonlNyT.js.map} +1 -1
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-A6m5lZKd.js → quadrantDiagram-AYHSOK5B-BTI8HbBu.js} +3 -3
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-A6m5lZKd.js.map → quadrantDiagram-AYHSOK5B-BTI8HbBu.js.map} +1 -1
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-Cac3zSJH.js → requirementDiagram-UZGBJVZJ-ZtSr9Q5R.js} +4 -4
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-Cac3zSJH.js.map → requirementDiagram-UZGBJVZJ-ZtSr9Q5R.js.map} +1 -1
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DXDdUUl1.js → sankeyDiagram-TZEHDZUN-DibLVGzg.js} +2 -2
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DXDdUUl1.js.map → sankeyDiagram-TZEHDZUN-DibLVGzg.js.map} +1 -1
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-Domsjl5Y.js → sequenceDiagram-WL72ISMW-qXatfzVt.js} +4 -4
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-Domsjl5Y.js.map → sequenceDiagram-WL72ISMW-qXatfzVt.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-Bu0lRQK1.js → stateDiagram-FKZM4ZOC-7fgxCQHo.js} +9 -9
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-Bu0lRQK1.js.map → stateDiagram-FKZM4ZOC-7fgxCQHo.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-D0K-n3ic.js → stateDiagram-v2-4FDKWEC3-DcWlOAnF.js} +5 -5
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-D0K-n3ic.js.map → stateDiagram-v2-4FDKWEC3-DcWlOAnF.js.map} +1 -1
- package/dist/static/assets/{timeline-definition-IT6M3QCI-BGvpddwR.js → timeline-definition-IT6M3QCI-iX2MRdpY.js} +3 -3
- package/dist/static/assets/{timeline-definition-IT6M3QCI-BGvpddwR.js.map → timeline-definition-IT6M3QCI-iX2MRdpY.js.map} +1 -1
- package/dist/static/assets/{treemap-GDKQZRPO-BoOzOm2j.js → treemap-GDKQZRPO-AVRnyXu1.js} +5 -5
- package/dist/static/assets/{treemap-GDKQZRPO-BoOzOm2j.js.map → treemap-GDKQZRPO-AVRnyXu1.js.map} +1 -1
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-C_h3_ICR.js → xychartDiagram-PRI3JC2R-DVYEo5aJ.js} +3 -3
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-C_h3_ICR.js.map → xychartDiagram-PRI3JC2R-DVYEo5aJ.js.map} +1 -1
- package/dist/static/index.html +1 -1
- package/dist/team.js +52 -48
- package/dist/tellask.js +439 -0
- package/dist/tools/context-health.js +177 -0
- package/dist/tools/diag.js +583 -0
- package/dist/tools/fs.js +194 -68
- package/dist/tools/prompts/memory/en/principles.md +13 -5
- package/dist/tools/prompts/memory/en/tools.md +11 -36
- package/dist/tools/prompts/memory/zh/principles.md +18 -8
- package/dist/tools/prompts/memory/zh/tools.md +11 -36
- package/dist/tools/team-mgmt.js +3487 -0
- package/dist/utils/task-doc.js +236 -0
- package/package.json +1 -1
- 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
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
53
|
+
throw new Error(`Failed to load rtws app manifest: ${loaded.errorText} (${loaded.filePathAbs})`);
|
|
9
54
|
}
|
|
10
|
-
|
|
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.
|
|
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
|
}
|
package/dist/apps/manifest.js
CHANGED
|
@@ -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
|
|
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) `<
|
|
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 {
|
|
39
|
+
return {
|
|
40
|
+
kind: 'found',
|
|
41
|
+
filePathAbs: preferredAbs,
|
|
42
|
+
source: 'rtws_override',
|
|
43
|
+
ownerAppId: null,
|
|
44
|
+
};
|
|
40
45
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
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
|
+
}
|