dominds 0.8.19 → 0.9.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.
- package/README.md +5 -1
- package/README.zh.md +5 -1
- package/dist/access-control.js +72 -23
- package/dist/docs/team_mgmt-toolset.md +1 -0
- package/dist/docs/team_mgmt-toolset.zh.md +1 -0
- package/dist/server/setup-routes.js +92 -26
- package/dist/static/assets/{_baseUniq-Bz-BK38X.js → _baseUniq-CoUduYbj.js} +2 -2
- package/dist/static/assets/{_baseUniq-Bz-BK38X.js.map → _baseUniq-CoUduYbj.js.map} +1 -1
- package/dist/static/assets/{arc-9gq7MlM9.js → arc-B79evgv8.js} +2 -2
- package/dist/static/assets/{arc-9gq7MlM9.js.map → arc-B79evgv8.js.map} +1 -1
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-CZIvAcDK.js → architectureDiagram-VXUJARFQ-rLlQb9R_.js} +6 -6
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-CZIvAcDK.js.map → architectureDiagram-VXUJARFQ-rLlQb9R_.js.map} +1 -1
- package/dist/static/assets/{blockDiagram-VD42YOAC-8XKqYs9h.js → blockDiagram-VD42YOAC-DKsP6RFH.js} +7 -7
- package/dist/static/assets/{blockDiagram-VD42YOAC-8XKqYs9h.js.map → blockDiagram-VD42YOAC-DKsP6RFH.js.map} +1 -1
- package/dist/static/assets/{c4Diagram-YG6GDRKO-01_3zzE3.js → c4Diagram-YG6GDRKO-BrSPmLIb.js} +3 -3
- package/dist/static/assets/{c4Diagram-YG6GDRKO-01_3zzE3.js.map → c4Diagram-YG6GDRKO-BrSPmLIb.js.map} +1 -1
- package/dist/static/assets/{channel-BGHx3NMy.js → channel-CQ18oNtY.js} +2 -2
- package/dist/static/assets/{channel-BGHx3NMy.js.map → channel-CQ18oNtY.js.map} +1 -1
- package/dist/static/assets/{chunk-4BX2VUAB-B12vclXR.js → chunk-4BX2VUAB-D8e6GJKc.js} +2 -2
- package/dist/static/assets/{chunk-4BX2VUAB-B12vclXR.js.map → chunk-4BX2VUAB-D8e6GJKc.js.map} +1 -1
- package/dist/static/assets/{chunk-55IACEB6-G6Q4T2VW.js → chunk-55IACEB6-0_nYvlGV.js} +2 -2
- package/dist/static/assets/{chunk-55IACEB6-G6Q4T2VW.js.map → chunk-55IACEB6-0_nYvlGV.js.map} +1 -1
- package/dist/static/assets/{chunk-B4BG7PRW-DV03ZyO0.js → chunk-B4BG7PRW-c3Osrj3P.js} +5 -5
- package/dist/static/assets/{chunk-B4BG7PRW-DV03ZyO0.js.map → chunk-B4BG7PRW-c3Osrj3P.js.map} +1 -1
- package/dist/static/assets/{chunk-DI55MBZ5-CMjP9HRy.js → chunk-DI55MBZ5-B3wy4mTI.js} +4 -4
- package/dist/static/assets/{chunk-DI55MBZ5-CMjP9HRy.js.map → chunk-DI55MBZ5-B3wy4mTI.js.map} +1 -1
- package/dist/static/assets/{chunk-FMBD7UC4-BX3p-W9Z.js → chunk-FMBD7UC4-DrcK9WUz.js} +2 -2
- package/dist/static/assets/{chunk-FMBD7UC4-BX3p-W9Z.js.map → chunk-FMBD7UC4-DrcK9WUz.js.map} +1 -1
- package/dist/static/assets/{chunk-QN33PNHL-CeixSGPE.js → chunk-QN33PNHL-fn6UG5b8.js} +2 -2
- package/dist/static/assets/{chunk-QN33PNHL-CeixSGPE.js.map → chunk-QN33PNHL-fn6UG5b8.js.map} +1 -1
- package/dist/static/assets/{chunk-QZHKN3VN-DHmlRthm.js → chunk-QZHKN3VN-lwz9tfKX.js} +2 -2
- package/dist/static/assets/{chunk-QZHKN3VN-DHmlRthm.js.map → chunk-QZHKN3VN-lwz9tfKX.js.map} +1 -1
- package/dist/static/assets/{chunk-TZMSLE5B-BQoTFJrz.js → chunk-TZMSLE5B-aXbZylkp.js} +2 -2
- package/dist/static/assets/{chunk-TZMSLE5B-BQoTFJrz.js.map → chunk-TZMSLE5B-aXbZylkp.js.map} +1 -1
- package/dist/static/assets/{classDiagram-2ON5EDUG-DmGBGhQA.js → classDiagram-2ON5EDUG-ByC6PvUi.js} +6 -6
- package/dist/static/assets/{classDiagram-2ON5EDUG-DmGBGhQA.js.map → classDiagram-2ON5EDUG-ByC6PvUi.js.map} +1 -1
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-DmGBGhQA.js → classDiagram-v2-WZHVMYZB-ByC6PvUi.js} +6 -6
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-DmGBGhQA.js.map → classDiagram-v2-WZHVMYZB-ByC6PvUi.js.map} +1 -1
- package/dist/static/assets/{clone-iHXiGToF.js → clone-BDJhQHyk.js} +2 -2
- package/dist/static/assets/{clone-iHXiGToF.js.map → clone-BDJhQHyk.js.map} +1 -1
- package/dist/static/assets/{cose-bilkent-S5V4N54A-M1lEFQCe.js → cose-bilkent-S5V4N54A-HAsn54-S.js} +2 -2
- package/dist/static/assets/{cose-bilkent-S5V4N54A-M1lEFQCe.js.map → cose-bilkent-S5V4N54A-HAsn54-S.js.map} +1 -1
- package/dist/static/assets/{dagre-6UL2VRFP-DCdK_t3m.js → dagre-6UL2VRFP-DgBnUfQ7.js} +7 -7
- package/dist/static/assets/{dagre-6UL2VRFP-DCdK_t3m.js.map → dagre-6UL2VRFP-DgBnUfQ7.js.map} +1 -1
- package/dist/static/assets/{diagram-PSM6KHXK-hjak5A8Z.js → diagram-PSM6KHXK-B0Oej_SM.js} +7 -7
- package/dist/static/assets/{diagram-PSM6KHXK-hjak5A8Z.js.map → diagram-PSM6KHXK-B0Oej_SM.js.map} +1 -1
- package/dist/static/assets/{diagram-QEK2KX5R-B4lGYVPl.js → diagram-QEK2KX5R-B-P9Chdj.js} +6 -6
- package/dist/static/assets/{diagram-QEK2KX5R-B4lGYVPl.js.map → diagram-QEK2KX5R-B-P9Chdj.js.map} +1 -1
- package/dist/static/assets/{diagram-S2PKOQOG-aeydbv9S.js → diagram-S2PKOQOG-BrnNRpnf.js} +6 -6
- package/dist/static/assets/{diagram-S2PKOQOG-aeydbv9S.js.map → diagram-S2PKOQOG-BrnNRpnf.js.map} +1 -1
- package/dist/static/assets/{erDiagram-Q2GNP2WA-Bjrr_17N.js → erDiagram-Q2GNP2WA-CjhZUP-_.js} +5 -5
- package/dist/static/assets/{erDiagram-Q2GNP2WA-Bjrr_17N.js.map → erDiagram-Q2GNP2WA-CjhZUP-_.js.map} +1 -1
- package/dist/static/assets/{flowDiagram-NV44I4VS-CmJUhZIL.js → flowDiagram-NV44I4VS-DW5irfHa.js} +6 -6
- package/dist/static/assets/{flowDiagram-NV44I4VS-CmJUhZIL.js.map → flowDiagram-NV44I4VS-DW5irfHa.js.map} +1 -1
- package/dist/static/assets/{ganttDiagram-JELNMOA3-D6FQehn7.js → ganttDiagram-JELNMOA3-CkFnAxLO.js} +3 -3
- package/dist/static/assets/{ganttDiagram-JELNMOA3-D6FQehn7.js.map → ganttDiagram-JELNMOA3-CkFnAxLO.js.map} +1 -1
- package/dist/static/assets/{gitGraphDiagram-NY62KEGX-Df_n9jMf.js → gitGraphDiagram-NY62KEGX-CW5UQfhl.js} +7 -7
- package/dist/static/assets/{gitGraphDiagram-NY62KEGX-Df_n9jMf.js.map → gitGraphDiagram-NY62KEGX-CW5UQfhl.js.map} +1 -1
- package/dist/static/assets/{graph--pnRzOJm.js → graph-QsUQvOUG.js} +3 -3
- package/dist/static/assets/{graph--pnRzOJm.js.map → graph-QsUQvOUG.js.map} +1 -1
- package/dist/static/assets/{index-BRtsWi20.js → index-BWgwzFdG.js} +64 -47
- package/dist/static/assets/index-BWgwzFdG.js.map +1 -0
- package/dist/static/assets/{infoDiagram-WHAUD3N6-DPBHtM_B.js → infoDiagram-WHAUD3N6-1hutUswv.js} +5 -5
- package/dist/static/assets/{infoDiagram-WHAUD3N6-DPBHtM_B.js.map → infoDiagram-WHAUD3N6-1hutUswv.js.map} +1 -1
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Bj7Wxlq5.js → journeyDiagram-XKPGCS4Q-CYEB2gYA.js} +5 -5
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Bj7Wxlq5.js.map → journeyDiagram-XKPGCS4Q-CYEB2gYA.js.map} +1 -1
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-C3R4ZPwh.js → kanban-definition-3W4ZIXB7-B_rokrwL.js} +3 -3
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-C3R4ZPwh.js.map → kanban-definition-3W4ZIXB7-B_rokrwL.js.map} +1 -1
- package/dist/static/assets/{layout-BJpf8jM4.js → layout-DD4e7kuc.js} +5 -5
- package/dist/static/assets/{layout-BJpf8jM4.js.map → layout-DD4e7kuc.js.map} +1 -1
- package/dist/static/assets/{linear-CNE3iYsu.js → linear-CpmZo_ZS.js} +2 -2
- package/dist/static/assets/{linear-CNE3iYsu.js.map → linear-CpmZo_ZS.js.map} +1 -1
- package/dist/static/assets/{min-Cswe2bqk.js → min-CFkzEekk.js} +3 -3
- package/dist/static/assets/{min-Cswe2bqk.js.map → min-CFkzEekk.js.map} +1 -1
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-CeuQ--gx.js → mindmap-definition-VGOIOE7T-WLy2VPYm.js} +4 -4
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-CeuQ--gx.js.map → mindmap-definition-VGOIOE7T-WLy2VPYm.js.map} +1 -1
- package/dist/static/assets/{pieDiagram-ADFJNKIX-BnHq9l2P.js → pieDiagram-ADFJNKIX-2nx2cHS8.js} +7 -7
- package/dist/static/assets/{pieDiagram-ADFJNKIX-BnHq9l2P.js.map → pieDiagram-ADFJNKIX-2nx2cHS8.js.map} +1 -1
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-2WOn9ed4.js → quadrantDiagram-AYHSOK5B-ELd4blG4.js} +3 -3
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-2WOn9ed4.js.map → quadrantDiagram-AYHSOK5B-ELd4blG4.js.map} +1 -1
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-CzbOZbJ8.js → requirementDiagram-UZGBJVZJ-BEleMcvW.js} +4 -4
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-CzbOZbJ8.js.map → requirementDiagram-UZGBJVZJ-BEleMcvW.js.map} +1 -1
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-BCY4ttm3.js → sankeyDiagram-TZEHDZUN-_xcwg8aT.js} +2 -2
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-BCY4ttm3.js.map → sankeyDiagram-TZEHDZUN-_xcwg8aT.js.map} +1 -1
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-DV3CMHo6.js → sequenceDiagram-WL72ISMW-B5W6BMbd.js} +4 -4
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-DV3CMHo6.js.map → sequenceDiagram-WL72ISMW-B5W6BMbd.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-B69ywNB2.js → stateDiagram-FKZM4ZOC-BtAHVsVQ.js} +9 -9
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-B69ywNB2.js.map → stateDiagram-FKZM4ZOC-BtAHVsVQ.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-YAQW9OlS.js → stateDiagram-v2-4FDKWEC3-DzGcYKQT.js} +5 -5
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-YAQW9OlS.js.map → stateDiagram-v2-4FDKWEC3-DzGcYKQT.js.map} +1 -1
- package/dist/static/assets/{timeline-definition-IT6M3QCI-DrrUTBG7.js → timeline-definition-IT6M3QCI-UdhLD6FT.js} +3 -3
- package/dist/static/assets/{timeline-definition-IT6M3QCI-DrrUTBG7.js.map → timeline-definition-IT6M3QCI-UdhLD6FT.js.map} +1 -1
- package/dist/static/assets/{treemap-KMMF4GRG-Ld__veZ8.js → treemap-KMMF4GRG-C9kUtGO2.js} +4 -4
- package/dist/static/assets/{treemap-KMMF4GRG-Ld__veZ8.js.map → treemap-KMMF4GRG-C9kUtGO2.js.map} +1 -1
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-DnCUF4Ds.js → xychartDiagram-PRI3JC2R-BZCzGwDm.js} +3 -3
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-DnCUF4Ds.js.map → xychartDiagram-PRI3JC2R-BZCzGwDm.js.map} +1 -1
- package/dist/static/index.html +1 -1
- package/dist/team.js +84 -0
- package/dist/tools/builtins.js +16 -14
- package/dist/tools/os.js +55 -6
- package/dist/tools/prompts/os/en/tools.md +1 -1
- package/dist/tools/prompts/os/zh/tools.md +1 -1
- package/dist/tools/prompts/team_mgmt/en/index.md +1 -0
- package/dist/tools/prompts/team_mgmt/en/tools.md +11 -1
- package/dist/tools/prompts/team_mgmt/zh/index.md +1 -0
- package/dist/tools/prompts/team_mgmt/zh/tools.md +11 -1
- package/dist/tools/team_mgmt.js +115 -26
- package/package.json +1 -1
- package/dist/static/assets/index-BRtsWi20.js.map +0 -1
package/README.md
CHANGED
|
@@ -167,9 +167,13 @@ Then:
|
|
|
167
167
|
1. Your browser should land on `http://localhost:5666/setup` (either directly, or via an automatic redirect).
|
|
168
168
|
2. In **Setup**, pick a provider + model. If your template didn’t create `.minds/team.yaml`, use Setup to create/overwrite it (this writes a minimal `member_defaults` config).
|
|
169
169
|
3. Still in **Setup**, set the required provider env var (the name comes from the provider catalog, e.g. `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `CODEX_HOME`, etc.).
|
|
170
|
-
- The setup UI can write it into `~/.zshrc` / `~/.bashrc` in
|
|
170
|
+
- The setup UI can write it to `.env.local` (all platforms), and on Linux/macOS it can also write into `~/.zshrc` / `~/.bashrc` in managed blocks. It also applies the value to the running server process immediately.
|
|
171
171
|
4. Click **Go to App**, create a dialog, and start working.
|
|
172
172
|
|
|
173
|
+
Platform note:
|
|
174
|
+
|
|
175
|
+
- On Windows, the runtime does not register the `codex_style_tools` toolset. Do not grant `codex_style_tools` in `.minds/team.yaml` for Windows hosts.
|
|
176
|
+
|
|
173
177
|
## Start from scratch
|
|
174
178
|
|
|
175
179
|
Starting from scratch means: create an empty folder, run `dominds`, let Setup generate the minimal `.minds/team.yaml`, then use the shadow team manager (`@fuxi`) to design a real team for your product.
|
package/README.zh.md
CHANGED
|
@@ -89,9 +89,13 @@ dominds
|
|
|
89
89
|
首次启动后,通常会自动跳转至 `http://localhost:5666/setup` 配置页面,按以下步骤操作:
|
|
90
90
|
|
|
91
91
|
1. 选择提供商(provider)及模型(model),创建或覆盖 `.minds/team.yaml`(最小化可运行配置文件)。
|
|
92
|
-
2.
|
|
92
|
+
2. 根据提示设置提供商所需的环境变量(配置页可将变量写入 `.env.local`,并在 Linux/macOS 上额外支持写入 `~/.zshrc` 或 `~/.bashrc` 的托管区块)。
|
|
93
93
|
3. 进入主界面,创建对话即可开始工作(对话、记忆、差遣牒等运行态数据均存储在当前 rtws 下)。
|
|
94
94
|
|
|
95
|
+
平台说明:
|
|
96
|
+
|
|
97
|
+
- Windows 运行时不会注册 `codex_style_tools` 工具集。在 Windows 主机上的 `.minds/team.yaml` 中不要授予 `codex_style_tools`。
|
|
98
|
+
|
|
95
99
|
## 从零开始(空文件夹启动)
|
|
96
100
|
|
|
97
101
|
若暂无模板或团队配置,可直接从空目录启动:
|
package/dist/access-control.js
CHANGED
|
@@ -10,7 +10,7 @@ exports.getAccessDeniedMessage = getAccessDeniedMessage;
|
|
|
10
10
|
/**
|
|
11
11
|
* Module: access-control
|
|
12
12
|
*
|
|
13
|
-
* Directory-based access control helpers:
|
|
13
|
+
* Directory/file-extension based access control helpers:
|
|
14
14
|
* - `matchesPattern` for glob-like directory scope matching (supports `*` and `**`)
|
|
15
15
|
* - `hasReadAccess`/`hasWriteAccess` to evaluate member permissions
|
|
16
16
|
* - `getAccessDeniedMessage` to format denial responses
|
|
@@ -31,6 +31,41 @@ function isRootDialogsPath(targetPath) {
|
|
|
31
31
|
const normalized = targetPath.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
32
32
|
return normalized === '.dialogs' || normalized.startsWith('.dialogs/');
|
|
33
33
|
}
|
|
34
|
+
function normalizeFileExtName(raw) {
|
|
35
|
+
return raw.trim().toLowerCase().replace(/^\.+/, '');
|
|
36
|
+
}
|
|
37
|
+
function extractFileExtName(targetPath) {
|
|
38
|
+
const normalized = targetPath.replace(/\\/g, '/').replace(/\/+$/g, '');
|
|
39
|
+
if (normalized === '' || normalized === '.')
|
|
40
|
+
return undefined;
|
|
41
|
+
const baseName = normalized.split('/').pop();
|
|
42
|
+
if (!baseName || baseName === '.' || baseName === '..')
|
|
43
|
+
return undefined;
|
|
44
|
+
const dotIndex = baseName.lastIndexOf('.');
|
|
45
|
+
if (dotIndex <= 0 || dotIndex === baseName.length - 1)
|
|
46
|
+
return undefined;
|
|
47
|
+
return normalizeFileExtName(baseName.slice(dotIndex + 1));
|
|
48
|
+
}
|
|
49
|
+
function hasFileExtAccess(fileExtName, whitelist, blacklist) {
|
|
50
|
+
// Extension rules only apply to file-like paths with a detectable extension.
|
|
51
|
+
if (!fileExtName)
|
|
52
|
+
return true;
|
|
53
|
+
for (const ext of blacklist ?? []) {
|
|
54
|
+
if (normalizeFileExtName(ext) === fileExtName) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const allow = whitelist ?? [];
|
|
59
|
+
if (allow.length === 0) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
for (const ext of allow) {
|
|
63
|
+
if (normalizeFileExtName(ext) === fileExtName) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
34
69
|
/**
|
|
35
70
|
* Directory-specific pattern matching for access control.
|
|
36
71
|
* This function determines if a target path (file or directory) should be controlled
|
|
@@ -142,8 +177,10 @@ function matchesPattern(targetPath, dirPattern) {
|
|
|
142
177
|
* Access control logic:
|
|
143
178
|
* 1. Check blacklist first (no_read_dirs) - if path matches any blacklist pattern, deny access
|
|
144
179
|
* 2. Check whitelist (read_dirs) - if path matches any whitelist pattern, allow access
|
|
145
|
-
* 3.
|
|
146
|
-
* 4.
|
|
180
|
+
* 3. Check extension blacklist (no_read_file_ext_names) - if extension matches, deny access
|
|
181
|
+
* 4. Check extension whitelist (read_file_ext_names)
|
|
182
|
+
* 5. If no whitelist patterns are defined for a dimension, allow access (default allow)
|
|
183
|
+
* 6. If whitelist patterns exist but none match, deny access
|
|
147
184
|
*/
|
|
148
185
|
function hasReadAccess(member, targetPath) {
|
|
149
186
|
// Get resolved relative path from rtws root
|
|
@@ -183,17 +220,19 @@ function hasReadAccess(member, targetPath) {
|
|
|
183
220
|
const whitelist = member.read_dirs || [];
|
|
184
221
|
// Note: `.minds/**` is handled above as a hard deny (unless internal bypass is enabled).
|
|
185
222
|
// If no whitelist is defined, allow access (after blacklist check)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
223
|
+
let directoryAllowed = whitelist.length === 0;
|
|
224
|
+
if (!directoryAllowed) {
|
|
225
|
+
// Check if path matches any whitelist pattern
|
|
226
|
+
for (const pattern of whitelist) {
|
|
227
|
+
if (matchesPattern(relativePath, pattern)) {
|
|
228
|
+
directoryAllowed = true;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
193
231
|
}
|
|
194
232
|
}
|
|
195
|
-
|
|
196
|
-
|
|
233
|
+
if (!directoryAllowed)
|
|
234
|
+
return false;
|
|
235
|
+
return hasFileExtAccess(extractFileExtName(relativePath), member.read_file_ext_names, member.no_read_file_ext_names);
|
|
197
236
|
}
|
|
198
237
|
/**
|
|
199
238
|
* Check if a member has write access to a specific path.
|
|
@@ -201,8 +240,10 @@ function hasReadAccess(member, targetPath) {
|
|
|
201
240
|
* Access control logic:
|
|
202
241
|
* 1. Check blacklist first (no_write_dirs) - if path matches any blacklist pattern, deny access
|
|
203
242
|
* 2. Check whitelist (write_dirs) - if path matches any whitelist pattern, allow access
|
|
204
|
-
* 3.
|
|
205
|
-
* 4.
|
|
243
|
+
* 3. Check extension blacklist (no_write_file_ext_names) - if extension matches, deny access
|
|
244
|
+
* 4. Check extension whitelist (write_file_ext_names)
|
|
245
|
+
* 5. If no whitelist patterns are defined for a dimension, allow access (default allow)
|
|
246
|
+
* 6. If whitelist patterns exist but none match, deny access
|
|
206
247
|
*/
|
|
207
248
|
function hasWriteAccess(member, targetPath) {
|
|
208
249
|
// Get resolved relative path from rtws root
|
|
@@ -242,17 +283,19 @@ function hasWriteAccess(member, targetPath) {
|
|
|
242
283
|
const whitelist = member.write_dirs || [];
|
|
243
284
|
// Note: `.minds/**` is handled above as a hard deny (unless internal bypass is enabled).
|
|
244
285
|
// If no whitelist is defined, allow access (after blacklist check)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
286
|
+
let directoryAllowed = whitelist.length === 0;
|
|
287
|
+
if (!directoryAllowed) {
|
|
288
|
+
// Check if path matches any whitelist pattern
|
|
289
|
+
for (const pattern of whitelist) {
|
|
290
|
+
if (matchesPattern(relativePath, pattern)) {
|
|
291
|
+
directoryAllowed = true;
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
252
294
|
}
|
|
253
295
|
}
|
|
254
|
-
|
|
255
|
-
|
|
296
|
+
if (!directoryAllowed)
|
|
297
|
+
return false;
|
|
298
|
+
return hasFileExtAccess(extractFileExtName(relativePath), member.write_file_ext_names, member.no_write_file_ext_names);
|
|
256
299
|
}
|
|
257
300
|
/**
|
|
258
301
|
* Get an access denied error message for a specific operation and path.
|
|
@@ -308,5 +351,11 @@ function getAccessDeniedMessage(operation, targetPath, language = 'en') {
|
|
|
308
351
|
lines.push(`- Hint: For Dominds debugging, reproduce in a nested rtws (e.g. \`ux-rtws/.dialogs/\`), which is not covered by this hard deny.`);
|
|
309
352
|
}
|
|
310
353
|
}
|
|
354
|
+
if (language === 'zh') {
|
|
355
|
+
lines.push(`- 说明:该路径可能命中目录权限(\`read_dirs/write_dirs/no_*_dirs\`)或扩展名权限(\`*_file_ext_names/no_*_file_ext_names\`)。`);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
lines.push(`- Note: This path may be blocked by directory rules (\`read_dirs/write_dirs/no_*_dirs\`) or file-extension rules (\`*_file_ext_names/no_*_file_ext_names\`).`);
|
|
359
|
+
}
|
|
311
360
|
return lines.join('\n');
|
|
312
361
|
}
|
|
@@ -424,6 +424,7 @@ Best practices:
|
|
|
424
424
|
|
|
425
425
|
- Make `member_defaults` conservative. Grant additional tools/dirs on a per-member basis.
|
|
426
426
|
- Prefer toolsets over individually enumerating tools unless you need a one-off tool.
|
|
427
|
+
- Platform note: Windows runtime intentionally does not register `codex_style_tools`; do not grant that toolset in `.minds/team.yaml` on Windows hosts.
|
|
427
428
|
- Keep `.minds/team.yaml` ownership tight; only the team manager should be able to edit it.
|
|
428
429
|
- Avoid repeating built-in constraints in `team.yaml`:
|
|
429
430
|
- `*.tsk/**` (encapsulated Taskdocs) are hard-denied for all general file tools.
|
|
@@ -370,6 +370,7 @@ members:
|
|
|
370
370
|
|
|
371
371
|
- 使 `member_defaults` 保守。按成员授予额外的工具/目录
|
|
372
372
|
- 优先使用工具集而不是单独枚举工具,除非你需要一次性工具
|
|
373
|
+
- 平台说明:Windows 运行时不会注册 `codex_style_tools`;在 Windows 主机上的 `.minds/team.yaml` 中不要授予该工具集
|
|
373
374
|
- 保持 `.minds/team.yaml` 的所有权严格;只有团队管理者应该能够编辑它
|
|
374
375
|
- 避免在 `team.yaml` 中重复内置约束:
|
|
375
376
|
- `*.tsk/**`(封装的 Taskdocs)对所有通用文件工具被硬性拒绝
|
|
@@ -19,14 +19,17 @@ const team_config_updates_1 = require("../team-config-updates");
|
|
|
19
19
|
const log = (0, log_1.createLogger)('setup-routes');
|
|
20
20
|
const TEAM_YAML_PATH = path_1.default.join('.minds', 'team.yaml');
|
|
21
21
|
const RTWS_LLM_YAML_PATH = path_1.default.join('.minds', 'llm.yaml');
|
|
22
|
+
const RTWS_ENV_LOCAL_PATH = '.env.local';
|
|
22
23
|
const BUILTIN_DEFAULTS_YAML_PATH = path_1.default.join(__dirname, '..', 'llm', 'defaults.yaml');
|
|
23
24
|
const DOMINDS_ENV_BLOCK_START = '# >>> dominds env >>>';
|
|
24
25
|
const DOMINDS_ENV_BLOCK_END = '# <<< dominds env <<<';
|
|
25
26
|
async function buildSetupStatusResponse() {
|
|
26
27
|
const builtin = await loadBuiltinProviders();
|
|
27
28
|
const merged = await client_1.LlmConfig.load();
|
|
29
|
+
const shellPlatform = resolveSetupPlatform(process.platform);
|
|
28
30
|
const shellEnv = typeof process.env.SHELL === 'string' ? process.env.SHELL : null;
|
|
29
31
|
const shellKind = resolveShellKind(shellEnv);
|
|
32
|
+
const envLocal = await statRcFile(RTWS_ENV_LOCAL_PATH);
|
|
30
33
|
const home = os_1.default.homedir();
|
|
31
34
|
const bashrcPath = path_1.default.join(home, '.bashrc');
|
|
32
35
|
const zshrcPath = path_1.default.join(home, '.zshrc');
|
|
@@ -44,7 +47,13 @@ async function buildSetupStatusResponse() {
|
|
|
44
47
|
return {
|
|
45
48
|
success: false,
|
|
46
49
|
requirement,
|
|
47
|
-
shell: {
|
|
50
|
+
shell: {
|
|
51
|
+
platform: shellPlatform,
|
|
52
|
+
env: shellEnv,
|
|
53
|
+
kind: shellKind,
|
|
54
|
+
defaultRc: shellKindToDefaultRc(shellKind),
|
|
55
|
+
},
|
|
56
|
+
envLocal,
|
|
48
57
|
rc,
|
|
49
58
|
teamYaml,
|
|
50
59
|
rtwsLlmYaml,
|
|
@@ -53,13 +62,20 @@ async function buildSetupStatusResponse() {
|
|
|
53
62
|
};
|
|
54
63
|
}
|
|
55
64
|
const providers = await buildProviderSummaries(builtin.providers, builtin.providerKeysInOrder, {
|
|
65
|
+
envLocalPath: RTWS_ENV_LOCAL_PATH,
|
|
56
66
|
bashrcPath,
|
|
57
67
|
zshrcPath,
|
|
58
68
|
});
|
|
59
69
|
return {
|
|
60
70
|
success: true,
|
|
61
71
|
requirement,
|
|
62
|
-
shell: {
|
|
72
|
+
shell: {
|
|
73
|
+
platform: shellPlatform,
|
|
74
|
+
env: shellEnv,
|
|
75
|
+
kind: shellKind,
|
|
76
|
+
defaultRc: shellKindToDefaultRc(shellKind),
|
|
77
|
+
},
|
|
78
|
+
envLocal,
|
|
63
79
|
rc,
|
|
64
80
|
teamYaml,
|
|
65
81
|
rtwsLlmYaml,
|
|
@@ -117,15 +133,27 @@ async function handleWriteShellEnv(rawBody) {
|
|
|
117
133
|
try {
|
|
118
134
|
// Apply to the current backend process immediately so setup can proceed without a restart.
|
|
119
135
|
process.env[req.envVar] = req.value;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
let filePath;
|
|
137
|
+
let result;
|
|
138
|
+
if (req.target === 'env_local') {
|
|
139
|
+
filePath = RTWS_ENV_LOCAL_PATH;
|
|
140
|
+
result = await upsertEnvVarIntoDotenvFile(filePath, req.envVar, req.value);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
if (!isPosixSetupPlatform(process.platform)) {
|
|
144
|
+
return {
|
|
145
|
+
kind: 'bad_request',
|
|
146
|
+
errorText: `Unsupported target on this platform: ${req.target}`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const home = os_1.default.homedir();
|
|
150
|
+
filePath = path_1.default.join(home, req.target === 'bashrc' ? '.bashrc' : '.zshrc');
|
|
151
|
+
result = await upsertEnvVarIntoRcFile(filePath, req.envVar, req.value);
|
|
127
152
|
}
|
|
128
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
kind: 'ok',
|
|
155
|
+
response: { success: true, outcome: { target: req.target, path: filePath, result } },
|
|
156
|
+
};
|
|
129
157
|
}
|
|
130
158
|
catch (error) {
|
|
131
159
|
log.error('Failed to write shell env vars', error);
|
|
@@ -270,8 +298,9 @@ async function buildProviderSummaries(providers, providerKeysInOrder, paths) {
|
|
|
270
298
|
for (const [providerKey, cfg] of orderedProviderEntries(providers, providerKeysInOrder)) {
|
|
271
299
|
const envVar = cfg.apiKeyEnvVar;
|
|
272
300
|
const envVarIsSet = typeof process.env[envVar] === 'string' && process.env[envVar] !== '';
|
|
273
|
-
const
|
|
274
|
-
const
|
|
301
|
+
const envLocalHas = await fileHasEnvVar(paths.envLocalPath, envVar);
|
|
302
|
+
const bashrcHas = await fileHasEnvVar(paths.bashrcPath, envVar);
|
|
303
|
+
const zshrcHas = await fileHasEnvVar(paths.zshrcPath, envVar);
|
|
275
304
|
const models = Object.entries(cfg.models ?? {}).map(([modelKey, modelInfo]) => {
|
|
276
305
|
const info = isRecord(modelInfo) ? modelInfo : {};
|
|
277
306
|
const name = typeof info.name === 'string' ? info.name : undefined;
|
|
@@ -298,7 +327,7 @@ async function buildProviderSummaries(providers, providerKeysInOrder, paths) {
|
|
|
298
327
|
apiKeyEnvVar: envVar,
|
|
299
328
|
techSpecUrl: cfg.tech_spec_url,
|
|
300
329
|
apiMgmtUrl: cfg.api_mgmt_url,
|
|
301
|
-
envVar: { isSet: envVarIsSet, bashrcHas, zshrcHas },
|
|
330
|
+
envVar: { isSet: envVarIsSet, envLocalHas, bashrcHas, zshrcHas },
|
|
302
331
|
models,
|
|
303
332
|
...(prominent.length > 0 ? { prominentModelParams: prominent } : {}),
|
|
304
333
|
};
|
|
@@ -515,6 +544,18 @@ async function resolveSetupRequirement(params) {
|
|
|
515
544
|
}
|
|
516
545
|
return { kind: 'ok' };
|
|
517
546
|
}
|
|
547
|
+
function resolveSetupPlatform(platform) {
|
|
548
|
+
if (platform === 'win32')
|
|
549
|
+
return 'windows';
|
|
550
|
+
if (platform === 'darwin')
|
|
551
|
+
return 'macos';
|
|
552
|
+
if (platform === 'linux')
|
|
553
|
+
return 'linux';
|
|
554
|
+
return 'other';
|
|
555
|
+
}
|
|
556
|
+
function isPosixSetupPlatform(platform) {
|
|
557
|
+
return platform === 'darwin' || platform === 'linux';
|
|
558
|
+
}
|
|
518
559
|
function resolveShellKind(shellEnv) {
|
|
519
560
|
if (!shellEnv)
|
|
520
561
|
return 'other';
|
|
@@ -537,21 +578,14 @@ function parseWriteShellEnvRequest(value) {
|
|
|
537
578
|
return null;
|
|
538
579
|
const envVar = value['envVar'];
|
|
539
580
|
const rawVal = value['value'];
|
|
540
|
-
const
|
|
581
|
+
const target = value['target'];
|
|
541
582
|
if (typeof envVar !== 'string' || !isSafeEnvVarName(envVar))
|
|
542
583
|
return null;
|
|
543
584
|
if (typeof rawVal !== 'string')
|
|
544
585
|
return null;
|
|
545
|
-
if (
|
|
546
|
-
return null;
|
|
547
|
-
const targets = [];
|
|
548
|
-
for (const t of targetsUnknown) {
|
|
549
|
-
if (t === 'bashrc' || t === 'zshrc')
|
|
550
|
-
targets.push(t);
|
|
551
|
-
}
|
|
552
|
-
if (targets.length === 0)
|
|
586
|
+
if (target !== 'env_local' && target !== 'bashrc' && target !== 'zshrc')
|
|
553
587
|
return null;
|
|
554
|
-
return { envVar, value: rawVal,
|
|
588
|
+
return { envVar, value: rawVal, target };
|
|
555
589
|
}
|
|
556
590
|
function parseWriteTeamYamlRequest(value) {
|
|
557
591
|
if (!isRecord(value))
|
|
@@ -640,10 +674,10 @@ async function isWritable(filePath) {
|
|
|
640
674
|
return false;
|
|
641
675
|
}
|
|
642
676
|
}
|
|
643
|
-
async function
|
|
677
|
+
async function fileHasEnvVar(filePath, envVar) {
|
|
644
678
|
try {
|
|
645
|
-
const raw = await promises_1.default.readFile(
|
|
646
|
-
const re = new RegExp(`(^|\\n)\\s*export\\s
|
|
679
|
+
const raw = await promises_1.default.readFile(filePath, 'utf-8');
|
|
680
|
+
const re = new RegExp(`(^|\\n)\\s*(?:export\\s+)?${escapeRegExp(envVar)}\\s*=`, 'm');
|
|
647
681
|
return re.test(raw);
|
|
648
682
|
}
|
|
649
683
|
catch {
|
|
@@ -657,6 +691,28 @@ function shellQuoteSingle(value) {
|
|
|
657
691
|
// Safe POSIX shell single-quoted string: close quote, escape single quote, reopen.
|
|
658
692
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
659
693
|
}
|
|
694
|
+
function dotenvQuoteDouble(value) {
|
|
695
|
+
const escaped = value
|
|
696
|
+
.replace(/\\/g, '\\\\')
|
|
697
|
+
.replace(/\n/g, '\\n')
|
|
698
|
+
.replace(/\r/g, '\\r')
|
|
699
|
+
.replace(/\t/g, '\\t')
|
|
700
|
+
.replace(/"/g, '\\"');
|
|
701
|
+
return `"${escaped}"`;
|
|
702
|
+
}
|
|
703
|
+
async function upsertEnvVarIntoDotenvFile(filePath, envVar, value) {
|
|
704
|
+
const line = `${envVar}=${dotenvQuoteDouble(value)}`;
|
|
705
|
+
const exists = await fileExists(filePath);
|
|
706
|
+
const original = exists ? await promises_1.default.readFile(filePath, 'utf-8') : '';
|
|
707
|
+
const normalized = original.replace(/\r\n/g, '\n');
|
|
708
|
+
const lines = normalized === '' ? [] : normalized.split('\n');
|
|
709
|
+
const nextLines = upsertDotenvLine(lines, envVar, line);
|
|
710
|
+
let next = nextLines.join('\n');
|
|
711
|
+
if (!next.endsWith('\n'))
|
|
712
|
+
next += '\n';
|
|
713
|
+
await promises_1.default.writeFile(filePath, next, 'utf-8');
|
|
714
|
+
return exists ? 'updated' : 'created';
|
|
715
|
+
}
|
|
660
716
|
async function upsertEnvVarIntoRcFile(filePath, envVar, value) {
|
|
661
717
|
const exportLine = `export ${envVar}=${shellQuoteSingle(value)}`;
|
|
662
718
|
const exists = await fileExists(filePath);
|
|
@@ -684,6 +740,16 @@ async function upsertEnvVarIntoRcFile(filePath, envVar, value) {
|
|
|
684
740
|
await promises_1.default.writeFile(filePath, next, 'utf-8');
|
|
685
741
|
return exists ? 'updated' : 'created';
|
|
686
742
|
}
|
|
743
|
+
function upsertDotenvLine(lines, envVar, envLine) {
|
|
744
|
+
const re = new RegExp(`^\\s*(?:export\\s+)?${escapeRegExp(envVar)}\\s*=`);
|
|
745
|
+
const idx = lines.findIndex((l) => re.test(l));
|
|
746
|
+
if (idx >= 0) {
|
|
747
|
+
const copy = [...lines];
|
|
748
|
+
copy[idx] = envLine;
|
|
749
|
+
return copy;
|
|
750
|
+
}
|
|
751
|
+
return [...lines, envLine];
|
|
752
|
+
}
|
|
687
753
|
function upsertExportLine(lines, envVar, exportLine) {
|
|
688
754
|
const re = new RegExp(`^\\s*export\\s+${escapeRegExp(envVar)}=`);
|
|
689
755
|
const idx = lines.findIndex((l) => re.test(l));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aV as isObjectLike, br as baseGetTag, aE as isArray, aT as Symbol$1, bs as arrayLikeKeys, bt as baseKeys, aD as isArrayLike, bu as memoize, bv as isArguments, bw as MapCache, bm as eq, bx as Uint8Array, aW as getTag, a$ as isBuffer, b2 as Stack, by as isTypedArray, aZ as isObject, bz as isLength, bp as isIndex, aF as identity, bn as baseFor, bA as Set } from "./index-
|
|
1
|
+
import { aV as isObjectLike, br as baseGetTag, aE as isArray, aT as Symbol$1, bs as arrayLikeKeys, bt as baseKeys, aD as isArrayLike, bu as memoize, bv as isArguments, bw as MapCache, bm as eq, bx as Uint8Array, aW as getTag, a$ as isBuffer, b2 as Stack, by as isTypedArray, aZ as isObject, bz as isLength, bp as isIndex, aF as identity, bn as baseFor, bA as Set } from "./index-BWgwzFdG.js";
|
|
2
2
|
var symbolTag$1 = "[object Symbol]";
|
|
3
3
|
function isSymbol(value) {
|
|
4
4
|
return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag$1;
|
|
@@ -658,4 +658,4 @@ export {
|
|
|
658
658
|
hasIn as x,
|
|
659
659
|
toString as y
|
|
660
660
|
};
|
|
661
|
-
//# sourceMappingURL=_baseUniq-
|
|
661
|
+
//# sourceMappingURL=_baseUniq-CoUduYbj.js.map
|