dominds 1.6.3 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dist/apps/installed-file.js +207 -0
  2. package/dist/apps/runtime-port.js +91 -0
  3. package/dist/docs/kernel-app-architecture.md +286 -0
  4. package/dist/docs/kernel-app-architecture.zh.md +285 -0
  5. package/dist/llm/driver-entry.js +28 -0
  6. package/dist/llm/driver-v2/context-health.js +121 -0
  7. package/dist/llm/driver-v2/context.js +56 -0
  8. package/dist/llm/driver-v2/core.js +1545 -0
  9. package/dist/llm/driver-v2/index.js +26 -0
  10. package/dist/llm/driver-v2/orchestrator.js +158 -0
  11. package/dist/llm/driver-v2/policy.js +129 -0
  12. package/dist/llm/driver-v2/restore-dialog-hierarchy.js +73 -0
  13. package/dist/llm/driver-v2/round.js +366 -0
  14. package/dist/llm/driver-v2/runtime-utils.js +365 -0
  15. package/dist/llm/driver-v2/saying-events.js +20 -0
  16. package/dist/llm/driver-v2/subdialog-txn.js +42 -0
  17. package/dist/llm/driver-v2/supdialog-response.js +400 -0
  18. package/dist/llm/driver-v2/tellask-bridge.js +1148 -0
  19. package/dist/llm/driver-v2/types.js +10 -0
  20. package/dist/llm/driver-v2-ref-only/context-health.js +121 -0
  21. package/dist/llm/driver-v2-ref-only/context.js +17 -0
  22. package/dist/llm/driver-v2-ref-only/core.js +1710 -0
  23. package/dist/llm/driver-v2-ref-only/index.js +26 -0
  24. package/dist/llm/driver-v2-ref-only/orchestrator.js +158 -0
  25. package/dist/llm/driver-v2-ref-only/policy.js +129 -0
  26. package/dist/llm/driver-v2-ref-only/restore-dialog-hierarchy.js +73 -0
  27. package/dist/llm/driver-v2-ref-only/round.js +366 -0
  28. package/dist/llm/driver-v2-ref-only/runtime-utils.js +473 -0
  29. package/dist/llm/driver-v2-ref-only/saying-events.js +18 -0
  30. package/dist/llm/driver-v2-ref-only/subdialog-txn.js +42 -0
  31. package/dist/llm/driver-v2-ref-only/supdialog-response.js +453 -0
  32. package/dist/llm/driver-v2-ref-only/tellask-bridge.js +1178 -0
  33. package/dist/llm/driver-v2-ref-only/types.js +10 -0
  34. package/dist/static/assets/{_basePickBy-DSCRdLZO.js → _basePickBy-BI5Rq0uy.js} +3 -3
  35. package/dist/static/assets/{_basePickBy-DSCRdLZO.js.map → _basePickBy-BI5Rq0uy.js.map} +1 -1
  36. package/dist/static/assets/{_baseUniq-4QF_OoKK.js → _baseUniq-B198d-KY.js} +2 -2
  37. package/dist/static/assets/{_baseUniq-4QF_OoKK.js.map → _baseUniq-B198d-KY.js.map} +1 -1
  38. package/dist/static/assets/{arc-BVQeKKx9.js → arc-DaOMBOGX.js} +2 -2
  39. package/dist/static/assets/{arc-BVQeKKx9.js.map → arc-DaOMBOGX.js.map} +1 -1
  40. package/dist/static/assets/{architectureDiagram-VXUJARFQ-B4I8KFTn.js → architectureDiagram-VXUJARFQ-D-S9nnw1.js} +7 -7
  41. package/dist/static/assets/{architectureDiagram-VXUJARFQ-B4I8KFTn.js.map → architectureDiagram-VXUJARFQ-D-S9nnw1.js.map} +1 -1
  42. package/dist/static/assets/{blockDiagram-VD42YOAC-CexS18Qs.js → blockDiagram-VD42YOAC-BTOxO1BR.js} +7 -7
  43. package/dist/static/assets/{blockDiagram-VD42YOAC-CexS18Qs.js.map → blockDiagram-VD42YOAC-BTOxO1BR.js.map} +1 -1
  44. package/dist/static/assets/{c4Diagram-YG6GDRKO-CuSqcxrm.js → c4Diagram-YG6GDRKO-BC30TrOS.js} +3 -3
  45. package/dist/static/assets/{c4Diagram-YG6GDRKO-CuSqcxrm.js.map → c4Diagram-YG6GDRKO-BC30TrOS.js.map} +1 -1
  46. package/dist/static/assets/{channel-BYCxsEk5.js → channel-BxJm9rVf.js} +2 -2
  47. package/dist/static/assets/{channel-BYCxsEk5.js.map → channel-BxJm9rVf.js.map} +1 -1
  48. package/dist/static/assets/{chunk-4BX2VUAB-N8tlmsFc.js → chunk-4BX2VUAB-DZhNVfjS.js} +2 -2
  49. package/dist/static/assets/{chunk-4BX2VUAB-N8tlmsFc.js.map → chunk-4BX2VUAB-DZhNVfjS.js.map} +1 -1
  50. package/dist/static/assets/{chunk-55IACEB6-DxOFWSAF.js → chunk-55IACEB6-CNu24wD5.js} +2 -2
  51. package/dist/static/assets/{chunk-55IACEB6-DxOFWSAF.js.map → chunk-55IACEB6-CNu24wD5.js.map} +1 -1
  52. package/dist/static/assets/{chunk-B4BG7PRW-C1tSyN_l.js → chunk-B4BG7PRW-B4pvVnuq.js} +5 -5
  53. package/dist/static/assets/{chunk-B4BG7PRW-C1tSyN_l.js.map → chunk-B4BG7PRW-B4pvVnuq.js.map} +1 -1
  54. package/dist/static/assets/{chunk-DI55MBZ5-BTmIrFZd.js → chunk-DI55MBZ5-DPtQdiEz.js} +4 -4
  55. package/dist/static/assets/{chunk-DI55MBZ5-BTmIrFZd.js.map → chunk-DI55MBZ5-DPtQdiEz.js.map} +1 -1
  56. package/dist/static/assets/{chunk-FMBD7UC4-s7Uar1x2.js → chunk-FMBD7UC4-BvHbQUmg.js} +2 -2
  57. package/dist/static/assets/{chunk-FMBD7UC4-s7Uar1x2.js.map → chunk-FMBD7UC4-BvHbQUmg.js.map} +1 -1
  58. package/dist/static/assets/{chunk-QN33PNHL-DC20K06j.js → chunk-QN33PNHL-BDzIqYT9.js} +2 -2
  59. package/dist/static/assets/{chunk-QN33PNHL-DC20K06j.js.map → chunk-QN33PNHL-BDzIqYT9.js.map} +1 -1
  60. package/dist/static/assets/{chunk-QZHKN3VN-6mPLLfRu.js → chunk-QZHKN3VN-DCSYTX8L.js} +2 -2
  61. package/dist/static/assets/{chunk-QZHKN3VN-6mPLLfRu.js.map → chunk-QZHKN3VN-DCSYTX8L.js.map} +1 -1
  62. package/dist/static/assets/{chunk-TZMSLE5B-GrDvKWzz.js → chunk-TZMSLE5B-CSzc4mi_.js} +2 -2
  63. package/dist/static/assets/{chunk-TZMSLE5B-GrDvKWzz.js.map → chunk-TZMSLE5B-CSzc4mi_.js.map} +1 -1
  64. package/dist/static/assets/{classDiagram-2ON5EDUG-fO59bj9m.js → classDiagram-2ON5EDUG-CJsEP-fz.js} +6 -6
  65. package/dist/static/assets/{classDiagram-2ON5EDUG-fO59bj9m.js.map → classDiagram-2ON5EDUG-CJsEP-fz.js.map} +1 -1
  66. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-fO59bj9m.js → classDiagram-v2-WZHVMYZB-CJsEP-fz.js} +6 -6
  67. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-fO59bj9m.js.map → classDiagram-v2-WZHVMYZB-CJsEP-fz.js.map} +1 -1
  68. package/dist/static/assets/{clone-IE0Tnwxn.js → clone-CNyZHFPL.js} +2 -2
  69. package/dist/static/assets/{clone-IE0Tnwxn.js.map → clone-CNyZHFPL.js.map} +1 -1
  70. package/dist/static/assets/{cose-bilkent-S5V4N54A-CfeoQnK-.js → cose-bilkent-S5V4N54A-DMvvhmW4.js} +2 -2
  71. package/dist/static/assets/{cose-bilkent-S5V4N54A-CfeoQnK-.js.map → cose-bilkent-S5V4N54A-DMvvhmW4.js.map} +1 -1
  72. package/dist/static/assets/{dagre-6UL2VRFP-DsiyUZhi.js → dagre-6UL2VRFP-BuNhcUpS.js} +7 -7
  73. package/dist/static/assets/{dagre-6UL2VRFP-DsiyUZhi.js.map → dagre-6UL2VRFP-BuNhcUpS.js.map} +1 -1
  74. package/dist/static/assets/{diagram-PSM6KHXK-IAjJ50CC.js → diagram-PSM6KHXK-D0APVthl.js} +8 -8
  75. package/dist/static/assets/{diagram-PSM6KHXK-IAjJ50CC.js.map → diagram-PSM6KHXK-D0APVthl.js.map} +1 -1
  76. package/dist/static/assets/{diagram-QEK2KX5R-DiZLndjJ.js → diagram-QEK2KX5R-_TJXK1XR.js} +7 -7
  77. package/dist/static/assets/{diagram-QEK2KX5R-DiZLndjJ.js.map → diagram-QEK2KX5R-_TJXK1XR.js.map} +1 -1
  78. package/dist/static/assets/{diagram-S2PKOQOG-ZL3Kts-u.js → diagram-S2PKOQOG-D58YgxwF.js} +7 -7
  79. package/dist/static/assets/{diagram-S2PKOQOG-ZL3Kts-u.js.map → diagram-S2PKOQOG-D58YgxwF.js.map} +1 -1
  80. package/dist/static/assets/{erDiagram-Q2GNP2WA-DbVLZtGY.js → erDiagram-Q2GNP2WA-DoStgM_4.js} +5 -5
  81. package/dist/static/assets/{erDiagram-Q2GNP2WA-DbVLZtGY.js.map → erDiagram-Q2GNP2WA-DoStgM_4.js.map} +1 -1
  82. package/dist/static/assets/{flowDiagram-NV44I4VS-CVd2p2Br.js → flowDiagram-NV44I4VS-CjRvEre8.js} +6 -6
  83. package/dist/static/assets/{flowDiagram-NV44I4VS-CVd2p2Br.js.map → flowDiagram-NV44I4VS-CjRvEre8.js.map} +1 -1
  84. package/dist/static/assets/{ganttDiagram-JELNMOA3-6NsYNEcf.js → ganttDiagram-JELNMOA3-BUTAh-bt.js} +3 -3
  85. package/dist/static/assets/{ganttDiagram-JELNMOA3-6NsYNEcf.js.map → ganttDiagram-JELNMOA3-BUTAh-bt.js.map} +1 -1
  86. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-B0Y7WTbj.js → gitGraphDiagram-V2S2FVAM-jNkE61r9.js} +8 -8
  87. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-B0Y7WTbj.js.map → gitGraphDiagram-V2S2FVAM-jNkE61r9.js.map} +1 -1
  88. package/dist/static/assets/{graph-BE1Fw6SE.js → graph-CCjti2O0.js} +3 -3
  89. package/dist/static/assets/{graph-BE1Fw6SE.js.map → graph-CCjti2O0.js.map} +1 -1
  90. package/dist/static/assets/{index-1Tlt2ebA.js → index-DLmfFirx.js} +328 -320
  91. package/dist/static/assets/index-DLmfFirx.js.map +1 -0
  92. package/dist/static/assets/{infoDiagram-HS3SLOUP-p6CQsk4A.js → infoDiagram-HS3SLOUP-BFxdxbX3.js} +6 -6
  93. package/dist/static/assets/{infoDiagram-HS3SLOUP-p6CQsk4A.js.map → infoDiagram-HS3SLOUP-BFxdxbX3.js.map} +1 -1
  94. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-DR4cvYtN.js → journeyDiagram-XKPGCS4Q-BCLnxPc7.js} +5 -5
  95. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-DR4cvYtN.js.map → journeyDiagram-XKPGCS4Q-BCLnxPc7.js.map} +1 -1
  96. package/dist/static/assets/{kanban-definition-3W4ZIXB7-JPOdtj9o.js → kanban-definition-3W4ZIXB7-BDeqtjCx.js} +3 -3
  97. package/dist/static/assets/{kanban-definition-3W4ZIXB7-JPOdtj9o.js.map → kanban-definition-3W4ZIXB7-BDeqtjCx.js.map} +1 -1
  98. package/dist/static/assets/{layout-BOn5O0Mv.js → layout-BcSBhjCx.js} +5 -5
  99. package/dist/static/assets/{layout-BOn5O0Mv.js.map → layout-BcSBhjCx.js.map} +1 -1
  100. package/dist/static/assets/{linear-BVAPTXI-.js → linear-yE500fJs.js} +2 -2
  101. package/dist/static/assets/{linear-BVAPTXI-.js.map → linear-yE500fJs.js.map} +1 -1
  102. package/dist/static/assets/{mindmap-definition-VGOIOE7T-DUJXw6w6.js → mindmap-definition-VGOIOE7T-B7T5bXb-.js} +4 -4
  103. package/dist/static/assets/{mindmap-definition-VGOIOE7T-DUJXw6w6.js.map → mindmap-definition-VGOIOE7T-B7T5bXb-.js.map} +1 -1
  104. package/dist/static/assets/{pieDiagram-ADFJNKIX-76JJOJvZ.js → pieDiagram-ADFJNKIX-CWFbaJ0k.js} +8 -8
  105. package/dist/static/assets/{pieDiagram-ADFJNKIX-76JJOJvZ.js.map → pieDiagram-ADFJNKIX-CWFbaJ0k.js.map} +1 -1
  106. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-iKXJUo4i.js → quadrantDiagram-AYHSOK5B-DNdamKCt.js} +3 -3
  107. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-iKXJUo4i.js.map → quadrantDiagram-AYHSOK5B-DNdamKCt.js.map} +1 -1
  108. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-B0uk_5yk.js → requirementDiagram-UZGBJVZJ-Ct8UB1vk.js} +4 -4
  109. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-B0uk_5yk.js.map → requirementDiagram-UZGBJVZJ-Ct8UB1vk.js.map} +1 -1
  110. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-O3weNg52.js → sankeyDiagram-TZEHDZUN-DC7E0Ymo.js} +2 -2
  111. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-O3weNg52.js.map → sankeyDiagram-TZEHDZUN-DC7E0Ymo.js.map} +1 -1
  112. package/dist/static/assets/{sequenceDiagram-WL72ISMW-DFnXuPNE.js → sequenceDiagram-WL72ISMW-IiC8_KXA.js} +4 -4
  113. package/dist/static/assets/{sequenceDiagram-WL72ISMW-DFnXuPNE.js.map → sequenceDiagram-WL72ISMW-IiC8_KXA.js.map} +1 -1
  114. package/dist/static/assets/{stateDiagram-FKZM4ZOC-BZjZXttD.js → stateDiagram-FKZM4ZOC-CCJb2r9z.js} +9 -9
  115. package/dist/static/assets/{stateDiagram-FKZM4ZOC-BZjZXttD.js.map → stateDiagram-FKZM4ZOC-CCJb2r9z.js.map} +1 -1
  116. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-C_R3IF0y.js → stateDiagram-v2-4FDKWEC3-BvHtU6GE.js} +5 -5
  117. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-C_R3IF0y.js.map → stateDiagram-v2-4FDKWEC3-BvHtU6GE.js.map} +1 -1
  118. package/dist/static/assets/{timeline-definition-IT6M3QCI-Kkhw0x0F.js → timeline-definition-IT6M3QCI-Bn2Z-SBO.js} +3 -3
  119. package/dist/static/assets/{timeline-definition-IT6M3QCI-Kkhw0x0F.js.map → timeline-definition-IT6M3QCI-Bn2Z-SBO.js.map} +1 -1
  120. package/dist/static/assets/{treemap-GDKQZRPO-DCcRUg7I.js → treemap-GDKQZRPO-BQopYfN_.js} +5 -5
  121. package/dist/static/assets/{treemap-GDKQZRPO-DCcRUg7I.js.map → treemap-GDKQZRPO-BQopYfN_.js.map} +1 -1
  122. package/dist/static/assets/{xychartDiagram-PRI3JC2R-DQKFjqLB.js → xychartDiagram-PRI3JC2R-CsLeQwkI.js} +3 -3
  123. package/dist/static/assets/{xychartDiagram-PRI3JC2R-DQKFjqLB.js.map → xychartDiagram-PRI3JC2R-CsLeQwkI.js.map} +1 -1
  124. package/dist/static/index.html +1 -1
  125. package/dist/tools/prompts/memory/en/errors.md +155 -0
  126. package/dist/tools/prompts/memory/en/index.md +47 -0
  127. package/dist/tools/prompts/memory/en/principles.md +79 -0
  128. package/dist/tools/prompts/memory/en/scenarios.md +174 -0
  129. package/dist/tools/prompts/memory/en/tools.md +154 -0
  130. package/dist/tools/prompts/memory/zh/errors.md +155 -0
  131. package/dist/tools/prompts/memory/zh/index.md +47 -0
  132. package/dist/tools/prompts/memory/zh/principles.md +79 -0
  133. package/dist/tools/prompts/memory/zh/scenarios.md +174 -0
  134. package/dist/tools/prompts/memory/zh/tools.md +154 -0
  135. package/package.json +1 -1
  136. package/dist/static/assets/index-1Tlt2ebA.js.map +0 -1
@@ -0,0 +1,207 @@
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.INSTALLED_APPS_REL_PATH = void 0;
7
+ exports.loadInstalledAppsFile = loadInstalledAppsFile;
8
+ exports.writeInstalledAppsFile = writeInstalledAppsFile;
9
+ exports.upsertInstalledApp = upsertInstalledApp;
10
+ exports.removeInstalledApp = removeInstalledApp;
11
+ exports.setAppEnabled = setAppEnabled;
12
+ exports.setAppRuntimePort = setAppRuntimePort;
13
+ exports.findInstalledApp = findInstalledApp;
14
+ const promises_1 = __importDefault(require("fs/promises"));
15
+ const path_1 = __importDefault(require("path"));
16
+ const yaml_1 = __importDefault(require("yaml"));
17
+ const time_1 = require("../shared/utils/time");
18
+ exports.INSTALLED_APPS_REL_PATH = path_1.default.join('.apps', 'installed.yaml');
19
+ function isRecord(v) {
20
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
21
+ }
22
+ function asString(v) {
23
+ return typeof v === 'string' ? v : null;
24
+ }
25
+ function asBool(v) {
26
+ return typeof v === 'boolean' ? v : null;
27
+ }
28
+ function asNullableNumber(v) {
29
+ if (v === null)
30
+ return null;
31
+ if (typeof v === 'number' && Number.isFinite(v))
32
+ return v;
33
+ return null;
34
+ }
35
+ function parseSource(v, at) {
36
+ if (!isRecord(v))
37
+ return { ok: false, errorText: `Invalid ${at}: expected object` };
38
+ const kind = asString(v['kind']);
39
+ if (kind !== 'npx' && kind !== 'local') {
40
+ return { ok: false, errorText: `Invalid ${at}.kind: expected 'npx'|'local'` };
41
+ }
42
+ if (kind === 'npx') {
43
+ const spec = asString(v['spec']);
44
+ if (!spec || spec.trim() === '')
45
+ return { ok: false, errorText: `Invalid ${at}.spec: required` };
46
+ return { ok: true, source: { kind, spec } };
47
+ }
48
+ const pathAbs = asString(v['pathAbs']);
49
+ if (!pathAbs || pathAbs.trim() === '')
50
+ return { ok: false, errorText: `Invalid ${at}.pathAbs: required` };
51
+ return { ok: true, source: { kind, pathAbs } };
52
+ }
53
+ function parseRuntime(v, at) {
54
+ if (!isRecord(v))
55
+ return { ok: false, errorText: `Invalid ${at}: expected object` };
56
+ const portRaw = v['port'];
57
+ const port = asNullableNumber(portRaw);
58
+ if (port === null) {
59
+ if (portRaw !== null) {
60
+ return { ok: false, errorText: `Invalid ${at}.port: expected number|null` };
61
+ }
62
+ return { ok: true, runtime: { port: null } };
63
+ }
64
+ if (port < 0 || !Number.isInteger(port))
65
+ return { ok: false, errorText: `Invalid ${at}.port: expected non-negative integer|null` };
66
+ return { ok: true, runtime: { port: port } };
67
+ }
68
+ function parseEntry(v, at) {
69
+ if (!isRecord(v))
70
+ return { ok: false, errorText: `Invalid ${at}: expected object` };
71
+ const id = asString(v['id']);
72
+ if (!id || id.trim() === '')
73
+ return { ok: false, errorText: `Invalid ${at}.id: required` };
74
+ const enabled = asBool(v['enabled']);
75
+ if (enabled === null)
76
+ return { ok: false, errorText: `Invalid ${at}.enabled: boolean required` };
77
+ const installedAt = asString(v['installedAt']);
78
+ const updatedAt = asString(v['updatedAt']);
79
+ if (!installedAt || installedAt.trim() === '')
80
+ return { ok: false, errorText: `Invalid ${at}.installedAt: required` };
81
+ if (!updatedAt || updatedAt.trim() === '')
82
+ return { ok: false, errorText: `Invalid ${at}.updatedAt: required` };
83
+ const sourceParsed = parseSource(v['source'], `${at}.source`);
84
+ if (!sourceParsed.ok)
85
+ return sourceParsed;
86
+ const runtimeParsed = parseRuntime(v['runtime'] ?? { port: null }, `${at}.runtime`);
87
+ if (!runtimeParsed.ok)
88
+ return runtimeParsed;
89
+ // installJson is validated by install/update command on write. On read we keep permissive:
90
+ // kernel will fail fast later if it needs a missing field.
91
+ const installJson = v['installJson'];
92
+ if (!isRecord(installJson))
93
+ return { ok: false, errorText: `Invalid ${at}.installJson: expected object` };
94
+ return {
95
+ ok: true,
96
+ entry: {
97
+ id,
98
+ enabled,
99
+ source: sourceParsed.source,
100
+ runtime: runtimeParsed.runtime,
101
+ installJson: installJson,
102
+ installedAt,
103
+ updatedAt,
104
+ },
105
+ };
106
+ }
107
+ async function loadInstalledAppsFile(params) {
108
+ const filePathAbs = path_1.default.resolve(params.rtwsRootAbs, exports.INSTALLED_APPS_REL_PATH);
109
+ let raw;
110
+ try {
111
+ raw = await promises_1.default.readFile(filePathAbs, 'utf-8');
112
+ }
113
+ catch (err) {
114
+ const isEnoent = typeof err === 'object' &&
115
+ err !== null &&
116
+ 'code' in err &&
117
+ err.code === 'ENOENT';
118
+ if (isEnoent) {
119
+ return { kind: 'ok', filePathAbs, file: { schemaVersion: 1, apps: [] } };
120
+ }
121
+ return {
122
+ kind: 'error',
123
+ filePathAbs,
124
+ errorText: err instanceof Error ? err.message : String(err),
125
+ };
126
+ }
127
+ let parsed;
128
+ try {
129
+ parsed = yaml_1.default.parse(raw);
130
+ }
131
+ catch (err) {
132
+ return {
133
+ kind: 'error',
134
+ filePathAbs,
135
+ errorText: `Failed to parse YAML: ${err instanceof Error ? err.message : String(err)}`,
136
+ };
137
+ }
138
+ if (!isRecord(parsed)) {
139
+ return { kind: 'error', filePathAbs, errorText: 'Invalid installed.yaml: expected object' };
140
+ }
141
+ const schemaVersion = parsed['schemaVersion'];
142
+ if (schemaVersion !== 1) {
143
+ return {
144
+ kind: 'error',
145
+ filePathAbs,
146
+ errorText: `Unsupported schemaVersion: ${String(schemaVersion)}`,
147
+ };
148
+ }
149
+ const appsRaw = parsed['apps'];
150
+ if (!Array.isArray(appsRaw)) {
151
+ return {
152
+ kind: 'error',
153
+ filePathAbs,
154
+ errorText: 'Invalid installed.yaml: apps must be an array',
155
+ };
156
+ }
157
+ const apps = [];
158
+ for (let i = 0; i < appsRaw.length; i += 1) {
159
+ const e = parseEntry(appsRaw[i], `apps[${i}]`);
160
+ if (!e.ok)
161
+ return { kind: 'error', filePathAbs, errorText: e.errorText };
162
+ apps.push(e.entry);
163
+ }
164
+ return { kind: 'ok', filePathAbs, file: { schemaVersion: 1, apps } };
165
+ }
166
+ async function writeInstalledAppsFile(params) {
167
+ const dirAbs = path_1.default.resolve(params.rtwsRootAbs, '.apps');
168
+ await promises_1.default.mkdir(dirAbs, { recursive: true });
169
+ const filePathAbs = path_1.default.resolve(params.rtwsRootAbs, exports.INSTALLED_APPS_REL_PATH);
170
+ const yamlText = yaml_1.default.stringify(params.file);
171
+ await promises_1.default.writeFile(filePathAbs, yamlText, 'utf-8');
172
+ }
173
+ function upsertInstalledApp(params) {
174
+ const apps = [...params.existing.apps];
175
+ const idx = apps.findIndex((a) => a.id === params.next.id);
176
+ if (idx >= 0) {
177
+ apps[idx] = params.next;
178
+ }
179
+ else {
180
+ apps.push(params.next);
181
+ }
182
+ return { schemaVersion: 1, apps };
183
+ }
184
+ function removeInstalledApp(params) {
185
+ return { schemaVersion: 1, apps: params.existing.apps.filter((a) => a.id !== params.appId) };
186
+ }
187
+ function setAppEnabled(params) {
188
+ const now = (0, time_1.formatUnifiedTimestamp)(new Date());
189
+ const apps = params.existing.apps.map((a) => a.id === params.appId ? { ...a, enabled: params.enabled, updatedAt: now } : a);
190
+ return { schemaVersion: 1, apps };
191
+ }
192
+ function setAppRuntimePort(params) {
193
+ const existingApp = findInstalledApp(params.existing, params.appId);
194
+ if (!existingApp)
195
+ return params.existing;
196
+ if (existingApp.runtime.port === params.port)
197
+ return params.existing;
198
+ const now = (0, time_1.formatUnifiedTimestamp)(new Date());
199
+ const apps = params.existing.apps.map((a) => a.id === params.appId
200
+ ? { ...a, runtime: { ...a.runtime, port: params.port }, updatedAt: now }
201
+ : a);
202
+ return { schemaVersion: 1, apps };
203
+ }
204
+ function findInstalledApp(file, appId) {
205
+ const found = file.apps.find((a) => a.id === appId);
206
+ return found ?? null;
207
+ }
@@ -0,0 +1,91 @@
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.resolveStableAppRuntimePort = resolveStableAppRuntimePort;
7
+ const node_net_1 = __importDefault(require("node:net"));
8
+ const STABLE_PORT_RANGE_START = 43000;
9
+ const STABLE_PORT_RANGE_END = 49999;
10
+ const PORT_MAX = 65535;
11
+ function isPositivePort(value) {
12
+ return (typeof value === 'number' &&
13
+ Number.isInteger(value) &&
14
+ value > 0 &&
15
+ value <= PORT_MAX &&
16
+ Number.isFinite(value));
17
+ }
18
+ function hashAppId(appId) {
19
+ // FNV-1a 32-bit hash for deterministic port probing order.
20
+ let hash = 0x811c9dc5;
21
+ for (let i = 0; i < appId.length; i += 1) {
22
+ hash ^= appId.charCodeAt(i);
23
+ hash = Math.imul(hash, 0x01000193);
24
+ }
25
+ return hash >>> 0;
26
+ }
27
+ function collectReservedPorts(existingApps, appId) {
28
+ const reserved = new Set();
29
+ for (const app of existingApps) {
30
+ if (app.id === appId)
31
+ continue;
32
+ if (isPositivePort(app.runtime.port)) {
33
+ reserved.add(app.runtime.port);
34
+ }
35
+ }
36
+ return reserved;
37
+ }
38
+ async function canBindPort(port) {
39
+ return await new Promise((resolve) => {
40
+ const server = node_net_1.default.createServer();
41
+ server.unref();
42
+ const finish = (ok) => {
43
+ server.removeAllListeners('error');
44
+ server.removeAllListeners('listening');
45
+ resolve(ok);
46
+ };
47
+ server.once('error', () => {
48
+ finish(false);
49
+ });
50
+ server.once('listening', () => {
51
+ server.close(() => finish(true));
52
+ });
53
+ server.listen({ host: '127.0.0.1', port, exclusive: true });
54
+ });
55
+ }
56
+ async function pickDeterministicAvailablePort(params) {
57
+ const rangeSize = STABLE_PORT_RANGE_END - STABLE_PORT_RANGE_START + 1;
58
+ if (rangeSize <= 0) {
59
+ throw new Error('Invalid stable app runtime port range configuration');
60
+ }
61
+ const baseHash = hashAppId(params.appId);
62
+ for (let i = 0; i < rangeSize; i += 1) {
63
+ const candidate = STABLE_PORT_RANGE_START + ((baseHash + i) % rangeSize);
64
+ if (params.reservedPorts.has(candidate))
65
+ continue;
66
+ if (await canBindPort(candidate))
67
+ return candidate;
68
+ }
69
+ throw new Error(`Failed to allocate stable runtime port for app '${params.appId}': no bindable port in ${STABLE_PORT_RANGE_START}-${STABLE_PORT_RANGE_END}`);
70
+ }
71
+ async function resolveStableAppRuntimePort(params) {
72
+ if (!params.installJson.frontend)
73
+ return null;
74
+ const reservedPorts = collectReservedPorts(params.existingApps, params.appId);
75
+ if (isPositivePort(params.existingRuntimePort)) {
76
+ if (reservedPorts.has(params.existingRuntimePort)) {
77
+ throw new Error(`Invalid installed apps state: runtime port ${params.existingRuntimePort} for '${params.appId}' collides with another installed app`);
78
+ }
79
+ return params.existingRuntimePort;
80
+ }
81
+ const defaultPort = params.installJson.frontend.defaultPort;
82
+ if (isPositivePort(defaultPort) &&
83
+ !reservedPorts.has(defaultPort) &&
84
+ (await canBindPort(defaultPort))) {
85
+ return defaultPort;
86
+ }
87
+ return await pickDeterministicAvailablePort({
88
+ appId: params.appId,
89
+ reservedPorts,
90
+ });
91
+ }
@@ -0,0 +1,286 @@
1
+ # Kernel–App Architecture (Prototype v0.1)
2
+
3
+ Chinese version: [中文版](./kernel-app-architecture.zh.md)
4
+
5
+ ## Scope and Goals
6
+
7
+ This document describes the Kernel–App separation prototype in Dominds, covering:
8
+
9
+ - Two-level namespace (kernel outer / app inner) and resolution rules
10
+ - App install json (`app --json`) extensions
11
+ - Export/import semantics and conflict handling
12
+ - App defunc semantics
13
+ - App integration manual (`app_integration_manual`)
14
+ - App language policy (work/ui language and i18n)
15
+ - Incremental override DSL for `<rtws>/.apps/<app-id>/team.yaml`
16
+
17
+ The prototype code is used for **concept and functional validation**. This document is the main artifact for “driving the integrated plan forward” (stable reference for implementation/migration/review).
18
+
19
+ ## Non-goals
20
+
21
+ - No protocol/schema versioning or compatibility strategy before 2.x
22
+ - No sandbox isolation before 2.x
23
+ - Run-control expansion is out of scope (will be specified in a dedicated doc)
24
+
25
+ ## Core Concepts
26
+
27
+ - Kernel registry stays in the current Dominds state; built-in capabilities will gradually move out to apps.
28
+ - Each app owns its own registry, **local-first, same-name override allowed**.
29
+ - Apps do not register objects into the kernel registry.
30
+ - Apps are isolated from each other; exchange only via explicit export/import.
31
+
32
+ ## Identity and Resolution
33
+
34
+ ### Namespaces
35
+
36
+ - Two-level scope: `kernel` and `app`.
37
+ - For runtime resolution, short IDs (e.g. `toolsetId`, `memberId`, `toolName`) follow current kernel conventions.
38
+ - For logs/diagnostics/Problems/docs, we need a stable, source-qualified identifier, so we introduce **Qualified Id** (display/diagnostics only; not forced into the wire protocol):
39
+ - `kernel:<name>`
40
+ - `app:<appId>:<name>`
41
+
42
+ ### Resolution order (inside an app)
43
+
44
+ For any resolution request (tool/toolset/member), the order is fixed:
45
+
46
+ 1. `local(app)` (app self-registered + imported objects)
47
+ 2. `kernel`
48
+
49
+ Notes:
50
+
51
+ - “Same-name override allowed” only applies when `local(app)` overrides `kernel`.
52
+ - Apps never override each other; if imports create same-name conflicts inside `local(app)`, the app becomes defunc.
53
+
54
+ ## App install json (`app --json`)
55
+
56
+ Add fields to `DomindsAppInstallJsonV1`:
57
+
58
+ - `depends?: [{ appId: string; versionRange: string }]`
59
+ - `exports?: { members?: string[]; toolsets?: string[] }`
60
+
61
+ Rules:
62
+
63
+ - Empty `exports` means nothing is importable.
64
+ - `exports` only lists **single member / single toolset** IDs (fixed granularity).
65
+ - `exports` may list multiple objects, but the minimal import unit is fixed to **a single member / a single toolset** (each import points to exactly one ID).
66
+ - Exported members must come from `contributes.teammatesYamlRelPath`.
67
+ - Exported toolsets must come from `contributes.toolsets`.
68
+
69
+ ## Registry and Resolution
70
+
71
+ - App resolution order: **local(app) → kernel**.
72
+ - Apps do not override each other; import conflicts put the app into defunc.
73
+ - Kernel registry never receives app objects, so there is no removal from kernel registry.
74
+ - A defunc app does not participate in resolution (but its objects are not “removed”, since they never entered the kernel registry).
75
+
76
+ ## Export / Import Semantics
77
+
78
+ ### Export
79
+
80
+ - Declared by `exports` in app install json.
81
+ - Kernel exposes app exports (API shape can be decided during implementation).
82
+
83
+ ### Import
84
+
85
+ - **Members**: declared in app `team.yaml`.
86
+ - **Toolsets**: declared in app `team.yaml`; loaded via dominds API and registered into the app registry.
87
+
88
+ Suggested structure (example):
89
+
90
+ ```yaml
91
+ imports:
92
+ members:
93
+ - app: foo_app
94
+ id: npc_foo
95
+ toolsets:
96
+ - app: bar_app
97
+ id: bar_toolset
98
+ ```
99
+
100
+ ### Conflicts and Dependency Failures
101
+
102
+ - Import conflicts or dependency failures → app defunc.
103
+
104
+ #### Conflict matrix (minimal rules)
105
+
106
+ | Case | Result |
107
+ | ----------------------------------------------------- | ------------------------------ |
108
+ | Same name in `local(app)` vs `kernel` | Allowed (local shadows kernel) |
109
+ | Imported member/toolset conflicts with app-local name | defunc |
110
+ | Imported member/toolset conflicts with another import | defunc |
111
+ | Import points to a non-exported object | defunc |
112
+ | depends not satisfied (missing/version mismatch) | defunc |
113
+
114
+ ## Defunc Semantics
115
+
116
+ - Defunc means the app is unusable.
117
+ - No registry removal is needed (app registry is no longer used; kernel has no app objects).
118
+ - Defunc reason should be recorded for diagnosis.
119
+
120
+ ### Defunc triggers (suggested enumeration)
121
+
122
+ - `MANIFEST_INVALID`: missing/invalid install json fields.
123
+ - `DEPENDENCY_MISSING` / `DEPENDENCY_VERSION_MISMATCH`: depends missing or not satisfied.
124
+ - `EXPORTS_INVALID`: exports references missing member/toolset.
125
+ - `IMPORT_NOT_EXPORTED`: import points to an object not declared in exports.
126
+ - `IMPORT_CONFLICT`: same-name conflicts introduced by imports.
127
+ - `TEAM_OVERRIDE_INVALID`: override DSL parse/validation failed for `<rtws>/.apps/<app-id>/team.yaml`.
128
+ - `IMPORT_FETCH_FAILED`: fetching toolset metadata via API failed or returned invalid data.
129
+
130
+ ### Retry semantics (suggested)
131
+
132
+ - Defunc is **retryable by default**: once dependencies/config are fixed, kernel retries loading the app on the next refresh cycle.
133
+ - Retry does not mutate existing dialogs/history; it only affects future resolution/new calls.
134
+
135
+ ### Observability (suggested)
136
+
137
+ - Defunc must surface in Problems (or equivalent), including at least: `appId`, `reasonKind`, `detail`, `firstSeenAt`, `lastSeenAt`, `retryable`, `suggestedAction`.
138
+ - `app_integration_manual` call failures **must not trigger defunc** (they should be observable but not make the app unusable).
139
+
140
+ ## App Integration Manual (`app_integration_manual`)
141
+
142
+ - Kernel-fixed tool: `app_integration_manual`
143
+ - Params: `{ appId: string, language?: string }`
144
+ - If `language` is omitted, default to **work language**.
145
+ - Kernel routes the call to the app host via IPC.
146
+ - App can return static markdown or runtime-generated content.
147
+ - Apps must provide zh/en content.
148
+ - Failure does not trigger defunc (return an error is enough).
149
+
150
+ ## Language Policy
151
+
152
+ - **Work language** comes from the `LANG` environment variable; kernel and app host inherit and it is immutable at runtime.
153
+ - Apps must follow kernel work language for reasoning/logic content.
154
+ - Apps may provide their own UI with a user-configurable UI language.
155
+ - All apps must support at least zh/en.
156
+
157
+ ## Incremental Override DSL for `team.yaml`
158
+
159
+ Override file: `<rtws>/.apps/<app-id>/team.yaml`
160
+
161
+ - No `actions:` top level.
162
+ - Domain-specific DSL with **add/replace/modify/delete**.
163
+ - Each load applies actions; failures put the app into defunc.
164
+
165
+ Example:
166
+
167
+ ```yaml
168
+ version: 1
169
+
170
+ add:
171
+ members:
172
+ - id: npc_new
173
+ value:
174
+ name: New NPC
175
+ toolsets: [trae_toolset]
176
+
177
+ replace:
178
+ members:
179
+ - id: npc_old
180
+ value:
181
+ name: Old NPC
182
+ hidden: true
183
+
184
+ modify:
185
+ members:
186
+ - id: npc_village_head
187
+ set:
188
+ toolsets: [trae_toolset, extra_toolset]
189
+ streaming: true
190
+ unset: [tools]
191
+ merge:
192
+ model_params:
193
+ codex:
194
+ temperature: 0.2
195
+ member_defaults:
196
+ set:
197
+ provider: codex
198
+
199
+ delete:
200
+ members:
201
+ - id: npc_removed
202
+
203
+ set_default_responder: npc_village_head
204
+
205
+ add_shell_specialist:
206
+ - npc_village_head
207
+
208
+ remove_shell_specialist:
209
+ - npc_foo
210
+ ```
211
+
212
+ Rules:
213
+
214
+ - `modify_member` supports `set`/`unset`/`merge`; `merge` is a deep merge on objects.
215
+ - All changes must pass existing team.yaml validation.
216
+ - Conflicts or parse failures → app defunc.
217
+
218
+ ## Suggested Load Flow
219
+
220
+ 1. Resolve and register toolsets first (local toolsets + imports.toolsets), **including their tools**
221
+ 2. Read app built-in team.yaml
222
+ 3. Resolve imports.members
223
+ 4. Apply `<rtws>/.apps/<app-id>/team.yaml` overrides
224
+ 5. Validate (toolsets/tools are now resolvable)
225
+ 6. Success → register members into app registry
226
+ 7. Failure → app defunc
227
+
228
+ ## Review Packet
229
+
230
+ This section is meant to let a reviewer validate and continue in ~30 minutes (without putting implementation details into Taskdoc progress).
231
+
232
+ ### Artifacts
233
+
234
+ - Architecture (semantic source): `dominds/docs/kernel-app-architecture.zh.md`
235
+ - English alignment: `dominds/docs/kernel-app-architecture.md`
236
+
237
+ ### Delta (recent changes)
238
+
239
+ - WebSocket driving no longer accepts `runControlId/runControlInput` (run-control expansion is intentionally split into a dedicated doc).
240
+ - apps-host run control result no longer supports `systemPromptPatch/prompt` (collapsed to a minimal continue/reject shape).
241
+ - kernel-driver context-health driving logic is aligned with driver-v2 style (prototype-stage cleanup).
242
+
243
+ ### Minimal smoke (suggested)
244
+
245
+ Given this is a prototype for concept/functional validation, this smoke list focuses on ensuring recent cleanups do not break existing paths:
246
+
247
+ 1. `pnpm -C dominds run lint:types` passes.
248
+ 2. If the current rtws has enabled apps: startup initializes apps-host and registers proxy tools for each app’s `contributes.toolsets` (no name collisions).
249
+ 3. WebUI dialog driving + Q4H answering no longer requires/sends `runControlId/runControlInput`.
250
+
251
+ ## Prototype Status and Gap List
252
+
253
+ What is already present as a verifiable skeleton (facts only, not a completeness claim):
254
+
255
+ - Apps runtime + apps-host IPC infrastructure exists (forks apps-host and forwards tool calls).
256
+ - Proxy registration for app-declared `contributes.toolsets` exists (concept/functional validation).
257
+ - App-declared dialog run controls can be registered (run-control semantic expansion is out of scope here).
258
+
259
+ What is not yet closed / needs implementation-level landing points (the “status & issues” deliverable):
260
+
261
+ - `depends/exports/imports` loading/validation/conflict handling is currently mostly at the spec level; needs implementation + end-to-end verification.
262
+ - Defunc lifecycle state machine, Problems surfacing, retry/reload entrypoints need an implementation-closed loop (including logging/error taxonomy).
263
+ - `<rtws>/.apps/<app-id>/team.yaml` override DSL: read/apply/validate landing points + regression.
264
+ - Kernel-fixed `app_integration_manual(appId, language?)` tool + IPC routing needs implementation + regression.
265
+ - Migration playbook (which built-ins to migrate first, rollback strategy, dogfooding gates) should be produced in the implementation phase.
266
+
267
+ ## Completion Criteria (Acceptance)
268
+
269
+ This prototype-stage “integrated plan” document can be considered complete when:
270
+
271
+ - It explicitly specifies: Identity/Resolution, defunc triggers + retry, imports/exports granularity + conflict matrix, team.yaml override DSL, and the `app_integration_manual` contract.
272
+ - Key rules are written as “when X happens → the system does Y”, without requiring readers to infer behavior from source.
273
+ - `kernel-app-architecture.zh.md` and this English version are kept consistent (zh is the semantic source of truth).
274
+
275
+ ## Key Anchors (existing code)
276
+
277
+ - install json parsing: `dominds/main/apps/app-json.ts`
278
+ - apps runtime: `dominds/main/apps/runtime.ts`
279
+ - apps host contract: `dominds/main/apps-host/app-host-contract.ts`
280
+ - apps host IPC: `dominds/main/apps-host/ipc-types.ts`
281
+ - team.yaml parsing: `dominds/main/team.ts`
282
+ - app teammates loader: `dominds/main/apps/teammates.ts`
283
+
284
+ ---
285
+
286
+ This document is a prototype-stage design draft; details may evolve during implementation.