dominds 1.25.10 → 1.25.12
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 +1 -1
- package/README.zh.md +1 -1
- package/dist/access-control.js +9 -5
- package/dist/docs/team_mgmt-toolset.md +1 -1
- package/dist/docs/team_mgmt-toolset.zh.md +1 -1
- package/dist/llm/kernel-driver/drive.js +68 -5
- package/dist/llm/kernel-driver/fbr.js +2 -0
- package/dist/llm/kernel-driver/tellask-special.d.ts +1 -0
- package/dist/llm/kernel-driver/tellask-special.js +6 -1
- package/dist/persistence.js +5 -11
- package/dist/server/dominds-self-update.js +36 -4
- package/dist/server/websocket-handler.js +31 -2
- package/dist/tools/builtins.js +14 -16
- package/dist/tools/ctrl.js +1 -0
- package/dist/tools/os.d.ts +14 -0
- package/dist/tools/os.js +508 -101
- package/dist/tools/prompts/codex_inspect_and_patch_tools/en/tools.md +2 -1
- package/dist/tools/prompts/codex_inspect_and_patch_tools/zh/tools.md +2 -1
- package/package.json +3 -3
- package/webapp/dist/assets/{_basePickBy-B4PyBhGX.js → _basePickBy-B1-brAPU.js} +3 -3
- package/webapp/dist/assets/{_basePickBy-B4PyBhGX.js.map → _basePickBy-B1-brAPU.js.map} +1 -1
- package/webapp/dist/assets/{_baseUniq-Cj1Wg2fB.js → _baseUniq-BuB0jmKD.js} +2 -2
- package/webapp/dist/assets/{_baseUniq-Cj1Wg2fB.js.map → _baseUniq-BuB0jmKD.js.map} +1 -1
- package/webapp/dist/assets/{arc-CWrSn-79.js → arc-CvsBvjnB.js} +2 -2
- package/webapp/dist/assets/{arc-CWrSn-79.js.map → arc-CvsBvjnB.js.map} +1 -1
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-7iHYM2Z2.js → architectureDiagram-2XIMDMQ5-B-xGuLbb.js} +7 -7
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-7iHYM2Z2.js.map → architectureDiagram-2XIMDMQ5-B-xGuLbb.js.map} +1 -1
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-B1TGBHuF.js → blockDiagram-WCTKOSBZ-Bu53fwsa.js} +7 -7
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-B1TGBHuF.js.map → blockDiagram-WCTKOSBZ-Bu53fwsa.js.map} +1 -1
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-BXTEEF9u.js → c4Diagram-IC4MRINW-D9-FJ4LB.js} +3 -3
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-BXTEEF9u.js.map → c4Diagram-IC4MRINW-D9-FJ4LB.js.map} +1 -1
- package/webapp/dist/assets/{channel-C9f2l1ub.js → channel-D1VPurpu.js} +2 -2
- package/webapp/dist/assets/{channel-C9f2l1ub.js.map → channel-D1VPurpu.js.map} +1 -1
- package/webapp/dist/assets/{chunk-4BX2VUAB-CXrwbryc.js → chunk-4BX2VUAB-DB14wcWS.js} +2 -2
- package/webapp/dist/assets/{chunk-4BX2VUAB-CXrwbryc.js.map → chunk-4BX2VUAB-DB14wcWS.js.map} +1 -1
- package/webapp/dist/assets/{chunk-55IACEB6-WAoUKKa8.js → chunk-55IACEB6-C5KCE85A.js} +2 -2
- package/webapp/dist/assets/{chunk-55IACEB6-WAoUKKa8.js.map → chunk-55IACEB6-C5KCE85A.js.map} +1 -1
- package/webapp/dist/assets/{chunk-FMBD7UC4-CP1cvzbf.js → chunk-FMBD7UC4-Bb6zm0iH.js} +2 -2
- package/webapp/dist/assets/{chunk-FMBD7UC4-CP1cvzbf.js.map → chunk-FMBD7UC4-Bb6zm0iH.js.map} +1 -1
- package/webapp/dist/assets/{chunk-JSJVCQXG-Od7hQgy7.js → chunk-JSJVCQXG-CJPrv6fM.js} +2 -2
- package/webapp/dist/assets/{chunk-JSJVCQXG-Od7hQgy7.js.map → chunk-JSJVCQXG-CJPrv6fM.js.map} +1 -1
- package/webapp/dist/assets/{chunk-KX2RTZJC-Cp53YoAm.js → chunk-KX2RTZJC-8J1Swk7E.js} +2 -2
- package/webapp/dist/assets/{chunk-KX2RTZJC-Cp53YoAm.js.map → chunk-KX2RTZJC-8J1Swk7E.js.map} +1 -1
- package/webapp/dist/assets/{chunk-NQ4KR5QH-DkyaPUwI.js → chunk-NQ4KR5QH-DySHY4x9.js} +4 -4
- package/webapp/dist/assets/{chunk-NQ4KR5QH-DkyaPUwI.js.map → chunk-NQ4KR5QH-DySHY4x9.js.map} +1 -1
- package/webapp/dist/assets/{chunk-QZHKN3VN-DPcrZWPF.js → chunk-QZHKN3VN-CTO5Z-4P.js} +2 -2
- package/webapp/dist/assets/{chunk-QZHKN3VN-DPcrZWPF.js.map → chunk-QZHKN3VN-CTO5Z-4P.js.map} +1 -1
- package/webapp/dist/assets/{chunk-WL4C6EOR-BCx3EtFm.js → chunk-WL4C6EOR-Ci_Ec8Ax.js} +6 -6
- package/webapp/dist/assets/{chunk-WL4C6EOR-BCx3EtFm.js.map → chunk-WL4C6EOR-Ci_Ec8Ax.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-BnwaVhDD.js → classDiagram-VBA2DB6C-CxAxBvv7.js} +7 -7
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-BnwaVhDD.js.map → classDiagram-VBA2DB6C-CxAxBvv7.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BnwaVhDD.js → classDiagram-v2-RAHNMMFH-CxAxBvv7.js} +7 -7
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BnwaVhDD.js.map → classDiagram-v2-RAHNMMFH-CxAxBvv7.js.map} +1 -1
- package/webapp/dist/assets/{clone-B32zbBXk.js → clone-ePiNaiNY.js} +2 -2
- package/webapp/dist/assets/{clone-B32zbBXk.js.map → clone-ePiNaiNY.js.map} +1 -1
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-DexuXMat.js → cose-bilkent-S5V4N54A-j-Ex-Sef.js} +2 -2
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-DexuXMat.js.map → cose-bilkent-S5V4N54A-j-Ex-Sef.js.map} +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-D-3S_ma4.js → dagre-KLK3FWXG-ihZ2wOCM.js} +7 -7
- package/webapp/dist/assets/{dagre-KLK3FWXG-D-3S_ma4.js.map → dagre-KLK3FWXG-ihZ2wOCM.js.map} +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-CR7hat4A.js → diagram-E7M64L7V-Cp4GQGS7.js} +8 -8
- package/webapp/dist/assets/{diagram-E7M64L7V-CR7hat4A.js.map → diagram-E7M64L7V-Cp4GQGS7.js.map} +1 -1
- package/webapp/dist/assets/{diagram-IFDJBPK2-B6qnqfZU.js → diagram-IFDJBPK2-B70cgyS5.js} +7 -7
- package/webapp/dist/assets/{diagram-IFDJBPK2-B6qnqfZU.js.map → diagram-IFDJBPK2-B70cgyS5.js.map} +1 -1
- package/webapp/dist/assets/{diagram-P4PSJMXO-BDGFMbld.js → diagram-P4PSJMXO-DMOv7eKE.js} +7 -7
- package/webapp/dist/assets/{diagram-P4PSJMXO-BDGFMbld.js.map → diagram-P4PSJMXO-DMOv7eKE.js.map} +1 -1
- package/webapp/dist/assets/{erDiagram-INFDFZHY-BcXnNg1A.js → erDiagram-INFDFZHY-BKpXWjIc.js} +5 -5
- package/webapp/dist/assets/{erDiagram-INFDFZHY-BcXnNg1A.js.map → erDiagram-INFDFZHY-BKpXWjIc.js.map} +1 -1
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CgKu7usU.js → flowDiagram-PKNHOUZH-DgrItj0h.js} +7 -7
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CgKu7usU.js.map → flowDiagram-PKNHOUZH-DgrItj0h.js.map} +1 -1
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-BwkrQGcZ.js → ganttDiagram-A5KZAMGK-7-8hlYsT.js} +3 -3
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-BwkrQGcZ.js.map → ganttDiagram-A5KZAMGK-7-8hlYsT.js.map} +1 -1
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-CVqi-T5p.js → gitGraphDiagram-K3NZZRJ6-cPSaCUUk.js} +8 -8
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-CVqi-T5p.js.map → gitGraphDiagram-K3NZZRJ6-cPSaCUUk.js.map} +1 -1
- package/webapp/dist/assets/{graph-B7VL6q5k.js → graph-CAlg3tEk.js} +3 -3
- package/webapp/dist/assets/{graph-B7VL6q5k.js.map → graph-CAlg3tEk.js.map} +1 -1
- package/webapp/dist/assets/{index-4xG_gPRh.js → index-DLTS_eOh.js} +245 -61
- package/webapp/dist/assets/{index-4xG_gPRh.js.map → index-DLTS_eOh.js.map} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-a9WBcgds.js → infoDiagram-LFFYTUFH-CHJHvxMC.js} +6 -6
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-a9WBcgds.js.map → infoDiagram-LFFYTUFH-CHJHvxMC.js.map} +1 -1
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-Bhiex3_9.js → ishikawaDiagram-PHBUUO56-S8N-XZ8E.js} +2 -2
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-Bhiex3_9.js.map → ishikawaDiagram-PHBUUO56-S8N-XZ8E.js.map} +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-DdMDmgOQ.js → journeyDiagram-4ABVD52K-ChHNpMtH.js} +5 -5
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-DdMDmgOQ.js.map → journeyDiagram-4ABVD52K-ChHNpMtH.js.map} +1 -1
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-C02Ns-Ee.js → kanban-definition-K7BYSVSG-Cqxd99wZ.js} +3 -3
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-C02Ns-Ee.js.map → kanban-definition-K7BYSVSG-Cqxd99wZ.js.map} +1 -1
- package/webapp/dist/assets/{layout-CKFoJLnz.js → layout-uOLcVthp.js} +5 -5
- package/webapp/dist/assets/{layout-CKFoJLnz.js.map → layout-uOLcVthp.js.map} +1 -1
- package/webapp/dist/assets/{linear-DK87WR34.js → linear-Ga_f4H_w.js} +2 -2
- package/webapp/dist/assets/{linear-DK87WR34.js.map → linear-Ga_f4H_w.js.map} +1 -1
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-CNPEaAdT.js → mindmap-definition-YRQLILUH-TSH7wOlZ.js} +4 -4
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-CNPEaAdT.js.map → mindmap-definition-YRQLILUH-TSH7wOlZ.js.map} +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-BAieZgqR.js → pieDiagram-SKSYHLDU-DPXszqns.js} +8 -8
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-BAieZgqR.js.map → pieDiagram-SKSYHLDU-DPXszqns.js.map} +1 -1
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-DNfJ-efQ.js → quadrantDiagram-337W2JSQ-BgA_GVhR.js} +3 -3
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-DNfJ-efQ.js.map → quadrantDiagram-337W2JSQ-BgA_GVhR.js.map} +1 -1
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-Ci2ficlW.js → requirementDiagram-Z7DCOOCP-CM-47daj.js} +4 -4
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-Ci2ficlW.js.map → requirementDiagram-Z7DCOOCP-CM-47daj.js.map} +1 -1
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-y2RH0qmH.js → sankeyDiagram-WA2Y5GQK-CxDCwHAj.js} +2 -2
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-y2RH0qmH.js.map → sankeyDiagram-WA2Y5GQK-CxDCwHAj.js.map} +1 -1
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-C4Mbfwyu.js → sequenceDiagram-2WXFIKYE-1UJP6Fff.js} +4 -4
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-C4Mbfwyu.js.map → sequenceDiagram-2WXFIKYE-1UJP6Fff.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-enKQJ7WW.js → stateDiagram-RAJIS63D-B2aqr0KQ.js} +9 -9
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-enKQJ7WW.js.map → stateDiagram-RAJIS63D-B2aqr0KQ.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-44zqAgYM.js → stateDiagram-v2-FVOUBMTO-DvmkevVb.js} +5 -5
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-44zqAgYM.js.map → stateDiagram-v2-FVOUBMTO-DvmkevVb.js.map} +1 -1
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-Byr_GVOH.js → timeline-definition-YZTLITO2-CaOrqzT1.js} +3 -3
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-Byr_GVOH.js.map → timeline-definition-YZTLITO2-CaOrqzT1.js.map} +1 -1
- package/webapp/dist/assets/{treemap-KZPCXAKY-BSv-k7HC.js → treemap-KZPCXAKY-CWs_8GJm.js} +5 -5
- package/webapp/dist/assets/{treemap-KZPCXAKY-BSv-k7HC.js.map → treemap-KZPCXAKY-CWs_8GJm.js.map} +1 -1
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-CPqduRWm.js → vennDiagram-LZ73GAT5-BuBxFDz6.js} +2 -2
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-CPqduRWm.js.map → vennDiagram-LZ73GAT5-BuBxFDz6.js.map} +1 -1
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-B8yG6HaE.js → xychartDiagram-JWTSCODW-ChjL-_2b.js} +3 -3
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-B8yG6HaE.js.map → xychartDiagram-JWTSCODW-ChjL-_2b.js.map} +1 -1
- package/webapp/dist/index.html +1 -1
package/README.md
CHANGED
|
@@ -251,7 +251,7 @@ Then:
|
|
|
251
251
|
|
|
252
252
|
Platform note:
|
|
253
253
|
|
|
254
|
-
-
|
|
254
|
+
- Windows also registers `codex_inspect_and_patch_tools`; its `readonly_shell` tool runs through `cmd.exe`, so prefer allowlisted commands available in that shell/PATH, such as `rg`, `git`, `dir`, `type`, and `where`.
|
|
255
255
|
|
|
256
256
|
## Start from scratch
|
|
257
257
|
|
package/README.zh.md
CHANGED
|
@@ -190,7 +190,7 @@ dominds
|
|
|
190
190
|
|
|
191
191
|
平台说明:
|
|
192
192
|
|
|
193
|
-
- Windows
|
|
193
|
+
- Windows 也会注册 `codex_inspect_and_patch_tools`;其中 `readonly_shell` 通过 `cmd.exe` 执行,因此优先使用该 shell/PATH 中可用的白名单命令,例如 `rg`、`git`、`dir`、`type` 和 `where`。
|
|
194
194
|
|
|
195
195
|
## 从零开始(空文件夹启动)
|
|
196
196
|
|
package/dist/access-control.js
CHANGED
|
@@ -10,19 +10,23 @@ exports.getAccessDeniedMessage = getAccessDeniedMessage;
|
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const log_1 = require("./log");
|
|
12
12
|
function isEncapsulatedTaskPath(targetPath) {
|
|
13
|
-
const normalized = targetPath
|
|
13
|
+
const normalized = normalizeAccessControlPath(targetPath);
|
|
14
14
|
// Matches: "foo.tsk", "foo.tsk/", "a/b/foo.tsk/x", etc.
|
|
15
15
|
return /(^|\/)[^/]+\.tsk(\/|$)/.test(normalized);
|
|
16
16
|
}
|
|
17
17
|
function isMindsPath(targetPath) {
|
|
18
|
-
const normalized = targetPath
|
|
18
|
+
const normalized = normalizeAccessControlPath(targetPath).replace(/^\/+/, '');
|
|
19
19
|
return normalized === '.minds' || normalized.startsWith('.minds/');
|
|
20
20
|
}
|
|
21
21
|
function isMainDialogsPath(targetPath) {
|
|
22
22
|
// Only deny `.dialogs/**` at rtws root; allow nested `foo/.dialogs/**` for dev rtws layouts.
|
|
23
|
-
const normalized = targetPath
|
|
23
|
+
const normalized = normalizeAccessControlPath(targetPath).replace(/^\/+/, '');
|
|
24
24
|
return normalized === '.dialogs' || normalized.startsWith('.dialogs/');
|
|
25
25
|
}
|
|
26
|
+
function normalizeAccessControlPath(targetPath) {
|
|
27
|
+
const normalized = targetPath.replace(/\\/g, '/');
|
|
28
|
+
return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
29
|
+
}
|
|
26
30
|
function normalizeFileExtName(raw) {
|
|
27
31
|
return raw.trim().toLowerCase().replace(/^\.+/, '');
|
|
28
32
|
}
|
|
@@ -84,8 +88,8 @@ function resolveRtwsRelativePath(targetPath) {
|
|
|
84
88
|
*/
|
|
85
89
|
function matchesPattern(targetPath, dirPattern) {
|
|
86
90
|
// Normalize paths - remove leading/trailing slashes, convert to forward slashes, handle empty paths
|
|
87
|
-
const normalizedTarget = targetPath
|
|
88
|
-
let normalizedDirPattern = dirPattern
|
|
91
|
+
const normalizedTarget = normalizeAccessControlPath(targetPath).replace(/^\/+|\/+$/g, '') || '.';
|
|
92
|
+
let normalizedDirPattern = normalizeAccessControlPath(dirPattern).replace(/^\/+|\/+$/g, '') || '.';
|
|
89
93
|
// Patterns ending in `/**` represent a directory scope and should match the directory itself too.
|
|
90
94
|
// Example: `.minds/**` must match both `.minds` and `.minds/team.yaml`.
|
|
91
95
|
while (normalizedDirPattern.endsWith('/**')) {
|
|
@@ -559,7 +559,7 @@ Best practices:
|
|
|
559
559
|
|
|
560
560
|
- Make `member_defaults` conservative. Grant additional tools/dirs on a per-member basis.
|
|
561
561
|
- Prefer toolsets over individually enumerating tools unless you need a one-off tool.
|
|
562
|
-
- Platform note: Windows
|
|
562
|
+
- Platform note: Windows also supports `codex_inspect_and_patch_tools`; `readonly_shell` runs through `cmd.exe`, so prefer allowlisted commands available in that shell/PATH.
|
|
563
563
|
- Keep `.minds/team.yaml` ownership tight; only the team manager should be able to edit it.
|
|
564
564
|
- Avoid repeating built-in constraints in `team.yaml`:
|
|
565
565
|
- `*.tsk/**` (encapsulated Taskdocs) are hard-denied for all general file tools.
|
|
@@ -473,7 +473,7 @@ members:
|
|
|
473
473
|
|
|
474
474
|
- 使 `member_defaults` 保守。按成员授予额外的工具/目录
|
|
475
475
|
- 优先使用工具集而不是单独枚举工具,除非你需要一次性工具
|
|
476
|
-
- 平台说明:Windows
|
|
476
|
+
- 平台说明:Windows 也支持 `codex_inspect_and_patch_tools`;`readonly_shell` 通过 `cmd.exe` 执行,因此优先使用该 shell/PATH 中可用的白名单命令
|
|
477
477
|
- 保持 `.minds/team.yaml` 的所有权严格;只有团队管理者应该能够编辑它
|
|
478
478
|
- 避免在 `team.yaml` 中重复内置约束:
|
|
479
479
|
- `*.tsk/**`(封装的差遣牒任务包)对所有通用文件工具被硬性拒绝
|
|
@@ -645,6 +645,7 @@ const TELLASK_SPECIAL_VIRTUAL_TOOLS = [
|
|
|
645
645
|
{
|
|
646
646
|
type: 'func',
|
|
647
647
|
name: 'replyTellask',
|
|
648
|
+
followupMode: 'deferred',
|
|
648
649
|
description: 'Deliver final reply for the current tellask session.',
|
|
649
650
|
parameters: {
|
|
650
651
|
type: 'object',
|
|
@@ -661,6 +662,7 @@ const TELLASK_SPECIAL_VIRTUAL_TOOLS = [
|
|
|
661
662
|
{
|
|
662
663
|
type: 'func',
|
|
663
664
|
name: 'replyTellaskSessionless',
|
|
665
|
+
followupMode: 'deferred',
|
|
664
666
|
description: 'Deliver final reply for the current one-shot tellask.',
|
|
665
667
|
parameters: {
|
|
666
668
|
type: 'object',
|
|
@@ -677,6 +679,7 @@ const TELLASK_SPECIAL_VIRTUAL_TOOLS = [
|
|
|
677
679
|
{
|
|
678
680
|
type: 'func',
|
|
679
681
|
name: 'replyTellaskBack',
|
|
682
|
+
followupMode: 'deferred',
|
|
680
683
|
description: 'Deliver final reply for the current tellaskBack request.',
|
|
681
684
|
parameters: {
|
|
682
685
|
type: 'object',
|
|
@@ -1228,6 +1231,49 @@ async function persistInvalidFuncCallRuntimeGuide(args) {
|
|
|
1228
1231
|
});
|
|
1229
1232
|
await persistAndPostRuntimeGuide(dlg, content);
|
|
1230
1233
|
}
|
|
1234
|
+
function isQueuedNewCourseRuntimePrompt(prompt) {
|
|
1235
|
+
return (prompt?.kind === 'new_course_runtime_guide' ||
|
|
1236
|
+
prompt?.kind === 'new_course_runtime_reply' ||
|
|
1237
|
+
prompt?.kind === 'new_course_runtime_sideDialog');
|
|
1238
|
+
}
|
|
1239
|
+
function queuedNewCourseRuntimePromptToKernelPrompt(prompt) {
|
|
1240
|
+
const common = {
|
|
1241
|
+
content: prompt.prompt,
|
|
1242
|
+
msgId: prompt.msgId,
|
|
1243
|
+
grammar: prompt.grammar ?? 'markdown',
|
|
1244
|
+
userLanguageCode: prompt.userLanguageCode,
|
|
1245
|
+
runControl: prompt.runControl,
|
|
1246
|
+
origin: 'runtime',
|
|
1247
|
+
...(prompt.skipTaskdoc === undefined ? {} : { skipTaskdoc: prompt.skipTaskdoc }),
|
|
1248
|
+
};
|
|
1249
|
+
switch (prompt.kind) {
|
|
1250
|
+
case 'new_course_runtime_guide':
|
|
1251
|
+
return common;
|
|
1252
|
+
case 'new_course_runtime_reply':
|
|
1253
|
+
return {
|
|
1254
|
+
...common,
|
|
1255
|
+
tellaskReplyDirective: prompt.tellaskReplyDirective,
|
|
1256
|
+
};
|
|
1257
|
+
case 'new_course_runtime_sideDialog':
|
|
1258
|
+
return {
|
|
1259
|
+
...common,
|
|
1260
|
+
tellaskReplyDirective: prompt.tellaskReplyDirective,
|
|
1261
|
+
calleeDialogReplyTarget: prompt.calleeDialogReplyTarget,
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
async function consumeQueuedNewCourseRuntimePromptForSameDrive(dlg) {
|
|
1266
|
+
const queuedPrompt = dlg.peekQueuedPrompt();
|
|
1267
|
+
if (!isQueuedNewCourseRuntimePrompt(queuedPrompt)) {
|
|
1268
|
+
return undefined;
|
|
1269
|
+
}
|
|
1270
|
+
const consumedPrompt = dlg.takeQueuedPrompt();
|
|
1271
|
+
if (!consumedPrompt || consumedPrompt.msgId !== queuedPrompt.msgId) {
|
|
1272
|
+
throw new Error(`queued new-course prompt invariant violation: expected queued prompt ${queuedPrompt.msgId} before same-drive continuation`);
|
|
1273
|
+
}
|
|
1274
|
+
await persistence_1.DialogPersistence.clearPendingRuntimePrompt(dlg.id, queuedPrompt.msgId, dlg.status);
|
|
1275
|
+
return queuedNewCourseRuntimePromptToKernelPrompt(queuedPrompt);
|
|
1276
|
+
}
|
|
1231
1277
|
function resolveFuncToolFollowupMode(tool) {
|
|
1232
1278
|
return tool?.followupMode ?? 'immediate';
|
|
1233
1279
|
}
|
|
@@ -1237,6 +1283,7 @@ function summarizeRoutedFunctionResult(routed) {
|
|
|
1237
1283
|
hasImmediateTellaskOutputs: routed.hasImmediateTellaskOutputs,
|
|
1238
1284
|
immediateFollowupCallIds: routed.immediateFollowupCallIds,
|
|
1239
1285
|
immediateTellaskOutputCallIds: routed.immediateTellaskOutputCallIds,
|
|
1286
|
+
invalidTellaskCallIds: routed.invalidTellaskCallIds,
|
|
1240
1287
|
shouldStopAfterReplyTool: routed.shouldStopAfterReplyTool,
|
|
1241
1288
|
shouldStopAfterPendingTellaskWait: routed.shouldStopAfterPendingTellaskWait,
|
|
1242
1289
|
pairedMessageTypes: routed.pairedMessages.map((msg) => msg.type),
|
|
@@ -1455,14 +1502,22 @@ function buildImmediateFollowupTriggerExpectation(args) {
|
|
|
1455
1502
|
replyCallId: args.routed.immediateTellaskOutputCallIds[0],
|
|
1456
1503
|
});
|
|
1457
1504
|
}
|
|
1505
|
+
const invalidRecoveryCallIds = new Set(args.routed.invalidTellaskCallIds);
|
|
1458
1506
|
if (args.invalidFuncCallCount > 0) {
|
|
1459
|
-
const
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1507
|
+
for (const call of args.streamedFuncCalls) {
|
|
1508
|
+
invalidRecoveryCallIds.add(call.id);
|
|
1509
|
+
}
|
|
1510
|
+
if (args.streamedFuncCalls.length === 0) {
|
|
1511
|
+
invalidRecoveryCallIds.add(`invalid-tool:${args.invalidFuncCallCount}`);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
if (invalidRecoveryCallIds.size > 0) {
|
|
1515
|
+
// Invalid provider tool payloads and invalid tellask specials are same-turn recovery facts,
|
|
1516
|
+
// not generic retry hints. Keep them inside the follow-up trigger so the next generation can
|
|
1517
|
+
// repair the current turn immediately, while the invalid payload itself stays loud.
|
|
1463
1518
|
reasons.push({
|
|
1464
1519
|
kind: 'invalid_tool_recovery',
|
|
1465
|
-
callIds:
|
|
1520
|
+
callIds: [...invalidRecoveryCallIds],
|
|
1466
1521
|
});
|
|
1467
1522
|
}
|
|
1468
1523
|
if (reasons.length === 0) {
|
|
@@ -1823,6 +1878,7 @@ async function executeFunctionRound(args) {
|
|
|
1823
1878
|
hasImmediateTellaskOutputs: false,
|
|
1824
1879
|
immediateFollowupCallIds: [],
|
|
1825
1880
|
immediateTellaskOutputCallIds: [],
|
|
1881
|
+
invalidTellaskCallIds: [],
|
|
1826
1882
|
shouldStopAfterReplyTool: false,
|
|
1827
1883
|
shouldStopAfterPendingTellaskWait: false,
|
|
1828
1884
|
pairedMessages: [],
|
|
@@ -1933,6 +1989,7 @@ async function executeFunctionRound(args) {
|
|
|
1933
1989
|
hasImmediateTellaskOutputs: tellaskRound.hasImmediateTellaskOutputs,
|
|
1934
1990
|
immediateFollowupCallIds,
|
|
1935
1991
|
immediateTellaskOutputCallIds: tellaskRound.immediateTellaskOutputCallIds,
|
|
1992
|
+
invalidTellaskCallIds: tellaskRound.invalidTellaskCallIds,
|
|
1936
1993
|
shouldStopAfterReplyTool: tellaskRound.shouldStopAfterReplyTool,
|
|
1937
1994
|
shouldStopAfterPendingTellaskWait: tellaskRound.shouldStopAfterPendingTellaskWait,
|
|
1938
1995
|
pairedMessages,
|
|
@@ -3255,6 +3312,12 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3255
3312
|
});
|
|
3256
3313
|
break;
|
|
3257
3314
|
}
|
|
3315
|
+
const queuedNewCoursePrompt = await consumeQueuedNewCourseRuntimePromptForSameDrive(dlg);
|
|
3316
|
+
if (queuedNewCoursePrompt !== undefined) {
|
|
3317
|
+
pendingPrompt = queuedNewCoursePrompt;
|
|
3318
|
+
skipTaskdocForThisDrive = false;
|
|
3319
|
+
continue;
|
|
3320
|
+
}
|
|
3258
3321
|
// Start an immediate post-tool generation only when this round produced tool outputs that
|
|
3259
3322
|
// warrant same-drive LLM reaction right away. Provider-native side-channel UI events are
|
|
3260
3323
|
// meaningful output, but they are not transcript/context inputs and therefore must not
|
|
@@ -48,6 +48,7 @@ function buildFbrConclusionTools(language) {
|
|
|
48
48
|
{
|
|
49
49
|
type: 'func',
|
|
50
50
|
name: exports.FBR_LOW_NOISE_CONCLUSION_TOOL_NAME,
|
|
51
|
+
followupMode: 'deferred',
|
|
51
52
|
description: buildFbrConclusionToolDescription({ language, kind: 'low_noise' }),
|
|
52
53
|
parameters: {
|
|
53
54
|
type: 'object',
|
|
@@ -67,6 +68,7 @@ function buildFbrConclusionTools(language) {
|
|
|
67
68
|
{
|
|
68
69
|
type: 'func',
|
|
69
70
|
name: exports.FBR_UNREASONABLE_SITUATION_TOOL_NAME,
|
|
71
|
+
followupMode: 'deferred',
|
|
70
72
|
description: buildFbrConclusionToolDescription({ language, kind: 'unreasonable' }),
|
|
71
73
|
parameters: {
|
|
72
74
|
type: 'object',
|
|
@@ -121,6 +121,7 @@ export type TellaskFunctionRoundResult = Readonly<{
|
|
|
121
121
|
hasInvalidTellaskCalls: boolean;
|
|
122
122
|
hasImmediateTellaskOutputs: boolean;
|
|
123
123
|
immediateTellaskOutputCallIds: readonly string[];
|
|
124
|
+
invalidTellaskCallIds: readonly string[];
|
|
124
125
|
shouldStopAfterReplyTool: boolean;
|
|
125
126
|
shouldStopAfterPendingTellaskWait: boolean;
|
|
126
127
|
}>;
|
|
@@ -2396,6 +2396,10 @@ async function processTellaskFunctionRound(args) {
|
|
|
2396
2396
|
const result = output;
|
|
2397
2397
|
tellaskFuncResultByCallId.set(result.id, result);
|
|
2398
2398
|
tellaskFuncResults.push(result);
|
|
2399
|
+
const originatingCall = specialCallById.get(result.id);
|
|
2400
|
+
if (originatingCall !== undefined && isReplyTellaskCallName(originatingCall.callName)) {
|
|
2401
|
+
continue;
|
|
2402
|
+
}
|
|
2399
2403
|
hasImmediateTellaskOutputs = true;
|
|
2400
2404
|
immediateTellaskOutputCallIds.push(result.id);
|
|
2401
2405
|
continue;
|
|
@@ -2460,7 +2464,8 @@ async function processTellaskFunctionRound(args) {
|
|
|
2460
2464
|
hasInvalidTellaskCalls: orderedInvalidCalls.length > 0,
|
|
2461
2465
|
hasImmediateTellaskOutputs,
|
|
2462
2466
|
immediateTellaskOutputCallIds,
|
|
2463
|
-
|
|
2467
|
+
invalidTellaskCallIds: orderedInvalidCalls.map((issue) => issue.originalCall.id),
|
|
2468
|
+
shouldStopAfterReplyTool: tellaskExecution.successfulReplyCallIds.length > 0,
|
|
2464
2469
|
shouldStopAfterPendingTellaskWait,
|
|
2465
2470
|
};
|
|
2466
2471
|
}
|
package/dist/persistence.js
CHANGED
|
@@ -2924,7 +2924,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
2924
2924
|
});
|
|
2925
2925
|
acceptedTriggers = triggerSelection.acceptedTriggers;
|
|
2926
2926
|
if (triggerSelection.supersededTriggers.length > 0) {
|
|
2927
|
-
log_1.log.debug('Superseded stale next-step triggers while starting
|
|
2927
|
+
log_1.log.debug('Superseded stale next-step triggers while starting prompt-driven generation', undefined, {
|
|
2928
2928
|
dialogId: this.dialogId.valueOf(),
|
|
2929
2929
|
rootId: this.dialogId.rootId,
|
|
2930
2930
|
selfId: this.dialogId.selfId,
|
|
@@ -2933,7 +2933,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
2933
2933
|
msgId: msgId ?? null,
|
|
2934
2934
|
acceptedTriggerIds: acceptedTriggers.map((trigger) => trigger.triggerId),
|
|
2935
2935
|
supersededTriggerIds: triggerSelection.supersededTriggers.map((trigger) => trigger.triggerId),
|
|
2936
|
-
reason: '
|
|
2936
|
+
reason: 'prompt_generation_takes_precedence',
|
|
2937
2937
|
});
|
|
2938
2938
|
}
|
|
2939
2939
|
const acceptedTriggerIds = acceptedTriggers.map((trigger) => trigger.triggerId);
|
|
@@ -4960,23 +4960,17 @@ function filterNextStepTriggersForGenerationStart(args) {
|
|
|
4960
4960
|
if (typeof args.msgId !== 'string' || args.msgId.trim() === '') {
|
|
4961
4961
|
return { acceptedTriggers: orderedTriggers, supersededTriggers: [] };
|
|
4962
4962
|
}
|
|
4963
|
-
const promptTrigger = orderedTriggers.find((trigger) => trigger.kind === 'queued_prompt' &&
|
|
4964
|
-
trigger.promptId === args.msgId &&
|
|
4965
|
-
trigger.course === args.currentCourse);
|
|
4966
|
-
if (promptTrigger === undefined) {
|
|
4967
|
-
return { acceptedTriggers: orderedTriggers, supersededTriggers: [] };
|
|
4968
|
-
}
|
|
4969
4963
|
const acceptedTriggers = [];
|
|
4970
4964
|
const supersededTriggers = [];
|
|
4971
4965
|
for (const trigger of orderedTriggers) {
|
|
4972
|
-
const
|
|
4966
|
+
const shouldAcceptTrigger = (() => {
|
|
4973
4967
|
switch (trigger.kind) {
|
|
4974
4968
|
case 'queued_prompt':
|
|
4975
4969
|
case 'user_input':
|
|
4976
4970
|
case 'open_generation_recovery':
|
|
4977
4971
|
return trigger.course === args.currentCourse;
|
|
4978
4972
|
case 'followup':
|
|
4979
|
-
return
|
|
4973
|
+
return false;
|
|
4980
4974
|
case 'mainline_diligence':
|
|
4981
4975
|
case 'result_arrival':
|
|
4982
4976
|
case 'reply_delivery_recovery':
|
|
@@ -4987,7 +4981,7 @@ function filterNextStepTriggersForGenerationStart(args) {
|
|
|
4987
4981
|
}
|
|
4988
4982
|
}
|
|
4989
4983
|
})();
|
|
4990
|
-
if (
|
|
4984
|
+
if (shouldAcceptTrigger) {
|
|
4991
4985
|
acceptedTriggers.push(trigger);
|
|
4992
4986
|
}
|
|
4993
4987
|
else {
|
|
@@ -21,6 +21,7 @@ const LATEST_VERSION_CHECK_TIMEOUT_MS = 60000;
|
|
|
21
21
|
const RESTART_PORT_RELEASE_TIMEOUT_MS = 15000;
|
|
22
22
|
const RESTART_PORT_PROBE_INTERVAL_MS = 150;
|
|
23
23
|
const RESTART_EXIT_GRACE_MS = 1000;
|
|
24
|
+
const RESTART_FORCE_KILL_AFTER_MS = 3000;
|
|
24
25
|
const COMMAND_OUTPUT_LOG_LIMIT = 2000;
|
|
25
26
|
const PROXY_URL_ENV_KEYS = new Set([
|
|
26
27
|
'HTTP_PROXY',
|
|
@@ -865,6 +866,8 @@ function spawnDetachedRestartHelper(params) {
|
|
|
865
866
|
cwd: params.cwd,
|
|
866
867
|
host: getRestartPortProbeHost(params.host),
|
|
867
868
|
port: params.port,
|
|
869
|
+
retiringPid: process.pid,
|
|
870
|
+
forceKillAfterMs: RESTART_FORCE_KILL_AFTER_MS,
|
|
868
871
|
probeIntervalMs: RESTART_PORT_PROBE_INTERVAL_MS,
|
|
869
872
|
portReleaseTimeoutMs: RESTART_PORT_RELEASE_TIMEOUT_MS,
|
|
870
873
|
stdioMode,
|
|
@@ -889,8 +892,8 @@ function spawnDetachedRestartHelper(params) {
|
|
|
889
892
|
' socket.setTimeout(1000, () => finish(true));',
|
|
890
893
|
' });',
|
|
891
894
|
'}',
|
|
892
|
-
'async function waitForPortRelease() {',
|
|
893
|
-
' const deadline = Date.now() +
|
|
895
|
+
'async function waitForPortRelease(timeoutMs) {',
|
|
896
|
+
' const deadline = Date.now() + timeoutMs;',
|
|
894
897
|
' let consecutiveIdle = 0;',
|
|
895
898
|
' while (Date.now() < deadline) {',
|
|
896
899
|
' if (await isPortBusy()) {',
|
|
@@ -899,13 +902,42 @@ function spawnDetachedRestartHelper(params) {
|
|
|
899
902
|
' continue;',
|
|
900
903
|
' }',
|
|
901
904
|
' consecutiveIdle += 1;',
|
|
902
|
-
' if (consecutiveIdle >= 2) return;',
|
|
905
|
+
' if (consecutiveIdle >= 2) return true;',
|
|
903
906
|
' await new Promise((resolve) => setTimeout(resolve, payload.probeIntervalMs));',
|
|
904
907
|
' }',
|
|
908
|
+
' return false;',
|
|
909
|
+
'}',
|
|
910
|
+
'function forceKillRetiringProcess() {',
|
|
911
|
+
' if (!Number.isInteger(payload.retiringPid) || payload.retiringPid <= 0) {',
|
|
912
|
+
' throw new Error(`Invalid retiring Dominds pid for restart: ${String(payload.retiringPid)}`);',
|
|
913
|
+
' }',
|
|
914
|
+
' if (payload.retiringPid === process.pid) {',
|
|
915
|
+
' throw new Error(`Refusing to kill restart helper pid ${String(process.pid)}`);',
|
|
916
|
+
' }',
|
|
917
|
+
" const killer = process.platform === 'win32'",
|
|
918
|
+
" ? spawn('taskkill.exe', ['/PID', String(payload.retiringPid), '/F'], { stdio: payload.stdioMode })",
|
|
919
|
+
" : spawn('kill', ['-KILL', String(payload.retiringPid)], { stdio: payload.stdioMode });",
|
|
920
|
+
' return new Promise((resolve, reject) => {',
|
|
921
|
+
" killer.once('error', reject);",
|
|
922
|
+
" killer.once('exit', (code) => {",
|
|
923
|
+
' if (code === 0) {',
|
|
924
|
+
' resolve();',
|
|
925
|
+
' return;',
|
|
926
|
+
' }',
|
|
927
|
+
' resolve();',
|
|
928
|
+
' });',
|
|
929
|
+
' });',
|
|
905
930
|
'}',
|
|
906
931
|
'(async () => {',
|
|
907
932
|
' try {',
|
|
908
|
-
' await waitForPortRelease();',
|
|
933
|
+
' const releasedGracefully = await waitForPortRelease(payload.forceKillAfterMs);',
|
|
934
|
+
' if (!releasedGracefully) {',
|
|
935
|
+
' await forceKillRetiringProcess();',
|
|
936
|
+
' const releasedAfterKill = await waitForPortRelease(payload.portReleaseTimeoutMs);',
|
|
937
|
+
' if (!releasedAfterKill) {',
|
|
938
|
+
' throw new Error(`Dominds restart port ${String(payload.host)}:${String(payload.port)} is still busy after force-killing pid ${String(payload.retiringPid)}`);',
|
|
939
|
+
' }',
|
|
940
|
+
' }',
|
|
909
941
|
" const child = spawn(payload.command, payload.args, { cwd: payload.cwd, env: process.env, detached, stdio: payload.stdioMode, shell: process.platform === 'win32' });",
|
|
910
942
|
' if (detached) child.unref();',
|
|
911
943
|
' process.exit(0);',
|
|
@@ -1035,8 +1035,23 @@ async function handleDisplayDialog(ws, packet) {
|
|
|
1035
1035
|
}
|
|
1036
1036
|
const rootPrimingConfig = dialogIdObj.selfId === dialogIdObj.rootId ? (0, priming_1.getMainDialogPrimingConfig)(metadata) : undefined;
|
|
1037
1037
|
const showPrimingEventsInUi = rootPrimingConfig?.showInUi !== false;
|
|
1038
|
-
|
|
1038
|
+
if (packet.course !== undefined && (!Number.isInteger(packet.course) || packet.course <= 0)) {
|
|
1039
|
+
ws.send(JSON.stringify({
|
|
1040
|
+
type: 'error',
|
|
1041
|
+
message: 'display_dialog course must be a positive integer when provided',
|
|
1042
|
+
}));
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
const latestCourse = (await persistence_1.DialogPersistence.getCurrentCourseNumber(dialogIdObj, requestedStatus)) ||
|
|
1039
1046
|
(dialogState.currentCourse ?? 1);
|
|
1047
|
+
const decidedCourse = packet.course ?? latestCourse;
|
|
1048
|
+
if (decidedCourse > latestCourse) {
|
|
1049
|
+
ws.send(JSON.stringify({
|
|
1050
|
+
type: 'error',
|
|
1051
|
+
message: `display_dialog course ${String(decidedCourse)} exceeds latest course ${String(latestCourse)}`,
|
|
1052
|
+
}));
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1040
1055
|
const enableLive = requestedStatus === 'running';
|
|
1041
1056
|
const mainDialog = await (0, dialog_instance_registry_1.getOrRestoreMainDialog)(dialogIdObj.rootId, requestedStatus);
|
|
1042
1057
|
if (!mainDialog) {
|
|
@@ -1068,7 +1083,7 @@ async function handleDisplayDialog(ws, packet) {
|
|
|
1068
1083
|
try {
|
|
1069
1084
|
const dialogStore = dialog.dlgStore;
|
|
1070
1085
|
if (dialogStore instanceof persistence_1.DiskFileDialogStore) {
|
|
1071
|
-
await dialogStore.sendDialogEventsDirectly(ws, dialog, decidedCourse,
|
|
1086
|
+
await dialogStore.sendDialogEventsDirectly(ws, dialog, decidedCourse, latestCourse, requestedStatus, { showPrimingEventsInUi });
|
|
1072
1087
|
}
|
|
1073
1088
|
else {
|
|
1074
1089
|
throw new Error('Unexpected dialog store type for sendDialogEventsDirectly');
|
|
@@ -1340,6 +1355,13 @@ async function handleDisplayCourse(ws, packet) {
|
|
|
1340
1355
|
if (!dialog || typeof course !== 'number') {
|
|
1341
1356
|
throw new Error('dialog and course are required');
|
|
1342
1357
|
}
|
|
1358
|
+
if (!Number.isInteger(course) || course <= 0) {
|
|
1359
|
+
ws.send(JSON.stringify({
|
|
1360
|
+
type: 'error',
|
|
1361
|
+
message: 'display_course course must be a positive integer',
|
|
1362
|
+
}));
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1343
1365
|
// Extract dialog ID from DialogIdent
|
|
1344
1366
|
let dialogIdStr = dialog.selfId;
|
|
1345
1367
|
let mainDialogIdStr = dialog.rootId;
|
|
@@ -1371,6 +1393,13 @@ async function handleDisplayCourse(ws, packet) {
|
|
|
1371
1393
|
return;
|
|
1372
1394
|
}
|
|
1373
1395
|
const totalCourses = (await persistence_1.DialogPersistence.getCurrentCourseNumber(dialogId, requestedStatus)) || course;
|
|
1396
|
+
if (course > totalCourses) {
|
|
1397
|
+
ws.send(JSON.stringify({
|
|
1398
|
+
type: 'error',
|
|
1399
|
+
message: `display_course course ${String(course)} exceeds latest course ${String(totalCourses)}`,
|
|
1400
|
+
}));
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1374
1403
|
const mainDialog = await (0, dialog_instance_registry_1.getOrRestoreMainDialog)(dialogId.rootId, requestedStatus);
|
|
1375
1404
|
if (!mainDialog)
|
|
1376
1405
|
return;
|
package/dist/tools/builtins.js
CHANGED
|
@@ -319,22 +319,20 @@ for (const tool of team_mgmt_1.teamMgmtTools) {
|
|
|
319
319
|
manualSpec: manualSpecFor('ws_mod'),
|
|
320
320
|
});
|
|
321
321
|
// Inspect-and-patch helpers (function tools only; useful for GPT-5.x coding agents)
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
});
|
|
337
|
-
}
|
|
322
|
+
(0, registry_1.registerToolset)('codex_inspect_and_patch_tools', [os_1.readonlyShellTool, apply_patch_1.applyPatchTool]);
|
|
323
|
+
(0, registry_1.setToolsetMeta)('codex_inspect_and_patch_tools', {
|
|
324
|
+
source: 'dominds',
|
|
325
|
+
descriptionI18n: {
|
|
326
|
+
en: 'Inspect-and-patch helpers: use readonly_shell for lightweight inspection and apply_patch for reviewable edits.',
|
|
327
|
+
zh: '检查与补丁工具:用 readonly_shell 做轻量检查,用 apply_patch 做可审查修改。',
|
|
328
|
+
},
|
|
329
|
+
promptI18n: {
|
|
330
|
+
en: 'Use `apply_patch` (apply_patch patch format) to modify files. Use `readonly_shell` for simple rtws (runtime workspace) inspection via its small allowlist; commands outside the allowlist are rejected. On Windows, `readonly_shell` runs through `cmd.exe`; use allowlisted commands available in that shell/PATH such as `rg`, `git`, `dir`, `type`, or `where`. For node/python, only exact version probes are allowed (no scripts). Chains via |/&&/|| are validated segment-by-segment. You are explicitly authorized to call `readonly_shell` yourself; do not delegate it to a shell specialist. Avoid multi-line script-style commands; single-line is preferred (|, &&, || are ok). Paths must be relative to the rtws (runtime workspace). Hard denies: `readonly_shell` refuses rtws-root `.minds/` and `.dialogs/`; `apply_patch` is subject to the same access-control (including hard denies for `*.tsk/`, `.minds/`, and rtws-root `.dialogs/`).',
|
|
331
|
+
zh: '使用 `apply_patch`(apply_patch patch 格式)修改文件;使用 `readonly_shell` 做少量只读命令行检查,仅允许白名单命令前缀,白名单之外的命令会被拒绝。Windows 上 `readonly_shell` 通过 `cmd.exe` 执行;请使用该 shell/PATH 中可用的白名单命令,例如 `rg`、`git`、`dir`、`type` 或 `where`。对 node/python 仅允许版本探针(不允许脚本执行)。通过 |/&&/|| 串联命令时会按子命令逐段校验。你已被明确授权自行调用 `readonly_shell`,不要把它委派给 shell 专员。不建议多行脚本式命令,优先单行(允许 |、&&、||)。路径必须相对 rtws(运行时工作区)根目录。硬拒绝点:`readonly_shell` 无条件拒绝访问 rtws root 的 `.minds/` 与 `.dialogs/`;`apply_patch` 也受相同的访问控制约束(包含对 `*.tsk/`、`.minds/`、rtws root `.dialogs/` 的硬拒绝)。',
|
|
332
|
+
},
|
|
333
|
+
promptFilesI18n: promptFilesFor('codex_inspect_and_patch_tools'),
|
|
334
|
+
manualSpec: manualSpecFor('codex_inspect_and_patch_tools'),
|
|
335
|
+
});
|
|
338
336
|
(0, registry_1.registerToolset)('team_mgmt', [...team_mgmt_1.teamMgmtTools]);
|
|
339
337
|
(0, registry_1.setToolsetMeta)('team_mgmt', {
|
|
340
338
|
source: 'dominds',
|
package/dist/tools/ctrl.js
CHANGED
|
@@ -612,6 +612,7 @@ exports.updateReminderTool = {
|
|
|
612
612
|
exports.clearMindTool = {
|
|
613
613
|
type: 'func',
|
|
614
614
|
name: 'clear_mind',
|
|
615
|
+
followupMode: 'deferred',
|
|
615
616
|
description: 'Start a new dialog course, optionally carrying one extra continuation reminder.',
|
|
616
617
|
descriptionI18n: {
|
|
617
618
|
en: 'Start a new dialog course, optionally carrying one extra continuation reminder.',
|
package/dist/tools/os.d.ts
CHANGED
|
@@ -19,6 +19,20 @@ export declare function formatShellExecutionErrorForTests(shell: string | undefi
|
|
|
19
19
|
export declare function resolveReadonlyShellSpawnSpecForTests(command: string, platform: NodeJS.Platform): ShellSpawnSpec;
|
|
20
20
|
export declare const shellCmdReminderOwner: ReminderOwner;
|
|
21
21
|
export declare const shellCmdTool: FuncTool;
|
|
22
|
+
type ReadonlyShellValidationFailureReason = 'MAX_DEPTH' | 'INVALID_CD_SYNTAX' | 'UNSAFE_RELATIVE_PATH' | 'CHAIN_PARSE_EMPTY_SEGMENT' | 'CHAIN_PARSE_UNSUPPORTED_OPERATOR' | 'CHAIN_PARSE_UNTERMINATED_QUOTE' | 'CHAIN_PARSE_TRAILING_ESCAPE' | 'UNSAFE_SHELL_SYNTAX' | 'GIT_C_INVALID' | 'GIT_C_UNSAFE_PATH' | 'GIT_C_UNSUPPORTED_SUBCOMMAND' | 'COMMAND_NOT_ALLOWLISTED';
|
|
23
|
+
type ReadonlyShellValidationFailure = Readonly<{
|
|
24
|
+
reason: ReadonlyShellValidationFailureReason;
|
|
25
|
+
rejectedSegment: string;
|
|
26
|
+
}>;
|
|
27
|
+
type ReadonlyShellValidationResult = Readonly<{
|
|
28
|
+
ok: true;
|
|
29
|
+
}> | Readonly<{
|
|
30
|
+
ok: false;
|
|
31
|
+
failure: ReadonlyShellValidationFailure;
|
|
32
|
+
}>;
|
|
33
|
+
export declare function validateReadonlyShellCommandForTests(command: string, platform: NodeJS.Platform): ReadonlyShellValidationResult;
|
|
34
|
+
type ForbiddenHiddenDir = '.minds' | '.dialogs';
|
|
35
|
+
export declare function detectReadonlyShellForbiddenHiddenDirAccessForTests(workspaceRootAbs: string, command: string, platform: NodeJS.Platform): ForbiddenHiddenDir | null;
|
|
22
36
|
export declare const readonlyShellTool: FuncTool;
|
|
23
37
|
export declare const stopDaemonTool: FuncTool;
|
|
24
38
|
export declare const getDaemonOutputTool: FuncTool;
|