dominds 1.5.1 → 1.6.0

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 (122) hide show
  1. package/dist/apps/configuration-file.js +21 -0
  2. package/dist/apps/enabled-apps.js +3 -53
  3. package/dist/apps/local-package-root.js +41 -0
  4. package/dist/apps/runtime.js +10 -0
  5. package/dist/apps-host/client.js +124 -1
  6. package/dist/apps-host/host.js +53 -0
  7. package/dist/apps-host/ipc-types.js +61 -1
  8. package/dist/cli/install.js +41 -8
  9. package/dist/dialog-fork.js +7 -6
  10. package/dist/docs/agent-priming.md +38 -0
  11. package/dist/docs/agent-priming.zh.md +34 -0
  12. package/dist/docs/app-constitution.md +22 -0
  13. package/dist/docs/app-constitution.zh.md +22 -0
  14. package/dist/llm/kernel-driver/runtime.js +112 -22
  15. package/dist/llm/kernel-driver/subdialog.js +17 -13
  16. package/dist/llm/kernel-driver/tellask-special.js +8 -7
  17. package/dist/minds/load.js +20 -2
  18. package/dist/minds/system-prompt.js +4 -0
  19. package/dist/persistence.js +48 -24
  20. package/dist/priming.js +153 -43
  21. package/dist/server/websocket-handler.js +5 -0
  22. package/dist/server.js +5 -2
  23. package/dist/shared/markdown-frontmatter.js +44 -0
  24. package/dist/shared/team_mgmt-manual.js +9 -0
  25. package/dist/shared/types/storage.js +77 -0
  26. package/dist/skills/load.js +281 -0
  27. package/dist/static/assets/{_basePickBy-C-nynT9f.js → _basePickBy-CFicLWwx.js} +3 -3
  28. package/dist/static/assets/{_basePickBy-C-nynT9f.js.map → _basePickBy-CFicLWwx.js.map} +1 -1
  29. package/dist/static/assets/{_baseUniq-CiHd-eVT.js → _baseUniq-DQTl8GFk.js} +2 -2
  30. package/dist/static/assets/{_baseUniq-CiHd-eVT.js.map → _baseUniq-DQTl8GFk.js.map} +1 -1
  31. package/dist/static/assets/{arc-_OJzDWy1.js → arc-Bc5lgJ6S.js} +2 -2
  32. package/dist/static/assets/{arc-_OJzDWy1.js.map → arc-Bc5lgJ6S.js.map} +1 -1
  33. package/dist/static/assets/{architectureDiagram-VXUJARFQ-CDEG85ub.js → architectureDiagram-VXUJARFQ-DygUo6iw.js} +7 -7
  34. package/dist/static/assets/{architectureDiagram-VXUJARFQ-CDEG85ub.js.map → architectureDiagram-VXUJARFQ-DygUo6iw.js.map} +1 -1
  35. package/dist/static/assets/{blockDiagram-VD42YOAC-1LzKVc5t.js → blockDiagram-VD42YOAC-0r3VY3gz.js} +7 -7
  36. package/dist/static/assets/{blockDiagram-VD42YOAC-1LzKVc5t.js.map → blockDiagram-VD42YOAC-0r3VY3gz.js.map} +1 -1
  37. package/dist/static/assets/{c4Diagram-YG6GDRKO-BzYnVyvY.js → c4Diagram-YG6GDRKO-pQD_vC1A.js} +3 -3
  38. package/dist/static/assets/{c4Diagram-YG6GDRKO-BzYnVyvY.js.map → c4Diagram-YG6GDRKO-pQD_vC1A.js.map} +1 -1
  39. package/dist/static/assets/{channel-VAEDAk9T.js → channel-CHWYhNRt.js} +2 -2
  40. package/dist/static/assets/{channel-VAEDAk9T.js.map → channel-CHWYhNRt.js.map} +1 -1
  41. package/dist/static/assets/{chunk-4BX2VUAB-D0r2u3mX.js → chunk-4BX2VUAB-K89xP4ET.js} +2 -2
  42. package/dist/static/assets/{chunk-4BX2VUAB-D0r2u3mX.js.map → chunk-4BX2VUAB-K89xP4ET.js.map} +1 -1
  43. package/dist/static/assets/{chunk-55IACEB6-Dkl8Xw7i.js → chunk-55IACEB6-DHAy4AJ-.js} +2 -2
  44. package/dist/static/assets/{chunk-55IACEB6-Dkl8Xw7i.js.map → chunk-55IACEB6-DHAy4AJ-.js.map} +1 -1
  45. package/dist/static/assets/{chunk-B4BG7PRW-9sxsI8ns.js → chunk-B4BG7PRW-BrImUg93.js} +5 -5
  46. package/dist/static/assets/{chunk-B4BG7PRW-9sxsI8ns.js.map → chunk-B4BG7PRW-BrImUg93.js.map} +1 -1
  47. package/dist/static/assets/{chunk-DI55MBZ5-AHaqkaLl.js → chunk-DI55MBZ5-_jVBMKQY.js} +4 -4
  48. package/dist/static/assets/{chunk-DI55MBZ5-AHaqkaLl.js.map → chunk-DI55MBZ5-_jVBMKQY.js.map} +1 -1
  49. package/dist/static/assets/{chunk-FMBD7UC4-NWDLDixD.js → chunk-FMBD7UC4-BmGs24Z_.js} +2 -2
  50. package/dist/static/assets/{chunk-FMBD7UC4-NWDLDixD.js.map → chunk-FMBD7UC4-BmGs24Z_.js.map} +1 -1
  51. package/dist/static/assets/{chunk-QN33PNHL-C2KeUqle.js → chunk-QN33PNHL-Bu8ZzYdl.js} +2 -2
  52. package/dist/static/assets/{chunk-QN33PNHL-C2KeUqle.js.map → chunk-QN33PNHL-Bu8ZzYdl.js.map} +1 -1
  53. package/dist/static/assets/{chunk-QZHKN3VN-B6Eoxo5L.js → chunk-QZHKN3VN-D4fM_-kX.js} +2 -2
  54. package/dist/static/assets/{chunk-QZHKN3VN-B6Eoxo5L.js.map → chunk-QZHKN3VN-D4fM_-kX.js.map} +1 -1
  55. package/dist/static/assets/{chunk-TZMSLE5B-Bc-VyQon.js → chunk-TZMSLE5B-xK6Lo8h6.js} +2 -2
  56. package/dist/static/assets/{chunk-TZMSLE5B-Bc-VyQon.js.map → chunk-TZMSLE5B-xK6Lo8h6.js.map} +1 -1
  57. package/dist/static/assets/{classDiagram-2ON5EDUG-DmPfsN1H.js → classDiagram-2ON5EDUG-Bn36uVsZ.js} +6 -6
  58. package/dist/static/assets/{classDiagram-2ON5EDUG-DmPfsN1H.js.map → classDiagram-2ON5EDUG-Bn36uVsZ.js.map} +1 -1
  59. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-DmPfsN1H.js → classDiagram-v2-WZHVMYZB-Bn36uVsZ.js} +6 -6
  60. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-DmPfsN1H.js.map → classDiagram-v2-WZHVMYZB-Bn36uVsZ.js.map} +1 -1
  61. package/dist/static/assets/{clone-B1R4pLTW.js → clone-BUW9sxY1.js} +2 -2
  62. package/dist/static/assets/{clone-B1R4pLTW.js.map → clone-BUW9sxY1.js.map} +1 -1
  63. package/dist/static/assets/{cose-bilkent-S5V4N54A-CxY__sKv.js → cose-bilkent-S5V4N54A-BMTYUmA4.js} +2 -2
  64. package/dist/static/assets/{cose-bilkent-S5V4N54A-CxY__sKv.js.map → cose-bilkent-S5V4N54A-BMTYUmA4.js.map} +1 -1
  65. package/dist/static/assets/{dagre-6UL2VRFP-CPkB5tQ0.js → dagre-6UL2VRFP-p-0HOF0Q.js} +7 -7
  66. package/dist/static/assets/{dagre-6UL2VRFP-CPkB5tQ0.js.map → dagre-6UL2VRFP-p-0HOF0Q.js.map} +1 -1
  67. package/dist/static/assets/{diagram-PSM6KHXK-C6kCVpCz.js → diagram-PSM6KHXK-CfpXvSJR.js} +8 -8
  68. package/dist/static/assets/{diagram-PSM6KHXK-C6kCVpCz.js.map → diagram-PSM6KHXK-CfpXvSJR.js.map} +1 -1
  69. package/dist/static/assets/{diagram-QEK2KX5R-BWF6htf1.js → diagram-QEK2KX5R-3T4XwT5a.js} +7 -7
  70. package/dist/static/assets/{diagram-QEK2KX5R-BWF6htf1.js.map → diagram-QEK2KX5R-3T4XwT5a.js.map} +1 -1
  71. package/dist/static/assets/{diagram-S2PKOQOG-lKGJH6O9.js → diagram-S2PKOQOG-CPHGTwGV.js} +7 -7
  72. package/dist/static/assets/{diagram-S2PKOQOG-lKGJH6O9.js.map → diagram-S2PKOQOG-CPHGTwGV.js.map} +1 -1
  73. package/dist/static/assets/{erDiagram-Q2GNP2WA-DJ3YaFob.js → erDiagram-Q2GNP2WA-Bj7OGj2H.js} +5 -5
  74. package/dist/static/assets/{erDiagram-Q2GNP2WA-DJ3YaFob.js.map → erDiagram-Q2GNP2WA-Bj7OGj2H.js.map} +1 -1
  75. package/dist/static/assets/{flowDiagram-NV44I4VS-h3eQwA3O.js → flowDiagram-NV44I4VS-DOGilHpN.js} +6 -6
  76. package/dist/static/assets/{flowDiagram-NV44I4VS-h3eQwA3O.js.map → flowDiagram-NV44I4VS-DOGilHpN.js.map} +1 -1
  77. package/dist/static/assets/{ganttDiagram-JELNMOA3-BCbsDOF_.js → ganttDiagram-JELNMOA3-585cSoqi.js} +3 -3
  78. package/dist/static/assets/{ganttDiagram-JELNMOA3-BCbsDOF_.js.map → ganttDiagram-JELNMOA3-585cSoqi.js.map} +1 -1
  79. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-D0kX6h-T.js → gitGraphDiagram-V2S2FVAM-gmTvHjpH.js} +8 -8
  80. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-D0kX6h-T.js.map → gitGraphDiagram-V2S2FVAM-gmTvHjpH.js.map} +1 -1
  81. package/dist/static/assets/{graph-CZIEXp3A.js → graph-Dtj8yklH.js} +3 -3
  82. package/dist/static/assets/{graph-CZIEXp3A.js.map → graph-Dtj8yklH.js.map} +1 -1
  83. package/dist/static/assets/{index-vIzCTZQE.js → index-BvNwR1gS.js} +672 -412
  84. package/dist/static/assets/{index-vIzCTZQE.js.map → index-BvNwR1gS.js.map} +1 -1
  85. package/dist/static/assets/{infoDiagram-HS3SLOUP-DUNbcXxv.js → infoDiagram-HS3SLOUP-BVq8aa78.js} +6 -6
  86. package/dist/static/assets/{infoDiagram-HS3SLOUP-DUNbcXxv.js.map → infoDiagram-HS3SLOUP-BVq8aa78.js.map} +1 -1
  87. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Cg_VhiqB.js → journeyDiagram-XKPGCS4Q-BY5Lcmin.js} +5 -5
  88. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Cg_VhiqB.js.map → journeyDiagram-XKPGCS4Q-BY5Lcmin.js.map} +1 -1
  89. package/dist/static/assets/{kanban-definition-3W4ZIXB7-DMVCZVFE.js → kanban-definition-3W4ZIXB7-zEbpyocs.js} +3 -3
  90. package/dist/static/assets/{kanban-definition-3W4ZIXB7-DMVCZVFE.js.map → kanban-definition-3W4ZIXB7-zEbpyocs.js.map} +1 -1
  91. package/dist/static/assets/{layout-DoKTmwlM.js → layout-Bst5DR3z.js} +5 -5
  92. package/dist/static/assets/{layout-DoKTmwlM.js.map → layout-Bst5DR3z.js.map} +1 -1
  93. package/dist/static/assets/{linear-DFVlPfX6.js → linear-TSyBw4eX.js} +2 -2
  94. package/dist/static/assets/{linear-DFVlPfX6.js.map → linear-TSyBw4eX.js.map} +1 -1
  95. package/dist/static/assets/{mindmap-definition-VGOIOE7T-l5K7agVV.js → mindmap-definition-VGOIOE7T-I6ArhFTa.js} +4 -4
  96. package/dist/static/assets/{mindmap-definition-VGOIOE7T-l5K7agVV.js.map → mindmap-definition-VGOIOE7T-I6ArhFTa.js.map} +1 -1
  97. package/dist/static/assets/{pieDiagram-ADFJNKIX-BfQzSE-A.js → pieDiagram-ADFJNKIX-DdaOCLgH.js} +8 -8
  98. package/dist/static/assets/{pieDiagram-ADFJNKIX-BfQzSE-A.js.map → pieDiagram-ADFJNKIX-DdaOCLgH.js.map} +1 -1
  99. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-CJWvA5jc.js → quadrantDiagram-AYHSOK5B-Bp82x7cE.js} +3 -3
  100. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-CJWvA5jc.js.map → quadrantDiagram-AYHSOK5B-Bp82x7cE.js.map} +1 -1
  101. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-CeBbmqBK.js → requirementDiagram-UZGBJVZJ-eSQPrL7r.js} +4 -4
  102. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-CeBbmqBK.js.map → requirementDiagram-UZGBJVZJ-eSQPrL7r.js.map} +1 -1
  103. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-JeUBTDxx.js → sankeyDiagram-TZEHDZUN-DbMClHuR.js} +2 -2
  104. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-JeUBTDxx.js.map → sankeyDiagram-TZEHDZUN-DbMClHuR.js.map} +1 -1
  105. package/dist/static/assets/{sequenceDiagram-WL72ISMW-Bd_7Pgc5.js → sequenceDiagram-WL72ISMW-CxQHJ2QR.js} +4 -4
  106. package/dist/static/assets/{sequenceDiagram-WL72ISMW-Bd_7Pgc5.js.map → sequenceDiagram-WL72ISMW-CxQHJ2QR.js.map} +1 -1
  107. package/dist/static/assets/{stateDiagram-FKZM4ZOC-D_WyM3K1.js → stateDiagram-FKZM4ZOC-BrJWwcfT.js} +9 -9
  108. package/dist/static/assets/{stateDiagram-FKZM4ZOC-D_WyM3K1.js.map → stateDiagram-FKZM4ZOC-BrJWwcfT.js.map} +1 -1
  109. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-Q_yh26yx.js → stateDiagram-v2-4FDKWEC3-AOoa1rfD.js} +5 -5
  110. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-Q_yh26yx.js.map → stateDiagram-v2-4FDKWEC3-AOoa1rfD.js.map} +1 -1
  111. package/dist/static/assets/{timeline-definition-IT6M3QCI-Ca8mCFDg.js → timeline-definition-IT6M3QCI-CGDQb8vq.js} +3 -3
  112. package/dist/static/assets/{timeline-definition-IT6M3QCI-Ca8mCFDg.js.map → timeline-definition-IT6M3QCI-CGDQb8vq.js.map} +1 -1
  113. package/dist/static/assets/{treemap-GDKQZRPO-CyBvKC8o.js → treemap-GDKQZRPO-DUkGxSl_.js} +5 -5
  114. package/dist/static/assets/{treemap-GDKQZRPO-CyBvKC8o.js.map → treemap-GDKQZRPO-DUkGxSl_.js.map} +1 -1
  115. package/dist/static/assets/{xychartDiagram-PRI3JC2R-DY0BLEdj.js → xychartDiagram-PRI3JC2R-DhC3pydn.js} +3 -3
  116. package/dist/static/assets/{xychartDiagram-PRI3JC2R-DY0BLEdj.js.map → xychartDiagram-PRI3JC2R-DhC3pydn.js.map} +1 -1
  117. package/dist/static/index.html +1 -1
  118. package/dist/team-config-updates.js +26 -0
  119. package/dist/team.js +23 -5
  120. package/dist/tools/team_mgmt.js +137 -0
  121. package/dist/tools/toolset-manual.js +12 -3
  122. package/package.json +1 -1
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.APPS_CONFIGURATION_REL_PATH = exports.DEFAULT_APPS_RESOLUTION_STRATEGY = void 0;
7
7
  exports.parseResolutionStrategy = parseResolutionStrategy;
8
+ exports.normalizeAppsResolutionStrategy = normalizeAppsResolutionStrategy;
8
9
  exports.loadAppsConfigurationFile = loadAppsConfigurationFile;
9
10
  exports.writeAppsConfigurationFile = writeAppsConfigurationFile;
10
11
  exports.writeAppsConfigurationFileIfChanged = writeAppsConfigurationFileIfChanged;
@@ -91,6 +92,26 @@ function parseResolutionStrategy(v, at) {
91
92
  },
92
93
  };
93
94
  }
95
+ function normalizeAppsResolutionStrategy(raw) {
96
+ const order = raw?.order ??
97
+ exports.DEFAULT_APPS_RESOLUTION_STRATEGY.order ??
98
+ ['local'];
99
+ const localRoots = raw?.localRoots ??
100
+ exports.DEFAULT_APPS_RESOLUTION_STRATEGY.localRoots ?? ['dominds-apps'];
101
+ if (order.length === 0) {
102
+ throw new Error(`Invalid ${exports.APPS_CONFIGURATION_REL_PATH}: resolutionStrategy.order must not be empty`);
103
+ }
104
+ if (localRoots.length === 0) {
105
+ throw new Error(`Invalid ${exports.APPS_CONFIGURATION_REL_PATH}: resolutionStrategy.localRoots must not be empty`);
106
+ }
107
+ if (new Set(order).size !== order.length) {
108
+ throw new Error(`Invalid ${exports.APPS_CONFIGURATION_REL_PATH}: resolutionStrategy.order has duplicates`);
109
+ }
110
+ if (new Set(localRoots).size !== localRoots.length) {
111
+ throw new Error(`Invalid ${exports.APPS_CONFIGURATION_REL_PATH}: resolutionStrategy.localRoots has duplicates`);
112
+ }
113
+ return { order, localRoots };
114
+ }
94
115
  function canonicalizeConfigurationFile(file) {
95
116
  const disabledApps = file.disabledApps
96
117
  ? [
@@ -5,11 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.materializeAppsResolution = materializeAppsResolution;
7
7
  exports.loadEnabledAppsSnapshot = loadEnabledAppsSnapshot;
8
- const promises_1 = __importDefault(require("node:fs/promises"));
9
8
  const node_path_1 = __importDefault(require("node:path"));
10
9
  const app_lock_file_1 = require("./app-lock-file");
11
10
  const assigned_port_1 = require("./assigned-port");
12
11
  const configuration_file_1 = require("./configuration-file");
12
+ const local_package_root_1 = require("./local-package-root");
13
13
  const manifest_1 = require("./manifest");
14
14
  const package_info_1 = require("./package-info");
15
15
  const resolution_file_1 = require("./resolution-file");
@@ -20,62 +20,12 @@ function getRuntimePort(entry) {
20
20
  const defaultPort = entry.installJson.frontend?.defaultPort;
21
21
  return typeof defaultPort === 'number' && defaultPort > 0 ? defaultPort : null;
22
22
  }
23
- async function dirExists(dirPathAbs) {
24
- try {
25
- const stat = await promises_1.default.stat(dirPathAbs);
26
- return stat.isDirectory();
27
- }
28
- catch (err) {
29
- const isEnoent = typeof err === 'object' &&
30
- err !== null &&
31
- 'code' in err &&
32
- err.code === 'ENOENT';
33
- if (isEnoent)
34
- return false;
35
- throw err;
36
- }
37
- }
38
- function normalizeStrategy(raw) {
39
- const order = raw?.order ??
40
- configuration_file_1.DEFAULT_APPS_RESOLUTION_STRATEGY.order ??
41
- ['local'];
42
- const localRoots = raw?.localRoots ??
43
- configuration_file_1.DEFAULT_APPS_RESOLUTION_STRATEGY.localRoots ?? ['dominds-apps'];
44
- if (order.length === 0) {
45
- throw new Error(`Invalid ${configuration_file_1.APPS_CONFIGURATION_REL_PATH}: resolutionStrategy.order must not be empty`);
46
- }
47
- if (localRoots.length === 0) {
48
- throw new Error(`Invalid ${configuration_file_1.APPS_CONFIGURATION_REL_PATH}: resolutionStrategy.localRoots must not be empty`);
49
- }
50
- if (new Set(order).size !== order.length) {
51
- throw new Error(`Invalid ${configuration_file_1.APPS_CONFIGURATION_REL_PATH}: resolutionStrategy.order has duplicates`);
52
- }
53
- if (new Set(localRoots).size !== localRoots.length) {
54
- throw new Error(`Invalid ${configuration_file_1.APPS_CONFIGURATION_REL_PATH}: resolutionStrategy.localRoots has duplicates`);
55
- }
56
- return { order, localRoots };
57
- }
58
23
  function getResolutionHint(params) {
59
24
  const filePathAbs = node_path_1.default.resolve(params.rtwsRootAbs, configuration_file_1.APPS_CONFIGURATION_REL_PATH);
60
25
  const action = params.hasConfigurationFile ? 'Edit' : 'Create';
61
26
  return (`${action} ${filePathAbs} to configure 'resolutionStrategy'. ` +
62
27
  `Default local root is 'dominds-apps' (rtws-relative) and expects local apps at '<root>/<appId>/'.`);
63
28
  }
64
- async function resolveLocalAppPackageRootAbs(params) {
65
- const candidates = new Set();
66
- if (params.previousResolutionEntry?.source.kind === 'local') {
67
- candidates.add(params.previousResolutionEntry.source.pathAbs);
68
- }
69
- for (const root of params.localRoots) {
70
- const rootAbs = node_path_1.default.isAbsolute(root) ? root : node_path_1.default.resolve(params.rtwsRootAbs, root);
71
- candidates.add(node_path_1.default.resolve(rootAbs, params.appId));
72
- }
73
- for (const candidateAbs of candidates) {
74
- if (await dirExists(candidateAbs))
75
- return candidateAbs;
76
- }
77
- return null;
78
- }
79
29
  async function loadManifestDepsFromResolvedApp(params) {
80
30
  const pkgInfo = await (0, package_info_1.readPackageInfo)({ packageRootAbs: params.packageRootAbs });
81
31
  const loaded = await (0, manifest_1.loadDomindsAppManifest)({
@@ -103,7 +53,7 @@ function buildNpxSpec(params) {
103
53
  async function probeAppByStrategy(params) {
104
54
  for (const item of params.strategy.order) {
105
55
  if (item === 'local') {
106
- const packageRootAbs = await resolveLocalAppPackageRootAbs({
56
+ const packageRootAbs = await (0, local_package_root_1.resolveLocalAppPackageRootAbs)({
107
57
  rtwsRootAbs: params.rtwsRootAbs,
108
58
  appId: params.appId,
109
59
  localRoots: params.strategy.localRoots,
@@ -426,7 +376,7 @@ async function materializeAppsResolution(params) {
426
376
  }
427
377
  const resolved = await resolveGraph({
428
378
  rtwsRootAbs: params.rtwsRootAbs,
429
- strategy: normalizeStrategy(loadedConfig.file.resolutionStrategy),
379
+ strategy: (0, configuration_file_1.normalizeAppsResolutionStrategy)(loadedConfig.file.resolutionStrategy),
430
380
  configurationDisabledApps: new Set(loadedConfig.file.disabledApps ?? []),
431
381
  previousResolutionById,
432
382
  lockedHintsById,
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveLocalAppPackageRootAbs = resolveLocalAppPackageRootAbs;
7
+ const promises_1 = __importDefault(require("node:fs/promises"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ async function dirExists(dirPathAbs) {
10
+ try {
11
+ const stat = await promises_1.default.stat(dirPathAbs);
12
+ return stat.isDirectory();
13
+ }
14
+ catch (err) {
15
+ const isEnoent = typeof err === 'object' &&
16
+ err !== null &&
17
+ 'code' in err &&
18
+ err.code === 'ENOENT';
19
+ if (isEnoent)
20
+ return false;
21
+ throw err;
22
+ }
23
+ }
24
+ async function resolveLocalAppPackageRootAbs(params) {
25
+ const candidates = new Set();
26
+ const trimmedAppId = params.appId.trim();
27
+ if (trimmedAppId === '')
28
+ return null;
29
+ if (params.previousResolutionEntry?.source.kind === 'local') {
30
+ candidates.add(params.previousResolutionEntry.source.pathAbs);
31
+ }
32
+ for (const root of params.localRoots) {
33
+ const rootAbs = node_path_1.default.isAbsolute(root) ? root : node_path_1.default.resolve(params.rtwsRootAbs, root);
34
+ candidates.add(node_path_1.default.resolve(rootAbs, trimmedAppId));
35
+ }
36
+ for (const candidateAbs of candidates) {
37
+ if (await dirExists(candidateAbs))
38
+ return candidateAbs;
39
+ }
40
+ return null;
41
+ }
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getAppsHostClient = getAppsHostClient;
7
7
  exports.shutdownAppsRuntime = shutdownAppsRuntime;
8
8
  exports.registerEnabledAppsToolProxies = registerEnabledAppsToolProxies;
9
+ exports.listDynamicAppToolsetsForMember = listDynamicAppToolsetsForMember;
9
10
  exports.initAppsRuntime = initAppsRuntime;
10
11
  const crypto_1 = require("crypto");
11
12
  const promises_1 = __importDefault(require("fs/promises"));
@@ -251,6 +252,7 @@ function registerAppArtifacts(app) {
251
252
  dialogId: dlg.id.selfId,
252
253
  rootDialogId: dlg.id.rootId,
253
254
  agentId: dlg.agentId,
255
+ taskDocPath: dlg.taskDocPath,
254
256
  sessionSlug: dlg instanceof dialog_1.SubDialog ? dlg.sessionSlug : undefined,
255
257
  callerId: caller.id,
256
258
  });
@@ -364,6 +366,14 @@ async function registerEnabledAppsToolProxies(params) {
364
366
  refreshQueue = run.catch(() => undefined);
365
367
  await run;
366
368
  }
369
+ async function listDynamicAppToolsetsForMember(_params) {
370
+ await registerEnabledAppsToolProxies({ rtwsRootAbs: _params.rtwsRootAbs });
371
+ const host = await ensureAppsHostReadyForToolCalls();
372
+ return await host.listDynamicToolsets({
373
+ memberId: _params.memberId,
374
+ taskDocPath: _params.taskDocPath,
375
+ });
376
+ }
367
377
  async function initAppsRuntime(params) {
368
378
  appsRuntimeConfig = {
369
379
  rtwsRootAbs: params.rtwsRootAbs,
@@ -18,6 +18,17 @@ function isRecord(v) {
18
18
  function asString(v) {
19
19
  return typeof v === 'string' ? v : null;
20
20
  }
21
+ function asStringArray(v) {
22
+ if (!Array.isArray(v))
23
+ return null;
24
+ const out = [];
25
+ for (const item of v) {
26
+ if (typeof item !== 'string')
27
+ return null;
28
+ out.push(item);
29
+ }
30
+ return out;
31
+ }
21
32
  function parseMessageToKernel(v) {
22
33
  if (!isRecord(v))
23
34
  throw new Error('Invalid IPC message from apps-host: expected object');
@@ -46,6 +57,27 @@ function parseMessageToKernel(v) {
46
57
  throw new Error('Invalid tool_result message: callId required');
47
58
  return v;
48
59
  }
60
+ if (type === 'dynamic_toolsets_result') {
61
+ const callId = asString(v['callId']);
62
+ if (!callId)
63
+ throw new Error('Invalid dynamic_toolsets_result message: callId required');
64
+ const ok = v['ok'];
65
+ if (ok === true) {
66
+ const toolsetIds = asStringArray(v['toolsetIds']);
67
+ if (toolsetIds === null) {
68
+ throw new Error('Invalid dynamic_toolsets_result message: toolsetIds must be string[]');
69
+ }
70
+ return { type, callId, ok: true, toolsetIds };
71
+ }
72
+ if (ok === false) {
73
+ const errorText = asString(v['errorText']);
74
+ if (!errorText) {
75
+ throw new Error('Invalid dynamic_toolsets_result message: errorText required when ok=false');
76
+ }
77
+ return { type, callId, ok: false, errorText };
78
+ }
79
+ return v;
80
+ }
49
81
  if (type === 'reminder_apply_result') {
50
82
  const callId = asString(v['callId']);
51
83
  if (!callId)
@@ -101,6 +133,7 @@ async function startAppsHost(params) {
101
133
  throw new Error('Failed to start apps-host: child process has no IPC channel');
102
134
  }
103
135
  const pendingTools = new Map();
136
+ const pendingDynamicToolsets = new Map();
104
137
  const pendingRunControls = new Map();
105
138
  const pendingReminderApplies = new Map();
106
139
  const pendingReminderUpdates = new Map();
@@ -122,6 +155,11 @@ async function startAppsHost(params) {
122
155
  p.reject(err);
123
156
  }
124
157
  pendingTools.clear();
158
+ for (const p of pendingDynamicToolsets.values()) {
159
+ clearTimeout(p.timeout);
160
+ p.reject(err);
161
+ }
162
+ pendingDynamicToolsets.clear();
125
163
  for (const p of pendingRunControls.values()) {
126
164
  clearTimeout(p.timeout);
127
165
  p.reject(err);
@@ -187,6 +225,20 @@ async function startAppsHost(params) {
187
225
  p.reject(new Error(msg.errorText));
188
226
  return;
189
227
  }
228
+ if (msg.type === 'dynamic_toolsets_result') {
229
+ const p = pendingDynamicToolsets.get(msg.callId);
230
+ if (!p) {
231
+ throw new Error(`Unexpected dynamic_toolsets_result for unknown callId: ${msg.callId}`);
232
+ }
233
+ pendingDynamicToolsets.delete(msg.callId);
234
+ clearTimeout(p.timeout);
235
+ if (!msg.ok) {
236
+ p.reject(new Error(msg.errorText));
237
+ return;
238
+ }
239
+ p.resolve(msg.toolsetIds);
240
+ return;
241
+ }
190
242
  if (msg.type === 'run_control_result') {
191
243
  const p = pendingRunControls.get(msg.callId);
192
244
  if (!p) {
@@ -273,6 +325,25 @@ async function startAppsHost(params) {
273
325
  child.send(msg);
274
326
  });
275
327
  };
328
+ const listDynamicToolsets = async (ctx) => {
329
+ if (!ready) {
330
+ throw new Error('apps-host is not ready yet (dynamicToolsets)');
331
+ }
332
+ const callId = (0, crypto_1.randomUUID)();
333
+ const msg = {
334
+ type: 'dynamic_toolsets',
335
+ callId,
336
+ ctx,
337
+ };
338
+ return await new Promise((resolve, reject) => {
339
+ const timeout = setTimeout(() => {
340
+ pendingDynamicToolsets.delete(callId);
341
+ reject(new Error(`apps-host dynamic toolsets call timed out: callId=${callId}`));
342
+ }, 60000);
343
+ pendingDynamicToolsets.set(callId, { resolve, reject, timeout });
344
+ child.send(msg);
345
+ });
346
+ };
276
347
  const applyRunControl = async (controlId, payload) => {
277
348
  if (!ready) {
278
349
  throw new Error(`apps-host is not ready yet (runControl=${controlId})`);
@@ -358,19 +429,71 @@ async function startAppsHost(params) {
358
429
  });
359
430
  };
360
431
  const shutdown = async () => {
432
+ const awaitChildExit = () => {
433
+ if (child.exitCode !== null || child.signalCode !== null) {
434
+ return Promise.resolve();
435
+ }
436
+ return new Promise((resolve) => {
437
+ let settled = false;
438
+ const cleanup = () => {
439
+ child.off('exit', onExit);
440
+ child.off('error', onError);
441
+ clearTimeout(timeout);
442
+ };
443
+ const finish = () => {
444
+ if (settled)
445
+ return;
446
+ settled = true;
447
+ cleanup();
448
+ resolve();
449
+ };
450
+ const onExit = () => {
451
+ finish();
452
+ };
453
+ const onError = () => {
454
+ finish();
455
+ };
456
+ const timeout = setTimeout(() => {
457
+ try {
458
+ child.kill('SIGTERM');
459
+ }
460
+ catch (err) {
461
+ log.warn('Failed to SIGTERM timed-out apps-host during shutdown', err instanceof Error ? err : new Error(String(err)));
462
+ }
463
+ finish();
464
+ }, 5000);
465
+ child.once('exit', onExit);
466
+ child.once('error', onError);
467
+ });
468
+ };
361
469
  try {
362
470
  child.send({ type: 'shutdown' });
363
471
  }
364
472
  catch (err) {
365
473
  log.warn('Failed to send shutdown to apps-host', err instanceof Error ? err : new Error(String(err)));
474
+ try {
475
+ child.kill('SIGTERM');
476
+ }
477
+ catch (killErr) {
478
+ log.warn('Failed to SIGTERM apps-host after shutdown send failure', killErr instanceof Error ? killErr : new Error(String(killErr)));
479
+ }
366
480
  }
367
481
  failAllPending(new Error('apps-host shutdown'));
482
+ await awaitChildExit();
368
483
  };
369
484
  if (!readyMsg) {
370
485
  throw new Error('apps-host: internal error (readyMsg missing after readyPromise resolved)');
371
486
  }
372
487
  return {
373
- client: { callTool, applyRunControl, applyReminder, updateReminder, renderReminder, shutdown },
488
+ client: {
489
+ callTool,
490
+ listDynamicToolsets,
491
+ applyRunControl,
492
+ applyReminder,
493
+ updateReminder,
494
+ renderReminder,
495
+ shutdown,
496
+ },
374
497
  ready: readyResult,
375
498
  };
376
499
  }
@@ -28,6 +28,9 @@ function isJsonValue(value) {
28
28
  return false;
29
29
  return Object.values(value).every((item) => isJsonValue(item));
30
30
  }
31
+ function isStringArray(value) {
32
+ return Array.isArray(value) && value.every((item) => typeof item === 'string');
33
+ }
31
34
  function isToolCallOutput(value) {
32
35
  if (typeof value === 'string')
33
36
  return true;
@@ -217,6 +220,7 @@ const runningApps = new Map();
217
220
  const toolHandlers = new Map();
218
221
  const runControlHandlers = new Map();
219
222
  const reminderOwnerHandlers = new Map();
223
+ const dynamicToolsetHandlers = new Map();
220
224
  function buildReminderOwnerHandlerKey(appId, ownerRef) {
221
225
  return `${appId}::${ownerRef}`;
222
226
  }
@@ -253,6 +257,10 @@ function validateHostInstance(host, appId) {
253
257
  if (reminderOwners !== undefined && !isRecord(reminderOwners)) {
254
258
  throw new Error(`Invalid app host instance for '${appId}': reminderOwners must be an object`);
255
259
  }
260
+ const dynamicToolsets = host['dynamicToolsets'];
261
+ if (dynamicToolsets !== undefined && typeof dynamicToolsets !== 'function') {
262
+ throw new Error(`Invalid app host instance for '${appId}': dynamicToolsets must be a function`);
263
+ }
256
264
  const toolFns = tools;
257
265
  for (const [name, fn] of Object.entries(toolFns)) {
258
266
  if (typeof fn !== 'function') {
@@ -341,6 +349,9 @@ async function initOnce(msg) {
341
349
  reminderOwnerHandlers.set(handlerKey, { appId, ownerRef, fn });
342
350
  }
343
351
  }
352
+ if (host.dynamicToolsets) {
353
+ dynamicToolsetHandlers.set(appId, host.dynamicToolsets);
354
+ }
344
355
  let frontend = null;
345
356
  if (app.installJson.frontend) {
346
357
  if (!host.start) {
@@ -430,6 +441,48 @@ process.on('message', (raw) => {
430
441
  }
431
442
  return;
432
443
  }
444
+ case 'dynamic_toolsets': {
445
+ try {
446
+ const collected = new Set();
447
+ for (const [appId, handler] of dynamicToolsetHandlers.entries()) {
448
+ try {
449
+ const toolsetIds = await handler(msg.ctx);
450
+ if (!isStringArray(toolsetIds)) {
451
+ throw new Error('dynamicToolsets() must return string[]');
452
+ }
453
+ for (const toolsetId of toolsetIds) {
454
+ if (toolsetId.trim() !== '') {
455
+ collected.add(toolsetId);
456
+ }
457
+ }
458
+ }
459
+ catch (err) {
460
+ send({
461
+ type: 'log',
462
+ level: 'error',
463
+ msg: `dynamic_toolsets failed: ${err instanceof Error ? err.message : String(err)}`,
464
+ appId,
465
+ });
466
+ throw err;
467
+ }
468
+ }
469
+ send({
470
+ type: 'dynamic_toolsets_result',
471
+ callId: msg.callId,
472
+ ok: true,
473
+ toolsetIds: [...collected],
474
+ });
475
+ }
476
+ catch (err) {
477
+ send({
478
+ type: 'dynamic_toolsets_result',
479
+ callId: msg.callId,
480
+ ok: false,
481
+ errorText: err instanceof Error ? err.message : String(err),
482
+ });
483
+ }
484
+ return;
485
+ }
433
486
  case 'run_control_apply': {
434
487
  const found = runControlHandlers.get(msg.controlId);
435
488
  if (!found) {
@@ -158,6 +158,7 @@ function parseAppsHostMessageFromKernel(v) {
158
158
  const dialogId = asString(ctx['dialogId']);
159
159
  const rootDialogId = asString(ctx['rootDialogId']);
160
160
  const agentId = asString(ctx['agentId']);
161
+ const taskDocPath = asString(ctx['taskDocPath']);
161
162
  const sessionSlugRaw = ctx['sessionSlug'];
162
163
  const sessionSlug = sessionSlugRaw === undefined
163
164
  ? undefined
@@ -171,6 +172,8 @@ function parseAppsHostMessageFromKernel(v) {
171
172
  throw new Error('Invalid tool_call message: ctx.rootDialogId required');
172
173
  if (!agentId)
173
174
  throw new Error('Invalid tool_call message: ctx.agentId required');
175
+ if (!taskDocPath)
176
+ throw new Error('Invalid tool_call message: ctx.taskDocPath required');
174
177
  if (sessionSlugRaw !== undefined && !sessionSlug) {
175
178
  throw new Error('Invalid tool_call message: ctx.sessionSlug must be string when present');
176
179
  }
@@ -182,7 +185,64 @@ function parseAppsHostMessageFromKernel(v) {
182
185
  callId,
183
186
  toolName,
184
187
  args: args,
185
- ctx: { dialogId, rootDialogId, agentId, sessionSlug: normalizedSessionSlug, callerId },
188
+ ctx: {
189
+ dialogId,
190
+ rootDialogId,
191
+ agentId,
192
+ taskDocPath,
193
+ sessionSlug: normalizedSessionSlug,
194
+ callerId,
195
+ },
196
+ };
197
+ }
198
+ if (type === 'dynamic_toolsets') {
199
+ const callId = asString(v['callId']);
200
+ const ctx = v['ctx'];
201
+ if (!callId)
202
+ throw new Error('Invalid dynamic_toolsets message: callId required');
203
+ if (!isRecord(ctx))
204
+ throw new Error('Invalid dynamic_toolsets message: ctx must be object');
205
+ const memberId = asString(ctx['memberId']);
206
+ const taskDocPath = asString(ctx['taskDocPath']);
207
+ const dialogIdRaw = ctx['dialogId'];
208
+ const dialogId = dialogIdRaw === undefined ? undefined : asString(dialogIdRaw);
209
+ const rootDialogIdRaw = ctx['rootDialogId'];
210
+ const rootDialogId = rootDialogIdRaw === undefined ? undefined : asString(rootDialogIdRaw);
211
+ const agentIdRaw = ctx['agentId'];
212
+ const agentId = agentIdRaw === undefined ? undefined : asString(agentIdRaw);
213
+ const sessionSlugRaw = ctx['sessionSlug'];
214
+ const sessionSlug = sessionSlugRaw === undefined ? undefined : asString(sessionSlugRaw);
215
+ if (!memberId)
216
+ throw new Error('Invalid dynamic_toolsets message: ctx.memberId required');
217
+ if (!taskDocPath)
218
+ throw new Error('Invalid dynamic_toolsets message: ctx.taskDocPath required');
219
+ if (dialogIdRaw !== undefined && dialogId === null) {
220
+ throw new Error('Invalid dynamic_toolsets message: ctx.dialogId must be string when present');
221
+ }
222
+ if (rootDialogIdRaw !== undefined && rootDialogId === null) {
223
+ throw new Error('Invalid dynamic_toolsets message: ctx.rootDialogId must be string when present');
224
+ }
225
+ if (agentIdRaw !== undefined && agentId === null) {
226
+ throw new Error('Invalid dynamic_toolsets message: ctx.agentId must be string when present');
227
+ }
228
+ if (sessionSlugRaw !== undefined && sessionSlug === null) {
229
+ throw new Error('Invalid dynamic_toolsets message: ctx.sessionSlug must be string when present');
230
+ }
231
+ const normalizedDialogId = dialogId ?? undefined;
232
+ const normalizedRootDialogId = rootDialogId ?? undefined;
233
+ const normalizedAgentId = agentId ?? undefined;
234
+ const normalizedSessionSlug = sessionSlug ?? undefined;
235
+ return {
236
+ type: 'dynamic_toolsets',
237
+ callId,
238
+ ctx: {
239
+ memberId,
240
+ taskDocPath,
241
+ dialogId: normalizedDialogId,
242
+ rootDialogId: normalizedRootDialogId,
243
+ agentId: normalizedAgentId,
244
+ sessionSlug: normalizedSessionSlug,
245
+ },
186
246
  };
187
247
  }
188
248
  if (type === 'reminder_apply') {
@@ -15,6 +15,7 @@ const promises_1 = __importDefault(require("node:fs/promises"));
15
15
  const node_path_1 = __importDefault(require("node:path"));
16
16
  const app_lock_file_1 = require("../apps/app-lock-file");
17
17
  const configuration_file_1 = require("../apps/configuration-file");
18
+ const local_package_root_1 = require("../apps/local-package-root");
18
19
  const manifest_1 = require("../apps/manifest");
19
20
  const resolution_file_1 = require("../apps/resolution-file");
20
21
  const run_app_json_1 = require("../apps/run-app-json");
@@ -83,6 +84,34 @@ async function pathIsDirectory(pathAbs) {
83
84
  return false;
84
85
  }
85
86
  }
87
+ async function resolveInstallSource(params) {
88
+ if (params.treatAsExplicitLocalPath) {
89
+ return { kind: 'local', packageRootAbs: node_path_1.default.resolve(params.rtwsRootAbs, params.specOrPath) };
90
+ }
91
+ const loadedConfig = await (0, configuration_file_1.loadAppsConfigurationFile)({ rtwsRootAbs: params.rtwsRootAbs });
92
+ if (loadedConfig.kind === 'error') {
93
+ throw new Error(`failed to read .apps/configuration.yaml: ${loadedConfig.errorText}`);
94
+ }
95
+ const strategy = (0, configuration_file_1.normalizeAppsResolutionStrategy)(loadedConfig.file.resolutionStrategy);
96
+ for (const item of strategy.order) {
97
+ if (item === 'local') {
98
+ const packageRootAbs = await (0, local_package_root_1.resolveLocalAppPackageRootAbs)({
99
+ rtwsRootAbs: params.rtwsRootAbs,
100
+ appId: params.specOrPath,
101
+ localRoots: strategy.localRoots,
102
+ previousResolutionEntry: null,
103
+ });
104
+ if (packageRootAbs !== null)
105
+ return { kind: 'local', packageRootAbs };
106
+ continue;
107
+ }
108
+ if (item === 'npx')
109
+ return { kind: 'npx', spec: params.specOrPath };
110
+ const exhaustive = item;
111
+ throw new Error(`Unreachable install resolution strategy item: ${String(exhaustive)}`);
112
+ }
113
+ return { kind: 'npx', spec: params.specOrPath };
114
+ }
86
115
  async function main() {
87
116
  const rtwsRootAbs = process.cwd();
88
117
  let args;
@@ -102,10 +131,14 @@ async function main() {
102
131
  return;
103
132
  }
104
133
  const localAbs = node_path_1.default.resolve(rtwsRootAbs, specOrPath);
105
- const shouldUseLocal = args.local || (await pathIsDirectory(localAbs));
106
- const installJson = shouldUseLocal
107
- ? await (0, run_app_json_1.runDomindsAppJsonViaLocalPackage)({ packageRootAbs: localAbs })
108
- : await (0, run_app_json_1.runDomindsAppJsonViaNpx)({ spec: specOrPath, cwdAbs: rtwsRootAbs });
134
+ const installSource = await resolveInstallSource({
135
+ rtwsRootAbs,
136
+ specOrPath,
137
+ treatAsExplicitLocalPath: args.local || (await pathIsDirectory(localAbs)),
138
+ });
139
+ const installJson = installSource.kind === 'local'
140
+ ? await (0, run_app_json_1.runDomindsAppJsonViaLocalPackage)({ packageRootAbs: installSource.packageRootAbs })
141
+ : await (0, run_app_json_1.runDomindsAppJsonViaNpx)({ spec: installSource.spec, cwdAbs: rtwsRootAbs });
109
142
  if (args.idOverride && args.idOverride !== installJson.appId) {
110
143
  console.error(`Error: --id '${args.idOverride}' does not match appId '${installJson.appId}'`);
111
144
  process.exit(1);
@@ -156,7 +189,7 @@ async function main() {
156
189
  },
157
190
  });
158
191
  await (0, app_lock_file_1.writeAppLockFileIfChanged)({ rtwsRootAbs, file: nextLock });
159
- if (shouldUseLocal) {
192
+ if (installSource.kind === 'local') {
160
193
  const loadedResolution = await (0, resolution_file_1.loadAppsResolutionFile)({ rtwsRootAbs });
161
194
  if (loadedResolution.kind === 'error') {
162
195
  console.error(`Error: failed to read .apps/resolution.yaml: ${loadedResolution.errorText}`);
@@ -168,7 +201,7 @@ async function main() {
168
201
  next: {
169
202
  id: installJson.appId,
170
203
  enabled: true,
171
- source: { kind: 'local', pathAbs: localAbs },
204
+ source: { kind: 'local', pathAbs: installSource.packageRootAbs },
172
205
  assignedPort: null,
173
206
  installJson,
174
207
  },
@@ -177,8 +210,8 @@ async function main() {
177
210
  }
178
211
  await (0, workspace_app_state_1.refreshAppsDerivedState)({ rtwsRootAbs });
179
212
  void args.force;
180
- console.log(shouldUseLocal
181
- ? `Installed app '${installJson.appId}' from local package: ${localAbs}`
213
+ console.log(installSource.kind === 'local'
214
+ ? `Installed app '${installJson.appId}' from local package: ${installSource.packageRootAbs}`
182
215
  : `Installed app '${installJson.appId}' via resolver strategy seed: ${specOrPath}`);
183
216
  if (args.enable) {
184
217
  console.log(`Enabled app '${installJson.appId}'`);