qlogicagent 2.18.7 → 2.18.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +382 -382
  2. package/dist/cli.js +1 -1
  3. package/dist/default-project-knowledge/INSTRUCTIONS.md +7 -7
  4. package/dist/default-project-knowledge/rules/project-workflow.md +6 -6
  5. package/dist/index.js +469 -489
  6. package/dist/pet-host.js +19 -0
  7. package/dist/runtime/infra/mcp-bridge-server.js +275 -275
  8. package/dist/skills/builtin/desktop-screenshot/SKILL.md +62 -62
  9. package/dist/skills/builtin/office-doc-reading/SKILL.md +19 -19
  10. package/dist/skills/mcp/astraclaw-native-mcp-server.js +7 -7
  11. package/dist/types/cli/core-tools/registry.d.ts +1 -2
  12. package/dist/types/cli/handlers/turn-handler.d.ts +1 -1
  13. package/dist/types/cli/handlers/workflow-compute-handler.d.ts +8 -0
  14. package/dist/types/cli/rpc-registry.d.ts +0 -13
  15. package/dist/types/cli/stdio-rpc-handler-hosts.d.ts +2 -5
  16. package/dist/types/cli/stdio-server.d.ts +0 -3
  17. package/dist/types/contracts/structured-planner.d.ts +2 -0
  18. package/dist/types/orchestration/solo-evaluator.d.ts +7 -2
  19. package/dist/types/pet-host.d.ts +9 -0
  20. package/dist/types/protocol/wire/acp-protocol.d.ts +7 -0
  21. package/dist/types/runtime/pet/pet-reaction-engine.d.ts +1 -1
  22. package/dist/types/skills/mcp/mcp-manager.d.ts +4 -0
  23. package/dist/types/workflow-host.d.ts +33 -0
  24. package/dist/vendor/hatch-pet/LICENSE.txt +201 -201
  25. package/dist/vendor/hatch-pet/NOTICE.md +25 -25
  26. package/dist/vendor/hatch-pet/references/animation-rows.md +29 -29
  27. package/dist/vendor/hatch-pet/references/codex-pet-contract.md +35 -35
  28. package/dist/vendor/hatch-pet/references/qa-rubric.md +66 -66
  29. package/dist/vendor/hatch-pet/scripts/compose_atlas.py +169 -169
  30. package/dist/vendor/hatch-pet/scripts/derive_running_left_from_running_right.py +150 -150
  31. package/dist/vendor/hatch-pet/scripts/extract_strip_frames.py +408 -408
  32. package/dist/vendor/hatch-pet/scripts/inspect_frames.py +256 -256
  33. package/dist/vendor/hatch-pet/scripts/make_contact_sheet.py +96 -96
  34. package/dist/vendor/hatch-pet/scripts/prepare_pet_run.py +834 -834
  35. package/dist/vendor/hatch-pet/scripts/render_animation_previews.py +78 -78
  36. package/dist/vendor/hatch-pet/scripts/validate_atlas.py +157 -157
  37. package/dist/workflow-host.js +13 -0
  38. package/package.json +16 -2
  39. package/dist/types/cli/core-tools/cron-tool-bootstrap.d.ts +0 -8
  40. package/dist/types/cli/core-tools/cron-workflow-service.d.ts +0 -7
  41. package/dist/types/cli/handlers/pet-handler.d.ts +0 -49
  42. package/dist/types/cli/handlers/workflow-handler.d.ts +0 -182
  43. package/dist/types/cli/tool-bootstrap-workflow-registration.d.ts +0 -7
  44. package/dist/types/cli/workflow-host-adapter.d.ts +0 -31
  45. package/dist/types/orchestration/workflow/workflow-service.d.ts +0 -14
  46. package/dist/types/skills/tools/cron-tool.d.ts +0 -96
  47. package/dist/types/skills/tools/petdex-create-tool.d.ts +0 -47
  48. package/dist/types/skills/tools/workflow-tool.d.ts +0 -45
@@ -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,12 +1,12 @@
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 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
- `),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=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(`
2
+ import{createInterface as Ze}from"node:readline";import{existsSync as Xe,readFileSync as et}from"node:fs";import{readFileSync as Se}from"node:fs";import{randomUUID as Te}from"node:crypto";import{readdirSync as Rt,readFileSync as Mt,statSync as se,writeFileSync as Et}from"node:fs";import{readdir as ie,readFile as ae,stat as le,writeFile as ce}from"node:fs/promises";import{join as d}from"node:path";import{homedir as X}from"node:os";import{join as u}from"node:path";import{existsSync as yt}from"node:fs";import{createHash as ct}from"node:crypto";import{resolve as dt}from"node:path";var P=".qlogicagent";function p(){return process.env.QLOGICAGENT_HOME||u(X(),P)}function v(){return u(p(),"skills")}function _(){return u(p(),"mcp.json")}function ee(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(ee(t),"skills-disabled.json")}import{readFileSync as te,writeFileSync as Tt,mkdirSync as wt,renameSync as kt}from"node:fs";import{dirname as _t,join as re}from"node:path";function f(){return{version:1,disabled:[]}}function oe(t){let e;try{e=te(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 oe(t).list}function ne(){return re(p(),"skills-disabled.json")}function A(){return new Set(x(ne()).disabled)}function R(t){return new Set(x(C(t)).disabled)}var ue=["auto-skill-","test-skill-"],de=".skills_prompt_snapshot.json";function me(t){return ue.some(e=>t.startsWith(e))}function pe(t){let e=t.replace(/\r\n/g,`
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:fe(a),category:o?.[1]?.trim()||void 0,author:n?.[1]?.trim()||void 0,requiredTools:E(i?.[1]),environments:E(s?.[1])}}function fe(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 M=new Map,b=new Map;function ge(t,e,r,o){let n=e.has(t.name),i=r.has(t.name),s=!ve(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 he(t){let e;try{e=await ie(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 le(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=M.get(t);if(n&&n.fingerprint===o)return n.raw;let i=[];for(let s of r){let a;try{a=await ae(s.filePath,"utf8")}catch{continue}i.push({name:s.name,filePath:s.filePath,baseDir:s.baseDir,systemGenerated:me(s.name),mtimeMs:s.mtimeMs,size:s.size,meta:pe(a)})}return M.set(t,{fingerprint:o,raw:i}),be(t,i),i}async function ye(t,e){let r=v(),o=A(),n=t?R(t):new Set,i=b.get(r);return i||(i=he(r).finally(()=>b.delete(r)),b.set(r,i)),(await i).map(a=>ge(a,o,n,e))}async function D(t,e){return(await ye(t,e)).filter(r=>r.active)}function I(t){let e=v(),r=d(e,t),o=d(r,"SKILL.md");try{if(se(o).isFile())return{baseDir:r,filePath:o}}catch{}return null}function E(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 ve(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 be(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 ce(d(t,de),JSON.stringify(o,null,2),"utf8")}catch{}}var j="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(we)}};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=I(e);if(!r)throw new Error(`Skill not found: ${e}`);return{handled:!0,result:{name:e,content:Se(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:Pe(n.function.name),name:_e(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=ke(t.args.args),n=`astraclaw_mcp_${Te().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 we(t){return{name:t.name,description:t.description,version:t.version,category:t.category,requiredTools:t.requiredTools,environments:t.environments}}function ke(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function Pe(t){let e=t.split("__");return e.length>=3?e[1]??"":""}function _e(t){let e=t.split("__");return e.length>=3?e.slice(2).join("__"):t}import m from"node:path";import{fileURLToPath as Me}from"node:url";import{createRuntime as Ee}from"mcporter";var O=new Set(["gateway","agents_list","session_status","sessions_send","sessions_list","sessions_history","sessions_spawn","cron","config","workflow"]),Ce=new Set([...O,"agent"]);function $(t){return t?.riskLevel?t.riskLevel:t?.isDangerous?"system":t?.isReadOnly?"read":t?.isEgress?"external_egress":"write"}var S=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 S;function F(t){N.addTools(t)}function U(t){return N.removeTool(t)}var xe=new Set(["describe","fetch","find","get","inspect","list","query","read","search","stat"]),Ae=new Set(["append","copy","create","delete","edit","move","patch","remove","rename","set","update","upload","write"]);function q(t){let e=t.annotations,r=Re(t.name),o=r.some(l=>Ae.has(l)),n=r.some(l=>xe.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 Re(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)}var K=12e4,G=1e3,z=6e5;function De(t){if(t===void 0)return K;if(!Number.isInteger(t)||t<G||t>z)throw new RangeError(`MCP callTimeoutMs must be an integer between ${G} and ${z}`);return t}var g=3,Ie=1e3;async function je(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;serverCallTimeouts=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=Ve(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),this.serverCallTimeouts.set(r.name,De(r.callTimeoutMs)),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 Ee({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 je(()=>this.runtime.listTools(e.name,{includeSchema:!0,disableOAuth:this.serverOAuth.get(e.name)!==!0}),{attempts:g,baseDelayMs:Ie,onRetry:(n,i)=>this.log.warn(`[mcp] connect attempt ${n}/${g} for ${e.name} failed, retrying: ${i instanceof Error?i.message:i}`)}),o=H(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=H(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__${W(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:this.serverCallTimeouts.get(e)??K});return Le(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=$e(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__${W(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 Le(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=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}
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 W(t){return t.replace(/[^a-zA-Z0-9_]/g,"_").toLowerCase()}var Oe=/(?:^|_)(path|paths|file|files|filename|filenames|dir|dirs|directory|directories|folder|folders|cwd|root|uri)(?:$|_)/i;function $e(t,e,r){if(!r)return null;for(let o of w(e)){let n=Ue(o.value,r);if(n&&!qe(n.candidate,n.root,n.pathApi))return`Blocked: MCP tool "${t}" path "${o.value}" is outside the workspace boundary "${n.root}"`}return null}function w(t,e="",r=0){if(r>8)return[];if(typeof t=="string")return Ne(e,t)?[{key:e,value:t}]:[];if(Array.isArray(t))return t.flatMap(n=>w(n,e,r+1));if(!t||typeof t!="object")return[];let o=[];for(let[n,i]of Object.entries(t))o.push(...w(i,n,r+1));return o}function Ne(t,e){if(!Oe.test(t))return!1;let r=e.trim();return!r||/^https?:\/\//i.test(r)?!1:Fe(r)}function Fe(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 Ue(t,e){let r=t.trim();if(/^file:\/\//i.test(r))try{r=Me(r)}catch{return null}let o=B(r)||B(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 qe(t,e,r){let o=r.relative(e,t);return o===""||!o.startsWith("..")&&!r.isAbsolute(o)}function B(t){return/^[A-Za-z]:[\\/]/.test(t)||/^\\\\/.test(t)}function Q(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:J(s.tools),callTimeoutMs:typeof s.callTimeoutMs=="number"?s.callTimeoutMs:void 0});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:J(s.tools),callTimeoutMs:typeof s.callTimeoutMs=="number"?s.callTimeoutMs:void 0})}return r}function H(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 J(t){if(!t||typeof t!="object")return;let e=t,r=V(e.include),o=V(e.exclude);if(!(!r&&!o))return{...r?{include:r}:{},...o?{exclude:o}:{}}}function V(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 Ge=new Set(["bash","sh","zsh","fish","cmd","cmd.exe","powershell","powershell.exe","pwsh","pwsh.exe"]),ze=new Set(["-c","/c","-command","-encodedcommand","-e"]),We=["curl","wget","invokewebrequest","invoke-restmethod","iwr","irm","nc","netcat"],Be=["env","processenv","apikey","api_key","token","secret","credential","credentials","awsaccesskey","awssecret"],He=["authorizedkeys","sshknownhosts","crontab","launchctl","schtasks","startup","runkey","runonce","bashrc","profile"],Je=/\bssh-(?:rsa|ed25519|ecdsa-[^\s]+)\s+[A-Za-z0-9+/=]{40,}/i;function Ve(t){let e=[],r=[t.command??"",...t.args??[],...Object.keys(t.env??{}),...Object.values(t.env??{})].join(`
8
+ `);if(Je.test(r)&&e.push({code:"ioc_public_key",message:"configuration contains an inline SSH public key IOC"}),(t.type??(t.url?"http":"stdio"))!=="stdio"||!Ke(t.command))return e;let o=Qe(t.args??[]);if(!o)return e;let n=Ye(o);return T(n,He)&&e.push({code:"persistence",message:"stdio shell command attempts a persistence write"}),T(n,We)&&T(n,Be)&&e.push({code:"dangerous_egress",message:"stdio shell command combines network egress with likely secret access"}),e}function Ke(t){if(!t)return!1;let e=m.basename(t).toLowerCase();return Ge.has(e)}function Qe(t){for(let e=0;e<t.length;e++){let r=t[e]?.toLowerCase();if(r&&ze.has(r))return t.slice(e+1).join(" ")}return""}function Ye(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"")}function T(t,e){return e.some(r=>t.includes(r))}var tt=[{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,rt=Ze({input:process.stdin,crlfDelay:Number.POSITIVE_INFINITY});rt.on("line",t=>{ot(t)});async function ot(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 nt(r);Z({jsonrpc:"2.0",id:r.id,result:o})}catch(o){Z({jsonrpc:"2.0",id:r.id,error:{code:-32603,message:o instanceof Error?o.message:String(o)}})}}async function nt(t){switch(t.method){case"initialize":return{protocolVersion:"2024-11-05",capabilities:{tools:{}},serverInfo:{name:j,version:"1.0.0"}};case"tools/list":return{tools:tt};case"tools/call":{let e=Y(t.params),r=typeof e.name=="string"?e.name:"",o=Y(e.arguments),n=st(),i=r==="mcp_connectors_list"||r==="mcp_tool_call"?await it(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 st(){return process.env.ASTRACLAW_PROJECT_ROOT||process.env.QLOGICAGENT_PROJECT_ROOT||process.cwd()}async function it(t){if(c?.projectRoot===t)return await c.ready,c.catalog;c?.manager?.disconnectAll().catch(()=>{});let e=new k,r=new h({servers:at(),workspaceRoot:t,toolCatalog:e,log:{info:n=>process.stderr.write(`${n}
9
9
  `),warn:n=>process.stderr.write(`${n}
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
- `),[]}}function V(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function K(t){process.stdout.write(`${JSON.stringify(t)}
10
+ `)}}),o=r.connectAll().then(()=>r.injectTools());return c={projectRoot:t,catalog:e,manager:r,ready:o},await o,e}function at(){let t=process.env.ASTRACLAW_MCP_CONFIG_PATH||_();if(!Xe(t))return[];try{let e=et(t,"utf8").replace(/^\uFEFF/,"");return Q(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
+ `),[]}}function Y(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{}}function Z(t){process.stdout.write(`${JSON.stringify(t)}
12
12
  `)}
@@ -1,7 +1,6 @@
1
1
  import { type AgentToolRegistrationDeps } from "./agent-tool-bootstrap.js";
2
2
  import { type CheckpointToolRegistrationDeps } from "./checkpoint-tool-bootstrap.js";
3
3
  import { type ConfigToolRegistrationDeps } from "./config-tool-bootstrap.js";
4
- import { type CronToolRegistrationDeps } from "./cron-tool-bootstrap.js";
5
4
  import { type MonitorToolRegistrationDeps } from "./monitor-tool-bootstrap.js";
6
- export type CoreToolSetRegistrationDeps = AgentToolRegistrationDeps & CheckpointToolRegistrationDeps & ConfigToolRegistrationDeps & CronToolRegistrationDeps & MonitorToolRegistrationDeps;
5
+ export type CoreToolSetRegistrationDeps = AgentToolRegistrationDeps & CheckpointToolRegistrationDeps & ConfigToolRegistrationDeps & MonitorToolRegistrationDeps;
7
6
  export declare function registerCoreToolSet(deps: CoreToolSetRegistrationDeps): void;
@@ -6,6 +6,7 @@ import { type ModelPurpose } from "../../runtime/infra/model-registry.js";
6
6
  import { type UnderstandMediaKind } from "../media-understanding.js";
7
7
  import { type InstructionFileInfo } from "../../runtime/prompt/instruction-loader.js";
8
8
  import type { HookRegistry } from "../../contracts/hooks.js";
9
+ export { isStructuredPlannerSystemPrompt } from "../../contracts/structured-planner.js";
9
10
  import type { AppendMessageOutcome } from "../../runtime/session/session-transcript-store.js";
10
11
  import type { PermissionMetadataResolver, ToolCatalog } from "../../runtime/ports/index.js";
11
12
  import type { ChatMessage, TokenUsage, ToolDefinition, TurnConfig } from "../../agent/types.js";
@@ -227,4 +228,3 @@ export interface TurnPipelineResult {
227
228
  * Invoked with `.call(host, input)` by the standard-ACP `session/prompt` handler.
228
229
  */
229
230
  export declare function runTurnPipeline(this: any, input: TurnPipelineInput): Promise<TurnPipelineResult>;
230
- export {};
@@ -0,0 +1,8 @@
1
+ import { type AgentRpcError, type AgentRpcRequest } from "../../protocol/wire/index.js";
2
+ import type { ToolCatalog } from "../../runtime/ports/index.js";
3
+ export interface WorkflowComputeHandlerHost {
4
+ toolCatalog?: ToolCatalog;
5
+ sendResponse(id: string | number, result?: unknown, error?: AgentRpcError): void;
6
+ }
7
+ /** Stateless compute port. Workflow definitions, runs, credentials, and approvals remain gateway-owned. */
8
+ export declare function handleComputeToolInvoke(this: WorkflowComputeHandlerHost, msg: AgentRpcRequest): Promise<void>;
@@ -5,9 +5,6 @@ import { type ControlHandlerHost } from "./handlers/control-handler.js";
5
5
  import { type FilesHandlerHost } from "./handlers/files-handler.js";
6
6
  import { type MediaHandlerHost } from "./handlers/media-handler.js";
7
7
  import { type MemoryHandlerHost } from "./handlers/memory-handler.js";
8
- import { type PetConfirmHandlerHost } from "./handlers/pet-confirm-handler.js";
9
- import { type PetHandlerHost } from "./handlers/pet-handler.js";
10
- import { type WorkflowHandlerHost } from "./handlers/workflow-handler.js";
11
8
  import { type ProjectHandlerHost } from "./handlers/project-handler.js";
12
9
  import { type SessionHandlerHost } from "./handlers/session-handler.js";
13
10
  import { type SkillsHandlerHost } from "./handlers/skills-handler.js";
@@ -54,8 +51,6 @@ export interface RpcHandlerHosts {
54
51
  files: FilesHandlerHost;
55
52
  media: MediaHandlerHost;
56
53
  skills: SkillsHandlerHost;
57
- pet: PetHandlerHost;
58
- petConfirm: PetConfirmHandlerHost;
59
54
  project: ProjectHandlerHost;
60
55
  community: CommunityHandlerHost;
61
56
  dream: DreamHandlerHost;
@@ -65,13 +60,5 @@ export interface RpcHandlerHosts {
65
60
  workingMaterials: WorkingMaterialsHandlerHost;
66
61
  /** agents/solo/product are served by the multi-agent sub-host. */
67
62
  multiAgent: MultiAgentHandlerHost;
68
- /**
69
- * workflow.* binds to its own host: it needs `toolCatalog` plus the lazy engine slots
70
- * (controller/store/scheduler/processManager) that the multi-agent sub-host lacks. The host
71
- * (StdioServer) supplies a dedicated WorkflowHostAdapter that sources acpDetector from the
72
- * multi-agent sub-host and toolCatalog from the runtime — so this binding is compiler-checked
73
- * like every other domain, with no cast.
74
- */
75
- workflow: WorkflowHandlerHost;
76
63
  }
77
64
  export declare function createRpcMethodRegistry(host: RpcHandlerHosts): ReadonlyMap<string, RpcMethodHandler>;
@@ -1,13 +1,12 @@
1
1
  import type { LLMRequest } from "../agent/types.js";
2
2
  import type { ModelPurpose } from "../runtime/infra/model-registry.js";
3
3
  import type { RpcHandlerHosts } from "./rpc-registry.js";
4
- type DirectStdioRpcHost = RpcHandlerHosts["config"] & RpcHandlerHosts["control"] & RpcHandlerHosts["files"] & RpcHandlerHosts["skills"] & RpcHandlerHosts["project"] & RpcHandlerHosts["community"] & RpcHandlerHosts["petConfirm"] & {
4
+ type DirectStdioRpcHost = RpcHandlerHosts["config"] & RpcHandlerHosts["control"] & RpcHandlerHosts["files"] & RpcHandlerHosts["skills"] & RpcHandlerHosts["project"] & RpcHandlerHosts["community"] & {
5
5
  currentTurnId?: string;
6
6
  /** Mid-turn guidance queue (运行中引导) — shared between handleTurnGuide and the tool loop's drain. */
7
7
  pendingTurnGuidance?: string[];
8
8
  getActiveProjectRoot(): string;
9
9
  readonly multiAgentHandlerHost: RpcHandlerHosts["multiAgent"];
10
- readonly workflowHandlerHost: RpcHandlerHosts["workflow"];
11
10
  };
12
11
  type StdioRpcAdapterSource = DirectStdioRpcHost & {
13
12
  ensureTaskDistillation(): import("./rpc-registry.js").TaskDistillationRpcSurface;
@@ -24,7 +23,6 @@ type StdioRpcAdapterSource = DirectStdioRpcHost & {
24
23
  memoryDreamProvider: RpcHandlerHosts["dream"]["memoryProvider"];
25
24
  memoryUserId: NonNullable<RpcHandlerHosts["memory"]["memoryUserId"]>;
26
25
  pendingAskUser: RpcHandlerHosts["turn"]["pendingAskUser"];
27
- petRuntime: RpcHandlerHosts["pet"]["petRuntime"];
28
26
  verbose: NonNullable<RpcHandlerHosts["dream"]["verbose"]>;
29
27
  resolveClientForPurpose(purpose: ModelPurpose): {
30
28
  transport: {
@@ -37,9 +35,8 @@ type StdioRpcAdapterSource = DirectStdioRpcHost & {
37
35
  model: string;
38
36
  } | null;
39
37
  ensureMemoryProvider: NonNullable<RpcHandlerHosts["memory"]["ensureMemoryProvider"]>;
40
- ensureModelRegistryHydrated: NonNullable<RpcHandlerHosts["pet"]["ensureModelRegistryHydrated"]>;
41
38
  enableIdleDream: NonNullable<RpcHandlerHosts["session"]["enableIdleDream"]>;
42
- configureTurnMedia: NonNullable<RpcHandlerHosts["pet"]["configureTurnMedia"]>;
39
+ configureTurnMedia: NonNullable<RpcHandlerHosts["turn"]["configureTurnMedia"]>;
43
40
  sendError: NonNullable<RpcHandlerHosts["session"]["sendError"]>;
44
41
  createDreamHandlerHost(): RpcHandlerHosts["dream"];
45
42
  };
@@ -22,7 +22,6 @@ import type { AcpServer } from "../transport/acp-server.js";
22
22
  import type { NotificationMethod, NotificationMethodMap } from "../protocol/notifications.js";
23
23
  import { AgentRuntimeSessionState } from "./agent-runtime-session-state.js";
24
24
  import { type MultiAgentHandlerHost } from "./multi-agent-handler-host.js";
25
- import type { WorkflowHandlerHost } from "./handlers/workflow-handler.js";
26
25
  import { SessionHistoryCoordinator } from "./session-history-coordinator.js";
27
26
  import { PetConfirmCoordinator } from "./pet-confirm-coordinator.js";
28
27
  import type { MemoryDreamRuntimeProvider, MemoryHandlerProvider, PermissionMode, ProjectMemoryStore } from "../runtime/ports/index.js";
@@ -83,8 +82,6 @@ export declare class StdioServer {
83
82
  }>;
84
83
  /** Agents/solo/product handler facade. */
85
84
  readonly multiAgentHandlerHost: MultiAgentHandlerHost;
86
- /** Workflow handler host — carries toolCatalog + the lazy engine slots the multi-agent host lacks. */
87
- readonly workflowHandlerHost: WorkflowHandlerHost;
88
85
  /** ACP protocol coordinator — owns AcpServer lifecycle and ACP event mapping. */
89
86
  private readonly acp;
90
87
  sessionHistory: SessionHistoryCoordinator;
@@ -0,0 +1,2 @@
1
+ export declare const STRUCTURED_PLANNER_SYSTEM_PROMPT_MARKER = "<qlogicagent-mode>structured-planner</qlogicagent-mode>";
2
+ export declare function isStructuredPlannerSystemPrompt(value: unknown): boolean;
@@ -47,6 +47,12 @@ export interface SoloCallbacks {
47
47
  */
48
48
  onTerminal?: (soloId: string, state: SoloState) => void | Promise<void>;
49
49
  }
50
+ /**
51
+ * Solo is an explicit user-launched coding race and every racer is confined to its own disposable
52
+ * worktree. Permit a requested operation only for this turn; never upgrade the decision to a
53
+ * persistent allow. If the agent offers no one-shot allow, fail closed with a rejection option.
54
+ */
55
+ export declare function selectSoloApprovalOptionId(options: Array<Record<string, unknown>>): string;
50
56
  /**
51
57
  * Assemble the prompt every competitor receives (Cut4). Shared context (rules/memory) + optional
52
58
  * <spec> block, then the body. Body = spec.rawTask when a Spec was built (the task captured during
@@ -70,11 +76,10 @@ export declare function buildEvaluationPrompt(originalTask: string, spec: SoloSp
70
76
  }>): string;
71
77
  export declare class SoloEvaluator {
72
78
  private processManager;
73
- private acpDetector;
74
79
  private configStore;
75
80
  private callbacks;
76
81
  private sessions;
77
- constructor(processManager: AgentProcessManager, acpDetector: AcpDetector, configStore: AgentConfigStore | null, callbacks?: SoloCallbacks);
82
+ constructor(processManager: AgentProcessManager, _acpDetector: AcpDetector, configStore: AgentConfigStore | null, callbacks?: SoloCallbacks);
78
83
  /** Persist current session data to disk (fire-and-forget). */
79
84
  private persistSession;
80
85
  /** Restore sessions from disk (call once at startup). */
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Host-owned PET module surface.
3
+ *
4
+ * This entry point contains reusable domain and persistence components only. Importing it does not
5
+ * create a profile service or touch disk; the gateway is responsible for constructing the single
6
+ * production owner for a resolved owner id.
7
+ */
8
+ export { PetProfileService, PetSoulService, PetGrowthEngine, catchUpJourney, createPetdexAssetFromSpritesheet, forgePetdexAsset, forgePetdexAssetPackage, listBuiltinPetdexAssetIds, listBuiltinPetdexAssets, loadPetFile, petReactionEngine, petdexImageDataUrl, readGeneratedPetdexImage, toPetdexAssetSummary, validatePetManifest, writePetdexAssetPackage, } from "./runtime/pet/index.js";
9
+ export type { CatchUpJourneyOptions, JourneySnapshot, JourneyStats, PetFileBundle, PetManifest, PetPreferences, PetProfile, PetSoul, PetStats, PetdexPetAsset, PetdexPetAssetSummary, } from "./runtime/pet/index.js";
@@ -145,6 +145,8 @@ export interface AcpSessionMeta {
145
145
  /** Skills the user explicitly pinned for this turn (scope:name or name). The turn pipeline
146
146
  * force-loads each one's SKILL.md, identically to the `skill_view` tool (cc-parity). */
147
147
  activeSkills?: string[];
148
+ /** Session-scoped MCP servers normalized for the turn bootstrap. */
149
+ mcpServers?: Record<string, unknown>;
148
150
  }
149
151
  export interface AcpSessionNewParams {
150
152
  /** Working directory for the session (standard ACP field from host). */
@@ -159,6 +161,7 @@ export interface AcpSessionNewParams {
159
161
  name: string;
160
162
  value: string;
161
163
  }>;
164
+ callTimeoutMs?: number;
162
165
  }>;
163
166
  /** Optional session ID (host-assigned). If omitted, agent generates one. */
164
167
  sessionId?: string;
@@ -172,6 +175,10 @@ export interface AcpSessionLoadParams {
172
175
  sessionId: string;
173
176
  /** Working directory for the resumed session (standard ACP field). */
174
177
  cwd?: string;
178
+ /** MCP servers re-injected by the host when resuming the session. */
179
+ mcpServers?: AcpSessionNewParams["mcpServers"];
180
+ /** Per-session context supplement restored by the host. */
181
+ _meta?: AcpSessionMeta;
175
182
  }
176
183
  /** A selectable permission mode advertised to the host (standard ACP). */
177
184
  export interface AcpMode {
@@ -4,7 +4,7 @@ import { ReactionEngine } from "@xiaozhiclaw/pet-core";
4
4
  *
5
5
  * pet-core moved the original module-level `recentReactions` dedup buffer to a
6
6
  * ReactionEngine instance field. The original behaviour was a module singleton
7
- * shared by both pet-runtime and pet-handler, so the host keeps exactly one
7
+ * shared by the PET host/runtime surfaces, so the host keeps exactly one
8
8
  * shared instance here (seeded with defaultPetRng = Math.random) to preserve the
9
9
  * cross-call dedup semantics byte-for-byte.
10
10
  */
@@ -30,6 +30,8 @@ export interface McpServerEntry {
30
30
  include?: string[];
31
31
  exclude?: string[];
32
32
  };
33
+ /** Per-tool invocation budget for this server (1s..10min). */
34
+ callTimeoutMs?: number;
33
35
  }
34
36
  export interface McpSecurityIssue {
35
37
  code: "dangerous_egress" | "persistence" | "ioc_public_key";
@@ -57,6 +59,7 @@ export interface McpManagerConfig {
57
59
  /** Runtime-owned catalog used for dynamic MCP tool injection. */
58
60
  toolCatalog?: ToolRegistryLike;
59
61
  }
62
+ export declare function resolveMcpCallTimeoutMs(value: number | undefined): number;
60
63
  /**
61
64
  * Run `attempt` up to `options.attempts` times, backing off `baseDelayMs * n`
62
65
  * between tries. Returns the first success; rethrows the last error if every
@@ -78,6 +81,7 @@ export declare class McpManager {
78
81
  private toolCatalog?;
79
82
  private serverToolFilters;
80
83
  private serverOAuth;
84
+ private serverCallTimeouts;
81
85
  private failedServers;
82
86
  constructor(config: McpManagerConfig);
83
87
  /** Record (and loudly report) a server that will serve NO tools this session. */
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Host-owned Workflow module surface.
3
+ *
4
+ * All exports are inert until the gateway constructs a project-scoped store/controller/scheduler.
5
+ * The qlogicagent executable must consume the injected MCP capability instead of constructing these
6
+ * owners itself after cutover.
7
+ */
8
+ export { WorkflowStore, workflowsDir } from "./orchestration/workflow/workflow-store.js";
9
+ export type { ConcurrencyPolicy, WorkflowRecord } from "./orchestration/workflow/workflow-store.js";
10
+ export { WorkflowController, defaultRuntimeFactory } from "./orchestration/workflow/workflow-controller.js";
11
+ export type { RunContext, RunOutcome, RuntimeFactory } from "./orchestration/workflow/workflow-controller.js";
12
+ export { createQlaExecutorHost } from "./orchestration/workflow/qla-executor-host.js";
13
+ export type { QlaExecutorHostDeps } from "./orchestration/workflow/qla-executor-host.js";
14
+ export { WorkflowScheduler } from "./orchestration/workflow/workflow-scheduler.js";
15
+ export type { SchedulerClock, SchedulerDeps } from "./orchestration/workflow/workflow-scheduler.js";
16
+ export { WorkflowRuntime } from "./orchestration/workflow/workflow-runtime.js";
17
+ export type { RunResult, WorkflowRuntimeOptions } from "./orchestration/workflow/workflow-runtime.js";
18
+ export { NodeRegistry } from "./orchestration/workflow/node-registry.js";
19
+ export { hostExecutors, HOST_BACKED_KINDS } from "./orchestration/workflow/host-executors.js";
20
+ export type { ExecutorHost } from "./orchestration/workflow/node-schema.js";
21
+ export type { AgentHostRequest, ApprovalHostRequest, ChannelHostRequest, HttpHostRequest, McpHostRequest, MemoryHostRequest, SubworkflowHostRequest, ToolHostRequest, WebhookWaitHostRequest, } from "./orchestration/workflow/node-schema.js";
22
+ export { CredentialVault, credentialToHeaders } from "./cli/credential-vault.js";
23
+ export type { CredentialData, CredentialSummary, CredentialType } from "./cli/credential-vault.js";
24
+ export { WorkflowRunHistoryStore } from "./orchestration/workflow/run-history-store.js";
25
+ export { FileRunCheckpoint } from "./orchestration/workflow/run-checkpoint-store.js";
26
+ export type { RunCheckpoint } from "./orchestration/workflow/run-checkpoint-store.js";
27
+ export { WorkflowAuditStore } from "./orchestration/workflow/workflow-audit-store.js";
28
+ export { applyPatch, PatchError } from "./orchestration/workflow/workflow-patch.js";
29
+ export type { PatchEnvelope, WorkflowPatch } from "./orchestration/workflow/workflow-patch.js";
30
+ export { fromWorkflowBundle, toWorkflowBundle } from "./orchestration/workflow/workflow-bundle.js";
31
+ export type { ParsedBundle, WorkflowBundle } from "./orchestration/workflow/workflow-bundle.js";
32
+ export { renderWorkflow } from "./orchestration/workflow/workflow-render.js";
33
+ export type { WorkflowDef } from "./orchestration/workflow/node-schema.js";