qlogicagent 2.18.5 → 2.18.7
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 +382 -382
- package/dist/agent.js +30 -30
- package/dist/cli.js +1 -1
- package/dist/default-project-knowledge/INSTRUCTIONS.md +7 -7
- package/dist/default-project-knowledge/rules/project-workflow.md +6 -6
- package/dist/host-contract.js +1 -0
- package/dist/index.js +536 -525
- package/dist/orchestration.js +4 -4
- package/dist/permissions.js +1 -1
- package/dist/plugin-marketplace-compute.js +1 -0
- package/dist/protocol.js +1 -1
- package/dist/runtime/infra/mcp-bridge-server.js +275 -275
- package/dist/skills/builtin/desktop-screenshot/SKILL.md +62 -62
- package/dist/skills/builtin/office-doc-reading/SKILL.md +19 -19
- package/dist/skills/mcp/astraclaw-native-mcp-server.js +4 -4
- package/dist/tunables.js +1 -0
- package/dist/types/agent/runtime-vars.d.ts +1 -2
- package/dist/types/agent/tool-loop.d.ts +13 -0
- package/dist/types/agent/tool-loop.test-harness.d.ts +20 -0
- package/dist/types/agent/types.d.ts +8 -0
- package/dist/types/cli/acp-extended-handlers.d.ts +7 -0
- package/dist/types/cli/acp-extended-host-adapter.d.ts +2 -0
- package/dist/types/cli/acp-session-host.d.ts +15 -2
- package/dist/types/cli/base-tool-bootstrap.d.ts +1 -0
- package/dist/types/cli/community-skill-installer.d.ts +2 -0
- package/dist/types/cli/core-tool-coordinator.d.ts +4 -0
- package/dist/types/cli/core-tools/config-tool-bootstrap.d.ts +3 -1
- package/dist/types/cli/core-tools/config-tool-service.d.ts +7 -5
- package/dist/types/cli/default-project-bootstrap.d.ts +1 -0
- package/dist/types/cli/dream-host-adapter.d.ts +1 -0
- package/dist/types/cli/handlers/agents-handler.d.ts +4 -1
- package/dist/types/cli/handlers/community-handler.d.ts +2 -0
- package/dist/types/cli/handlers/config-handler.d.ts +2 -15
- package/dist/types/cli/handlers/dream-handler.d.ts +4 -0
- package/dist/types/cli/handlers/pet-handler.d.ts +3 -2
- package/dist/types/cli/handlers/session-handler.d.ts +1 -1
- package/dist/types/cli/handlers/skills-handler.d.ts +12 -10
- package/dist/types/cli/handlers/solo-handler.d.ts +3 -0
- package/dist/types/cli/handlers/turn-handler.d.ts +46 -32
- package/dist/types/cli/handlers/workflow-handler.d.ts +6 -0
- package/dist/types/cli/mcp-bootstrap.d.ts +0 -2
- package/dist/types/cli/media-inline.d.ts +31 -0
- package/dist/types/cli/media-understanding.d.ts +65 -8
- package/dist/types/cli/memory-coordinator.d.ts +8 -0
- package/dist/types/cli/multi-agent-handler-host.d.ts +2 -0
- package/dist/types/cli/permission-bootstrap.d.ts +2 -0
- package/dist/types/cli/pet-runtime.d.ts +0 -1
- package/dist/types/cli/plugin-bootstrap.d.ts +2 -1
- package/dist/types/cli/product-coordinator.d.ts +4 -1
- package/dist/types/cli/rpc-registry.d.ts +1 -3
- package/dist/types/cli/runtime-watcher-bootstrap.d.ts +0 -2
- package/dist/types/cli/session-context.d.ts +4 -2
- package/dist/types/cli/skill-invocation-service.d.ts +2 -0
- package/dist/types/cli/skill-tools-bootstrap.d.ts +2 -0
- package/dist/types/cli/skills-query-service.d.ts +2 -1
- package/dist/types/cli/stdio-acp-protocol-coordinator.d.ts +9 -0
- package/dist/types/cli/stdio-acp-request-host.d.ts +11 -2
- package/dist/types/cli/stdio-rpc-handler-hosts.d.ts +1 -1
- package/dist/types/cli/stdio-runtime-bootstrap.d.ts +6 -0
- package/dist/types/cli/stdio-runtime-services.d.ts +6 -1
- package/dist/types/cli/stdio-server.d.ts +33 -4
- package/dist/types/cli/task-distillation-coordinator.d.ts +9 -4
- package/dist/types/cli/tool-bootstrap-core-registration.d.ts +3 -0
- package/dist/types/cli/tool-bootstrap-media-registration.d.ts +10 -0
- package/dist/types/cli/tool-bootstrap-web-registration.d.ts +1 -0
- package/dist/types/cli/tool-bootstrap.d.ts +9 -0
- package/dist/types/cli/turn-core.d.ts +4 -0
- package/dist/types/cli/turn-preview-browser-setup.d.ts +15 -0
- package/dist/types/cli/turn-project-router.d.ts +1 -1
- package/dist/types/cli/workflow-host-adapter.d.ts +2 -0
- package/dist/types/host-contract/index.d.ts +1475 -0
- package/dist/types/host-contract/project-id.d.ts +5 -0
- package/dist/types/host-contract/provider-profile.d.ts +46 -0
- package/dist/types/orchestration/agent-instance.d.ts +6 -0
- package/dist/types/orchestration/delegation-coordinator.d.ts +40 -0
- package/dist/types/orchestration/goal-mode-adapters.d.ts +3 -0
- package/dist/types/orchestration/product-planner.d.ts +3 -0
- package/dist/types/orchestration/solo-evaluator.d.ts +18 -3
- package/dist/types/orchestration/solo-persistence.d.ts +2 -0
- package/dist/types/orchestration/testing/delegate-test-bridge.d.ts +4 -0
- package/dist/types/permissions.d.ts +2 -0
- package/dist/types/protocol/methods.d.ts +0 -199
- package/dist/types/protocol/wire/acp-protocol.d.ts +16 -1
- package/dist/types/protocol/wire/agent-methods.d.ts +1 -173
- package/dist/types/protocol/wire/chat-types.d.ts +6 -0
- package/dist/types/runtime/config/tunable-defaults.d.ts +13 -3
- package/dist/types/runtime/execution/dream-agent.d.ts +9 -8
- package/dist/types/runtime/infra/agent-paths.d.ts +3 -3
- package/dist/types/runtime/infra/astraclaw-capabilities.d.ts +1 -1
- package/dist/types/runtime/infra/clixml-sanitize.d.ts +16 -0
- package/dist/types/runtime/infra/external-agent-approvals.d.ts +18 -0
- package/dist/types/runtime/infra/feedback-distillation.d.ts +3 -1
- package/dist/types/runtime/infra/feedback-host-authority.d.ts +4 -0
- package/dist/types/runtime/infra/llmrouter-catalog.d.ts +2 -13
- package/dist/types/runtime/infra/model-registry.d.ts +3 -1
- package/dist/types/runtime/infra/project-authority-facade.d.ts +11 -0
- package/dist/types/runtime/infra/project-host-authority.d.ts +10 -0
- package/dist/types/runtime/ports/memory-provider.d.ts +11 -7
- package/dist/types/runtime/ports/tool-contracts.d.ts +2 -0
- package/dist/types/runtime/prompt/fresh-workspace-evidence.d.ts +2 -2
- package/dist/types/runtime/session/session-catalog.d.ts +12 -0
- package/dist/types/runtime/session/session-persistence.d.ts +30 -11
- package/dist/types/runtime/session/session-recovery.d.ts +4 -0
- package/dist/types/runtime/session/session-summary.d.ts +3 -1
- package/dist/types/runtime/session/session-transcript-store.d.ts +7 -0
- package/dist/types/skills/memory/host-memory-provider.d.ts +148 -0
- package/dist/types/skills/memory/local-memory-provider.d.ts +20 -11
- package/dist/types/skills/memory/local-store.d.ts +5 -2
- package/dist/types/skills/memory/task-distillation.d.ts +6 -0
- package/dist/types/skills/plugins/plugin-marketplace.d.ts +23 -57
- package/dist/types/skills/tools/media-understand-tool.d.ts +28 -0
- package/dist/types/skills/tools/preview-browser-tool.d.ts +136 -0
- package/dist/types/skills/tools/shell/task-output.d.ts +10 -1
- package/dist/types/skills/tools/skill-tool.d.ts +1 -1
- package/dist/types/skills/web-search/brave-source.d.ts +2 -1
- package/dist/types/skills/web-search/crawl4ai-extractor.d.ts +3 -2
- package/dist/types/skills/web-search/exa-source.d.ts +2 -1
- package/dist/types/skills/web-search/search-svc-source.d.ts +4 -3
- package/dist/types/skills/web-search/searxng-source.d.ts +3 -1
- package/dist/types/skills/web-search/serper-source.d.ts +2 -1
- package/dist/types/skills/web-search/source-factory.d.ts +2 -1
- package/dist/types/skills/web-search/web-tunable-resolver.d.ts +16 -0
- package/dist/types/test-support/global-home-setup.d.ts +2 -0
- package/dist/types/transport/acp-server.d.ts +29 -0
- package/dist/types/transport/delegate-client.d.ts +82 -0
- package/dist/types/transport/host-capability-client.d.ts +21 -0
- package/dist/types/transport/host-feedback-client.d.ts +25 -0
- package/dist/types/transport/host-profile-client.d.ts +19 -0
- package/dist/types/transport/host-project-client.d.ts +16 -0
- package/dist/types/transport/host-request-client.d.ts +38 -0
- package/dist/types/transport/host-session-client.d.ts +29 -0
- package/dist/types/tunables.d.ts +2 -0
- package/dist/vendor/hatch-pet/LICENSE.txt +201 -201
- package/dist/vendor/hatch-pet/NOTICE.md +25 -25
- package/dist/vendor/hatch-pet/references/animation-rows.md +29 -29
- package/dist/vendor/hatch-pet/references/codex-pet-contract.md +35 -35
- package/dist/vendor/hatch-pet/references/qa-rubric.md +66 -66
- package/dist/vendor/hatch-pet/scripts/compose_atlas.py +169 -169
- package/dist/vendor/hatch-pet/scripts/derive_running_left_from_running_right.py +150 -150
- package/dist/vendor/hatch-pet/scripts/extract_strip_frames.py +408 -408
- package/dist/vendor/hatch-pet/scripts/inspect_frames.py +256 -256
- package/dist/vendor/hatch-pet/scripts/make_contact_sheet.py +96 -96
- package/dist/vendor/hatch-pet/scripts/prepare_pet_run.py +834 -834
- package/dist/vendor/hatch-pet/scripts/render_animation_previews.py +78 -78
- package/dist/vendor/hatch-pet/scripts/validate_atlas.py +157 -157
- package/package.json +25 -2
- package/dist/types/cli/handlers/settings-handler.d.ts +0 -19
- package/dist/types/cli/permission-rule-persistence.d.ts +0 -16
- package/dist/types/cli/tunable-store.d.ts +0 -26
- package/dist/types/skills/permissions/settings-watcher.d.ts +0 -26
- /package/dist/types/{skills/memory → host-contract}/fts-segment.d.ts +0 -0
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: desktop-screenshot
|
|
3
|
-
description: 用户要求截屏/截图/看看我的屏幕时使用 —— 用 exec 跑系统命令截取桌面,把图片文件路径回给用户。无需专用截图工具。
|
|
4
|
-
requires: [exec, write]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Desktop Screenshot
|
|
8
|
-
|
|
9
|
-
用户要求截取桌面/屏幕时,用 exec 执行系统自带命令,**不要**说自己没有截图能力。
|
|
10
|
-
|
|
11
|
-
## 通用规则
|
|
12
|
-
|
|
13
|
-
- **输出到系统临时目录**(Windows = `$env:TEMP`;macOS/Linux = `$TMPDIR`,回退 `/tmp`)。系统会自动把临时目录里的截图桥接到工作区可代理的 `assets/` 目录并作为图片回给用户 —— 你只要把命令打印出来的那条路径原样转告用户即可,**不必**手动搬运文件,也**不要**写到工作区其它目录(那样前端反而加载不出图)。
|
|
14
|
-
- 文件名带时间戳(如 `qla-shot-20260703-142530.png`),避免覆盖。
|
|
15
|
-
|
|
16
|
-
## Windows
|
|
17
|
-
|
|
18
|
-
不要把一长串截图命令内联到 exec。改为分两步:
|
|
19
|
-
|
|
20
|
-
1. 用 **write 工具**把下面这个脚本写到工作区 `.qla-tmp/shot.ps1`(`$out` 落在系统临时目录 `$env:TEMP`):
|
|
21
|
-
|
|
22
|
-
```powershell
|
|
23
|
-
Add-Type -AssemblyName System.Windows.Forms, System.Drawing
|
|
24
|
-
$out = Join-Path $env:TEMP ("qla-shot-" + (Get-Date -Format yyyyMMdd-HHmmss) + ".png")
|
|
25
|
-
$b = [System.Windows.Forms.SystemInformation]::VirtualScreen
|
|
26
|
-
$bmp = New-Object System.Drawing.Bitmap $b.Width, $b.Height
|
|
27
|
-
$g = [System.Drawing.Graphics]::FromImage($bmp)
|
|
28
|
-
$g.CopyFromScreen($b.Left, $b.Top, 0, 0, $bmp.Size)
|
|
29
|
-
$bmp.Save($out)
|
|
30
|
-
$g.Dispose(); $bmp.Dispose()
|
|
31
|
-
Write-Output $out
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
2. 再用 exec 运行它,**显式写 `powershell.exe`**(不要假设当前 shell 是 PowerShell —— 即便是 opt-in 的 Git Bash 也能这样截图):
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .qla-tmp/shot.ps1
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
脚本会把最终 PNG 的绝对路径打印到 stdout。
|
|
41
|
-
|
|
42
|
-
## macOS
|
|
43
|
-
|
|
44
|
-
截到系统临时目录并把路径打印出来(不要固定文件名):
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
f="${TMPDIR:-/tmp}/qla-shot-$(date +%Y%m%d-%H%M%S).png"; screencapture -x "$f"; echo "$f"
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Linux
|
|
51
|
-
|
|
52
|
-
优先 grim(Wayland)或 `import -window root`(X11/ImageMagick),同样输出到系统临时目录并打印路径:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
f="${TMPDIR:-/tmp}/qla-shot-$(date +%Y%m%d-%H%M%S).png"; grim "$f" && echo "$f"
|
|
56
|
-
# 或 X11/ImageMagick:
|
|
57
|
-
f="${TMPDIR:-/tmp}/qla-shot-$(date +%Y%m%d-%H%M%S).png"; import -window root "$f" && echo "$f"
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## 之后
|
|
61
|
-
|
|
62
|
-
把命令打印出来的那条图片路径**用反引号包成行内代码**回给用户(如 `C:\Users\…\image.png`)——前端会把工作区内的图片路径**内联渲染成图片**,反引号能避免路径里的反斜杠被 markdown 转义破坏。再一句话说明截的是什么。命令失败时报告确切错误,不要改用安装大型依赖的方案。
|
|
1
|
+
---
|
|
2
|
+
name: desktop-screenshot
|
|
3
|
+
description: 用户要求截屏/截图/看看我的屏幕时使用 —— 用 exec 跑系统命令截取桌面,把图片文件路径回给用户。无需专用截图工具。
|
|
4
|
+
requires: [exec, write]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Desktop Screenshot
|
|
8
|
+
|
|
9
|
+
用户要求截取桌面/屏幕时,用 exec 执行系统自带命令,**不要**说自己没有截图能力。
|
|
10
|
+
|
|
11
|
+
## 通用规则
|
|
12
|
+
|
|
13
|
+
- **输出到系统临时目录**(Windows = `$env:TEMP`;macOS/Linux = `$TMPDIR`,回退 `/tmp`)。系统会自动把临时目录里的截图桥接到工作区可代理的 `assets/` 目录并作为图片回给用户 —— 你只要把命令打印出来的那条路径原样转告用户即可,**不必**手动搬运文件,也**不要**写到工作区其它目录(那样前端反而加载不出图)。
|
|
14
|
+
- 文件名带时间戳(如 `qla-shot-20260703-142530.png`),避免覆盖。
|
|
15
|
+
|
|
16
|
+
## Windows
|
|
17
|
+
|
|
18
|
+
不要把一长串截图命令内联到 exec。改为分两步:
|
|
19
|
+
|
|
20
|
+
1. 用 **write 工具**把下面这个脚本写到工作区 `.qla-tmp/shot.ps1`(`$out` 落在系统临时目录 `$env:TEMP`):
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
Add-Type -AssemblyName System.Windows.Forms, System.Drawing
|
|
24
|
+
$out = Join-Path $env:TEMP ("qla-shot-" + (Get-Date -Format yyyyMMdd-HHmmss) + ".png")
|
|
25
|
+
$b = [System.Windows.Forms.SystemInformation]::VirtualScreen
|
|
26
|
+
$bmp = New-Object System.Drawing.Bitmap $b.Width, $b.Height
|
|
27
|
+
$g = [System.Drawing.Graphics]::FromImage($bmp)
|
|
28
|
+
$g.CopyFromScreen($b.Left, $b.Top, 0, 0, $bmp.Size)
|
|
29
|
+
$bmp.Save($out)
|
|
30
|
+
$g.Dispose(); $bmp.Dispose()
|
|
31
|
+
Write-Output $out
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
2. 再用 exec 运行它,**显式写 `powershell.exe`**(不要假设当前 shell 是 PowerShell —— 即便是 opt-in 的 Git Bash 也能这样截图):
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .qla-tmp/shot.ps1
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
脚本会把最终 PNG 的绝对路径打印到 stdout。
|
|
41
|
+
|
|
42
|
+
## macOS
|
|
43
|
+
|
|
44
|
+
截到系统临时目录并把路径打印出来(不要固定文件名):
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
f="${TMPDIR:-/tmp}/qla-shot-$(date +%Y%m%d-%H%M%S).png"; screencapture -x "$f"; echo "$f"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Linux
|
|
51
|
+
|
|
52
|
+
优先 grim(Wayland)或 `import -window root`(X11/ImageMagick),同样输出到系统临时目录并打印路径:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
f="${TMPDIR:-/tmp}/qla-shot-$(date +%Y%m%d-%H%M%S).png"; grim "$f" && echo "$f"
|
|
56
|
+
# 或 X11/ImageMagick:
|
|
57
|
+
f="${TMPDIR:-/tmp}/qla-shot-$(date +%Y%m%d-%H%M%S).png"; import -window root "$f" && echo "$f"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 之后
|
|
61
|
+
|
|
62
|
+
把命令打印出来的那条图片路径**用反引号包成行内代码**回给用户(如 `C:\Users\…\image.png`)——前端会把工作区内的图片路径**内联渲染成图片**,反引号能避免路径里的反斜杠被 markdown 转义破坏。再一句话说明截的是什么。命令失败时报告确切错误,不要改用安装大型依赖的方案。
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: office-doc-reading
|
|
3
|
-
description: 用户上传或提到 xls/xlsx/doc/docx/ppt/pdf 等 office 文档并询问内容时使用 —— 用 exec + python 一行脚本直接读取,严禁格式转换迂回和重复装包。
|
|
4
|
-
requires: [exec, read]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Office Document Reading
|
|
8
|
-
|
|
9
|
-
read 工具无法解析二进制 office 文档(会返回结构化拒绝)。正确路径:
|
|
10
|
-
|
|
11
|
-
1. **定位本地文件**:上传清单里的 `[Uploaded file saved locally: <path>]` 即本地路径;没有则先用 search 找。
|
|
12
|
-
2. **一行脚本直读**(exec):
|
|
13
|
-
- 表格:python -c "import openpyxl;wb=openpyxl.load_workbook(r'<path>',read_only=True);ws=wb.active;[print(*[c.value for c in r],sep='\t') for r in ws.iter_rows(max_rows=30)]"
|
|
14
|
-
(.xls 老格式用 pandas.read_excel,engine 自动回退 xlrd)
|
|
15
|
-
- Word:python -c "import docx;print('\n'.join(p.text for p in docx.Document(r'<path>').paragraphs[:60]))"
|
|
16
|
-
- PDF:python -c "import pypdf;r=pypdf.PdfReader(r'<path>');print('\n'.join((p.extract_text() or '')[:2000] for p in r.pages[:5]))"
|
|
17
|
-
3. **缺依赖时**:最多补装一次对应包(如 pip install openpyxl);装完立即回到第 2 步。
|
|
18
|
-
4. **禁止**:把文档转成 XML/BOM/其他格式的迂回链;同一目标装第二轮依赖;对二进制文件重复调用 read。
|
|
19
|
-
5. 回答用户问题本身(表里有什么 → 列名 + 行数 + 前几行概要),不要倾倒全部内容。
|
|
1
|
+
---
|
|
2
|
+
name: office-doc-reading
|
|
3
|
+
description: 用户上传或提到 xls/xlsx/doc/docx/ppt/pdf 等 office 文档并询问内容时使用 —— 用 exec + python 一行脚本直接读取,严禁格式转换迂回和重复装包。
|
|
4
|
+
requires: [exec, read]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Office Document Reading
|
|
8
|
+
|
|
9
|
+
read 工具无法解析二进制 office 文档(会返回结构化拒绝)。正确路径:
|
|
10
|
+
|
|
11
|
+
1. **定位本地文件**:上传清单里的 `[Uploaded file saved locally: <path>]` 即本地路径;没有则先用 search 找。
|
|
12
|
+
2. **一行脚本直读**(exec):
|
|
13
|
+
- 表格:python -c "import openpyxl;wb=openpyxl.load_workbook(r'<path>',read_only=True);ws=wb.active;[print(*[c.value for c in r],sep='\t') for r in ws.iter_rows(max_rows=30)]"
|
|
14
|
+
(.xls 老格式用 pandas.read_excel,engine 自动回退 xlrd)
|
|
15
|
+
- Word:python -c "import docx;print('\n'.join(p.text for p in docx.Document(r'<path>').paragraphs[:60]))"
|
|
16
|
+
- PDF:python -c "import pypdf;r=pypdf.PdfReader(r'<path>');print('\n'.join((p.extract_text() or '')[:2000] for p in r.pages[:5]))"
|
|
17
|
+
3. **缺依赖时**:最多补装一次对应包(如 pip install openpyxl);装完立即回到第 2 步。
|
|
18
|
+
4. **禁止**:把文档转成 XML/BOM/其他格式的迂回链;同一目标装第二轮依赖;对二进制文件重复调用 read。
|
|
19
|
+
5. 回答用户问题本身(表里有什么 → 列名 + 行数 + 前几行概要),不要倾倒全部内容。
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createInterface as Ke}from"node:readline";import{existsSync as Qe,readFileSync as Ye}from"node:fs";import{readFileSync as ye}from"node:fs";import{randomUUID as ve}from"node:crypto";import{readdirSync as
|
|
2
|
+
import{createInterface as Ke}from"node:readline";import{existsSync as Qe,readFileSync as Ye}from"node:fs";import{readFileSync as ye}from"node:fs";import{randomUUID as ve}from"node:crypto";import{readdirSync as Ct,readFileSync as xt,statSync as re,writeFileSync as At}from"node:fs";import{readdir as oe,readFile as ne,stat as se,writeFile as ie}from"node:fs/promises";import{join as d}from"node:path";import{homedir as Q}from"node:os";import{join as u}from"node:path";import{existsSync as ft}from"node:fs";import{createHash as it}from"node:crypto";import{resolve as lt}from"node:path";var P=".qlogicagent";function p(){return process.env.QLOGICAGENT_HOME||u(Q(),P)}function v(){return u(p(),"skills")}function _(){return u(p(),"mcp.json")}function Y(t){if(!t)throw new Error("getProjectAgentDir: cwd is required (must not fall back to process.cwd())");return u(t,P)}function C(t){return u(Y(t),"skills-disabled.json")}import{readFileSync as Z,writeFileSync as vt,mkdirSync as St,renameSync as bt}from"node:fs";import{dirname as Tt,join as X}from"node:path";function f(){return{version:1,disabled:[]}}function ee(t){let e;try{e=Z(t,"utf8")}catch(n){return n.code==="ENOENT"?{list:f(),corrupt:!1}:(console.error(`[project-skill-manifest] Cannot read skill mute list at ${t} (${n instanceof Error?n.message:String(n)}); treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0})}let r;try{r=JSON.parse(e)}catch(n){return console.error(`[project-skill-manifest] Skill mute list at ${t} is corrupted (${n instanceof Error?n.message:String(n)}); treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0}}return!r||typeof r!="object"||!Array.isArray(r.disabled)?(console.error(`[project-skill-manifest] Skill mute list at ${t} has an unexpected shape; treating it as empty for reads \u2014 muted skills may reactivate.`),{list:f(),corrupt:!0}):{list:{version:1,disabled:[...new Set(r.disabled.filter(n=>typeof n=="string"&&n.trim().length>0))]},corrupt:!1}}function x(t){return ee(t).list}function te(){return X(p(),"skills-disabled.json")}function A(){return new Set(x(te()).disabled)}function R(t){return new Set(x(C(t)).disabled)}var ae=["auto-skill-","test-skill-"],le=".skills_prompt_snapshot.json";function ce(t){return ae.some(e=>t.startsWith(e))}function ue(t){let e=t.replace(/\r\n/g,`
|
|
3
3
|
`),r=e.match(/^---\n[\s\S]*?^version:\s*(\S+)/m),o=e.match(/^---\n[\s\S]*?^category:\s*(.+)/m),n=e.match(/^---\n[\s\S]*?^author:\s*(.+)/m),i=e.match(/^---\n[\s\S]*?^requires:\s*(.+)/m),s=e.match(/^---\n[\s\S]*?^environments:\s*(.+)/m),a=e.match(/^---\n([\s\S]*?)\n---/)?.[1]??"";return{version:r?.[1],description:de(a),category:o?.[1]?.trim()||void 0,author:n?.[1]?.trim()||void 0,requiredTools:M(i?.[1]),environments:M(s?.[1])}}function de(t){let e=t.split(`
|
|
4
|
-
`),r=e.findIndex(s=>/^description:/.test(s));if(r===-1)return;let o=e[r].replace(/^description:[ \t]*/,"").trim(),n=/^[>|][+-]?$/.test(o),i=[];!n&&o&&i.push(o);for(let s=r+1;s<e.length;s++){let a=e[s];if(!/^[ \t]/.test(a))break;let l=a.trim();l&&i.push(l)}if(i.length!==0)return i.join(" ").replace(/^["']|["']$/g,"").trim()||void 0}var E=new Map,S=new Map;function me(t,e,r,o){let n=e.has(t.name),i=r.has(t.name),s=!ge(t.meta,o);return{name:t.name,filePath:t.filePath,baseDir:t.baseDir,globallyDisabled:n,projectDisabled:i,active:!n&&!i&&!s,systemGenerated:t.systemGenerated,description:t.meta.description,version:t.meta.version,category:t.meta.category,author:t.meta.author,requiredTools:t.meta.requiredTools,environments:t.meta.environments}}async function pe(t){let e;try{e=await oe(t,{withFileTypes:!0})}catch{e=[]}let r=[];for(let s of e){if(!s.isDirectory()||s.name.startsWith("."))continue;let a=d(t,s.name),l=d(a,"SKILL.md");try{let y=await se(l);if(!y.isFile())continue;r.push({name:s.name,filePath:l,baseDir:a,mtimeMs:y.mtimeMs,size:y.size})}catch{continue}}r.sort((s,a)=>s.name.localeCompare(a.name));let o=r.map(s=>`${s.name}:${s.mtimeMs}:${s.size}`).join("|"),n=E.get(t);if(n&&n.fingerprint===o)return n.raw;let i=[];for(let s of r){let a;try{a=await ne(s.filePath,"utf8")}catch{continue}i.push({name:s.name,filePath:s.filePath,baseDir:s.baseDir,systemGenerated:ce(s.name),mtimeMs:s.mtimeMs,size:s.size,meta:ue(a)})}return E.set(t,{fingerprint:o,raw:i}),he(t,i),i}async function fe(t,e){let r=v(),o=A(),n=t?R(t):new Set,i=S.get(r);return i||(i=pe(r).finally(()=>S.delete(r)),S.set(r,i)),(await i).map(a=>me(a,o,n,e))}async function D(t,e){return(await fe(t,e)).filter(r=>r.active)}function j(t){let e=v(),r=d(e,t),o=d(r,"SKILL.md");try{if(re(o).isFile())return{baseDir:r,filePath:o}}catch{}return null}function M(t){if(!t)return;let e=t.replace(/^\[|\]$/g,"").split(/[,\s]+/).map(r=>r.replace(/^["']|["']$/g,"").trim()).filter(Boolean);return e.length>0?e:void 0}function ge(t,e){if(t.environments&&e?.currentEnvironment&&!t.environments.includes(e.currentEnvironment))return!1;if(t.requiredTools){if(!e?.availableToolNames)return!1;let r=new Set(e.availableToolNames);return t.requiredTools.every(o=>r.has(o))}return!0}async function he(t,e){try{let o={version:1,entries:e.map(n=>({name:n.name,size:n.size,mtimeMs:n.mtimeMs,description:n.meta.description,version:n.meta.version,requiredTools:n.meta.requiredTools,environments:n.meta.environments}))};await ie(d(t,le),JSON.stringify(o,null,2),"utf8")}catch{}}var I="astraclaw_capabilities";async function L(t){if(t.tool==="skills_list")return{handled:!0,result:{skills:(await D(t.projectRoot,{availableToolNames:t.availableToolNames,currentEnvironment:t.currentEnvironment??process.platform})).map(Se)}};if(t.tool==="skill_view"){let e=typeof t.args.name=="string"?t.args.name.trim():"";if(!e)throw new Error("skill_view requires a skill name");let r=j(e);if(!r)throw new Error(`Skill not found: ${e}`);return{handled:!0,result:{name:e,content:ye(r.filePath,"utf8")}}}if(t.tool==="mcp_connectors_list"){let e=t.mcpServerFailures??[],r=e.length>0?{failedServers:e,note:`${e.length} configured MCP server(s) are unavailable this session; their tools are missing from this list.`}:{};if(!t.toolCatalog)return{handled:!0,result:{tools:[],note:"AstraClaw MCP connector catalog is not attached to this capability server instance.",...e.length>0?{failedServers:e}:{}}};let o=t.toolCatalog.getToolManifest().filter(n=>n.function.name.startsWith("mcp__")).map(n=>({toolName:n.function.name,server:we(n.function.name),name:Te(n.function.name),description:n.function.description,inputSchema:n.function.parameters}));return{handled:!0,result:{tools:o,count:o.length,...r}}}if(t.tool==="mcp_tool_call"){if(!t.toolCatalog)throw new Error("AstraClaw MCP connector catalog is not attached");let e=typeof t.args.toolName=="string"?t.args.toolName.trim():"";if(!e.startsWith("mcp__"))throw new Error("mcp_tool_call requires a connector toolName returned by mcp_connectors_list");let r=t.toolCatalog.findTool(e);if(!r?.execute)throw new Error(`MCP connector tool not found or not executable: ${e}`);let o=be(t.args.args),n=`astraclaw_mcp_${ve().slice(0,8)}`,i=await r.execute(n,o);return{handled:!0,result:{toolName:e,content:i.content,details:i.details,imageUrls:i.imageUrls}}}return{handled:!1}}function Se(t){return{name:t.name,description:t.description,version:t.version,category:t.category,requiredTools:t.requiredTools,environments:t.environments}}function be(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function we(t){let e=t.split("__");return e.length>=3?e[1]??"":""}function Te(t){let e=t.split("__");return e.length>=3?e.slice(2).join("__"):t}import m from"node:path";import{fileURLToPath as xe}from"node:url";import{createRuntime as Ae}from"mcporter";var O=new Set(["gateway","agents_list","session_status","sessions_send","sessions_list","sessions_history","sessions_spawn","cron","config","workflow"]),ke=new Set([...O,"agent"]);function $(t){return t?.riskLevel?t.riskLevel:t?.isDangerous?"system":t?.isReadOnly?"read":t?.isEgress?"external_egress":"write"}var b=class{toolPool=new Map;setTools(e){this.toolPool.clear();for(let r of e)this.toolPool.set(r.name,r)}addTool(e){this.toolPool.set(e.name,e)}addTools(e){for(let r of e)this.addTool(r)}removeTool(e){return this.toolPool.delete(e)}findTool(e){return this.toolPool.get(e)}hasTool(e){return this.toolPool.has(e)}getToolNames(){return Array.from(this.toolPool.keys())}getToolCount(){return this.toolPool.size}async executeTool(e,r,o,n){let i=this.toolPool.get(e);if(!i)throw new Error(`Tool not found: ${e}`);return i.execute(r,o,n)}getTools(){return Array.from(this.toolPool.values()).filter(e=>e.isEnabled?.()!==!1)}getToolManifest(){let e=[];for(let r of this.toolPool.values()){if(r.isEnabled?.()===!1)continue;let o=$(r);e.push({type:"function",function:{name:r.name,description:r.description,parameters:r.parameters},meta:{category:r.category??"other",displayName:r.displayName??{key:`capability.tool.${r.name}.name`,fallback:r.label},displayDescription:r.displayDescription??{key:`capability.tool.${r.name}.description`,fallback:""},parallelSafe:r.isConcurrencySafe??!1,riskLevel:o,isReadOnly:o==="read",isDangerous:o==="system",isDelete:r.isDelete??!1,isEgress:r.isEgress??o==="external_egress",egressCarriesData:r.egressCarriesData??!1}})}return e}},N=new b;function F(t){N.addTools(t)}function U(t){return N.removeTool(t)}var Pe=new Set(["describe","fetch","find","get","inspect","list","query","read","search","stat"]),_e=new Set(["append","copy","create","delete","edit","move","patch","remove","rename","set","update","upload","write"]);function q(t){let e=t.annotations,r=Ce(t.name),o=r.some(l=>_e.has(l)),n=r.some(l=>Pe.has(l)),i=e?.destructiveHint===!0||o,s=e?.readOnlyHint===!0||!i&&n,a=s||e?.idempotentHint===!0&&!i;return{isReadOnly:s,isConcurrencySafe:a,isDestructive:i}}function Ce(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)}var Re=12e4,g=3,Ee=1e3;async function Me(t,e){let r=e.sleep??(i=>new Promise(s=>setTimeout(s,i))),o=Math.max(1,e.attempts),n;for(let i=1;i<=o;i++)try{return await t()}catch(s){n=s,i<o&&(e.onRetry?.(i,s),await r(e.baseDelayMs*i))}throw n}var h=class{runtime=null;definitions=[];toolsByServer=new Map;injectedNames=new Set;log;workspaceRoot;toolCatalog;serverToolFilters=new Map;serverOAuth=new Map;failedServers=new Map;constructor(e){this.log=e.log??{info:()=>{},warn:()=>{}},this.workspaceRoot=e.workspaceRoot?m.resolve(e.workspaceRoot):void 0,this.toolCatalog=e.toolCatalog,this.definitions=e.servers.filter(r=>!r.disabled).filter(r=>{let o=Be(r);for(let n of o)this.log.warn(`[mcp] rejected server "${r.name}": ${n.message}`);return r.tools&&this.serverToolFilters.set(r.name,r.tools),r.oauth===!0&&this.serverOAuth.set(r.name,!0),o.length===0}).map(r=>this.toServerDefinition(r)).filter(r=>r!==null)}markServerFailed(e,r,o){this.failedServers.set(e,{name:e,phase:r,error:o}),console.error(`[mcp] server "${e}" unavailable this session (${r}): ${o}`)}toServerDefinition(e){if((e.type??(e.url?"http":"stdio"))==="http"){if(!e.url)return this.log.warn(`[mcp] server "${e.name}" is type "http" but has no url, skipping`),this.markServerFailed(e.name,"config",'type "http" but no url'),null;let o;try{o=new URL(e.url)}catch{return this.log.warn(`[mcp] server "${e.name}" has an invalid url "${e.url}", skipping`),this.markServerFailed(e.name,"config",`invalid url "${e.url}"`),null}return{name:e.name,command:{kind:"http",url:o,headers:e.headers}}}return e.command?{name:e.name,command:{kind:"stdio",command:e.command,args:e.args??[],cwd:e.cwd??this.workspaceRoot??process.cwd()},env:e.env}:(this.log.warn(`[mcp] server "${e.name}" is type "stdio" but has no command, skipping`),this.markServerFailed(e.name,"config",'type "stdio" but no command'),null)}async connectAll(){this.definitions.length!==0&&(this.runtime=await Ae({servers:this.definitions,clientInfo:{name:"qlogicagent",version:"1.0.0"},logger:{info:e=>this.log.info(`[mcp] ${e}`),warn:e=>this.log.warn(`[mcp] ${e}`),error:(e,r)=>this.log.warn(`[mcp] ${e}${r?` (${r instanceof Error?r.message:String(r)})`:""}`),debug:()=>{}}}),await Promise.allSettled(this.definitions.map(async e=>{try{let r=await Me(()=>this.runtime.listTools(e.name,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e.name)!==!0}),{attempts:g,baseDelayMs:Ee,onRetry:(n,i)=>this.log.warn(`[mcp] connect attempt ${n}/${g} for ${e.name} failed, retrying: ${i instanceof Error?i.message:i}`)}),o=z(r,this.serverToolFilters.get(e.name));this.toolsByServer.set(e.name,o),this.failedServers.delete(e.name),this.log.info(`[mcp] connected to ${e.name} (${o.length}/${r.length} tools)`)}catch(r){this.log.warn(`[mcp] failed to connect to ${e.name} after ${g} attempts: ${r instanceof Error?r.message:r}`),this.markServerFailed(e.name,"connect",`${r instanceof Error?r.message:String(r)} (after ${g} attempts)`)}})))}injectTools(){for(let[e,r]of this.toolsByServer){let o=this.injectPortableTools(e,r);this.log.info(`[mcp] injected ${o.length} tools from ${e}`)}}async refreshServerTools(e){if(!this.runtime)throw new Error("MCP runtime is not connected");let r=await this.runtime.listTools(e,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e)!==!0}),o=z(r,this.serverToolFilters.get(e));return this.toolsByServer.set(e,o),this.failedServers.delete(e),this.retractServerTools(e),this.injectPortableTools(e,o),o.length}getConnectedServers(){return Array.from(this.toolsByServer.keys())}getFailedServers(){return Array.from(this.failedServers.values())}getToolCount(){let e=0;for(let r of this.toolsByServer.values())e+=r.length;return e}async disconnectAll(){for(let r of this.injectedNames)this.removeRegisteredTool(r);this.injectedNames.clear(),this.toolsByServer.clear(),this.failedServers.clear();let e=this.runtime;if(this.runtime=null,e)try{await e.close()}catch{}}toPortableTool(e,r){let o=q({name:r.name,description:r.description});return{name:`mcp__${G(e)}__${r.name}`,label:`[${e}] ${r.name}`,category:"mcp",description:r.description??`MCP tool from ${e}`,parameters:r.inputSchema??{type:"object",properties:{}},isConcurrencySafe:o.isConcurrencySafe,isReadOnly:o.isReadOnly,isDestructive:o.isDestructive,searchHint:`mcp ${e} ${r.name.replace(/[_-]+/g," ")}`,execute:async(n,i)=>{let s=this.runtime;if(!s)return{content:[{type:"text",text:`MCP server "${e}" is not connected.`}],details:{error:"mcp_not_connected"}};try{let a=await s.callTool(e,r.name,{args:i,timeoutMs:Re});return De(a)}catch(a){let l=a instanceof Error?a.message:String(a);return{content:[{type:"text",text:`MCP tool error: ${l}`}],details:{error:l}}}}}}wrapToolsForWorkspaceBoundary(e){return this.workspaceRoot?e.map(r=>{if(!r.execute)return r;let o=r.execute;return{...r,execute:async(n,i,s)=>{let a=Ie(r.name,i,this.workspaceRoot);return a?{content:[{type:"text",text:a}],details:{type:"mcp",error:"workspace_boundary"}}:o(n,i,s)}}}):e}injectPortableTools(e,r){let o=this.wrapToolsForWorkspaceBoundary(r.map(n=>this.toPortableTool(e,n)));this.registerTools(o);for(let n of o)this.injectedNames.add(n.name);return o}retractServerTools(e){let r=`mcp__${G(e)}__`;for(let o of[...this.injectedNames])o.startsWith(r)&&(this.removeRegisteredTool(o),this.injectedNames.delete(o))}registerTools(e){this.toolCatalog?this.toolCatalog.addTools(e):F(e)}removeRegisteredTool(e){return this.toolCatalog?.removeTool(e)??U(e)}};function De(t){let e=t&&typeof t=="object"?t:{},o=(Array.isArray(e.content)?e.content:[]).filter(a=>!!a&&typeof a=="object"),n=o.filter(a=>a.type==="text"&&typeof a.text=="string").map(a=>a.text),i=o.filter(a=>!(a.type==="text"&&typeof a.text=="string")).map(a=>typeof a.type=="string"&&a.type?a.type:"unknown"),s=n.join(`
|
|
4
|
+
`),r=e.findIndex(s=>/^description:/.test(s));if(r===-1)return;let o=e[r].replace(/^description:[ \t]*/,"").trim(),n=/^[>|][+-]?$/.test(o),i=[];!n&&o&&i.push(o);for(let s=r+1;s<e.length;s++){let a=e[s];if(!/^[ \t]/.test(a))break;let l=a.trim();l&&i.push(l)}if(i.length!==0)return i.join(" ").replace(/^["']|["']$/g,"").trim()||void 0}var E=new Map,S=new Map;function me(t,e,r,o){let n=e.has(t.name),i=r.has(t.name),s=!ge(t.meta,o);return{name:t.name,filePath:t.filePath,baseDir:t.baseDir,globallyDisabled:n,projectDisabled:i,active:!n&&!i&&!s,systemGenerated:t.systemGenerated,description:t.meta.description,version:t.meta.version,category:t.meta.category,author:t.meta.author,requiredTools:t.meta.requiredTools,environments:t.meta.environments}}async function pe(t){let e;try{e=await oe(t,{withFileTypes:!0})}catch{e=[]}let r=[];for(let s of e){if(!s.isDirectory()||s.name.startsWith("."))continue;let a=d(t,s.name),l=d(a,"SKILL.md");try{let y=await se(l);if(!y.isFile())continue;r.push({name:s.name,filePath:l,baseDir:a,mtimeMs:y.mtimeMs,size:y.size})}catch{continue}}r.sort((s,a)=>s.name.localeCompare(a.name));let o=r.map(s=>`${s.name}:${s.mtimeMs}:${s.size}`).join("|"),n=E.get(t);if(n&&n.fingerprint===o)return n.raw;let i=[];for(let s of r){let a;try{a=await ne(s.filePath,"utf8")}catch{continue}i.push({name:s.name,filePath:s.filePath,baseDir:s.baseDir,systemGenerated:ce(s.name),mtimeMs:s.mtimeMs,size:s.size,meta:ue(a)})}return E.set(t,{fingerprint:o,raw:i}),he(t,i),i}async function fe(t,e){let r=v(),o=A(),n=t?R(t):new Set,i=S.get(r);return i||(i=pe(r).finally(()=>S.delete(r)),S.set(r,i)),(await i).map(a=>me(a,o,n,e))}async function D(t,e){return(await fe(t,e)).filter(r=>r.active)}function j(t){let e=v(),r=d(e,t),o=d(r,"SKILL.md");try{if(re(o).isFile())return{baseDir:r,filePath:o}}catch{}return null}function M(t){if(!t)return;let e=t.replace(/^\[|\]$/g,"").split(/[,\s]+/).map(r=>r.replace(/^["']|["']$/g,"").trim()).filter(Boolean);return e.length>0?e:void 0}function ge(t,e){if(t.environments&&e?.currentEnvironment&&!t.environments.includes(e.currentEnvironment))return!1;if(t.requiredTools){if(!e?.availableToolNames)return!1;let r=new Set(e.availableToolNames);return t.requiredTools.every(o=>r.has(o))}return!0}async function he(t,e){try{let o={version:1,entries:e.map(n=>({name:n.name,size:n.size,mtimeMs:n.mtimeMs,description:n.meta.description,version:n.meta.version,requiredTools:n.meta.requiredTools,environments:n.meta.environments}))};await ie(d(t,le),JSON.stringify(o,null,2),"utf8")}catch{}}var I="astraclaw_capabilities";async function L(t){if(t.tool==="skills_list")return{handled:!0,result:{skills:(await D(t.projectRoot,{availableToolNames:t.availableToolNames,currentEnvironment:t.currentEnvironment??process.platform})).map(Se)}};if(t.tool==="skill_view"){let e=typeof t.args.name=="string"?t.args.name.trim():"";if(!e)throw new Error("skill_view requires a skill name");let r=j(e);if(!r)throw new Error(`Skill not found: ${e}`);return{handled:!0,result:{name:e,content:ye(r.filePath,"utf8")}}}if(t.tool==="mcp_connectors_list"){let e=t.mcpServerFailures??[],r=e.length>0?{failedServers:e,note:`${e.length} configured MCP server(s) are unavailable this session; their tools are missing from this list.`}:{};if(!t.toolCatalog)return{handled:!0,result:{tools:[],note:"AstraClaw MCP connector catalog is not attached to this capability server instance.",...e.length>0?{failedServers:e}:{}}};let o=t.toolCatalog.getToolManifest().filter(n=>n.function.name.startsWith("mcp__")).map(n=>({toolName:n.function.name,server:we(n.function.name),name:Te(n.function.name),description:n.function.description,inputSchema:n.function.parameters}));return{handled:!0,result:{tools:o,count:o.length,...r}}}if(t.tool==="mcp_tool_call"){if(!t.toolCatalog)throw new Error("AstraClaw MCP connector catalog is not attached");let e=typeof t.args.toolName=="string"?t.args.toolName.trim():"";if(!e.startsWith("mcp__"))throw new Error("mcp_tool_call requires a connector toolName returned by mcp_connectors_list");let r=t.toolCatalog.findTool(e);if(!r?.execute)throw new Error(`MCP connector tool not found or not executable: ${e}`);let o=be(t.args.args),n=`astraclaw_mcp_${ve().slice(0,8)}`,i=await r.execute(n,o);return{handled:!0,result:{toolName:e,content:i.content,details:i.details,imageUrls:i.imageUrls}}}return{handled:!1}}function Se(t){return{name:t.name,description:t.description,version:t.version,category:t.category,requiredTools:t.requiredTools,environments:t.environments}}function be(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function we(t){let e=t.split("__");return e.length>=3?e[1]??"":""}function Te(t){let e=t.split("__");return e.length>=3?e.slice(2).join("__"):t}import m from"node:path";import{fileURLToPath as xe}from"node:url";import{createRuntime as Ae}from"mcporter";var O=new Set(["gateway","agents_list","session_status","sessions_send","sessions_list","sessions_history","sessions_spawn","cron","config","workflow"]),ke=new Set([...O,"agent"]);function $(t){return t?.riskLevel?t.riskLevel:t?.isDangerous?"system":t?.isReadOnly?"read":t?.isEgress?"external_egress":"write"}var b=class{toolPool=new Map;setTools(e){this.toolPool.clear();for(let r of e)this.toolPool.set(r.name,r)}addTool(e){this.toolPool.set(e.name,e)}addTools(e){for(let r of e)this.addTool(r)}removeTool(e){return this.toolPool.delete(e)}findTool(e){return this.toolPool.get(e)}hasTool(e){return this.toolPool.has(e)}getToolNames(){return Array.from(this.toolPool.keys())}getToolCount(){return this.toolPool.size}async executeTool(e,r,o,n){let i=this.toolPool.get(e);if(!i)throw new Error(`Tool not found: ${e}`);return i.execute(r,o,n)}getTools(){return Array.from(this.toolPool.values()).filter(e=>e.isEnabled?.()!==!1)}getToolManifest(){let e=[];for(let r of this.toolPool.values()){if(r.isEnabled?.()===!1)continue;let o=$(r);e.push({type:"function",function:{name:r.name,description:r.description,parameters:r.parameters},meta:{category:r.category??"other",displayName:r.displayName??{key:`capability.tool.${r.name}.name`,fallback:r.label},displayDescription:r.displayDescription??{key:`capability.tool.${r.name}.description`,fallback:""},parallelSafe:r.isConcurrencySafe??!1,riskLevel:o,isReadOnly:o==="read",isDangerous:o==="system",isDelete:r.isDelete??!1,isEgress:r.isEgress??o==="external_egress",egressCarriesData:r.egressCarriesData??!1}})}return e}},N=new b;function F(t){N.addTools(t)}function U(t){return N.removeTool(t)}var Pe=new Set(["describe","fetch","find","get","inspect","list","query","read","search","stat"]),_e=new Set(["append","copy","create","delete","edit","move","patch","remove","rename","set","update","upload","write"]);function q(t){let e=t.annotations,r=Ce(t.name),o=r.some(l=>_e.has(l)),n=r.some(l=>Pe.has(l)),i=e?.destructiveHint===!0||o,s=e?.readOnlyHint===!0||!i&&n,a=s||e?.idempotentHint===!0&&!i;return{isReadOnly:s,isConcurrencySafe:a,isDestructive:i}}function Ce(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)}var Re=12e4,g=3,Ee=1e3;async function Me(t,e){let r=e.sleep??(i=>new Promise(s=>setTimeout(s,i))),o=Math.max(1,e.attempts),n;for(let i=1;i<=o;i++)try{return await t()}catch(s){n=s,i<o&&(e.onRetry?.(i,s),await r(e.baseDelayMs*i))}throw n}var h=class{runtime=null;definitions=[];toolsByServer=new Map;injectedNames=new Set;log;workspaceRoot;toolCatalog;serverToolFilters=new Map;serverOAuth=new Map;failedServers=new Map;constructor(e){this.log=e.log??{info:()=>{},warn:()=>{}},this.workspaceRoot=e.workspaceRoot?m.resolve(e.workspaceRoot):void 0,this.toolCatalog=e.toolCatalog,this.definitions=e.servers.filter(r=>!r.disabled).filter(r=>{let o=Be(r);for(let n of o)this.log.warn(`[mcp] rejected server "${r.name}": ${n.message}`);return r.tools&&this.serverToolFilters.set(r.name,r.tools),r.oauth===!0&&this.serverOAuth.set(r.name,!0),o.length===0}).map(r=>this.toServerDefinition(r)).filter(r=>r!==null)}markServerFailed(e,r,o){this.failedServers.set(e,{name:e,phase:r,error:o}),console.error(`[mcp] server "${e}" unavailable this session (${r}): ${o}`)}toServerDefinition(e){if((e.type??(e.url?"http":"stdio"))==="http"){if(!e.url)return this.log.warn(`[mcp] server "${e.name}" is type "http" but has no url, skipping`),this.markServerFailed(e.name,"config",'type "http" but no url'),null;let o;try{o=new URL(e.url)}catch{return this.log.warn(`[mcp] server "${e.name}" has an invalid url "${e.url}", skipping`),this.markServerFailed(e.name,"config",`invalid url "${e.url}"`),null}return{name:e.name,command:{kind:"http",url:o,headers:e.headers}}}return e.command?{name:e.name,command:{kind:"stdio",command:e.command,args:e.args??[],cwd:e.cwd??this.workspaceRoot??process.cwd()},env:e.env}:(this.log.warn(`[mcp] server "${e.name}" is type "stdio" but has no command, skipping`),this.markServerFailed(e.name,"config",'type "stdio" but no command'),null)}async connectAll(){this.definitions.length!==0&&(this.runtime=await Ae({servers:this.definitions,clientInfo:{name:"qlogicagent",version:"1.0.0"},logger:{info:e=>this.log.info(`[mcp] ${e}`),warn:e=>this.log.warn(`[mcp] ${e}`),error:(e,r)=>this.log.warn(`[mcp] ${e}${r?` (${r instanceof Error?r.message:String(r)})`:""}`),debug:()=>{}}}),await Promise.allSettled(this.definitions.map(async e=>{try{let r=await Me(()=>this.runtime.listTools(e.name,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e.name)!==!0}),{attempts:g,baseDelayMs:Ee,onRetry:(n,i)=>this.log.warn(`[mcp] connect attempt ${n}/${g} for ${e.name} failed, retrying: ${i instanceof Error?i.message:i}`)}),o=W(r,this.serverToolFilters.get(e.name));this.toolsByServer.set(e.name,o),this.failedServers.delete(e.name),this.log.info(`[mcp] connected to ${e.name} (${o.length}/${r.length} tools)`)}catch(r){this.log.warn(`[mcp] failed to connect to ${e.name} after ${g} attempts: ${r instanceof Error?r.message:r}`),this.markServerFailed(e.name,"connect",`${r instanceof Error?r.message:String(r)} (after ${g} attempts)`)}})))}injectTools(){for(let[e,r]of this.toolsByServer){let o=this.injectPortableTools(e,r);this.log.info(`[mcp] injected ${o.length} tools from ${e}`)}}async refreshServerTools(e){if(!this.runtime)throw new Error("MCP runtime is not connected");let r=await this.runtime.listTools(e,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e)!==!0}),o=W(r,this.serverToolFilters.get(e));return this.toolsByServer.set(e,o),this.failedServers.delete(e),this.retractServerTools(e),this.injectPortableTools(e,o),o.length}getConnectedServers(){return Array.from(this.toolsByServer.keys())}getFailedServers(){return Array.from(this.failedServers.values())}getToolCount(){let e=0;for(let r of this.toolsByServer.values())e+=r.length;return e}async disconnectAll(){for(let r of this.injectedNames)this.removeRegisteredTool(r);this.injectedNames.clear(),this.toolsByServer.clear(),this.failedServers.clear();let e=this.runtime;if(this.runtime=null,e)try{await e.close()}catch{}}toPortableTool(e,r){let o=q({name:r.name,description:r.description});return{name:`mcp__${G(e)}__${r.name}`,label:`[${e}] ${r.name}`,category:"mcp",description:r.description??`MCP tool from ${e}`,parameters:r.inputSchema??{type:"object",properties:{}},isConcurrencySafe:o.isConcurrencySafe,isReadOnly:o.isReadOnly,isDestructive:o.isDestructive,searchHint:`mcp ${e} ${r.name.replace(/[_-]+/g," ")}`,execute:async(n,i)=>{let s=this.runtime;if(!s)return{content:[{type:"text",text:`MCP server "${e}" is not connected.`}],details:{error:"mcp_not_connected"}};try{let a=await s.callTool(e,r.name,{args:i,timeoutMs:Re});return De(a)}catch(a){let l=a instanceof Error?a.message:String(a);return{content:[{type:"text",text:`MCP tool error: ${l}`}],details:{error:l}}}}}}wrapToolsForWorkspaceBoundary(e){return this.workspaceRoot?e.map(r=>{if(!r.execute)return r;let o=r.execute;return{...r,execute:async(n,i,s)=>{let a=Ie(r.name,i,this.workspaceRoot);return a?{content:[{type:"text",text:a}],details:{type:"mcp",error:"workspace_boundary"}}:o(n,i,s)}}}):e}injectPortableTools(e,r){let o=this.wrapToolsForWorkspaceBoundary(r.map(n=>this.toPortableTool(e,n)));this.registerTools(o);for(let n of o)this.injectedNames.add(n.name);return o}retractServerTools(e){let r=`mcp__${G(e)}__`;for(let o of[...this.injectedNames])o.startsWith(r)&&(this.removeRegisteredTool(o),this.injectedNames.delete(o))}registerTools(e){this.toolCatalog?this.toolCatalog.addTools(e):F(e)}removeRegisteredTool(e){return this.toolCatalog?.removeTool(e)??U(e)}};function De(t){let e=t&&typeof t=="object"?t:{},o=(Array.isArray(e.content)?e.content:[]).filter(a=>!!a&&typeof a=="object"),n=o.filter(a=>a.type==="text"&&typeof a.text=="string").map(a=>a.text),i=o.filter(a=>!(a.type==="text"&&typeof a.text=="string")).map(a=>typeof a.type=="string"&&a.type?a.type:"unknown"),s=n.join(`
|
|
5
5
|
`);if(i.length>0){let a=[...new Set(i)].join(", ");s=s?`${s}
|
|
6
6
|
|
|
7
|
-
[${i.length} non-text blocks omitted: ${a}]`:`[output contains only non-text blocks: ${a}]`}return{content:[{type:"text",text:s||"(no text output)"}],...e.isError?{details:{error:"mcp_tool_error"}}:{}}}function G(t){return t.replace(/[^a-zA-Z0-9_]/g,"_").toLowerCase()}var je=/(?:^|_)(path|paths|file|files|filename|filenames|dir|dirs|directory|directories|folder|folders|cwd|root|uri)(?:$|_)/i;function Ie(t,e,r){if(!r)return null;for(let o of T(e)){let n=$e(o.value,r);if(n&&!Ne(n.candidate,n.root,n.pathApi))return`Blocked: MCP tool "${t}" path "${o.value}" is outside the workspace boundary "${n.root}"`}return null}function T(t,e="",r=0){if(r>8)return[];if(typeof t=="string")return Le(e,t)?[{key:e,value:t}]:[];if(Array.isArray(t))return t.flatMap(n=>T(n,e,r+1));if(!t||typeof t!="object")return[];let o=[];for(let[n,i]of Object.entries(t))o.push(...T(i,n,r+1));return o}function Le(t,e){if(!je.test(t))return!1;let r=e.trim();return!r||/^https?:\/\//i.test(r)?!1:Oe(r)}function Oe(t){return m.isAbsolute(t)||/^[A-Za-z]:[\\/]/.test(t)||/^\\\\/.test(t)||/^file:\/\//i.test(t)||t.includes("../")||t.includes("..\\")||t.startsWith(".\\")||t.startsWith("./")||t.includes("/")||t.includes("\\")}function $e(t,e){let r=t.trim();if(/^file:\/\//i.test(r))try{r=xe(r)}catch{return null}let o=
|
|
8
|
-
`);if(
|
|
7
|
+
[${i.length} non-text blocks omitted: ${a}]`:`[output contains only non-text blocks: ${a}]`}return{content:[{type:"text",text:s||"(no text output)"}],...e.isError?{details:{error:"mcp_tool_error"}}:{}}}function G(t){return t.replace(/[^a-zA-Z0-9_]/g,"_").toLowerCase()}var je=/(?:^|_)(path|paths|file|files|filename|filenames|dir|dirs|directory|directories|folder|folders|cwd|root|uri)(?:$|_)/i;function Ie(t,e,r){if(!r)return null;for(let o of T(e)){let n=$e(o.value,r);if(n&&!Ne(n.candidate,n.root,n.pathApi))return`Blocked: MCP tool "${t}" path "${o.value}" is outside the workspace boundary "${n.root}"`}return null}function T(t,e="",r=0){if(r>8)return[];if(typeof t=="string")return Le(e,t)?[{key:e,value:t}]:[];if(Array.isArray(t))return t.flatMap(n=>T(n,e,r+1));if(!t||typeof t!="object")return[];let o=[];for(let[n,i]of Object.entries(t))o.push(...T(i,n,r+1));return o}function Le(t,e){if(!je.test(t))return!1;let r=e.trim();return!r||/^https?:\/\//i.test(r)?!1:Oe(r)}function Oe(t){return m.isAbsolute(t)||/^[A-Za-z]:[\\/]/.test(t)||/^\\\\/.test(t)||/^file:\/\//i.test(t)||t.includes("../")||t.includes("..\\")||t.startsWith(".\\")||t.startsWith("./")||t.includes("/")||t.includes("\\")}function $e(t,e){let r=t.trim();if(/^file:\/\//i.test(r))try{r=xe(r)}catch{return null}let o=z(r)||z(e)?m.win32:m,n=o.resolve(e);return{candidate:o.isAbsolute(r)?o.resolve(r):o.resolve(n,r),root:n,pathApi:o}}function Ne(t,e,r){let o=r.relative(e,t);return o===""||!o.startsWith("..")&&!r.isAbsolute(o)}function z(t){return/^[A-Za-z]:[\\/]/.test(t)||/^\\\\/.test(t)}function J(t){if(!t||typeof t!="object")return[];let e=t,r=[],o=e.mcpServers??e.servers??e;for(let[n,i]of Object.entries(o)){if(!i||typeof i!="object")continue;let s=i;if(typeof s.url=="string"){r.push({name:n,type:"http",url:s.url,headers:s.headers&&typeof s.headers=="object"?s.headers:void 0,disabled:s.disabled===!0,oauth:s.oauth===!0,tools:B(s.tools)});continue}typeof s.command=="string"&&r.push({name:n,type:"stdio",command:s.command,args:Array.isArray(s.args)?s.args:void 0,env:s.env&&typeof s.env=="object"?s.env:void 0,cwd:typeof s.cwd=="string"?s.cwd:void 0,disabled:s.disabled===!0,oauth:s.oauth===!0,tools:B(s.tools)})}return r}function W(t,e){let r=new Set(e?.include??[]),o=new Set(e?.exclude??[]);return t.filter(n=>r.size>0&&!r.has(n.name)?!1:!o.has(n.name))}function B(t){if(!t||typeof t!="object")return;let e=t,r=H(e.include),o=H(e.exclude);if(!(!r&&!o))return{...r?{include:r}:{},...o?{exclude:o}:{}}}function H(t){if(!Array.isArray(t))return;let e=t.filter(r=>typeof r=="string"&&r.trim().length>0);return e.length>0?e:void 0}var Fe=new Set(["bash","sh","zsh","fish","cmd","cmd.exe","powershell","powershell.exe","pwsh","pwsh.exe"]),Ue=new Set(["-c","/c","-command","-encodedcommand","-e"]),qe=["curl","wget","invokewebrequest","invoke-restmethod","iwr","irm","nc","netcat"],Ge=["env","processenv","apikey","api_key","token","secret","credential","credentials","awsaccesskey","awssecret"],ze=["authorizedkeys","sshknownhosts","crontab","launchctl","schtasks","startup","runkey","runonce","bashrc","profile"],We=/\bssh-(?:rsa|ed25519|ecdsa-[^\s]+)\s+[A-Za-z0-9+/=]{40,}/i;function Be(t){let e=[],r=[t.command??"",...t.args??[],...Object.keys(t.env??{}),...Object.values(t.env??{})].join(`
|
|
8
|
+
`);if(We.test(r)&&e.push({code:"ioc_public_key",message:"configuration contains an inline SSH public key IOC"}),(t.type??(t.url?"http":"stdio"))!=="stdio"||!He(t.command))return e;let o=Je(t.args??[]);if(!o)return e;let n=Ve(o);return w(n,ze)&&e.push({code:"persistence",message:"stdio shell command attempts a persistence write"}),w(n,qe)&&w(n,Ge)&&e.push({code:"dangerous_egress",message:"stdio shell command combines network egress with likely secret access"}),e}function He(t){if(!t)return!1;let e=m.basename(t).toLowerCase();return Fe.has(e)}function Je(t){for(let e=0;e<t.length;e++){let r=t[e]?.toLowerCase();if(r&&Ue.has(r))return t.slice(e+1).join(" ")}return""}function Ve(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"")}function w(t,e){return e.some(r=>t.includes(r))}var Ze=[{name:"skills_list",description:"List AstraClaw skills active for the current workspace.",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"skill_view",description:"Read the full SKILL.md instructions for one AstraClaw skill.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Skill name from skills_list."}},required:["name"],additionalProperties:!1}},{name:"mcp_connectors_list",description:"List MCP connector tools installed in AstraClaw's Plugins page and shared with this external agent.",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"mcp_tool_call",description:"Call one AstraClaw shared MCP connector tool by toolName from mcp_connectors_list.",inputSchema:{type:"object",properties:{toolName:{type:"string",description:"Connector tool name, for example mcp__filesystem__read_text_file."},args:{type:"object",description:"Arguments for the connector tool."}},required:["toolName"],additionalProperties:!1}}],k=class{tools=new Map;findTool(e){return this.tools.get(e)}getToolManifest(){return Array.from(this.tools.values()).map(e=>({type:"function",function:{name:e.name,description:e.description,parameters:e.parameters}}))}getToolNames(){return Array.from(this.tools.keys())}setTools(e){this.tools.clear(),this.addTools(e)}addTool(e){this.tools.set(e.name,e)}addTools(e){for(let r of e)this.addTool(r)}removeTool(e){return this.tools.delete(e)}},c=null,Xe=Ke({input:process.stdin,crlfDelay:Number.POSITIVE_INFINITY});Xe.on("line",t=>{et(t)});async function et(t){let e=t.trim();if(!e)return;let r;try{r=JSON.parse(e)}catch{return}if(r.id===void 0||r.id===null)return r.method==="notifications/initialized",void 0;try{let o=await tt(r);K({jsonrpc:"2.0",id:r.id,result:o})}catch(o){K({jsonrpc:"2.0",id:r.id,error:{code:-32603,message:o instanceof Error?o.message:String(o)}})}}async function tt(t){switch(t.method){case"initialize":return{protocolVersion:"2024-11-05",capabilities:{tools:{}},serverInfo:{name:I,version:"1.0.0"}};case"tools/list":return{tools:Ze};case"tools/call":{let e=V(t.params),r=typeof e.name=="string"?e.name:"",o=V(e.arguments),n=rt(),i=r==="mcp_connectors_list"||r==="mcp_tool_call"?await ot(n):void 0,s=await L({tool:r,args:o,projectRoot:n,toolCatalog:i,mcpServerFailures:i?c?.manager?.getFailedServers():void 0});if(!s.handled)throw new Error(`Unknown tool: ${r}`);return{content:[{type:"text",text:JSON.stringify(s.result)}]}}default:throw new Error(`Unknown method: ${t.method}`)}}function rt(){return process.env.ASTRACLAW_PROJECT_ROOT||process.env.QLOGICAGENT_PROJECT_ROOT||process.cwd()}async function ot(t){if(c?.projectRoot===t)return await c.ready,c.catalog;c?.manager?.disconnectAll().catch(()=>{});let e=new k,r=new h({servers:nt(),workspaceRoot:t,toolCatalog:e,log:{info:n=>process.stderr.write(`${n}
|
|
9
9
|
`),warn:n=>process.stderr.write(`${n}
|
|
10
10
|
`)}}),o=r.connectAll().then(()=>r.injectTools());return c={projectRoot:t,catalog:e,manager:r,ready:o},await o,e}function nt(){let t=process.env.ASTRACLAW_MCP_CONFIG_PATH||_();if(!Qe(t))return[];try{let e=Ye(t,"utf8").replace(/^\uFEFF/,"");return J(JSON.parse(e))}catch(e){return process.stderr.write(`[astraclaw-native-mcp] failed to read MCP config: ${e instanceof Error?e.message:String(e)}
|
|
11
11
|
`),[]}}function V(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function K(t){process.stdout.write(`${JSON.stringify(t)}
|
package/dist/tunables.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var _=Math.min(Math.max(1,Number(process.env.TOOL_LOOP_DEFAULT_BUDGET)||25),100),u=Math.max(1e3,Number(process.env.TOOL_LOOP_TOOL_TIMEOUT_MS)||24e4),i=3,T=2;var M=128e3,m=13e3,E=16384,c=65536,p=3,l=65536,S=500,R=3,x=5e4,A=2e5,O=2e3,I=3e4,d=3,b=2,L=3e5,C=216e5,D=.75,N=16e3,f=12e4,U=3,P=4,B=50,k=3,g=2,y=300*1e3;var me=720*60*60*1e3,F=4,X=0,h=50,K=50,w=30,Ee=3600*1e3;var v=5,G=4e4,H=50*1024,V=500*1024,Y=500*1024*1024,z=50*1024*1024,W=3e5,$=2,j=3e3,Z=3,q=5e3,J=1e3,Q=3e3,ee=3e4,te=60*1024,ne=10;var re=100,oe=24,se=5,ae=6e5,_e=30,ue=144e5,ie=3e5;function o(){return{maxRoundsLimit:100,defaultMaxRounds:25,defaultTemperature:0,maxToolBudgetCap:100,defaultToolBudget:_,defaultToolExecutionTimeoutMs:u,maxConsecutiveFailures:i,maxIdenticalCallRepeats:T,defaultContextWindowTokens:M,responseBufferTokens:m,defaultMaxOutputTokens:E,defaultModelMaxOutputTokens:c,maxOutputTokensRecoveryLimit:p,escalatedMaxOutputTokens:l,diminishingReturnsThreshold:S,diminishingReturnsMinContinuations:R,defaultMaxResultSizeChars:x,maxToolResultsPerMessageChars:A,toolResultPreviewBytes:O,heartbeatIntervalMs:I,max529Retries:d,maxApiRetries:b,persistentRetryMaxBackoffMs:L,persistentRetryResetCapMs:C,compressionTargetUsageRatio:D,compressionMinBudget:N,compressionMaxBudget:f,reactiveCompactMaxFailures:U,reactiveCompactMinMessages:P,reactiveCompactTargetPercent:B,minToolCallsForSkill:k,minDistinctToolsForSkill:g,skillCreationCooldownMs:y,maxForkDepth:F,maxSessions:h,taskSummaryTurnThreshold:K,taskSummaryRegenInterval:w,maxIncludeDepth:v,maxInstructionChars:G,instructionsMaxFileSize:H,instructionsMaxDirSize:V,mediaMaxDownloadSize:Y,mediaMaxUploadSize:z,mediaDownloadTimeoutMs:W,acpMaxSpawnRetries:$,acpRetryBackoffBase:j,acpRuntimeRestartMax:Z,acpRuntimeRestartBackoffBase:q,taskPollIntervalMs:J,taskStoppedDisplayMs:Q,taskPanelGraceMs:ee,memoryPrefetchMaxSessionBytes:te,memoryPrefetchLimitPerRecall:ne,memoryMaxSurfacedEntries:re,dreamMinIntervalHours:oe,dreamMinSessions:se,dreamScanIntervalMs:ae,idleDreamMinutes:_e,dreamCooldownMs:ue,dreamMaxDurationMs:ie,teamBudgetTokens:X,braveApiKey:"",exaApiKey:"",serperApiKey:"",searxngBaseUrl:"",crawl4aiBaseUrl:"",searchSvcBaseUrl:""}}function a(t){let e=o();return Object.prototype.hasOwnProperty.call(e,t)?null:`Unknown tunable key: "${t}". Valid keys: ${Object.keys(e).join(", ")}`}function Te(t,e){let r=a(t);if(r)return r;let n=typeof o()[t];return e==null||typeof e!==n?`Invalid value for "${t}": expected ${n}, got ${e===null?"null":typeof e}`:n==="number"&&!Number.isFinite(e)?`Invalid value for "${t}": expected a finite number`:null}function Me(t,e){if(typeof e!="string")return e;let r=o();if(!Object.prototype.hasOwnProperty.call(r,t))return e;let s=typeof r[t];if(s==="number"){let n=Number(e);if(Number.isFinite(n)&&e.trim()!=="")return n}else if(s==="boolean"){if(e==="true")return!0;if(e==="false")return!1}return e}export{Me as coerceTunableValue,o as getTunableDefaults,a as validateTunableKey,Te as validateTunableUpdate};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* RuntimeVars — Unified mutable runtime variables for the agent server.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* (config.updateTunable) or internal logic should live here. This avoids
|
|
4
|
+
* Mutable runtime state owned by agent-internal logic should live here. This avoids
|
|
6
5
|
* scattering mutable state as private fields across stdio-server.ts.
|
|
7
6
|
*
|
|
8
7
|
* Categories:
|
|
@@ -78,6 +78,19 @@ export interface ToolLoopParams {
|
|
|
78
78
|
* the next LLM call, steering the run without waiting for the turn to finish.
|
|
79
79
|
*/
|
|
80
80
|
drainPendingGuidance?: () => string[];
|
|
81
|
+
/**
|
|
82
|
+
* Sanitize a tool-result message's media the MAIN model can't consume (e.g. the `read` tool
|
|
83
|
+
* returning an image for a text-only model → provider closes the stream, -32603): route it to
|
|
84
|
+
* the understanding model + fold the description into the message text, dropping the raw media.
|
|
85
|
+
* Mutates in place; called before each tool result enters the model context.
|
|
86
|
+
*/
|
|
87
|
+
sanitizeToolResultMedia?: (message: Record<string, unknown>) => Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Persist a model-visible tool-stream message (assistant tool_calls / role:"tool" result) to the
|
|
90
|
+
* transcript. Fired by pushTranscriptMessage for EVERY such push. Host must synchronously clone
|
|
91
|
+
* before enqueueing. Keeps src/agent/** I/O-free.
|
|
92
|
+
*/
|
|
93
|
+
persistTurnMessage?: (message: ChatMessage) => void;
|
|
81
94
|
/**
|
|
82
95
|
* Post-sampling hooks -fire-and-forget after LLM response completes (CC executePostSamplingHooks parity).
|
|
83
96
|
* Cannot modify messages. Used for background tasks (memory extraction, skill learning, etc.).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentLogger, LLMChunk, LLMRequest, LLMTransport, ToolDefinition, TurnEvent } from "./types.js";
|
|
2
|
+
import { type ToolLoopParams } from "./tool-loop.js";
|
|
3
|
+
import type { ToolLoopRuntimePorts } from "../runtime/ports/index.js";
|
|
4
|
+
/** A scripted LLM round: chunks to stream, or an error to throw on stream(). */
|
|
5
|
+
export type Round = LLMChunk[] | {
|
|
6
|
+
throw: unknown;
|
|
7
|
+
};
|
|
8
|
+
/** Transport that replays a fixed script of rounds — one round consumed per stream() call. */
|
|
9
|
+
export declare class ScriptedTransport implements LLMTransport {
|
|
10
|
+
private readonly rounds;
|
|
11
|
+
readonly requests: LLMRequest[];
|
|
12
|
+
constructor(rounds: Round[]);
|
|
13
|
+
stream(request: LLMRequest): AsyncGenerator<LLMChunk>;
|
|
14
|
+
}
|
|
15
|
+
export declare const log: AgentLogger;
|
|
16
|
+
export declare function tool(name?: string): ToolDefinition;
|
|
17
|
+
export declare function runtimePorts(overrides?: Partial<ToolLoopRuntimePorts>): ToolLoopRuntimePorts;
|
|
18
|
+
export declare function collect(events: AsyncIterable<TurnEvent>): Promise<TurnEvent[]>;
|
|
19
|
+
export declare const eventTypes: (events: TurnEvent[]) => string[];
|
|
20
|
+
export declare function baseParams(overrides: Partial<ToolLoopParams> & Pick<ToolLoopParams, "runtimePorts">): ToolLoopParams;
|
|
@@ -93,6 +93,14 @@ export interface TurnRequest {
|
|
|
93
93
|
* tool-loop round; returned strings become user messages before the next LLM call.
|
|
94
94
|
*/
|
|
95
95
|
drainPendingGuidance?: () => string[];
|
|
96
|
+
/**
|
|
97
|
+
* Route media a tool returns that the MAIN model can't consume (e.g. `read` returning an image
|
|
98
|
+
* for a text-only model) to the understanding model; folds the description into the message text
|
|
99
|
+
* and drops the raw media. Forwarded to the tool loop; mutates the message in place.
|
|
100
|
+
*/
|
|
101
|
+
sanitizeToolResultMedia?: (message: Record<string, unknown>) => Promise<void>;
|
|
102
|
+
/** Persist each model-visible tool-stream message to the transcript — forwarded to the tool loop. */
|
|
103
|
+
persistTurnMessage?: (message: ChatMessage) => void;
|
|
96
104
|
systemPrompt?: string;
|
|
97
105
|
config?: TurnConfig;
|
|
98
106
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SoloSpecChatResult, SoloSpecJudgeResult, WorkflowChatResult } from "../protocol/wire/acp-agent-management.js";
|
|
2
|
+
import { type DelegateBridge } from "../orchestration/delegation-coordinator.js";
|
|
2
3
|
import { type DreamHandlerHost } from "./handlers/dream-handler.js";
|
|
3
4
|
import { type ProductCoordinatorHost } from "./handlers/product-handler.js";
|
|
4
5
|
import { type SoloHandlerHost } from "./handlers/solo-handler.js";
|
|
@@ -9,6 +10,12 @@ export interface AcpExtendedHost extends DreamHandlerHost, SoloHandlerHost, Prod
|
|
|
9
10
|
currentSessionId?: string;
|
|
10
11
|
getActiveProjectRoot(): string;
|
|
11
12
|
log(message: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* 激活层(S3c):gateway-routed delegate 传输桥(可选;缺省/undefined = 旧 ProductOrchestrator 委派路径)。
|
|
15
|
+
* 懒读 AcpServer.delegate/supportsDelegate(server 在 initialize 后才 init,故 getter 而非常量);
|
|
16
|
+
* gateway 未声明 delegate 能力位 → bridge.isSupported()=false → DelegationCoordinator 走旧路径(单轨,gate 关零回归)。
|
|
17
|
+
*/
|
|
18
|
+
getDelegateBridge?(): DelegateBridge | undefined;
|
|
12
19
|
resolveClientForPurpose(purpose: "textGeneration"): {
|
|
13
20
|
transport: LLMTransport;
|
|
14
21
|
apiKey: string;
|
|
@@ -24,6 +24,8 @@ export interface AcpExtendedHostAdapterDeps {
|
|
|
24
24
|
handleMcpToolCall(memberId: string, toolName: string, args: Record<string, unknown>): Promise<unknown>;
|
|
25
25
|
resolveClientForPurpose: AcpExtendedHost["resolveClientForPurpose"];
|
|
26
26
|
pendingAskUser: AcpExtendedHost["pendingAskUser"];
|
|
27
|
+
/** 激活层(S3c):gateway-routed delegate 桥(懒读 AcpServer;缺省 = 旧委派路径)。 */
|
|
28
|
+
getDelegateBridge?: AcpExtendedHost["getDelegateBridge"];
|
|
27
29
|
}
|
|
28
30
|
export declare function createAcpExtendedHostAdapter(deps: AcpExtendedHostAdapterDeps): AcpExtendedHost;
|
|
29
31
|
export {};
|
|
@@ -3,6 +3,7 @@ import type { AcpSessionMeta } from "../protocol/wire/index.js";
|
|
|
3
3
|
import { createMemoryPrefetchState } from "../runtime/hooks/memory-hooks.js";
|
|
4
4
|
import type { SessionState } from "../runtime/session/session-state.js";
|
|
5
5
|
import type { SessionHistoryCoordinator } from "./session-history-coordinator.js";
|
|
6
|
+
import type { HostCapabilityClient } from "../transport/host-capability-client.js";
|
|
6
7
|
/**
|
|
7
8
|
* LLM config pinned on the session by the host (session/set_config_option /
|
|
8
9
|
* session/set_model / the /model command). This is host-supplied INPUT — distinct
|
|
@@ -18,6 +19,14 @@ export interface SessionLlmConfig {
|
|
|
18
19
|
apiKey?: string;
|
|
19
20
|
baseUrl?: string;
|
|
20
21
|
}
|
|
22
|
+
export interface MaterializedSessionBinding extends SessionLlmConfig {
|
|
23
|
+
routing?: string;
|
|
24
|
+
}
|
|
25
|
+
/** Gateway-materialized session-private profile. apiKey exists in memory only. */
|
|
26
|
+
export interface MaterializedSessionProfile {
|
|
27
|
+
bindings: Record<string, MaterializedSessionBinding>;
|
|
28
|
+
permissions: Record<string, unknown>;
|
|
29
|
+
}
|
|
21
30
|
export interface AcpSessionHost {
|
|
22
31
|
/** Gateway-supplied per-session context (_meta from session/new).
|
|
23
32
|
* LEGACY fallback: a per-CONNECTION singleton overwritten by the last session/new — kept only
|
|
@@ -25,8 +34,10 @@ export interface AcpSessionHost {
|
|
|
25
34
|
acpSessionMeta: AcpSessionMeta | null;
|
|
26
35
|
/** Per-session gateway _meta(session/new 注册;prompt 按 sessionId 取,消除跨会话串扰)。 */
|
|
27
36
|
acpSessionMetaBySession: Map<string, AcpSessionMeta>;
|
|
28
|
-
/**
|
|
29
|
-
|
|
37
|
+
/** Legacy per-option pins, keyed by session (never a connection singleton). */
|
|
38
|
+
sessionLlmConfigBySession: Map<string, SessionLlmConfig>;
|
|
39
|
+
/** F2 full gateway profile, keyed by session; secrets are memory-only. */
|
|
40
|
+
materializedSessionProfiles: Map<string, MaterializedSessionProfile>;
|
|
30
41
|
currentHooks: HookRegistry | null;
|
|
31
42
|
currentSessionId: string;
|
|
32
43
|
memoryPrefetchState: ReturnType<typeof createMemoryPrefetchState>;
|
|
@@ -36,6 +47,7 @@ export interface AcpSessionHost {
|
|
|
36
47
|
disposeSessionRuntime?(): void;
|
|
37
48
|
enableIdleDream(): void;
|
|
38
49
|
ensureDefaultProject(): void;
|
|
50
|
+
initializeHostProjectAuthority?(): Promise<void>;
|
|
39
51
|
/**
|
|
40
52
|
* Ensure the model-registry catalog (this.models) is hydrated from the owner profile +
|
|
41
53
|
* built-in/llmrouter catalog. A spawned/headless qlogicagent only runs load() (bindings +
|
|
@@ -45,6 +57,7 @@ export interface AcpSessionHost {
|
|
|
45
57
|
*/
|
|
46
58
|
ensureModelRegistryHydrated?(): Promise<void>;
|
|
47
59
|
getActiveProjectRoot(): string;
|
|
60
|
+
getHostCapabilityClient?(): HostCapabilityClient | undefined;
|
|
48
61
|
log(message: string): void;
|
|
49
62
|
sendNotification(method: string, params: Record<string, unknown>): void;
|
|
50
63
|
setActiveWorkdir(dir: string): void;
|
|
@@ -18,5 +18,6 @@ export interface BaseToolBootstrapDeps {
|
|
|
18
18
|
} | null;
|
|
19
19
|
getTaskScopeKey?(): string | undefined;
|
|
20
20
|
getCurrentTurnId?(): string | undefined;
|
|
21
|
+
loadTunableOverrides?(): Promise<Record<string, unknown>>;
|
|
21
22
|
}
|
|
22
23
|
export declare function configureBaseToolBootstrap(deps: BaseToolBootstrapDeps): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommunityInstallResolution } from "../runtime/community/community-consent-client.js";
|
|
2
|
+
import type { HostCapabilityClient } from "../transport/host-capability-client.js";
|
|
2
3
|
export interface CommunityInstalledResource {
|
|
3
4
|
resourceId: string;
|
|
4
5
|
version: string;
|
|
@@ -10,5 +11,6 @@ export interface InstallCommunitySkillOptions {
|
|
|
10
11
|
fetchFn?: typeof fetch;
|
|
11
12
|
/** Replace an existing install in place (update flow) instead of erroring. */
|
|
12
13
|
allowReplace?: boolean;
|
|
14
|
+
hostCapabilityClient?: Pick<HostCapabilityClient, "prepareSkillInstall" | "finalizeSkillInstall">;
|
|
13
15
|
}
|
|
14
16
|
export declare function installCommunitySkillResource(install: CommunityInstallResolution, options?: InstallCommunitySkillOptions): Promise<CommunityInstalledResource>;
|
|
@@ -3,6 +3,8 @@ import type { HookRegistry } from "../contracts/hooks.js";
|
|
|
3
3
|
import type { BackgroundTaskManager } from "../runtime/infra/background-tasks.js";
|
|
4
4
|
import type { ToolCatalog } from "../runtime/ports/index.js";
|
|
5
5
|
import type { LLMTransport } from "./provider-core-facade.js";
|
|
6
|
+
import type { HostProfileClient } from "../transport/host-profile-client.js";
|
|
7
|
+
import type { HostCapabilityClient } from "../transport/host-capability-client.js";
|
|
6
8
|
export interface CliCoreToolHostDeps {
|
|
7
9
|
getAgent(): unknown | null;
|
|
8
10
|
getCurrentTransport(): LLMTransport | null;
|
|
@@ -28,6 +30,8 @@ export interface CliCoreToolHostDeps {
|
|
|
28
30
|
};
|
|
29
31
|
}): void;
|
|
30
32
|
handleMcpToolCall(memberId: string, toolName: string, args: Record<string, unknown>): Promise<unknown>;
|
|
33
|
+
getHostProfileClient?(): HostProfileClient | undefined;
|
|
34
|
+
getHostCapabilityClient?(): HostCapabilityClient | undefined;
|
|
31
35
|
}
|
|
32
36
|
export interface CliCoreToolCoordinatorDeps {
|
|
33
37
|
config: Record<string, unknown>;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ToolCatalog } from "../../runtime/ports/index.js";
|
|
2
|
+
import type { HostProfileClient } from "../../transport/host-profile-client.js";
|
|
2
3
|
export interface ConfigToolRegistrationDeps {
|
|
3
4
|
toolCatalog: ToolCatalog;
|
|
5
|
+
resolveHostProfileClient?: () => HostProfileClient | undefined;
|
|
4
6
|
}
|
|
5
|
-
export declare function registerConfigTool({ toolCatalog }: ConfigToolRegistrationDeps): void;
|
|
7
|
+
export declare function registerConfigTool({ toolCatalog, resolveHostProfileClient }: ConfigToolRegistrationDeps): void;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Config tool service —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Config tool service — a thin compute-side proxy over the gateway-owned tunable store.
|
|
3
|
+
*
|
|
4
|
+
* Defaults/coercion/validation come from the public qlogicagent/tunables contract. Persistent
|
|
5
|
+
* overrides are read and mutated only through HostProfileClient's private X7 profile service.
|
|
6
|
+
* The agent never reads or writes settings.json and has no local fallback.
|
|
6
7
|
*/
|
|
7
8
|
import type { ConfigToolDeps } from "../../skills/tools/config-tool.js";
|
|
9
|
+
import type { HostProfileClient } from "../../transport/host-profile-client.js";
|
|
8
10
|
export interface ConfigToolServiceOptions {
|
|
9
|
-
|
|
11
|
+
resolveHostProfileClient?: () => HostProfileClient | undefined;
|
|
10
12
|
}
|
|
11
13
|
export declare function createConfigToolService(options?: ConfigToolServiceOptions): ConfigToolDeps;
|
|
@@ -20,6 +20,7 @@ export interface DefaultProjectBootstrapDeps {
|
|
|
20
20
|
interface DeferredHeavyWork {
|
|
21
21
|
/** A default project was freshly created this run → its starter templates still need seeding. */
|
|
22
22
|
freshDefaultDir?: string;
|
|
23
|
+
hostOwned?: boolean;
|
|
23
24
|
}
|
|
24
25
|
/** Resolves once the most recently scheduled deferred heavy work has settled (never rejects). */
|
|
25
26
|
export declare function getDefaultProjectHeavyWorkPromise(): Promise<void>;
|
|
@@ -10,6 +10,7 @@ export interface DreamHostAdapterDeps {
|
|
|
10
10
|
getCurrentHooks(): DreamHandlerHost["currentHooks"];
|
|
11
11
|
getMemoryProvider(): DreamHandlerHost["memoryProvider"];
|
|
12
12
|
getMemoryUserId(): string;
|
|
13
|
+
ensureMemoryProvider(): void;
|
|
13
14
|
getToolCatalog(): DreamHandlerHost["toolCatalog"];
|
|
14
15
|
getTaskStore(): DreamHandlerHost["taskStore"];
|
|
15
16
|
getVerbose(): boolean;
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* agents.kill, agents.listConfigured, agents.getLog, agents.testConnection
|
|
6
6
|
*/
|
|
7
7
|
import { type AgentRpcError, type AgentRpcRequest } from "../../protocol/wire/index.js";
|
|
8
|
-
import { AgentProcessManager } from "../../runtime/infra/agent-process.js";
|
|
8
|
+
import type { AgentProcessManager } from "../../runtime/infra/agent-process.js";
|
|
9
9
|
import type { AgentConfigStore } from "../../runtime/infra/agent-config-store.js";
|
|
10
10
|
import { type AcpDetector } from "../../runtime/infra/acp-detector.js";
|
|
11
11
|
import { type PooledTurnCtx } from "../../runtime/infra/external-agent-pool.js";
|
|
12
|
+
import type { DelegateBridge } from "../../orchestration/delegation-coordinator.js";
|
|
12
13
|
export interface AgentsHandlerHost {
|
|
13
14
|
acpDetector: AcpDetector;
|
|
14
15
|
soloProcessManager: AgentProcessManager | null;
|
|
@@ -19,6 +20,8 @@ export interface AgentsHandlerHost {
|
|
|
19
20
|
log?(message: string): void;
|
|
20
21
|
sendResponse(id: string | number, result?: unknown, error?: AgentRpcError): void;
|
|
21
22
|
sendNotification?(method: string, params: Record<string, unknown>): void;
|
|
23
|
+
/** 激活层(S3c §1.1):gateway-routed delegate 桥(懒读;未挂/gate 关 = undefined → 旧进程池路径)。 */
|
|
24
|
+
getDelegateBridge?(): DelegateBridge | undefined;
|
|
22
25
|
}
|
|
23
26
|
export declare function relayPooledTurnNotification(input: {
|
|
24
27
|
agentId: string;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type CommunityConsentClient } from "../../runtime/community/community-consent-client.js";
|
|
2
2
|
import { type AgentRpcError, type AgentRpcRequest } from "../../protocol/wire/index.js";
|
|
3
|
+
import type { HostCapabilityClient } from "../../transport/host-capability-client.js";
|
|
3
4
|
export type { CommunityConsentClient, CommunityInstallRiskTier, CommunityInstallResolution, } from "../../runtime/community/community-consent-client.js";
|
|
4
5
|
export interface CommunityHandlerHost {
|
|
5
6
|
resolveCommunityConsentClient?: () => CommunityConsentClient | null;
|
|
7
|
+
getHostCapabilityClient?(): HostCapabilityClient | undefined;
|
|
6
8
|
sendResponse(id: string | number, result?: unknown, error?: AgentRpcError): void;
|
|
7
9
|
/** Push a JSON-RPC notification (e.g. pet.asset.updated after a community pet install hydrates the UI store). */
|
|
8
10
|
sendNotification(method: string, params: Record<string, unknown>): void;
|