dominds 0.3.2 → 0.3.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 (116) hide show
  1. package/dist/dialog-instance-registry.js +40 -1
  2. package/dist/dialog.js +2 -2
  3. package/dist/docs/dialog-system.md +6 -0
  4. package/dist/docs/dialog-system.zh.md +6 -0
  5. package/dist/docs/dominds-terminology.md +18 -0
  6. package/dist/docs/keep-going.zh.md +162 -0
  7. package/dist/llm/driver.js +66 -9
  8. package/dist/llm/gen/codex.js +11 -0
  9. package/dist/persistence.js +8 -4
  10. package/dist/server/api-routes.js +19 -1
  11. package/dist/server/setup-routes.js +2 -0
  12. package/dist/server/websocket-handler.js +18 -0
  13. package/dist/shared/utils/inter-dialog-format.js +7 -8
  14. package/dist/snippets/README.en.md +3 -0
  15. package/dist/static/assets/{_baseUniq-SokIVT_l.js → _baseUniq-mRW6pj4A.js} +2 -2
  16. package/dist/static/assets/{_baseUniq-SokIVT_l.js.map → _baseUniq-mRW6pj4A.js.map} +1 -1
  17. package/dist/static/assets/{arc-kjR8x1Ck.js → arc-QuaW82W7.js} +2 -2
  18. package/dist/static/assets/{arc-kjR8x1Ck.js.map → arc-QuaW82W7.js.map} +1 -1
  19. package/dist/static/assets/{architectureDiagram-VXUJARFQ-Dqg6NBDR.js → architectureDiagram-VXUJARFQ-DnVRLy2e.js} +6 -6
  20. package/dist/static/assets/{architectureDiagram-VXUJARFQ-Dqg6NBDR.js.map → architectureDiagram-VXUJARFQ-DnVRLy2e.js.map} +1 -1
  21. package/dist/static/assets/{blockDiagram-VD42YOAC-B-BQL_cY.js → blockDiagram-VD42YOAC-oj3riBZV.js} +7 -7
  22. package/dist/static/assets/{blockDiagram-VD42YOAC-B-BQL_cY.js.map → blockDiagram-VD42YOAC-oj3riBZV.js.map} +1 -1
  23. package/dist/static/assets/{c4Diagram-YG6GDRKO-Bzr91V4Y.js → c4Diagram-YG6GDRKO-D4aghgki.js} +3 -3
  24. package/dist/static/assets/{c4Diagram-YG6GDRKO-Bzr91V4Y.js.map → c4Diagram-YG6GDRKO-D4aghgki.js.map} +1 -1
  25. package/dist/static/assets/{channel-r5ULc-CH.js → channel-CO8pOP10.js} +2 -2
  26. package/dist/static/assets/{channel-r5ULc-CH.js.map → channel-CO8pOP10.js.map} +1 -1
  27. package/dist/static/assets/{chunk-4BX2VUAB-DbPnZ3jR.js → chunk-4BX2VUAB-wUTrHXKr.js} +2 -2
  28. package/dist/static/assets/{chunk-4BX2VUAB-DbPnZ3jR.js.map → chunk-4BX2VUAB-wUTrHXKr.js.map} +1 -1
  29. package/dist/static/assets/{chunk-55IACEB6-jRbyNM-u.js → chunk-55IACEB6-DuCJC-29.js} +2 -2
  30. package/dist/static/assets/{chunk-55IACEB6-jRbyNM-u.js.map → chunk-55IACEB6-DuCJC-29.js.map} +1 -1
  31. package/dist/static/assets/{chunk-B4BG7PRW-_roYgl4_.js → chunk-B4BG7PRW-BDM_YTnz.js} +5 -5
  32. package/dist/static/assets/{chunk-B4BG7PRW-_roYgl4_.js.map → chunk-B4BG7PRW-BDM_YTnz.js.map} +1 -1
  33. package/dist/static/assets/{chunk-DI55MBZ5-65DWu0ny.js → chunk-DI55MBZ5-Xyqh4xSb.js} +4 -4
  34. package/dist/static/assets/{chunk-DI55MBZ5-65DWu0ny.js.map → chunk-DI55MBZ5-Xyqh4xSb.js.map} +1 -1
  35. package/dist/static/assets/{chunk-FMBD7UC4-suO96TII.js → chunk-FMBD7UC4-Dh2eumwL.js} +2 -2
  36. package/dist/static/assets/{chunk-FMBD7UC4-suO96TII.js.map → chunk-FMBD7UC4-Dh2eumwL.js.map} +1 -1
  37. package/dist/static/assets/{chunk-QN33PNHL-CSWxSU4j.js → chunk-QN33PNHL-ozUUvqW2.js} +2 -2
  38. package/dist/static/assets/{chunk-QN33PNHL-CSWxSU4j.js.map → chunk-QN33PNHL-ozUUvqW2.js.map} +1 -1
  39. package/dist/static/assets/{chunk-QZHKN3VN-uzgBslqF.js → chunk-QZHKN3VN-DSB7FsZ7.js} +2 -2
  40. package/dist/static/assets/{chunk-QZHKN3VN-uzgBslqF.js.map → chunk-QZHKN3VN-DSB7FsZ7.js.map} +1 -1
  41. package/dist/static/assets/{chunk-TZMSLE5B-Bs3-ioaP.js → chunk-TZMSLE5B-CPAaVWZK.js} +2 -2
  42. package/dist/static/assets/{chunk-TZMSLE5B-Bs3-ioaP.js.map → chunk-TZMSLE5B-CPAaVWZK.js.map} +1 -1
  43. package/dist/static/assets/{classDiagram-2ON5EDUG-BwRTuVYR.js → classDiagram-2ON5EDUG-C-sqbbO5.js} +6 -6
  44. package/dist/static/assets/{classDiagram-2ON5EDUG-BwRTuVYR.js.map → classDiagram-2ON5EDUG-C-sqbbO5.js.map} +1 -1
  45. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-BwRTuVYR.js → classDiagram-v2-WZHVMYZB-C-sqbbO5.js} +6 -6
  46. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-BwRTuVYR.js.map → classDiagram-v2-WZHVMYZB-C-sqbbO5.js.map} +1 -1
  47. package/dist/static/assets/{clone-DTU0L3GE.js → clone-By5ScCya.js} +2 -2
  48. package/dist/static/assets/{clone-DTU0L3GE.js.map → clone-By5ScCya.js.map} +1 -1
  49. package/dist/static/assets/{cose-bilkent-S5V4N54A-DFN-M43c.js → cose-bilkent-S5V4N54A-C4NGA9He.js} +2 -2
  50. package/dist/static/assets/{cose-bilkent-S5V4N54A-DFN-M43c.js.map → cose-bilkent-S5V4N54A-C4NGA9He.js.map} +1 -1
  51. package/dist/static/assets/{dagre-6UL2VRFP-Db2QO3fw.js → dagre-6UL2VRFP-BkWOYnuR.js} +7 -7
  52. package/dist/static/assets/{dagre-6UL2VRFP-Db2QO3fw.js.map → dagre-6UL2VRFP-BkWOYnuR.js.map} +1 -1
  53. package/dist/static/assets/{diagram-PSM6KHXK-KdgI-gRF.js → diagram-PSM6KHXK-BzrBbXJK.js} +7 -7
  54. package/dist/static/assets/{diagram-PSM6KHXK-KdgI-gRF.js.map → diagram-PSM6KHXK-BzrBbXJK.js.map} +1 -1
  55. package/dist/static/assets/{diagram-QEK2KX5R-xH-jYUSp.js → diagram-QEK2KX5R-B0MnvOMb.js} +6 -6
  56. package/dist/static/assets/{diagram-QEK2KX5R-xH-jYUSp.js.map → diagram-QEK2KX5R-B0MnvOMb.js.map} +1 -1
  57. package/dist/static/assets/{diagram-S2PKOQOG-xaw91UrD.js → diagram-S2PKOQOG-BcO1Dh4d.js} +6 -6
  58. package/dist/static/assets/{diagram-S2PKOQOG-xaw91UrD.js.map → diagram-S2PKOQOG-BcO1Dh4d.js.map} +1 -1
  59. package/dist/static/assets/{erDiagram-Q2GNP2WA-BBxSVxZ2.js → erDiagram-Q2GNP2WA-DhJ57Zr6.js} +5 -5
  60. package/dist/static/assets/{erDiagram-Q2GNP2WA-BBxSVxZ2.js.map → erDiagram-Q2GNP2WA-DhJ57Zr6.js.map} +1 -1
  61. package/dist/static/assets/{flowDiagram-NV44I4VS-yzYTEiMx.js → flowDiagram-NV44I4VS-DE2_JdPY.js} +6 -6
  62. package/dist/static/assets/{flowDiagram-NV44I4VS-yzYTEiMx.js.map → flowDiagram-NV44I4VS-DE2_JdPY.js.map} +1 -1
  63. package/dist/static/assets/{ganttDiagram-JELNMOA3-CfOHq8RS.js → ganttDiagram-JELNMOA3-DkBsTv2T.js} +3 -3
  64. package/dist/static/assets/{ganttDiagram-JELNMOA3-CfOHq8RS.js.map → ganttDiagram-JELNMOA3-DkBsTv2T.js.map} +1 -1
  65. package/dist/static/assets/{gitGraphDiagram-NY62KEGX-DeZv5Du8.js → gitGraphDiagram-NY62KEGX-DV3eZqmy.js} +7 -7
  66. package/dist/static/assets/{gitGraphDiagram-NY62KEGX-DeZv5Du8.js.map → gitGraphDiagram-NY62KEGX-DV3eZqmy.js.map} +1 -1
  67. package/dist/static/assets/{graph-CDFIwKM1.js → graph-Dzw1schx.js} +3 -3
  68. package/dist/static/assets/{graph-CDFIwKM1.js.map → graph-Dzw1schx.js.map} +1 -1
  69. package/dist/static/assets/{index-BW6RWfVV.js → index-smy5Hge5.js} +84 -46
  70. package/dist/static/assets/{index-BW6RWfVV.js.map → index-smy5Hge5.js.map} +1 -1
  71. package/dist/static/assets/{infoDiagram-WHAUD3N6-DDDknjUc.js → infoDiagram-WHAUD3N6-BYQkShzE.js} +5 -5
  72. package/dist/static/assets/{infoDiagram-WHAUD3N6-DDDknjUc.js.map → infoDiagram-WHAUD3N6-BYQkShzE.js.map} +1 -1
  73. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Bj6kqefO.js → journeyDiagram-XKPGCS4Q-B2Ofj4oX.js} +5 -5
  74. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Bj6kqefO.js.map → journeyDiagram-XKPGCS4Q-B2Ofj4oX.js.map} +1 -1
  75. package/dist/static/assets/{kanban-definition-3W4ZIXB7-DyIxtovg.js → kanban-definition-3W4ZIXB7-Be4yiLP0.js} +3 -3
  76. package/dist/static/assets/{kanban-definition-3W4ZIXB7-DyIxtovg.js.map → kanban-definition-3W4ZIXB7-Be4yiLP0.js.map} +1 -1
  77. package/dist/static/assets/{layout-CenW9Lg4.js → layout-omu98FP8.js} +5 -5
  78. package/dist/static/assets/{layout-CenW9Lg4.js.map → layout-omu98FP8.js.map} +1 -1
  79. package/dist/static/assets/{linear-CIqoXI1R.js → linear-Csyd8pXl.js} +2 -2
  80. package/dist/static/assets/{linear-CIqoXI1R.js.map → linear-Csyd8pXl.js.map} +1 -1
  81. package/dist/static/assets/{min-PhMlVnVp.js → min-CdkxEeTW.js} +3 -3
  82. package/dist/static/assets/{min-PhMlVnVp.js.map → min-CdkxEeTW.js.map} +1 -1
  83. package/dist/static/assets/{mindmap-definition-VGOIOE7T-BEc0C731.js → mindmap-definition-VGOIOE7T-nc4RuImy.js} +4 -4
  84. package/dist/static/assets/{mindmap-definition-VGOIOE7T-BEc0C731.js.map → mindmap-definition-VGOIOE7T-nc4RuImy.js.map} +1 -1
  85. package/dist/static/assets/{pieDiagram-ADFJNKIX-Y9g6QrPu.js → pieDiagram-ADFJNKIX-D9-0_cv2.js} +7 -7
  86. package/dist/static/assets/{pieDiagram-ADFJNKIX-Y9g6QrPu.js.map → pieDiagram-ADFJNKIX-D9-0_cv2.js.map} +1 -1
  87. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-0flyaoAo.js → quadrantDiagram-AYHSOK5B-C2fbgOCn.js} +3 -3
  88. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-0flyaoAo.js.map → quadrantDiagram-AYHSOK5B-C2fbgOCn.js.map} +1 -1
  89. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-F46cCDfo.js → requirementDiagram-UZGBJVZJ-DTesSf61.js} +4 -4
  90. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-F46cCDfo.js.map → requirementDiagram-UZGBJVZJ-DTesSf61.js.map} +1 -1
  91. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-B56j3BkK.js → sankeyDiagram-TZEHDZUN-ZWNntzxe.js} +2 -2
  92. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-B56j3BkK.js.map → sankeyDiagram-TZEHDZUN-ZWNntzxe.js.map} +1 -1
  93. package/dist/static/assets/{sequenceDiagram-WL72ISMW-DzQxEivA.js → sequenceDiagram-WL72ISMW-Ci-51cqk.js} +4 -4
  94. package/dist/static/assets/{sequenceDiagram-WL72ISMW-DzQxEivA.js.map → sequenceDiagram-WL72ISMW-Ci-51cqk.js.map} +1 -1
  95. package/dist/static/assets/{stateDiagram-FKZM4ZOC-8zkC6mTh.js → stateDiagram-FKZM4ZOC-EPKqXOfY.js} +9 -9
  96. package/dist/static/assets/{stateDiagram-FKZM4ZOC-8zkC6mTh.js.map → stateDiagram-FKZM4ZOC-EPKqXOfY.js.map} +1 -1
  97. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-CwSo5ElY.js → stateDiagram-v2-4FDKWEC3-CQHvPi94.js} +5 -5
  98. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-CwSo5ElY.js.map → stateDiagram-v2-4FDKWEC3-CQHvPi94.js.map} +1 -1
  99. package/dist/static/assets/{timeline-definition-IT6M3QCI-ZlRniSmj.js → timeline-definition-IT6M3QCI-ByNrm0qi.js} +3 -3
  100. package/dist/static/assets/{timeline-definition-IT6M3QCI-ZlRniSmj.js.map → timeline-definition-IT6M3QCI-ByNrm0qi.js.map} +1 -1
  101. package/dist/static/assets/{treemap-KMMF4GRG-D1jARXF5.js → treemap-KMMF4GRG-CoEvR_zQ.js} +4 -4
  102. package/dist/static/assets/{treemap-KMMF4GRG-D1jARXF5.js.map → treemap-KMMF4GRG-CoEvR_zQ.js.map} +1 -1
  103. package/dist/static/assets/{xychartDiagram-PRI3JC2R-BPX1HHsI.js → xychartDiagram-PRI3JC2R-Dex1o_-m.js} +3 -3
  104. package/dist/static/assets/{xychartDiagram-PRI3JC2R-BPX1HHsI.js.map → xychartDiagram-PRI3JC2R-Dex1o_-m.js.map} +1 -1
  105. package/dist/static/index.html +1 -1
  106. package/dist/team-config-updates.js +180 -0
  107. package/dist/team.js +82 -3
  108. package/dist/tellask.js +11 -3
  109. package/dist/tools/context-health.js +7 -7
  110. package/dist/tools/diag.js +2 -2
  111. package/dist/tools/team-mgmt.js +2 -2
  112. package/dist/utils/task-doc.js +16 -16
  113. package/package.json +1 -1
  114. package/dist/minds/builtin/cmdr/persona.md +0 -3
  115. package/dist/minds/builtin/dijiang/knowledge.md +0 -287
  116. package/dist/minds/builtin/dijiang/persona.md +0 -7
@@ -52,7 +52,7 @@
52
52
  padding: 20px;
53
53
  }
54
54
  </style>
55
- <script type="module" crossorigin src="/assets/index-BW6RWfVV.js"></script>
55
+ <script type="module" crossorigin src="/assets/index-smy5Hge5.js"></script>
56
56
  <link rel="stylesheet" crossorigin href="/assets/index-DaIsSzC_.css">
57
57
  </head>
58
58
  <body>
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ /**
3
+ * Module: team-config-updates
4
+ *
5
+ * Best-effort broadcast when `.minds/team.yaml` changes so multi-tab WebUIs can refresh
6
+ * their cached team config without polling.
7
+ *
8
+ * Notes:
9
+ * - File watching is inherently best-effort (editors may write via rename; some platforms miss events).
10
+ * - We use a polling fallback for reliability, mirroring the MCP supervisor pattern.
11
+ */
12
+ var __importDefault = (this && this.__importDefault) || function (mod) {
13
+ return (mod && mod.__esModule) ? mod : { "default": mod };
14
+ };
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.setTeamConfigBroadcaster = setTeamConfigBroadcaster;
17
+ exports.startTeamConfigWatcher = startTeamConfigWatcher;
18
+ exports.notifyTeamConfigUpdated = notifyTeamConfigUpdated;
19
+ const fs_1 = __importDefault(require("fs"));
20
+ const path_1 = __importDefault(require("path"));
21
+ const log_1 = require("./log");
22
+ const time_1 = require("./shared/utils/time");
23
+ const log = (0, log_1.createLogger)('team-config-updates');
24
+ const MINDS_DIR = '.minds';
25
+ const TEAM_YAML_BASENAME = 'team.yaml';
26
+ const TEAM_YAML_PATH = path_1.default.join(MINDS_DIR, TEAM_YAML_BASENAME);
27
+ function isFsErrWithCode(err) {
28
+ if (typeof err !== 'object' || err === null)
29
+ return false;
30
+ const maybe = err.code;
31
+ return typeof maybe === 'string';
32
+ }
33
+ async function readTeamYamlSig() {
34
+ try {
35
+ const st = await fs_1.default.promises.stat(TEAM_YAML_PATH);
36
+ if (!st.isFile()) {
37
+ return { sig: `not_file/${st.size}/${st.mtimeMs}`, exists: false };
38
+ }
39
+ return { sig: `${st.size}/${st.mtimeMs}`, exists: true };
40
+ }
41
+ catch (err) {
42
+ if (isFsErrWithCode(err) && err.code === 'ENOENT') {
43
+ return { sig: 'missing', exists: false };
44
+ }
45
+ log.warn('Failed to stat .minds/team.yaml', err);
46
+ return { sig: 'error', exists: false };
47
+ }
48
+ }
49
+ let broadcastToClients;
50
+ function setTeamConfigBroadcaster(fn) {
51
+ broadcastToClients = fn;
52
+ }
53
+ function broadcast(msg) {
54
+ const fn = broadcastToClients;
55
+ if (!fn)
56
+ return;
57
+ try {
58
+ fn(msg);
59
+ }
60
+ catch (err) {
61
+ log.warn('Failed to broadcast team config update', err);
62
+ }
63
+ }
64
+ let mindsDirWatcher;
65
+ let workspaceWatcher;
66
+ let pollTimer;
67
+ let debounceTimer;
68
+ let lastSeenSig;
69
+ let watcherStarted = false;
70
+ let checkChain = Promise.resolve();
71
+ function makeUpdateMessage(args) {
72
+ return {
73
+ type: 'team_config_updated',
74
+ path: TEAM_YAML_PATH,
75
+ exists: args.exists,
76
+ timestamp: (0, time_1.formatUnifiedTimestamp)(new Date()),
77
+ trigger: args.trigger,
78
+ };
79
+ }
80
+ async function checkAndMaybeBroadcast(trigger) {
81
+ const state = await readTeamYamlSig();
82
+ if (lastSeenSig === undefined) {
83
+ // Initialize without broadcasting; clients load team config on boot anyway.
84
+ lastSeenSig = state.sig;
85
+ return;
86
+ }
87
+ if (state.sig === lastSeenSig)
88
+ return;
89
+ lastSeenSig = state.sig;
90
+ broadcast(makeUpdateMessage({ exists: state.exists, trigger }));
91
+ }
92
+ function scheduleCheck(trigger) {
93
+ if (debounceTimer) {
94
+ clearTimeout(debounceTimer);
95
+ debounceTimer = undefined;
96
+ }
97
+ debounceTimer = setTimeout(() => {
98
+ checkChain = checkChain
99
+ .then(async () => await checkAndMaybeBroadcast(trigger))
100
+ .catch((err) => {
101
+ log.warn('Team config check failed', err);
102
+ });
103
+ }, 150);
104
+ }
105
+ async function ensureMindsDirWatcher(reason) {
106
+ if (mindsDirWatcher)
107
+ return;
108
+ try {
109
+ mindsDirWatcher = fs_1.default.watch(MINDS_DIR, { persistent: false }, (_event, filename) => {
110
+ const name = filename ? filename.toString() : '';
111
+ if (name !== '' && name !== TEAM_YAML_BASENAME)
112
+ return;
113
+ scheduleCheck(`minds.watch:${reason}`);
114
+ });
115
+ mindsDirWatcher.on('error', () => {
116
+ if (mindsDirWatcher) {
117
+ mindsDirWatcher.close();
118
+ mindsDirWatcher = undefined;
119
+ }
120
+ });
121
+ }
122
+ catch {
123
+ // ignore; polling still works
124
+ }
125
+ }
126
+ function startTeamConfigWatcher() {
127
+ if (watcherStarted)
128
+ return;
129
+ watcherStarted = true;
130
+ checkChain = checkChain
131
+ .then(async () => {
132
+ const initial = await readTeamYamlSig();
133
+ lastSeenSig = initial.sig;
134
+ })
135
+ .catch((err) => {
136
+ log.warn('Initial team config signature read failed', err);
137
+ });
138
+ // Best-effort fast watcher.
139
+ void ensureMindsDirWatcher('startup');
140
+ // Watch workspace root for `.minds/` create/delete.
141
+ try {
142
+ workspaceWatcher = fs_1.default.watch('.', { persistent: false }, (_event, filename) => {
143
+ const name = filename ? filename.toString() : '';
144
+ if (name !== '' && name !== MINDS_DIR)
145
+ return;
146
+ void ensureMindsDirWatcher('workspace.watch');
147
+ scheduleCheck('workspace.watch');
148
+ });
149
+ workspaceWatcher.on('error', () => {
150
+ if (workspaceWatcher) {
151
+ workspaceWatcher.close();
152
+ workspaceWatcher = undefined;
153
+ }
154
+ });
155
+ }
156
+ catch {
157
+ // ignore; polling still works
158
+ }
159
+ // Polling fallback for reliability.
160
+ pollTimer = setInterval(() => {
161
+ void ensureMindsDirWatcher('poll');
162
+ scheduleCheck('poll');
163
+ }, 1500);
164
+ }
165
+ /**
166
+ * Explicit notification hook for code paths that are known to mutate `.minds/team.yaml`.
167
+ *
168
+ * This is used for the setup flow so the UI updates immediately even if file watch is flaky.
169
+ */
170
+ function notifyTeamConfigUpdated(trigger) {
171
+ checkChain = checkChain
172
+ .then(async () => {
173
+ const state = await readTeamYamlSig();
174
+ lastSeenSig = state.sig;
175
+ broadcast(makeUpdateMessage({ exists: state.exists, trigger }));
176
+ })
177
+ .catch((err) => {
178
+ log.warn('Failed to notify team config updated', err);
179
+ });
180
+ }
package/dist/team.js CHANGED
@@ -334,8 +334,8 @@ exports.Team = Team;
334
334
  });
335
335
  Object.setPrototypeOf(pangu, md);
336
336
  const issuesById = new Map();
337
- const addIssue = (id, message, errorText) => {
338
- issuesById.set(id, { message, errorText });
337
+ const addIssue = (id, message, errorText, filePath) => {
338
+ issuesById.set(id, { message, errorText, filePath });
339
339
  };
340
340
  const finalizeProblems = () => {
341
341
  const now = (0, time_1.formatUnifiedTimestamp)(new Date());
@@ -348,7 +348,7 @@ exports.Team = Team;
348
348
  severity: 'error',
349
349
  timestamp: now,
350
350
  message: issue.message,
351
- detail: { filePath: TEAM_YAML_PATH, errorText: issue.errorText },
351
+ detail: { filePath: issue.filePath ?? TEAM_YAML_PATH, errorText: issue.errorText },
352
352
  });
353
353
  }
354
354
  (0, problems_1.reconcileProblemsByPrefix)(TEAM_YAML_PROBLEM_PREFIX, desired);
@@ -411,6 +411,82 @@ exports.Team = Team;
411
411
  addIssue(`shell_specialists/non_specialist_has_shell_tools/${sanitizeProblemIdSegment(member.id)}`, 'Invalid .minds/team.yaml: non-shell-specialist member has shell tools.', `member '${member.id}' has shell tools (${shellTools.join(', ')}) but is not listed in shell_specialists.`);
412
412
  }
413
413
  }
414
+ function previewKeys(obj, max) {
415
+ const keys = Object.keys(obj).sort((a, b) => a.localeCompare(b));
416
+ const head = keys.slice(0, Math.max(0, max));
417
+ const suffix = keys.length > head.length ? ` …(+${keys.length - head.length})` : '';
418
+ return head.join(', ') + suffix;
419
+ }
420
+ async function validateResolvedProviderModelBindings(team, md) {
421
+ let llmCfg;
422
+ try {
423
+ llmCfg = await client_1.LlmConfig.load();
424
+ }
425
+ catch (err) {
426
+ // Fail-open: team must remain usable, but surface this to Problems panel.
427
+ addIssue('llm/load', 'Failed to load LLM configuration for validating .minds/team.yaml provider/model bindings.', asErrorText(err), '.minds/llm.yaml');
428
+ return;
429
+ }
430
+ const validateAt = (args) => {
431
+ const providerKey = args.provider;
432
+ if (!providerKey)
433
+ return;
434
+ const providerCfg = llmCfg.getProvider(providerKey);
435
+ if (!providerCfg) {
436
+ addIssue(`${args.idPrefix}/provider/unknown`, `Invalid .minds/team.yaml: ${args.atPrefix}.provider refers to an unknown provider key.`, [
437
+ `Resolved ${args.atPrefix}.provider = '${providerKey}', but no such provider exists in the effective LLM config.`,
438
+ `Fix: update ${args.atPrefix}.provider to a valid provider key (see .minds/llm.yaml providers.<providerKey>), or add providers.${providerKey} in .minds/llm.yaml.`,
439
+ `Tip: run team_mgmt_list_providers({}) / team_mgmt_list_models({ source: "effective", provider_pattern: "*", model_pattern: "*" }) to confirm keys.`,
440
+ ].join('\n'));
441
+ return;
442
+ }
443
+ const modelsUnknown = providerCfg.models;
444
+ const models = typeof modelsUnknown === 'object' &&
445
+ modelsUnknown !== null &&
446
+ !Array.isArray(modelsUnknown)
447
+ ? modelsUnknown
448
+ : undefined;
449
+ if (!models) {
450
+ addIssue(`${args.idPrefix}/provider/models/invalid`, `Invalid .minds/llm.yaml: providers.${providerKey}.models is missing or invalid (cannot validate team model bindings).`, `Expected providers.${providerKey}.models to be an object mapping model keys to model info.`, '.minds/llm.yaml');
451
+ return;
452
+ }
453
+ const modelKey = args.model;
454
+ if (!modelKey)
455
+ return;
456
+ if (!Object.prototype.hasOwnProperty.call(models, modelKey)) {
457
+ addIssue(`${args.idPrefix}/model/unknown`, `Invalid .minds/team.yaml: ${args.atPrefix}.model is not present in provider '${providerKey}' models list.`, [
458
+ `Resolved ${args.atPrefix}.provider = '${providerKey}'.`,
459
+ `Resolved ${args.atPrefix}.model = '${modelKey}', but it is not defined under providers.${providerKey}.models.`,
460
+ `Known model keys (preview): ${previewKeys(models, 12)}`,
461
+ `Fix: change ${args.atPrefix}.model to a valid key, or add providers.${providerKey}.models.${modelKey} in .minds/llm.yaml.`,
462
+ `After fixing, run team_mgmt_validate_team_cfg({}) to confirm there are no Problems panel errors.`,
463
+ ].join('\n'));
464
+ }
465
+ };
466
+ // Always validate member_defaults (they influence all members via prototype defaults).
467
+ validateAt({
468
+ idPrefix: 'member_defaults',
469
+ atPrefix: 'member_defaults',
470
+ provider: md.provider,
471
+ model: md.model,
472
+ });
473
+ for (const member of Object.values(team.members)) {
474
+ // Only validate members whose provider/model binding is explicitly overridden.
475
+ const hasProviderOverride = Object.prototype.hasOwnProperty.call(member, 'provider');
476
+ const hasModelOverride = Object.prototype.hasOwnProperty.call(member, 'model');
477
+ if (!hasProviderOverride && !hasModelOverride)
478
+ continue;
479
+ const provider = member.provider ?? md.provider;
480
+ const model = member.model ?? md.model;
481
+ const idSeg = sanitizeProblemIdSegment(member.id);
482
+ validateAt({
483
+ idPrefix: `members/${idSeg}`,
484
+ atPrefix: `members.${member.id}`,
485
+ provider,
486
+ model,
487
+ });
488
+ }
489
+ }
414
490
  const buildBootstrapTeam = async () => {
415
491
  try {
416
492
  await applyBootstrapMemberDefaults(md);
@@ -487,6 +563,9 @@ exports.Team = Team;
487
563
  if (configuredDefaultResponder && !team.getMember(configuredDefaultResponder)) {
488
564
  addIssue('default_responder/unknown', 'Invalid .minds/team.yaml: default_responder does not match any member.', `default_responder '${configuredDefaultResponder}' does not exist in team members.`);
489
565
  }
566
+ // Validate provider/model bindings (models must exist under the selected provider's models list).
567
+ // Fail-open: always keep Team usable; publish config errors to Problems panel.
568
+ await validateResolvedProviderModelBindings(team, md);
490
569
  finalizeProblems();
491
570
  return team;
492
571
  }
package/dist/tellask.js CHANGED
@@ -40,6 +40,8 @@ class TellaskStreamParser {
40
40
  this.currentLineKind = 'unknown';
41
41
  this.pendingCallLineRole = false;
42
42
  this.currentCallLineRole = null;
43
+ // Total raw upstream characters consumed so far.
44
+ this.upstreamPos = 0;
43
45
  this.downstream = downstream;
44
46
  }
45
47
  async takeUpstreamChunk(chunk) {
@@ -50,6 +52,7 @@ class TellaskStreamParser {
50
52
  const consumed = await this.processLineStartProbe(char);
51
53
  if (consumed) {
52
54
  pos += 1;
55
+ this.upstreamPos += 1;
53
56
  continue;
54
57
  }
55
58
  // Not consumed means we decided the line kind and need to re-process this char
@@ -58,16 +61,19 @@ class TellaskStreamParser {
58
61
  if (this.currentLineKind === 'markdown') {
59
62
  await this.processMarkdownChar(char);
60
63
  pos += 1;
64
+ this.upstreamPos += 1;
61
65
  continue;
62
66
  }
63
67
  if (this.currentLineKind === 'call') {
64
68
  await this.processCallChar(char);
65
69
  pos += 1;
70
+ this.upstreamPos += 1;
66
71
  continue;
67
72
  }
68
73
  // Fallback: should be unreachable, but keep safe to avoid infinite loops.
69
74
  await this.processMarkdownChar(char);
70
75
  pos += 1;
76
+ this.upstreamPos += 1;
71
77
  }
72
78
  await this.flushAtUpstreamChunkEnd();
73
79
  }
@@ -332,6 +338,7 @@ class TellaskStreamParser {
332
338
  const call = this.activeCall;
333
339
  if (!call)
334
340
  return;
341
+ const upstreamEndOffset = this.upstreamPos;
335
342
  // If the first line never encountered an invalid mention delimiter, ensure we still resolve.
336
343
  await this.resolvePendingFirstLineMentionAtEofIfNeeded();
337
344
  await this.finishHeadlineIfNeeded();
@@ -341,13 +348,14 @@ class TellaskStreamParser {
341
348
  }
342
349
  const validation = call.validation ?? { kind: 'malformed', reason: 'missing_mention_prefix' };
343
350
  const callId = (0, id_1.generateContentHash)(`tellask\n${validation.kind === 'valid' ? validation.firstMention : ''}\n${call.headLine}\n${call.body}`, this.callCounter++);
344
- this.collectedCalls.push({
351
+ const collected = {
345
352
  validation,
346
353
  headLine: call.headLine,
347
354
  body: call.body,
348
355
  callId,
349
- });
350
- await this.downstream.callFinish(callId);
356
+ };
357
+ this.collectedCalls.push(collected);
358
+ await this.downstream.callFinish(collected, upstreamEndOffset);
351
359
  this.activeCall = null;
352
360
  this.headlineBuffer = '';
353
361
  this.bodyBuffer = '';
@@ -39,12 +39,12 @@ function formatContextHealthOwnerHeader(args) {
39
39
  ];
40
40
  if (!snapshot) {
41
41
  lines.push('- 状态:未知(尚未获取上下文统计)');
42
- lines.push('- 现在就做:用提醒项收敛关键细节(update_reminder)→ change_mind(progress) → clear_mind');
42
+ lines.push('- 优先动作:change_mind(progress) → clear_mind');
43
43
  return lines.join('\n');
44
44
  }
45
45
  if (snapshot.kind !== 'available') {
46
46
  lines.push('- 状态:未知(token 统计不可用)');
47
- lines.push('- 现在就做:用提醒项收敛关键细节(update_reminder)→ change_mind(progress) → clear_mind');
47
+ lines.push('- 优先动作:change_mind(progress) → clear_mind');
48
48
  return lines.join('\n');
49
49
  }
50
50
  switch (snapshot.level) {
@@ -53,16 +53,16 @@ function formatContextHealthOwnerHeader(args) {
53
53
  return lines.join('\n');
54
54
  }
55
55
  case 'caution': {
56
- lines.push('- 状态:🟡 黄(必须尽快清理)');
57
- lines.push('- 硬规程:先 update_reminder 收敛工作集 → 再 change_mind(progress) → 然后 clear_mind');
56
+ lines.push('- 状态:🟡 黄(警告)');
57
+ lines.push('- 优先动作:change_mind(progress) → clear_mind');
58
58
  return lines.join('\n');
59
59
  }
60
60
  case 'critical': {
61
- lines.push('- 状态:🔴 红(硬闸门)');
61
+ lines.push('- 状态:🔴 红(危险)');
62
62
  if (remainingGenTurns !== undefined) {
63
- lines.push(`- 倒数:剩余 ${remainingGenTurns} 次生成机会;到 0 系统将被动开启新一轮/新回合以保持稳定性`);
63
+ lines.push(`- 倒数:剩余 ${remainingGenTurns} 次生成机会;到 0 系统将自动开启新一轮以保持稳定性`);
64
64
  }
65
- lines.push('- 禁止继续推进实现:先 update_reminder 收敛工作集 → 再 change_mind(progress) → 然后 clear_mind');
65
+ lines.push('- 立刻:change_mind(progress) → clear_mind');
66
66
  return lines.join('\n');
67
67
  }
68
68
  default: {
@@ -112,8 +112,8 @@ class DiagTellaskReceiver {
112
112
  async callBodyFinish() {
113
113
  this.events.push({ kind: 'callBodyFinish' });
114
114
  }
115
- async callFinish(callId) {
116
- this.events.push({ kind: 'callFinish', callId });
115
+ async callFinish(call, _upstreamEndOffset) {
116
+ this.events.push({ kind: 'callFinish', callId: call.callId });
117
117
  }
118
118
  }
119
119
  function segmentsDiff(baseline, got) {
@@ -3202,14 +3202,14 @@ exports.teamMgmtValidateTeamCfgTool = {
3202
3202
  ? fmtHeader('team.yaml 校验失败') +
3203
3203
  fmtList([
3204
3204
  `\`${TEAM_YAML_REL}\`:❌ 检测到 ${teamProblems.length} 个问题(详见 Problems 面板)`,
3205
- '说明:坏的成员配置会被运行时跳过(为了保持 Team 可用),但你仍应立即修复以免行为偏离预期。',
3205
+ '说明:坏的成员配置可能会在运行时被跳过或在使用时失败(为了保持 Team 可用),但你仍应立即修复以免行为偏离预期。',
3206
3206
  ]) +
3207
3207
  '\n' +
3208
3208
  issueLines.join('\n')
3209
3209
  : fmtHeader('team.yaml Validation Failed') +
3210
3210
  fmtList([
3211
3211
  `\`${TEAM_YAML_REL}\`: ❌ ${teamProblems.length} issue(s) detected (see Problems panel)`,
3212
- 'Note: invalid member configs are omitted at runtime (to keep the Team usable), but you should fix them immediately.',
3212
+ 'Note: invalid member configs may be omitted at runtime or fail when used (to keep the Team usable), but you should fix them immediately.',
3213
3213
  ]) +
3214
3214
  '\n' +
3215
3215
  issueLines.join('\n');
@@ -120,33 +120,33 @@ If you provided a regular file path (e.g. a \`.md\`), that is unexpected. Please
120
120
  return [
121
121
  `**差遣牒结构(封装差遣牒 \`*.tsk/\`):**`,
122
122
  `- 我们的差遣牒是一个 \`*.tsk/\` 目录,分为 3 个分段:\`goals\` / \`constraints\` / \`progress\`。`,
123
- `- 维护方式:每次 \`!?@change_mind\` 必须指定一个分段(\`!goals\` / \`!constraints\` / \`!progress\`);可在同一条消息中连续发出多个 \`!?@change_mind\` 来一次更新多个分段。`,
123
+ `- 维护方式:每次调用函数工具 \`change_mind\` 必须指定一个分段(selector: \`!goals\` / \`!constraints\` / \`!progress\`);可在同一轮中多次调用 \`change_mind\` 来一次更新多个分段。`,
124
124
  ``,
125
125
  `**分段状态:**`,
126
126
  `- \`goals.md\`:${goalsZh}`,
127
127
  `- \`constraints.md\`:${constraintsZh}`,
128
128
  `- \`progress.md\`:${progressZh}`,
129
129
  ``,
130
- `若某个分段缺失,请用 \`!?@change_mind\` 创建(不要用通用文件工具):`,
131
- `- \`!?@change_mind !goals\\n!?<content>\``,
132
- `- \`!?@change_mind !constraints\\n!?<content>\``,
133
- `- \`!?@change_mind !progress\\n!?<content>\``,
130
+ `若某个分段缺失,请用函数工具 \`change_mind\` 创建(不要用通用文件工具):`,
131
+ `- \`change_mind({\"selector\":\"!goals\",\"content\":\"...\"})\``,
132
+ `- \`change_mind({\"selector\":\"!constraints\",\"content\":\"...\"})\``,
133
+ `- \`change_mind({\"selector\":\"!progress\",\"content\":\"...\"})\``,
134
134
  ].join('\n');
135
135
  }
136
136
  return [
137
137
  `**Task Doc Constitution (Encapsulated \`*.tsk/\`):**`,
138
138
  `- Our Task Doc is a \`*.tsk/\` directory with exactly 3 sections: \`goals\` / \`constraints\` / \`progress\`.`,
139
- `- Maintenance: each \`!?@change_mind\` call must target one section (\`!goals\` / \`!constraints\` / \`!progress\`). You may include multiple \`!?@change_mind\` calls in a single message to update multiple sections.`,
139
+ `- Maintenance: each function tool call \`change_mind\` must target one section (selector: \`!goals\` / \`!constraints\` / \`!progress\`). You may call \`change_mind\` multiple times in a single turn to update multiple sections.`,
140
140
  ``,
141
141
  `**Sections:**`,
142
142
  `- \`goals.md\`: ${goalsStatus}`,
143
143
  `- \`constraints.md\`: ${constraintsStatus}`,
144
144
  `- \`progress.md\`: ${progressStatus}`,
145
145
  ``,
146
- `If any section is missing, create it with \`!?@change_mind\` (never via general file tools):`,
147
- `- \`!?@change_mind !goals\\n!?<content>\``,
148
- `- \`!?@change_mind !constraints\\n!?<content>\``,
149
- `- \`!?@change_mind !progress\\n!?<content>\``,
146
+ `If any section is missing, create it with the function tool \`change_mind\` (never via general file tools):`,
147
+ `- \`change_mind({\"selector\":\"!goals\",\"content\":\"...\"})\``,
148
+ `- \`change_mind({\"selector\":\"!constraints\",\"content\":\"...\"})\``,
149
+ `- \`change_mind({\"selector\":\"!progress\",\"content\":\"...\"})\``,
150
150
  ].join('\n');
151
151
  })();
152
152
  const effectiveDoc = (0, task_package_1.formatEffectiveTaskDocFromSections)(language, sections);
@@ -164,7 +164,7 @@ If you provided a regular file path (e.g. a \`.md\`), that is unexpected. Please
164
164
  ${statusBlock}
165
165
 
166
166
  ⚠️ **注意:** 差遣牒是封装的。不要用文件工具去读/写/列目录 \`*.tsk/\` 下的任何路径。
167
- 请用 \`!?@change_mind !goals\` / \`!?@change_mind !constraints\` / \`!?@change_mind !progress\` 来更新(每次调用只更新一个分段;你可以在同一条消息里写多个 \`!?@change_mind\` 调用来批量更新)。`,
167
+ 请用函数工具 \`change_mind\` 来更新(每次调用只更新一个分段;你可以在同一轮中多次调用来批量更新),例如:\`change_mind({\"selector\":\"!goals\",\"content\":\"...\"})\` / \`change_mind({\"selector\":\"!constraints\",\"content\":\"...\"})\` / \`change_mind({\"selector\":\"!progress\",\"content\":\"...\"})\`。`,
168
168
  };
169
169
  }
170
170
  return {
@@ -177,7 +177,7 @@ ${statusBlock}
177
177
  ${statusBlock}
178
178
 
179
179
  ⚠️ **Note:** Task Docs are encapsulated. Do not use file tools to read/write/list anything under \`*.tsk/\`.
180
- Use \`!?@change_mind !goals\` / \`!?@change_mind !constraints\` / \`!?@change_mind !progress\` to update (each call updates one section; you may include multiple \`!?@change_mind\` calls in a single message to batch updates).`,
180
+ Use the function tool \`change_mind\` to update (each call updates one section; you may call it multiple times in a single turn to batch updates), e.g. \`change_mind({\"selector\":\"!goals\",\"content\":\"...\"})\` / \`change_mind({\"selector\":\"!constraints\",\"content\":\"...\"})\` / \`change_mind({\"selector\":\"!progress\",\"content\":\"...\"})\`.`,
181
181
  };
182
182
  }
183
183
  if (language === 'zh') {
@@ -194,9 +194,9 @@ ${statusBlock}
194
194
  ${effectiveDoc}
195
195
  ---
196
196
 
197
- *用 \`!?@change_mind !goals\` / \`!?@change_mind !constraints\` / \`!?@change_mind !progress\` 来替换分段(每次调用只替换一个分段;你可以在同一条消息里写多个 \`!?@change_mind\` 调用来批量替换)。*
197
+ *用函数工具 \`change_mind\` 来替换分段(每次调用只替换一个分段;你可以在同一轮中多次调用来批量替换)。*
198
198
 
199
- 指令:不要对 \`*.tsk/\` 下的任何路径调用通用文件工具(\`!?@read_file\`, \`!?@replace_file_contents\`, \`!?@plan_file_modification\`, \`!?@apply_file_modification\`, \`!?@list_dir\`, \`!?@rm_file\`, \`!?@rm_dir\`)。差遣牒状态只能通过显式的差遣牒操作进行管理。`,
199
+ 指令:不要对 \`*.tsk/\` 下的任何路径调用通用文件工具(\`read_file\`, \`overwrite_entire_file\`, \`preview_file_modification\`, \`apply_file_modification\`, \`list_dir\`, \`rm_file\`, \`rm_dir\`)。差遣牒状态只能通过显式的差遣牒操作进行管理。`,
200
200
  };
201
201
  }
202
202
  return {
@@ -212,9 +212,9 @@ ${statusBlock}
212
212
  ${effectiveDoc}
213
213
  ---
214
214
 
215
- *Use \`!?@change_mind !goals\` / \`!?@change_mind !constraints\` / \`!?@change_mind !progress\` to replace sections (each call replaces one section; you may include multiple \`!?@change_mind\` calls in a single message to batch replacements).*
215
+ *Use the function tool \`change_mind\` to replace sections (each call replaces one section; you may call it multiple times in a single turn to batch replacements).*
216
216
 
217
- Directive: Do not invoke any general file tools (\`!?@read_file\`, \`!?@replace_file_contents\`, \`!?@plan_file_modification\`, \`!?@apply_file_modification\`, \`!?@list_dir\`, \`!?@rm_file\`, \`!?@rm_dir\`) on any path under \`*.tsk/\`. Task package state is managed only through explicit task-doc actions.`,
217
+ Directive: Do not invoke any general file tools (\`read_file\`, \`overwrite_entire_file\`, \`preview_file_modification\`, \`apply_file_modification\`, \`list_dir\`, \`rm_file\`, \`rm_dir\`) on any path under \`*.tsk/\`. Task package state is managed only through explicit task-doc actions.`,
218
218
  };
219
219
  }
220
220
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dominds",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "in-tree developer team with self-improving mindsets",
5
5
  "type": "commonjs",
6
6
  "private": false,
@@ -1,3 +0,0 @@
1
- You are the commander, in charge of os shell command execution.
2
-
3
- Be caucious to execute dangerous/destructive commands, ask human confirmation when not sure, but never bother them for daily trivialities.