Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7503fccbf2 | |||
| a76bd0d3e4 | |||
| 1556a9d3e9 | |||
| 19ba58ca40 | |||
| 8662b73adb | |||
| 9e848045f7 | |||
| 8827a55768 | |||
| 37b6e98a81 | |||
| 35911c21de | |||
| 7403e769d0 | |||
| 0ee110cf7d | |||
| 0a8965b781 |
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-12-15 - 1.1.1 - fix(ci)
|
||||
Update CI/release config and bump devDependencies; enable verbose tests
|
||||
|
||||
- Add @git.zone/cli release configuration with registries (verdaccio.lossless.digital and registry.npmjs.org) and public access in npmextra.json
|
||||
- Bump devDependencies: @git.zone/tsbuild -> ^4.0.2, @git.zone/tsbundle -> ^2.6.3, @git.zone/tsrun -> ^2.0.1, @types/node -> ^25.0.2
|
||||
- Change test script to run tstest with --verbose
|
||||
|
||||
## 2025-12-02 - 1.1.0 - feat(deno)
|
||||
Add Deno tool and smartdeno integration; export and register DenoTool; update docs and tests
|
||||
|
||||
|
||||
@@ -14,5 +14,14 @@
|
||||
"npmci": {
|
||||
"npmGlobalTools": [],
|
||||
"npmAccessLevel": "public"
|
||||
},
|
||||
"@git.zone/cli": {
|
||||
"release": {
|
||||
"registries": [
|
||||
"https://verdaccio.lossless.digital",
|
||||
"https://registry.npmjs.org"
|
||||
],
|
||||
"accessLevel": "public"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
package.json
15
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@push.rocks/smartagent",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.5",
|
||||
"private": false,
|
||||
"description": "an agentic framework built on top of @push.rocks/smartai",
|
||||
"main": "dist_ts/index.js",
|
||||
@@ -9,16 +9,16 @@
|
||||
"author": "Task Venture Capital GmbH",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "(tstest test/ --web)",
|
||||
"test": "(tstest test/ --verbose)",
|
||||
"build": "(tsbuild --web --allowimplicitany)",
|
||||
"buildDocs": "(tsdoc)"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^3.1.2",
|
||||
"@git.zone/tsbundle": "^2.6.2",
|
||||
"@git.zone/tsrun": "^2.0.0",
|
||||
"@git.zone/tsbuild": "^4.0.2",
|
||||
"@git.zone/tsbundle": "^2.6.3",
|
||||
"@git.zone/tsrun": "^2.0.1",
|
||||
"@git.zone/tstest": "^3.1.3",
|
||||
"@types/node": "^24.10.1"
|
||||
"@types/node": "^25.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@push.rocks/smartai": "^0.8.0",
|
||||
@@ -26,7 +26,8 @@
|
||||
"@push.rocks/smartdeno": "^1.2.0",
|
||||
"@push.rocks/smartfs": "^1.2.0",
|
||||
"@push.rocks/smartrequest": "^5.0.1",
|
||||
"@push.rocks/smartshell": "^3.3.0"
|
||||
"@push.rocks/smartshell": "^3.3.0",
|
||||
"minimatch": "^10.1.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.18.1+sha512.77a884a165cbba2d8d1c19e3b4880eee6d2fcabd0d879121e282196b80042351d5eb3ca0935fa599da1dc51265cc68816ad2bddd2a2de5ea9fdf92adbec7cd34",
|
||||
"repository": {
|
||||
|
||||
434
pnpm-lock.yaml
generated
434
pnpm-lock.yaml
generated
@@ -26,22 +26,25 @@ importers:
|
||||
'@push.rocks/smartshell':
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0
|
||||
minimatch:
|
||||
specifier: ^10.1.1
|
||||
version: 10.1.1
|
||||
devDependencies:
|
||||
'@git.zone/tsbuild':
|
||||
specifier: ^3.1.2
|
||||
version: 3.1.2
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2
|
||||
'@git.zone/tsbundle':
|
||||
specifier: ^2.6.2
|
||||
version: 2.6.2
|
||||
specifier: ^2.6.3
|
||||
version: 2.6.3
|
||||
'@git.zone/tsrun':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
'@git.zone/tstest':
|
||||
specifier: ^3.1.3
|
||||
version: 3.1.3(socks@2.8.7)(typescript@5.9.3)
|
||||
'@types/node':
|
||||
specifier: ^24.10.1
|
||||
version: 24.10.1
|
||||
specifier: ^25.0.2
|
||||
version: 25.0.2
|
||||
|
||||
packages:
|
||||
|
||||
@@ -267,176 +270,176 @@ packages:
|
||||
'@emnapi/wasi-threads@1.1.0':
|
||||
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.0':
|
||||
resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==}
|
||||
'@esbuild/aix-ppc64@0.27.1':
|
||||
resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.27.0':
|
||||
resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==}
|
||||
'@esbuild/android-arm64@0.27.1':
|
||||
resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.27.0':
|
||||
resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==}
|
||||
'@esbuild/android-arm@0.27.1':
|
||||
resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.27.0':
|
||||
resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==}
|
||||
'@esbuild/android-x64@0.27.1':
|
||||
resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.27.0':
|
||||
resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==}
|
||||
'@esbuild/darwin-arm64@0.27.1':
|
||||
resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.27.0':
|
||||
resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==}
|
||||
'@esbuild/darwin-x64@0.27.1':
|
||||
resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.27.0':
|
||||
resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==}
|
||||
'@esbuild/freebsd-arm64@0.27.1':
|
||||
resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.27.0':
|
||||
resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==}
|
||||
'@esbuild/freebsd-x64@0.27.1':
|
||||
resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.27.0':
|
||||
resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==}
|
||||
'@esbuild/linux-arm64@0.27.1':
|
||||
resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.27.0':
|
||||
resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==}
|
||||
'@esbuild/linux-arm@0.27.1':
|
||||
resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.27.0':
|
||||
resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==}
|
||||
'@esbuild/linux-ia32@0.27.1':
|
||||
resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.27.0':
|
||||
resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==}
|
||||
'@esbuild/linux-loong64@0.27.1':
|
||||
resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.27.0':
|
||||
resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==}
|
||||
'@esbuild/linux-mips64el@0.27.1':
|
||||
resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.27.0':
|
||||
resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==}
|
||||
'@esbuild/linux-ppc64@0.27.1':
|
||||
resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.27.0':
|
||||
resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==}
|
||||
'@esbuild/linux-riscv64@0.27.1':
|
||||
resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.27.0':
|
||||
resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==}
|
||||
'@esbuild/linux-s390x@0.27.1':
|
||||
resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.27.0':
|
||||
resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==}
|
||||
'@esbuild/linux-x64@0.27.1':
|
||||
resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.27.0':
|
||||
resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==}
|
||||
'@esbuild/netbsd-arm64@0.27.1':
|
||||
resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.27.0':
|
||||
resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==}
|
||||
'@esbuild/netbsd-x64@0.27.1':
|
||||
resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.27.0':
|
||||
resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==}
|
||||
'@esbuild/openbsd-arm64@0.27.1':
|
||||
resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.0':
|
||||
resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==}
|
||||
'@esbuild/openbsd-x64@0.27.1':
|
||||
resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.27.0':
|
||||
resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==}
|
||||
'@esbuild/openharmony-arm64@0.27.1':
|
||||
resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.27.0':
|
||||
resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==}
|
||||
'@esbuild/sunos-x64@0.27.1':
|
||||
resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.27.0':
|
||||
resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==}
|
||||
'@esbuild/win32-arm64@0.27.1':
|
||||
resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.27.0':
|
||||
resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==}
|
||||
'@esbuild/win32-ia32@0.27.1':
|
||||
resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.27.0':
|
||||
resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==}
|
||||
'@esbuild/win32-x64@0.27.1':
|
||||
resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@git.zone/tsbuild@3.1.2':
|
||||
resolution: {integrity: sha512-K0u840Qo0WEhvcpAtktvdBX6KEXjelU32o820WzcK7dMA7dd2YV+mPOEYfbmWLcdtFJkrjkigQq5fpLhTN4oKQ==}
|
||||
'@git.zone/tsbuild@4.0.2':
|
||||
resolution: {integrity: sha512-LcRlFnDbcUe53Pdoob585iXq9TAT90TyEaYl/wml/etFoPeBX+oQLm6GryejUPXrUP7i1opyTonadkQN1OyXOA==}
|
||||
hasBin: true
|
||||
|
||||
'@git.zone/tsbundle@2.6.2':
|
||||
resolution: {integrity: sha512-wj32zHpvbDUdStEjJ9RCqffmafqlopWSROSRBQDgpJ8hnMAO3ftWkTWWfGdTGh2p2pALfPqgSFzwxCd4RJG8aQ==}
|
||||
'@git.zone/tsbundle@2.6.3':
|
||||
resolution: {integrity: sha512-YD1qMYA/4eOuF57V0ccR+xo6ww1+QOYFA2K5gBPFBDNh9VdfvWxxDhOUybja8lT9PVMoli8PHG5WA5tKJkdXIQ==}
|
||||
hasBin: true
|
||||
|
||||
'@git.zone/tspublish@1.10.3':
|
||||
resolution: {integrity: sha512-o2/jvNsdLC8SRdH1kQ7JjNOQNu9el0FpJ/QOW3mgiC5C9reuTp18iU4kijsVVLgvw4KZv6Z289SoKPh3HPsS0g==}
|
||||
hasBin: true
|
||||
|
||||
'@git.zone/tsrun@2.0.0':
|
||||
resolution: {integrity: sha512-yA6zCjL+kn7xfZe6sL/m4K+zYqgkznG/pF6++i/E17iwzpG6dHmW+VZmYldHe86sW4DcLMvqM6CxM+KlgaEpKw==}
|
||||
'@git.zone/tsrun@2.0.1':
|
||||
resolution: {integrity: sha512-NEcnsjvlC1o3Z6SS3VhKCf6Ev+Sh4EAinmggslrIR/ppMrvjDbXNFXoyr3PB+GLeSAR0JRZ1fGvVYjpEzjBdIg==}
|
||||
hasBin: true
|
||||
|
||||
'@git.zone/tstest@3.1.3':
|
||||
@@ -744,6 +747,9 @@ packages:
|
||||
'@napi-rs/wasm-runtime@1.0.7':
|
||||
resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==}
|
||||
|
||||
'@napi-rs/wasm-runtime@1.1.0':
|
||||
resolution: {integrity: sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==}
|
||||
|
||||
'@oxc-project/types@0.99.0':
|
||||
resolution: {integrity: sha512-LLDEhXB7g1m5J+woRSgfKsFPS3LhR9xRhTeIoEBm5WrkwMxn6eZ0Ld0c0K5eHB57ChZX6I3uSmmLjZ8pcjlRcw==}
|
||||
|
||||
@@ -907,6 +913,9 @@ packages:
|
||||
'@push.rocks/smartfile@13.1.0':
|
||||
resolution: {integrity: sha512-bSjH9vHl6l1nbe/gcSi4PcutFcTHUCVkMuQGGTVtn1cOgCuOXIHV04uhOXrZoKvlcSxxoiq8THolFt65lqn7cg==}
|
||||
|
||||
'@push.rocks/smartfile@13.1.2':
|
||||
resolution: {integrity: sha512-DaEhwmnGEpX4coeeToaw4cZe3pNBhH7CY1iGr+d3pIXihozREvzzAR9/0i2r7bUXXL5+Lgy8YYIk5ZS+fwxMKA==}
|
||||
|
||||
'@push.rocks/smartfs@1.2.0':
|
||||
resolution: {integrity: sha512-1R47jJZwX869z7DYgKeAZKTU1SbGnM7W/ZmgsI7AkQQhiascNqY3/gF4V5kIprmuf1WhpRbCbZyum8s7J1LDdg==}
|
||||
|
||||
@@ -1181,60 +1190,60 @@ packages:
|
||||
'@rolldown/pluginutils@1.0.0-beta.52':
|
||||
resolution: {integrity: sha512-/L0htLJZbaZFL1g9OHOblTxbCYIGefErJjtYOwgl9ZqNx27P3L0SDfjhhHIss32gu5NWgnxuT2a2Hnnv6QGHKA==}
|
||||
|
||||
'@rspack/binding-darwin-arm64@1.6.6':
|
||||
resolution: {integrity: sha512-vGVDP0rlWa2w/gLba/sncVfkCah0HmhdmK5vGj/7sSX0iViwQneA2xjxDHyCNSQrvfq9GJmj4Kmdq/9tGh0KuA==}
|
||||
'@rspack/binding-darwin-arm64@1.6.7':
|
||||
resolution: {integrity: sha512-QiIAP8JTAtht0j8/xZZEQTJRB9e+KrOm9c7JJm73CewVg55rDWRrwopiVfBNlTu1coem1ztUHJYdQhg2uXfqww==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rspack/binding-darwin-x64@1.6.6':
|
||||
resolution: {integrity: sha512-IcdEG2kOmbPPO70Zl7gDnowDjK7d7C1hWew2vU7dPltr2t1JalRIMnS051lhiur0ULkSxV3cW1zXqv0Oi8AnOg==}
|
||||
'@rspack/binding-darwin-x64@1.6.7':
|
||||
resolution: {integrity: sha512-DpQRxxTXkMMNPmBXeJBaAB8HmWKxH2IfvHv7vU+kBhJ3xdPtXU4/xBv1W3biluoNRG11gc1WLIgjzeGgaLCxmw==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rspack/binding-linux-arm64-gnu@1.6.6':
|
||||
resolution: {integrity: sha512-rIguCCtlTcwoFlwheDiUgdImk27spuCRn43zGJogARpM/ZYRFKIuSwFDGUtJT2g0TSLUAHUhWAUqC36NwvrbMQ==}
|
||||
'@rspack/binding-linux-arm64-gnu@1.6.7':
|
||||
resolution: {integrity: sha512-211/XoBiooGGgUo/NxNpsrzGUXtH1d7g/4+UTtjYtfc8QHwu7ZMHcsqg0wss53fXzn/yyxd0DZ56vBHq52BiFw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rspack/binding-linux-arm64-musl@1.6.6':
|
||||
resolution: {integrity: sha512-x6X6Gr0fUw6qrJGxZt3Rb6oIX+jd9pdcyp0VbtofcLaqGVQbzustYsYnuLATPOys0q4J/4kWnmEhkjLJHwkhpQ==}
|
||||
'@rspack/binding-linux-arm64-musl@1.6.7':
|
||||
resolution: {integrity: sha512-0WnqAWz3WPDsXGvOOA++or7cHpoidVsH3FlqNaAfRu6ni6n7ig/s0/jKUB+C5FtXOgmGjAGkZHfFgNHsvZ0FWw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rspack/binding-linux-x64-gnu@1.6.6':
|
||||
resolution: {integrity: sha512-gSlVdASszWHosQKn+nzYOInBijdQboUnmNMGgW9/PijVg3433IvQjzviUuJFno8CMGgrACV9yw+ZFDuK0J57VA==}
|
||||
'@rspack/binding-linux-x64-gnu@1.6.7':
|
||||
resolution: {integrity: sha512-iMrE0Q4IuYpkE0MjpaOVaUDYbQFiCRI9D3EPoXzlXJj4kJSdNheODpHTBVRlWt8Xp7UAoWuIFXCvKFKcSMm3aQ==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rspack/binding-linux-x64-musl@1.6.6':
|
||||
resolution: {integrity: sha512-TZaqVkh7memsTK/hxkOBrbpdzbmBUMea1YnYt++7QjMgco1kWFvAQ+YhAWtIaOaEg8s6C07Lt0Zp8izM2Dja0g==}
|
||||
'@rspack/binding-linux-x64-musl@1.6.7':
|
||||
resolution: {integrity: sha512-e7gKFxpdEQwYGk7lTC/hukTgNtaoAstBXehnZNk4k3kuU6+86WDrkn18Cd949iNqfIPtIG/wIsFNGbkHsH69hQ==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rspack/binding-wasm32-wasi@1.6.6':
|
||||
resolution: {integrity: sha512-W4mWdlLnYrbUaktyHOGNfATblxMTbgF7CBfDw8PhbDtjd2l8e/TnaHgIDkwITHXAOMEF/QEKfo9FtusbcQJNKw==}
|
||||
'@rspack/binding-wasm32-wasi@1.6.7':
|
||||
resolution: {integrity: sha512-yx88EFdE9RP3hh7VhjjW6uc6wGU0KcpOcZp8T8E/a+X8L98fX0aVrtM1IDbndhmdluIMqGbfJNap2+QqOCY9Mw==}
|
||||
cpu: [wasm32]
|
||||
|
||||
'@rspack/binding-win32-arm64-msvc@1.6.6':
|
||||
resolution: {integrity: sha512-cw5OgxqoDwjoZlk0L3vGEwcjPZsOVFYLwr2ssiC05rsTbhBwxj8coLpAJdvUvbf6C2TTmCB7iPe2sPq1KWD37g==}
|
||||
'@rspack/binding-win32-arm64-msvc@1.6.7':
|
||||
resolution: {integrity: sha512-vgxVYpFK8P5ulSXQQA+EbX78R/SUU+WIf0JIY+LoUoP89gZOsise/lKAJMAybzpeTJ1t0ndLchFznDYnzq+l4Q==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rspack/binding-win32-ia32-msvc@1.6.6':
|
||||
resolution: {integrity: sha512-M4ruR+VZ59iy+mPjy6FQPT27cOgeytf3wFBrt7e0suKeNLYGxrNyI9YhgpCTY++SMJsAMgRLGDHoI3ZgWulw1Q==}
|
||||
'@rspack/binding-win32-ia32-msvc@1.6.7':
|
||||
resolution: {integrity: sha512-bV5RTW0Va0UQKJm9HWLt7fWNBPaBBBxCJOA2pJT3nGGm6CCXKnZSyEiVbFUk4jI/uiwBfqenlLkzaGoMRbeDhA==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rspack/binding-win32-x64-msvc@1.6.6':
|
||||
resolution: {integrity: sha512-q5QTvdhPUh+CA93cQG5zWKRIHMIWPzw+ftFDEwBw52zYdvNAoLniqD8o5Mi8CT0pndhulXgR5aw0Sjd3eMah+A==}
|
||||
'@rspack/binding-win32-x64-msvc@1.6.7':
|
||||
resolution: {integrity: sha512-8xlbuJQtYktlBjZupOHlO8FeZqSIhsV3ih7xBSiOYar6LI6uQzA7XiO3I5kaPSDirBMMMKv1Z4rKCxWx10a3TQ==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rspack/binding@1.6.6':
|
||||
resolution: {integrity: sha512-noiV+qhyBTVpvG2M4bnOwKk2Ynl6G47Wf7wpCjPCFr87qr3txNwTTnhkEJEU59yj+VvIhbRD2rf5+9TLoT0Wxg==}
|
||||
'@rspack/binding@1.6.7':
|
||||
resolution: {integrity: sha512-7ICabuBN3gHc6PPN52+m1kruz3ogiJjg1C0gSWdLRk18m/4jlcM2aAy6wfXjgODJdB0Yh2ro/lIpBbj+AYWUGA==}
|
||||
|
||||
'@rspack/core@1.6.6':
|
||||
resolution: {integrity: sha512-2mR+2YBydlgZ7Q0Rpd6bCC3MBnV9TS0x857K0zIhbDj4BQOqaWVy1n7fx/B3MrS8TR0QCuzKfyDAjNz+XTyJVQ==}
|
||||
'@rspack/core@1.6.7':
|
||||
resolution: {integrity: sha512-tkd4nSzTf+pDa9OAE4INi/JEa93HNszjWy5C9+trf4ZCXLLHsHxHQFbzoreuz4Vv2PlCWajgvAdiPMV1vGIkuw==}
|
||||
engines: {node: '>=18.12.0'}
|
||||
peerDependencies:
|
||||
'@swc/helpers': '>=0.5.1'
|
||||
@@ -1572,8 +1581,8 @@ packages:
|
||||
'@types/node@16.9.1':
|
||||
resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==}
|
||||
|
||||
'@types/node@24.10.1':
|
||||
resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==}
|
||||
'@types/node@25.0.2':
|
||||
resolution: {integrity: sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==}
|
||||
|
||||
'@types/ping@0.4.4':
|
||||
resolution: {integrity: sha512-ifvo6w2f5eJYlXm+HiVx67iJe8WZp87sfa683nlqED5Vnt9Z93onkokNoWqOG21EaE8fMxyKPobE+mkPEyxsdw==}
|
||||
@@ -2100,8 +2109,8 @@ packages:
|
||||
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esbuild@0.27.0:
|
||||
resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==}
|
||||
esbuild@0.27.1:
|
||||
resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
@@ -4379,91 +4388,92 @@ snapshots:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.0':
|
||||
'@esbuild/aix-ppc64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.27.0':
|
||||
'@esbuild/android-arm64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.27.0':
|
||||
'@esbuild/android-arm@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.27.0':
|
||||
'@esbuild/android-x64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.27.0':
|
||||
'@esbuild/darwin-arm64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.27.0':
|
||||
'@esbuild/darwin-x64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.27.0':
|
||||
'@esbuild/freebsd-arm64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.27.0':
|
||||
'@esbuild/freebsd-x64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.27.0':
|
||||
'@esbuild/linux-arm64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.27.0':
|
||||
'@esbuild/linux-arm@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.27.0':
|
||||
'@esbuild/linux-ia32@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.27.0':
|
||||
'@esbuild/linux-loong64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.27.0':
|
||||
'@esbuild/linux-mips64el@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.27.0':
|
||||
'@esbuild/linux-ppc64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.27.0':
|
||||
'@esbuild/linux-riscv64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.27.0':
|
||||
'@esbuild/linux-s390x@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.27.0':
|
||||
'@esbuild/linux-x64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.27.0':
|
||||
'@esbuild/netbsd-arm64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.27.0':
|
||||
'@esbuild/netbsd-x64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.27.0':
|
||||
'@esbuild/openbsd-arm64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.0':
|
||||
'@esbuild/openbsd-x64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.27.0':
|
||||
'@esbuild/openharmony-arm64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.27.0':
|
||||
'@esbuild/sunos-x64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.27.0':
|
||||
'@esbuild/win32-arm64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.27.0':
|
||||
'@esbuild/win32-ia32@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.27.0':
|
||||
'@esbuild/win32-x64@0.27.1':
|
||||
optional: true
|
||||
|
||||
'@git.zone/tsbuild@3.1.2':
|
||||
'@git.zone/tsbuild@4.0.2':
|
||||
dependencies:
|
||||
'@git.zone/tspublish': 1.10.3
|
||||
'@push.rocks/early': 4.0.4
|
||||
'@push.rocks/smartcli': 4.0.19
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartfile': 11.2.7
|
||||
'@push.rocks/smartfile': 13.1.2
|
||||
'@push.rocks/smartfs': 1.2.0
|
||||
'@push.rocks/smartlog': 3.1.10
|
||||
'@push.rocks/smartpath': 6.0.0
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
@@ -4477,7 +4487,7 @@ snapshots:
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
'@git.zone/tsbundle@2.6.2':
|
||||
'@git.zone/tsbundle@2.6.3':
|
||||
dependencies:
|
||||
'@push.rocks/early': 4.0.4
|
||||
'@push.rocks/smartcli': 4.0.19
|
||||
@@ -4488,9 +4498,9 @@ snapshots:
|
||||
'@push.rocks/smartpath': 6.0.0
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartspawn': 3.0.3
|
||||
'@rspack/core': 1.6.6
|
||||
'@rspack/core': 1.6.7
|
||||
'@types/html-minifier': 4.0.6
|
||||
esbuild: 0.27.0
|
||||
esbuild: 0.27.1
|
||||
html-minifier: 4.0.0
|
||||
rolldown: 1.0.0-beta.52
|
||||
typescript: 5.9.3
|
||||
@@ -4518,17 +4528,17 @@ snapshots:
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
'@git.zone/tsrun@2.0.0':
|
||||
'@git.zone/tsrun@2.0.1':
|
||||
dependencies:
|
||||
'@push.rocks/smartfile': 11.2.7
|
||||
'@push.rocks/smartfile': 13.1.2
|
||||
'@push.rocks/smartshell': 3.3.0
|
||||
tsx: 4.21.0
|
||||
|
||||
'@git.zone/tstest@3.1.3(socks@2.8.7)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@api.global/typedserver': 3.0.80
|
||||
'@git.zone/tsbundle': 2.6.2
|
||||
'@git.zone/tsrun': 2.0.0
|
||||
'@git.zone/tsbundle': 2.6.3
|
||||
'@git.zone/tsrun': 2.0.1
|
||||
'@push.rocks/consolecolor': 2.0.3
|
||||
'@push.rocks/qenv': 6.1.3
|
||||
'@push.rocks/smartbrowser': 2.0.8(typescript@5.9.3)
|
||||
@@ -4922,6 +4932,13 @@ snapshots:
|
||||
'@tybys/wasm-util': 0.10.1
|
||||
optional: true
|
||||
|
||||
'@napi-rs/wasm-runtime@1.1.0':
|
||||
dependencies:
|
||||
'@emnapi/core': 1.7.1
|
||||
'@emnapi/runtime': 1.7.1
|
||||
'@tybys/wasm-util': 0.10.1
|
||||
optional: true
|
||||
|
||||
'@oxc-project/types@0.99.0': {}
|
||||
|
||||
'@pdf-lib/standard-fonts@1.0.0':
|
||||
@@ -5153,7 +5170,7 @@ snapshots:
|
||||
'@push.rocks/smartarchive@4.2.4':
|
||||
dependencies:
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartfile': 13.1.0
|
||||
'@push.rocks/smartfile': 13.1.2
|
||||
'@push.rocks/smartpath': 6.0.0
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartrequest': 4.4.2
|
||||
@@ -5409,6 +5426,23 @@ snapshots:
|
||||
glob: 11.1.0
|
||||
js-yaml: 4.1.1
|
||||
|
||||
'@push.rocks/smartfile@13.1.2':
|
||||
dependencies:
|
||||
'@push.rocks/lik': 6.2.2
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartfile-interfaces': 1.0.7
|
||||
'@push.rocks/smartfs': 1.2.0
|
||||
'@push.rocks/smarthash': 3.2.6
|
||||
'@push.rocks/smartjson': 5.2.0
|
||||
'@push.rocks/smartmime': 2.0.4
|
||||
'@push.rocks/smartpath': 6.0.0
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartrequest': 4.4.2
|
||||
'@push.rocks/smartstream': 3.2.5
|
||||
'@types/js-yaml': 4.0.9
|
||||
glob: 11.1.0
|
||||
js-yaml: 4.1.1
|
||||
|
||||
'@push.rocks/smartfs@1.2.0':
|
||||
dependencies:
|
||||
'@push.rocks/smartpath': 6.0.0
|
||||
@@ -5940,7 +5974,7 @@ snapshots:
|
||||
|
||||
'@rolldown/binding-wasm32-wasi@1.0.0-beta.52':
|
||||
dependencies:
|
||||
'@napi-rs/wasm-runtime': 1.0.7
|
||||
'@napi-rs/wasm-runtime': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.52':
|
||||
@@ -5954,55 +5988,55 @@ snapshots:
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.52': {}
|
||||
|
||||
'@rspack/binding-darwin-arm64@1.6.6':
|
||||
'@rspack/binding-darwin-arm64@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-darwin-x64@1.6.6':
|
||||
'@rspack/binding-darwin-x64@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-linux-arm64-gnu@1.6.6':
|
||||
'@rspack/binding-linux-arm64-gnu@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-linux-arm64-musl@1.6.6':
|
||||
'@rspack/binding-linux-arm64-musl@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-linux-x64-gnu@1.6.6':
|
||||
'@rspack/binding-linux-x64-gnu@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-linux-x64-musl@1.6.6':
|
||||
'@rspack/binding-linux-x64-musl@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-wasm32-wasi@1.6.6':
|
||||
'@rspack/binding-wasm32-wasi@1.6.7':
|
||||
dependencies:
|
||||
'@napi-rs/wasm-runtime': 1.0.7
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-win32-arm64-msvc@1.6.6':
|
||||
'@rspack/binding-win32-arm64-msvc@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-win32-ia32-msvc@1.6.6':
|
||||
'@rspack/binding-win32-ia32-msvc@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-win32-x64-msvc@1.6.6':
|
||||
'@rspack/binding-win32-x64-msvc@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding@1.6.6':
|
||||
'@rspack/binding@1.6.7':
|
||||
optionalDependencies:
|
||||
'@rspack/binding-darwin-arm64': 1.6.6
|
||||
'@rspack/binding-darwin-x64': 1.6.6
|
||||
'@rspack/binding-linux-arm64-gnu': 1.6.6
|
||||
'@rspack/binding-linux-arm64-musl': 1.6.6
|
||||
'@rspack/binding-linux-x64-gnu': 1.6.6
|
||||
'@rspack/binding-linux-x64-musl': 1.6.6
|
||||
'@rspack/binding-wasm32-wasi': 1.6.6
|
||||
'@rspack/binding-win32-arm64-msvc': 1.6.6
|
||||
'@rspack/binding-win32-ia32-msvc': 1.6.6
|
||||
'@rspack/binding-win32-x64-msvc': 1.6.6
|
||||
'@rspack/binding-darwin-arm64': 1.6.7
|
||||
'@rspack/binding-darwin-x64': 1.6.7
|
||||
'@rspack/binding-linux-arm64-gnu': 1.6.7
|
||||
'@rspack/binding-linux-arm64-musl': 1.6.7
|
||||
'@rspack/binding-linux-x64-gnu': 1.6.7
|
||||
'@rspack/binding-linux-x64-musl': 1.6.7
|
||||
'@rspack/binding-wasm32-wasi': 1.6.7
|
||||
'@rspack/binding-win32-arm64-msvc': 1.6.7
|
||||
'@rspack/binding-win32-ia32-msvc': 1.6.7
|
||||
'@rspack/binding-win32-x64-msvc': 1.6.7
|
||||
|
||||
'@rspack/core@1.6.6':
|
||||
'@rspack/core@1.6.7':
|
||||
dependencies:
|
||||
'@module-federation/runtime-tools': 0.21.6
|
||||
'@rspack/binding': 1.6.6
|
||||
'@rspack/binding': 1.6.7
|
||||
'@rspack/lite-tapable': 1.1.0
|
||||
|
||||
'@rspack/lite-tapable@1.1.0': {}
|
||||
@@ -6383,27 +6417,27 @@ snapshots:
|
||||
|
||||
'@types/bn.js@5.2.0':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/body-parser@1.19.6':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/buffer-json@2.0.3': {}
|
||||
|
||||
'@types/clean-css@4.2.11':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
source-map: 0.6.1
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/cors@2.8.19':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
dependencies:
|
||||
@@ -6411,7 +6445,7 @@ snapshots:
|
||||
|
||||
'@types/dns-packet@5.6.5':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/elliptic@6.4.18':
|
||||
dependencies:
|
||||
@@ -6419,7 +6453,7 @@ snapshots:
|
||||
|
||||
'@types/express-serve-static-core@5.1.0':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
'@types/qs': 6.14.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 1.2.1
|
||||
@@ -6433,7 +6467,7 @@ snapshots:
|
||||
'@types/fs-extra@11.0.4':
|
||||
dependencies:
|
||||
'@types/jsonfile': 6.1.4
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/hast@3.0.4':
|
||||
dependencies:
|
||||
@@ -6455,7 +6489,7 @@ snapshots:
|
||||
|
||||
'@types/jsonfile@6.1.4':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/mdast@4.0.4':
|
||||
dependencies:
|
||||
@@ -6469,11 +6503,11 @@ snapshots:
|
||||
|
||||
'@types/node-forge@1.3.14':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/node@16.9.1': {}
|
||||
|
||||
'@types/node@24.10.1':
|
||||
'@types/node@25.0.2':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
@@ -6491,22 +6525,22 @@ snapshots:
|
||||
|
||||
'@types/send@1.2.1':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/serve-static@2.2.0':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.5
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/symbol-tree@3.2.5': {}
|
||||
|
||||
'@types/tar-stream@3.1.4':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/through2@2.0.41':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/trusted-types@2.0.7': {}
|
||||
|
||||
@@ -6530,11 +6564,11 @@ snapshots:
|
||||
|
||||
'@types/ws@8.18.1':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
|
||||
'@types/yauzl@2.10.3':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
optional: true
|
||||
|
||||
'@ungap/structured-clone@1.3.0': {}
|
||||
@@ -6951,7 +6985,7 @@ snapshots:
|
||||
engine.io@6.6.4:
|
||||
dependencies:
|
||||
'@types/cors': 2.8.19
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.2
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
cookie: 0.7.2
|
||||
@@ -6987,34 +7021,34 @@ snapshots:
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
|
||||
esbuild@0.27.0:
|
||||
esbuild@0.27.1:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.27.0
|
||||
'@esbuild/android-arm': 0.27.0
|
||||
'@esbuild/android-arm64': 0.27.0
|
||||
'@esbuild/android-x64': 0.27.0
|
||||
'@esbuild/darwin-arm64': 0.27.0
|
||||
'@esbuild/darwin-x64': 0.27.0
|
||||
'@esbuild/freebsd-arm64': 0.27.0
|
||||
'@esbuild/freebsd-x64': 0.27.0
|
||||
'@esbuild/linux-arm': 0.27.0
|
||||
'@esbuild/linux-arm64': 0.27.0
|
||||
'@esbuild/linux-ia32': 0.27.0
|
||||
'@esbuild/linux-loong64': 0.27.0
|
||||
'@esbuild/linux-mips64el': 0.27.0
|
||||
'@esbuild/linux-ppc64': 0.27.0
|
||||
'@esbuild/linux-riscv64': 0.27.0
|
||||
'@esbuild/linux-s390x': 0.27.0
|
||||
'@esbuild/linux-x64': 0.27.0
|
||||
'@esbuild/netbsd-arm64': 0.27.0
|
||||
'@esbuild/netbsd-x64': 0.27.0
|
||||
'@esbuild/openbsd-arm64': 0.27.0
|
||||
'@esbuild/openbsd-x64': 0.27.0
|
||||
'@esbuild/openharmony-arm64': 0.27.0
|
||||
'@esbuild/sunos-x64': 0.27.0
|
||||
'@esbuild/win32-arm64': 0.27.0
|
||||
'@esbuild/win32-ia32': 0.27.0
|
||||
'@esbuild/win32-x64': 0.27.0
|
||||
'@esbuild/aix-ppc64': 0.27.1
|
||||
'@esbuild/android-arm': 0.27.1
|
||||
'@esbuild/android-arm64': 0.27.1
|
||||
'@esbuild/android-x64': 0.27.1
|
||||
'@esbuild/darwin-arm64': 0.27.1
|
||||
'@esbuild/darwin-x64': 0.27.1
|
||||
'@esbuild/freebsd-arm64': 0.27.1
|
||||
'@esbuild/freebsd-x64': 0.27.1
|
||||
'@esbuild/linux-arm': 0.27.1
|
||||
'@esbuild/linux-arm64': 0.27.1
|
||||
'@esbuild/linux-ia32': 0.27.1
|
||||
'@esbuild/linux-loong64': 0.27.1
|
||||
'@esbuild/linux-mips64el': 0.27.1
|
||||
'@esbuild/linux-ppc64': 0.27.1
|
||||
'@esbuild/linux-riscv64': 0.27.1
|
||||
'@esbuild/linux-s390x': 0.27.1
|
||||
'@esbuild/linux-x64': 0.27.1
|
||||
'@esbuild/netbsd-arm64': 0.27.1
|
||||
'@esbuild/netbsd-x64': 0.27.1
|
||||
'@esbuild/openbsd-arm64': 0.27.1
|
||||
'@esbuild/openbsd-x64': 0.27.1
|
||||
'@esbuild/openharmony-arm64': 0.27.1
|
||||
'@esbuild/sunos-x64': 0.27.1
|
||||
'@esbuild/win32-arm64': 0.27.1
|
||||
'@esbuild/win32-ia32': 0.27.1
|
||||
'@esbuild/win32-x64': 0.27.1
|
||||
|
||||
escalade@3.2.0: {}
|
||||
|
||||
@@ -8826,7 +8860,7 @@ snapshots:
|
||||
|
||||
tsx@4.21.0:
|
||||
dependencies:
|
||||
esbuild: 0.27.0
|
||||
esbuild: 0.27.1
|
||||
get-tsconfig: 4.13.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
184
readme.md
184
readme.md
@@ -1,21 +1,31 @@
|
||||
# @push.rocks/smartagent
|
||||
A dual-agent agentic framework with Driver and Guardian agents for safe, policy-controlled AI task execution.
|
||||
|
||||
A dual-agent agentic framework with **Driver** and **Guardian** agents for safe, policy-controlled AI task execution. 🤖🛡️
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install @push.rocks/smartagent
|
||||
# or
|
||||
pnpm install @push.rocks/smartagent
|
||||
```
|
||||
|
||||
## Issue Reporting and Security
|
||||
|
||||
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
||||
|
||||
## Overview
|
||||
|
||||
SmartAgent implements a dual-agent architecture:
|
||||
SmartAgent implements a **dual-agent architecture** where AI safety isn't just an afterthought—it's baked into the core design:
|
||||
|
||||
- **Driver Agent**: Executes tasks, reasons about goals, and proposes tool calls
|
||||
- **Guardian Agent**: Evaluates tool call proposals against a policy prompt, approving or rejecting with feedback
|
||||
- **🎯 Driver Agent**: The executor. Reasons about goals, plans steps, and proposes tool calls
|
||||
- **🛡️ Guardian Agent**: The gatekeeper. Evaluates every tool call against your policy, approving or rejecting with feedback
|
||||
|
||||
This design ensures safe tool use through AI-based policy evaluation rather than rigid programmatic rules.
|
||||
This design ensures safe tool use through **AI-based policy evaluation** rather than rigid programmatic rules. The Guardian can understand context, nuance, and intent—catching dangerous operations that simple regex or allowlists would miss.
|
||||
|
||||
### Why Dual-Agent?
|
||||
|
||||
Traditional AI agents have a fundamental problem: they're given tools and expected to use them responsibly. SmartAgent adds a second AI specifically trained to evaluate whether each action is safe and appropriate. Think of it as separation of concerns, but for AI safety.
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -89,8 +99,11 @@ await orchestrator.stop();
|
||||
|
||||
## Standard Tools
|
||||
|
||||
### FilesystemTool
|
||||
File and directory operations using `@push.rocks/smartfs`.
|
||||
SmartAgent comes with five battle-tested tools out of the box:
|
||||
|
||||
### 🗂️ FilesystemTool
|
||||
|
||||
File and directory operations powered by `@push.rocks/smartfs`.
|
||||
|
||||
**Actions**: `read`, `write`, `append`, `list`, `delete`, `exists`, `stat`, `copy`, `move`, `mkdir`
|
||||
|
||||
@@ -104,7 +117,15 @@ File and directory operations using `@push.rocks/smartfs`.
|
||||
</tool_call>
|
||||
```
|
||||
|
||||
### HttpTool
|
||||
**Scoped Filesystem**: Lock file operations to a specific directory:
|
||||
|
||||
```typescript
|
||||
// Only allow access within a specific directory
|
||||
orchestrator.registerScopedFilesystemTool('/home/user/workspace');
|
||||
```
|
||||
|
||||
### 🌐 HttpTool
|
||||
|
||||
HTTP requests using `@push.rocks/smartrequest`.
|
||||
|
||||
**Actions**: `get`, `post`, `put`, `patch`, `delete`
|
||||
@@ -113,13 +134,14 @@ HTTP requests using `@push.rocks/smartrequest`.
|
||||
<tool_call>
|
||||
<tool>http</tool>
|
||||
<action>get</action>
|
||||
<params>{"url": "https://api.example.com/data"}</params>
|
||||
<params>{"url": "https://api.example.com/data", "headers": {"Authorization": "Bearer token"}}</params>
|
||||
<reasoning>Fetching data from the API endpoint</reasoning>
|
||||
</tool_call>
|
||||
```
|
||||
|
||||
### ShellTool
|
||||
Secure shell command execution using `@push.rocks/smartshell` with `execSpawn` (no shell injection).
|
||||
### 💻 ShellTool
|
||||
|
||||
Secure shell command execution using `@push.rocks/smartshell` with `execSpawn` (no shell injection possible).
|
||||
|
||||
**Actions**: `execute`, `which`
|
||||
|
||||
@@ -132,7 +154,10 @@ Secure shell command execution using `@push.rocks/smartshell` with `execSpawn` (
|
||||
</tool_call>
|
||||
```
|
||||
|
||||
### BrowserTool
|
||||
> 🔒 **Security Note**: The shell tool uses `execSpawn` with `shell: false`, meaning command and arguments are passed separately. This makes shell injection attacks impossible.
|
||||
|
||||
### 🌍 BrowserTool
|
||||
|
||||
Web page interaction using `@push.rocks/smartbrowser` (Puppeteer-based).
|
||||
|
||||
**Actions**: `screenshot`, `pdf`, `evaluate`, `getPageContent`
|
||||
@@ -146,17 +171,18 @@ Web page interaction using `@push.rocks/smartbrowser` (Puppeteer-based).
|
||||
</tool_call>
|
||||
```
|
||||
|
||||
### DenoTool
|
||||
Execute TypeScript/JavaScript code in a sandboxed Deno environment using `@push.rocks/smartdeno`.
|
||||
### 🦕 DenoTool
|
||||
|
||||
Execute TypeScript/JavaScript code in a **sandboxed Deno environment** with fine-grained permission control.
|
||||
|
||||
**Actions**: `execute`, `executeWithResult`
|
||||
|
||||
**Permissions**: `all`, `env`, `ffi`, `hrtime`, `net`, `read`, `run`, `sys`, `write`
|
||||
|
||||
By default, code runs fully sandboxed with no permissions. Permissions must be explicitly requested.
|
||||
By default, code runs **fully sandboxed with no permissions**. Permissions must be explicitly requested and are subject to Guardian approval.
|
||||
|
||||
```typescript
|
||||
// Simple code execution
|
||||
// Simple code execution (sandboxed, no permissions)
|
||||
<tool_call>
|
||||
<tool>deno</tool>
|
||||
<action>execute</action>
|
||||
@@ -188,7 +214,10 @@ By default, code runs fully sandboxed with no permissions. Permissions must be e
|
||||
|
||||
## Guardian Policy Examples
|
||||
|
||||
### Strict Security Policy
|
||||
The Guardian's power comes from your policy. Here are battle-tested examples:
|
||||
|
||||
### 🔐 Strict Security Policy
|
||||
|
||||
```typescript
|
||||
const securityPolicy = `
|
||||
SECURITY POLICY:
|
||||
@@ -204,7 +233,8 @@ When rejecting, always explain:
|
||||
`;
|
||||
```
|
||||
|
||||
### Development Environment Policy
|
||||
### 🛠️ Development Environment Policy
|
||||
|
||||
```typescript
|
||||
const devPolicy = `
|
||||
DEVELOPMENT POLICY:
|
||||
@@ -221,7 +251,8 @@ Always verify:
|
||||
`;
|
||||
```
|
||||
|
||||
### Deno Code Execution Policy
|
||||
### 🦕 Deno Code Execution Policy
|
||||
|
||||
```typescript
|
||||
const denoPolicy = `
|
||||
DENO CODE EXECUTION POLICY:
|
||||
@@ -253,6 +284,9 @@ interface IDualAgentOptions {
|
||||
groqToken?: string;
|
||||
xaiToken?: string;
|
||||
|
||||
// Use existing SmartAi instance (optional - avoids duplicate providers)
|
||||
smartAiInstance?: SmartAi;
|
||||
|
||||
// Provider selection
|
||||
defaultProvider?: TProvider; // For both Driver and Guardian
|
||||
guardianProvider?: TProvider; // Optional: separate provider for Guardian
|
||||
@@ -278,6 +312,14 @@ interface IDualAgentRunResult {
|
||||
history: IAgentMessage[]; // Full conversation history
|
||||
status: TDualAgentRunStatus; // 'completed' | 'max_iterations_reached' | etc.
|
||||
}
|
||||
|
||||
type TDualAgentRunStatus =
|
||||
| 'completed'
|
||||
| 'in_progress'
|
||||
| 'max_iterations_reached'
|
||||
| 'max_rejections_reached'
|
||||
| 'clarification_needed'
|
||||
| 'error';
|
||||
```
|
||||
|
||||
## Custom Tools
|
||||
@@ -306,10 +348,12 @@ class MyCustomTool extends BaseToolWrapper {
|
||||
];
|
||||
|
||||
public async initialize(): Promise<void> {
|
||||
// Setup your tool (called when orchestrator.start() runs)
|
||||
this.isInitialized = true;
|
||||
}
|
||||
|
||||
public async cleanup(): Promise<void> {
|
||||
// Cleanup resources (called when orchestrator.stop() runs)
|
||||
this.isInitialized = false;
|
||||
}
|
||||
|
||||
@@ -327,6 +371,7 @@ class MyCustomTool extends BaseToolWrapper {
|
||||
return { success: false, error: 'Unknown action' };
|
||||
}
|
||||
|
||||
// Human-readable summary for Guardian evaluation
|
||||
public getCallSummary(action: string, params: Record<string, unknown>): string {
|
||||
return `Custom action "${action}" with input "${params.input}"`;
|
||||
}
|
||||
@@ -336,32 +381,111 @@ class MyCustomTool extends BaseToolWrapper {
|
||||
orchestrator.registerTool(new MyCustomTool());
|
||||
```
|
||||
|
||||
## Reusing SmartAi Instances
|
||||
|
||||
If you already have a `@push.rocks/smartai` instance, you can share it:
|
||||
|
||||
```typescript
|
||||
import { SmartAi } from '@push.rocks/smartai';
|
||||
import { DualAgentOrchestrator } from '@push.rocks/smartagent';
|
||||
|
||||
const smartai = new SmartAi({ openaiToken: 'sk-...' });
|
||||
await smartai.start();
|
||||
|
||||
const orchestrator = new DualAgentOrchestrator({
|
||||
smartAiInstance: smartai, // Reuse existing instance
|
||||
guardianPolicyPrompt: '...',
|
||||
});
|
||||
|
||||
await orchestrator.start();
|
||||
// ... use orchestrator ...
|
||||
await orchestrator.stop();
|
||||
|
||||
// SmartAi instance lifecycle is managed separately
|
||||
await smartai.stop();
|
||||
```
|
||||
|
||||
## Supported Providers
|
||||
|
||||
SmartAgent supports all providers from `@push.rocks/smartai`:
|
||||
|
||||
| Provider | Driver | Guardian |
|
||||
|----------|:------:|:--------:|
|
||||
| OpenAI | Yes | Yes |
|
||||
| Anthropic | Yes | Yes |
|
||||
| Perplexity | Yes | Yes |
|
||||
| Groq | Yes | Yes |
|
||||
| Ollama | Yes | Yes |
|
||||
| XAI | Yes | Yes |
|
||||
| OpenAI | ✅ | ✅ |
|
||||
| Anthropic | ✅ | ✅ |
|
||||
| Perplexity | ✅ | ✅ |
|
||||
| Groq | ✅ | ✅ |
|
||||
| Ollama | ✅ | ✅ |
|
||||
| XAI | ✅ | ✅ |
|
||||
| Exo | ✅ | ✅ |
|
||||
|
||||
**💡 Pro tip**: Use a faster/cheaper model for Guardian (like Groq) and a more capable model for Driver:
|
||||
|
||||
```typescript
|
||||
const orchestrator = new DualAgentOrchestrator({
|
||||
openaiToken: 'sk-...',
|
||||
groqToken: 'gsk-...',
|
||||
defaultProvider: 'openai', // Driver uses OpenAI
|
||||
guardianProvider: 'groq', // Guardian uses Groq (faster, cheaper)
|
||||
guardianPolicyPrompt: '...',
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### DualAgentOrchestrator
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `start()` | Initialize all tools and AI providers |
|
||||
| `stop()` | Cleanup all tools and resources |
|
||||
| `run(task: string)` | Execute a task and return result |
|
||||
| `continueTask(input: string)` | Continue a task with user input |
|
||||
| `registerTool(tool)` | Register a custom tool |
|
||||
| `registerStandardTools()` | Register all built-in tools |
|
||||
| `registerScopedFilesystemTool(basePath)` | Register filesystem tool with path restriction |
|
||||
| `setGuardianPolicy(policy)` | Update Guardian policy at runtime |
|
||||
| `getHistory()` | Get conversation history |
|
||||
| `getToolNames()` | Get list of registered tool names |
|
||||
| `isActive()` | Check if orchestrator is running |
|
||||
|
||||
### Exports
|
||||
|
||||
```typescript
|
||||
// Main classes
|
||||
export { DualAgentOrchestrator } from '@push.rocks/smartagent';
|
||||
export { DriverAgent } from '@push.rocks/smartagent';
|
||||
export { GuardianAgent } from '@push.rocks/smartagent';
|
||||
|
||||
// Tools
|
||||
export { BaseToolWrapper } from '@push.rocks/smartagent';
|
||||
export { FilesystemTool } from '@push.rocks/smartagent';
|
||||
export { HttpTool } from '@push.rocks/smartagent';
|
||||
export { ShellTool } from '@push.rocks/smartagent';
|
||||
export { BrowserTool } from '@push.rocks/smartagent';
|
||||
export { DenoTool } from '@push.rocks/smartagent';
|
||||
|
||||
// Types and interfaces
|
||||
export * from '@push.rocks/smartagent'; // All interfaces
|
||||
```
|
||||
|
||||
## License and Legal Information
|
||||
|
||||
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
||||
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
|
||||
|
||||
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
||||
|
||||
### Trademarks
|
||||
|
||||
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
|
||||
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
||||
|
||||
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
||||
|
||||
### Company Information
|
||||
|
||||
Task Venture Capital GmbH
|
||||
Registered at District court Bremen HRB 35230 HB, Germany
|
||||
Task Venture Capital GmbH
|
||||
Registered at District Court Bremen HRB 35230 HB, Germany
|
||||
|
||||
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||||
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
||||
|
||||
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartagent',
|
||||
version: '1.1.0',
|
||||
version: '1.1.1',
|
||||
description: 'an agentic framework built on top of @push.rocks/smartai'
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export { GuardianAgent } from './smartagent.classes.guardianagent.js';
|
||||
export { BaseToolWrapper } from './smartagent.tools.base.js';
|
||||
|
||||
// Export standard tools
|
||||
export { FilesystemTool } from './smartagent.tools.filesystem.js';
|
||||
export { FilesystemTool, type IFilesystemToolOptions } from './smartagent.tools.filesystem.js';
|
||||
export { HttpTool } from './smartagent.tools.http.js';
|
||||
export { ShellTool } from './smartagent.tools.shell.js';
|
||||
export { BrowserTool } from './smartagent.tools.browser.js';
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
// node native
|
||||
import * as path from 'path';
|
||||
|
||||
export { path };
|
||||
|
||||
// third party
|
||||
import { minimatch } from 'minimatch';
|
||||
|
||||
export { minimatch };
|
||||
|
||||
// @push.rocks scope
|
||||
import * as smartai from '@push.rocks/smartai';
|
||||
import * as smartdeno from '@push.rocks/smartdeno';
|
||||
|
||||
@@ -2,6 +2,16 @@ import * as plugins from './plugins.js';
|
||||
import * as interfaces from './smartagent.interfaces.js';
|
||||
import type { BaseToolWrapper } from './smartagent.tools.base.js';
|
||||
|
||||
/**
|
||||
* Options for configuring the DriverAgent
|
||||
*/
|
||||
export interface IDriverAgentOptions {
|
||||
/** Custom system message for the driver */
|
||||
systemMessage?: string;
|
||||
/** Maximum history messages to pass to API (default: 20). Set to 0 for unlimited. */
|
||||
maxHistoryMessages?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* DriverAgent - Executes tasks by reasoning and proposing tool calls
|
||||
* Works in conjunction with GuardianAgent for approval
|
||||
@@ -9,15 +19,24 @@ import type { BaseToolWrapper } from './smartagent.tools.base.js';
|
||||
export class DriverAgent {
|
||||
private provider: plugins.smartai.MultiModalModel;
|
||||
private systemMessage: string;
|
||||
private maxHistoryMessages: number;
|
||||
private messageHistory: plugins.smartai.ChatMessage[] = [];
|
||||
private tools: Map<string, BaseToolWrapper> = new Map();
|
||||
|
||||
constructor(
|
||||
provider: plugins.smartai.MultiModalModel,
|
||||
systemMessage?: string
|
||||
options?: IDriverAgentOptions | string
|
||||
) {
|
||||
this.provider = provider;
|
||||
this.systemMessage = systemMessage || this.getDefaultSystemMessage();
|
||||
|
||||
// Support both legacy string systemMessage and new options object
|
||||
if (typeof options === 'string') {
|
||||
this.systemMessage = options || this.getDefaultSystemMessage();
|
||||
this.maxHistoryMessages = 20;
|
||||
} else {
|
||||
this.systemMessage = options?.systemMessage || this.getDefaultSystemMessage();
|
||||
this.maxHistoryMessages = options?.maxHistoryMessages ?? 20;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,8 +60,14 @@ export class DriverAgent {
|
||||
// Reset message history
|
||||
this.messageHistory = [];
|
||||
|
||||
// Build the user message
|
||||
const userMessage = `TASK: ${task}\n\nAnalyze this task and determine what actions are needed. If you need to use a tool, provide a tool call proposal.`;
|
||||
// Build the user message based on available tools
|
||||
const hasTools = this.tools.size > 0;
|
||||
let userMessage: string;
|
||||
if (hasTools) {
|
||||
userMessage = `TASK: ${task}\n\nAnalyze this task and determine what actions are needed. If you need to use a tool, provide a tool call proposal.`;
|
||||
} else {
|
||||
userMessage = `TASK: ${task}\n\nComplete this task directly. When done, wrap your final output in <task_complete>your output here</task_complete> tags.`;
|
||||
}
|
||||
|
||||
// Add to history
|
||||
this.messageHistory.push({
|
||||
@@ -50,9 +75,15 @@ export class DriverAgent {
|
||||
content: userMessage,
|
||||
});
|
||||
|
||||
// Build tool descriptions for the system message
|
||||
const toolDescriptions = this.buildToolDescriptions();
|
||||
const fullSystemMessage = `${this.systemMessage}\n\n## Available Tools\n${toolDescriptions}`;
|
||||
// Build the system message - adapt based on available tools
|
||||
let fullSystemMessage: string;
|
||||
if (hasTools) {
|
||||
const toolDescriptions = this.buildToolDescriptions();
|
||||
fullSystemMessage = `${this.systemMessage}\n\n## Available Tools\n${toolDescriptions}`;
|
||||
} else {
|
||||
// Use a simpler system message when no tools are available
|
||||
fullSystemMessage = this.getNoToolsSystemMessage();
|
||||
}
|
||||
|
||||
// Get response from provider
|
||||
const response = await this.provider.chat({
|
||||
@@ -83,12 +114,30 @@ export class DriverAgent {
|
||||
content: message,
|
||||
});
|
||||
|
||||
// Build tool descriptions for the system message
|
||||
const toolDescriptions = this.buildToolDescriptions();
|
||||
const fullSystemMessage = `${this.systemMessage}\n\n## Available Tools\n${toolDescriptions}`;
|
||||
// Build the system message - adapt based on available tools
|
||||
const hasTools = this.tools.size > 0;
|
||||
let fullSystemMessage: string;
|
||||
if (hasTools) {
|
||||
const toolDescriptions = this.buildToolDescriptions();
|
||||
fullSystemMessage = `${this.systemMessage}\n\n## Available Tools\n${toolDescriptions}`;
|
||||
} else {
|
||||
fullSystemMessage = this.getNoToolsSystemMessage();
|
||||
}
|
||||
|
||||
// Get response from provider (pass all but last user message as history)
|
||||
const historyForChat = this.messageHistory.slice(0, -1);
|
||||
// Get response from provider with history windowing
|
||||
// Keep original task and most recent messages to avoid token explosion
|
||||
let historyForChat: plugins.smartai.ChatMessage[];
|
||||
const fullHistory = this.messageHistory.slice(0, -1); // Exclude the just-added message
|
||||
|
||||
if (this.maxHistoryMessages > 0 && fullHistory.length > this.maxHistoryMessages) {
|
||||
// Keep the original task (first message) and most recent messages
|
||||
historyForChat = [
|
||||
fullHistory[0], // Original task
|
||||
...fullHistory.slice(-(this.maxHistoryMessages - 1)), // Recent messages
|
||||
];
|
||||
} else {
|
||||
historyForChat = fullHistory;
|
||||
}
|
||||
|
||||
const response = await this.provider.chat({
|
||||
systemMessage: fullSystemMessage,
|
||||
@@ -312,6 +361,35 @@ When you need to use a tool, output a tool call proposal in this format:
|
||||
- If you need clarification, ask using <needs_clarification>your question</needs_clarification>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the system message when no tools are available
|
||||
* Used for direct task completion without tool usage
|
||||
*/
|
||||
private getNoToolsSystemMessage(): string {
|
||||
// Use custom system message if provided, otherwise use a simple default
|
||||
if (this.systemMessage && this.systemMessage !== this.getDefaultSystemMessage()) {
|
||||
return this.systemMessage;
|
||||
}
|
||||
|
||||
return `You are an AI assistant that completes tasks directly.
|
||||
|
||||
## Your Role
|
||||
You analyze tasks and provide complete, high-quality outputs.
|
||||
|
||||
## Output Format
|
||||
When you have completed the task, wrap your final output in task_complete tags:
|
||||
|
||||
<task_complete>
|
||||
Your complete output here
|
||||
</task_complete>
|
||||
|
||||
## Guidelines
|
||||
1. Analyze the task requirements carefully
|
||||
2. Provide a complete and accurate response
|
||||
3. Always wrap your final output in <task_complete></task_complete> tags
|
||||
4. If you need clarification, ask using <needs_clarification>your question</needs_clarification>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the conversation state
|
||||
*/
|
||||
|
||||
@@ -23,27 +23,27 @@ export class DualAgentOrchestrator {
|
||||
private tools: Map<string, BaseToolWrapper> = new Map();
|
||||
private isRunning = false;
|
||||
private conversationHistory: interfaces.IAgentMessage[] = [];
|
||||
private ownsSmartAi = true; // true if we created the SmartAi instance, false if it was provided
|
||||
|
||||
constructor(options: interfaces.IDualAgentOptions) {
|
||||
this.options = {
|
||||
maxIterations: 20,
|
||||
maxConsecutiveRejections: 3,
|
||||
defaultProvider: 'openai',
|
||||
maxResultChars: 15000,
|
||||
maxHistoryMessages: 20,
|
||||
...options,
|
||||
};
|
||||
|
||||
// Create SmartAi instance
|
||||
this.smartai = new plugins.smartai.SmartAi(options);
|
||||
|
||||
// Get providers
|
||||
this.driverProvider = this.getProviderByName(this.options.defaultProvider!);
|
||||
this.guardianProvider = this.options.guardianProvider
|
||||
? this.getProviderByName(this.options.guardianProvider)
|
||||
: this.driverProvider;
|
||||
|
||||
// Create agents
|
||||
this.driver = new DriverAgent(this.driverProvider, options.driverSystemMessage);
|
||||
this.guardian = new GuardianAgent(this.guardianProvider, options.guardianPolicyPrompt);
|
||||
// Use existing SmartAi instance if provided, otherwise create a new one
|
||||
if (options.smartAiInstance) {
|
||||
this.smartai = options.smartAiInstance;
|
||||
this.ownsSmartAi = false; // Don't manage lifecycle of provided instance
|
||||
} else {
|
||||
this.smartai = new plugins.smartai.SmartAi(options);
|
||||
this.ownsSmartAi = true;
|
||||
}
|
||||
// Note: Don't access providers here - they don't exist until start() is called
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,13 +70,72 @@ export class DualAgentOrchestrator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a progress event if callback is configured
|
||||
*/
|
||||
private emitProgress(event: Omit<interfaces.IProgressEvent, 'timestamp' | 'logLevel' | 'logMessage'>): void {
|
||||
if (this.options.onProgress) {
|
||||
const prefix = this.options.logPrefix ? `${this.options.logPrefix} ` : '';
|
||||
const { logLevel, logMessage } = this.formatProgressEvent(event, prefix);
|
||||
|
||||
this.options.onProgress({
|
||||
...event,
|
||||
timestamp: new Date(),
|
||||
logLevel,
|
||||
logMessage,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a progress event into a log level and message
|
||||
*/
|
||||
private formatProgressEvent(
|
||||
event: Omit<interfaces.IProgressEvent, 'timestamp' | 'logLevel' | 'logMessage'>,
|
||||
prefix: string
|
||||
): { logLevel: interfaces.TLogLevel; logMessage: string } {
|
||||
switch (event.type) {
|
||||
case 'task_started':
|
||||
return { logLevel: 'info', logMessage: `${prefix}Task started` };
|
||||
case 'iteration_started':
|
||||
return { logLevel: 'info', logMessage: `${prefix}Iteration ${event.iteration}/${event.maxIterations}` };
|
||||
case 'tool_proposed':
|
||||
return { logLevel: 'info', logMessage: `${prefix} → Proposing: ${event.toolName}.${event.action}` };
|
||||
case 'guardian_evaluating':
|
||||
return { logLevel: 'info', logMessage: `${prefix} ⏳ Guardian evaluating...` };
|
||||
case 'tool_approved':
|
||||
return { logLevel: 'info', logMessage: `${prefix} ✓ Approved: ${event.toolName}.${event.action}` };
|
||||
case 'tool_rejected':
|
||||
return { logLevel: 'warn', logMessage: `${prefix} ✗ Rejected: ${event.toolName}.${event.action} - ${event.reason}` };
|
||||
case 'tool_executing':
|
||||
return { logLevel: 'info', logMessage: `${prefix} ⚡ Executing: ${event.toolName}.${event.action}...` };
|
||||
case 'tool_completed':
|
||||
return { logLevel: 'info', logMessage: `${prefix} ✓ Completed: ${event.message}` };
|
||||
case 'task_completed':
|
||||
return { logLevel: 'success', logMessage: `${prefix}Task completed in ${event.iteration} iterations` };
|
||||
case 'clarification_needed':
|
||||
return { logLevel: 'warn', logMessage: `${prefix}Clarification needed from user` };
|
||||
case 'max_iterations':
|
||||
return { logLevel: 'error', logMessage: `${prefix}${event.message}` };
|
||||
case 'max_rejections':
|
||||
return { logLevel: 'error', logMessage: `${prefix}${event.message}` };
|
||||
default:
|
||||
return { logLevel: 'info', logMessage: `${prefix}${event.type}` };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom tool
|
||||
*/
|
||||
public registerTool(tool: BaseToolWrapper): void {
|
||||
this.tools.set(tool.name, tool);
|
||||
this.driver.registerTool(tool);
|
||||
this.guardian.registerTool(tool);
|
||||
// Register with agents if they exist (they're created in start())
|
||||
if (this.driver) {
|
||||
this.driver.registerTool(tool);
|
||||
}
|
||||
if (this.guardian) {
|
||||
this.guardian.registerTool(tool);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,12 +155,43 @@ export class DualAgentOrchestrator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a scoped filesystem tool that can only access files within the specified directory
|
||||
* @param basePath The directory to scope filesystem operations to
|
||||
* @param excludePatterns Optional glob patterns to exclude from listings (e.g., ['.nogit/**', 'node_modules/**'])
|
||||
*/
|
||||
public registerScopedFilesystemTool(basePath: string, excludePatterns?: string[]): void {
|
||||
const scopedTool = new FilesystemTool({ basePath, excludePatterns });
|
||||
this.registerTool(scopedTool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all tools (eager loading)
|
||||
*/
|
||||
public async start(): Promise<void> {
|
||||
// Start smartai
|
||||
await this.smartai.start();
|
||||
// Start smartai only if we created it (external instances should already be started)
|
||||
if (this.ownsSmartAi) {
|
||||
await this.smartai.start();
|
||||
}
|
||||
|
||||
// NOW get providers (after they've been initialized by smartai.start())
|
||||
this.driverProvider = this.getProviderByName(this.options.defaultProvider!);
|
||||
this.guardianProvider = this.options.guardianProvider
|
||||
? this.getProviderByName(this.options.guardianProvider)
|
||||
: this.driverProvider;
|
||||
|
||||
// NOW create agents with initialized providers
|
||||
this.driver = new DriverAgent(this.driverProvider, {
|
||||
systemMessage: this.options.driverSystemMessage,
|
||||
maxHistoryMessages: this.options.maxHistoryMessages,
|
||||
});
|
||||
this.guardian = new GuardianAgent(this.guardianProvider, this.options.guardianPolicyPrompt);
|
||||
|
||||
// Register any tools that were added before start() with the agents
|
||||
for (const tool of this.tools.values()) {
|
||||
this.driver.registerTool(tool);
|
||||
this.guardian.registerTool(tool);
|
||||
}
|
||||
|
||||
// Initialize all tools
|
||||
const initPromises: Promise<void>[] = [];
|
||||
@@ -124,9 +214,16 @@ export class DualAgentOrchestrator {
|
||||
}
|
||||
|
||||
await Promise.all(cleanupPromises);
|
||||
await this.smartai.stop();
|
||||
|
||||
// Only stop smartai if we created it (don't stop external instances)
|
||||
if (this.ownsSmartAi) {
|
||||
await this.smartai.stop();
|
||||
}
|
||||
|
||||
this.isRunning = false;
|
||||
this.driver.reset();
|
||||
if (this.driver) {
|
||||
this.driver.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,6 +250,12 @@ export class DualAgentOrchestrator {
|
||||
let driverResponse = await this.driver.startTask(task);
|
||||
this.conversationHistory.push(driverResponse);
|
||||
|
||||
// Emit task started event
|
||||
this.emitProgress({
|
||||
type: 'task_started',
|
||||
message: task.length > 100 ? task.substring(0, 100) + '...' : task,
|
||||
});
|
||||
|
||||
while (
|
||||
iterations < this.options.maxIterations! &&
|
||||
consecutiveRejections < this.options.maxConsecutiveRejections! &&
|
||||
@@ -160,15 +263,36 @@ export class DualAgentOrchestrator {
|
||||
) {
|
||||
iterations++;
|
||||
|
||||
// Emit iteration started event
|
||||
this.emitProgress({
|
||||
type: 'iteration_started',
|
||||
iteration: iterations,
|
||||
maxIterations: this.options.maxIterations,
|
||||
});
|
||||
|
||||
// Check if task is complete
|
||||
if (this.driver.isTaskComplete(driverResponse.content)) {
|
||||
completed = true;
|
||||
finalResult = this.driver.extractTaskResult(driverResponse.content) || driverResponse.content;
|
||||
|
||||
// Emit task completed event
|
||||
this.emitProgress({
|
||||
type: 'task_completed',
|
||||
iteration: iterations,
|
||||
message: 'Task completed successfully',
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if driver needs clarification
|
||||
if (this.driver.needsClarification(driverResponse.content)) {
|
||||
// Emit clarification needed event
|
||||
this.emitProgress({
|
||||
type: 'clarification_needed',
|
||||
iteration: iterations,
|
||||
message: 'Driver needs clarification from user',
|
||||
});
|
||||
|
||||
// Return with clarification needed status
|
||||
return {
|
||||
success: false,
|
||||
@@ -195,6 +319,15 @@ export class DualAgentOrchestrator {
|
||||
// Process the first proposal (one at a time)
|
||||
const proposal = proposals[0];
|
||||
|
||||
// Emit tool proposed event
|
||||
this.emitProgress({
|
||||
type: 'tool_proposed',
|
||||
iteration: iterations,
|
||||
toolName: proposal.toolName,
|
||||
action: proposal.action,
|
||||
message: `${proposal.toolName}.${proposal.action}`,
|
||||
});
|
||||
|
||||
// Quick validation first
|
||||
const quickDecision = this.guardian.quickValidate(proposal);
|
||||
let decision: interfaces.IGuardianDecision;
|
||||
@@ -202,6 +335,14 @@ export class DualAgentOrchestrator {
|
||||
if (quickDecision) {
|
||||
decision = quickDecision;
|
||||
} else {
|
||||
// Emit guardian evaluating event
|
||||
this.emitProgress({
|
||||
type: 'guardian_evaluating',
|
||||
iteration: iterations,
|
||||
toolName: proposal.toolName,
|
||||
action: proposal.action,
|
||||
});
|
||||
|
||||
// Full AI evaluation
|
||||
decision = await this.guardian.evaluate(proposal, task);
|
||||
}
|
||||
@@ -209,6 +350,14 @@ export class DualAgentOrchestrator {
|
||||
if (decision.decision === 'approve') {
|
||||
consecutiveRejections = 0;
|
||||
|
||||
// Emit tool approved event
|
||||
this.emitProgress({
|
||||
type: 'tool_approved',
|
||||
iteration: iterations,
|
||||
toolName: proposal.toolName,
|
||||
action: proposal.action,
|
||||
});
|
||||
|
||||
// Execute the tool
|
||||
const tool = this.tools.get(proposal.toolName);
|
||||
if (!tool) {
|
||||
@@ -221,12 +370,48 @@ export class DualAgentOrchestrator {
|
||||
}
|
||||
|
||||
try {
|
||||
// Emit tool executing event
|
||||
this.emitProgress({
|
||||
type: 'tool_executing',
|
||||
iteration: iterations,
|
||||
toolName: proposal.toolName,
|
||||
action: proposal.action,
|
||||
});
|
||||
|
||||
const result = await tool.execute(proposal.action, proposal.params);
|
||||
|
||||
// Send result to driver
|
||||
const resultMessage = result.success
|
||||
? `TOOL RESULT (${proposal.toolName}.${proposal.action}):\n${JSON.stringify(result.result, null, 2)}`
|
||||
: `TOOL ERROR (${proposal.toolName}.${proposal.action}):\n${result.error}`;
|
||||
// Emit tool completed event
|
||||
this.emitProgress({
|
||||
type: 'tool_completed',
|
||||
iteration: iterations,
|
||||
toolName: proposal.toolName,
|
||||
action: proposal.action,
|
||||
message: result.success ? 'success' : result.error,
|
||||
});
|
||||
|
||||
// Build result message (prefer summary if provided, otherwise stringify result)
|
||||
let resultMessage: string;
|
||||
if (result.success) {
|
||||
if (result.summary) {
|
||||
// Use tool-provided summary
|
||||
resultMessage = `TOOL RESULT (${proposal.toolName}.${proposal.action}):\n${result.summary}`;
|
||||
} else {
|
||||
// Stringify and potentially truncate
|
||||
const resultStr = JSON.stringify(result.result, null, 2);
|
||||
const maxChars = this.options.maxResultChars ?? 15000;
|
||||
|
||||
if (maxChars > 0 && resultStr.length > maxChars) {
|
||||
// Truncate the result
|
||||
const truncated = resultStr.substring(0, maxChars);
|
||||
const omittedTokens = Math.round((resultStr.length - maxChars) / 4);
|
||||
resultMessage = `TOOL RESULT (${proposal.toolName}.${proposal.action}):\n${truncated}\n\n[... output truncated, ~${omittedTokens} tokens omitted. Use more specific parameters to reduce output size.]`;
|
||||
} else {
|
||||
resultMessage = `TOOL RESULT (${proposal.toolName}.${proposal.action}):\n${resultStr}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resultMessage = `TOOL ERROR (${proposal.toolName}.${proposal.action}):\n${result.error}`;
|
||||
}
|
||||
|
||||
this.conversationHistory.push({
|
||||
role: 'system',
|
||||
@@ -248,6 +433,15 @@ export class DualAgentOrchestrator {
|
||||
// Rejected
|
||||
consecutiveRejections++;
|
||||
|
||||
// Emit tool rejected event
|
||||
this.emitProgress({
|
||||
type: 'tool_rejected',
|
||||
iteration: iterations,
|
||||
toolName: proposal.toolName,
|
||||
action: proposal.action,
|
||||
reason: decision.reason,
|
||||
});
|
||||
|
||||
// Build rejection feedback
|
||||
let feedback = `TOOL CALL REJECTED by Guardian:\n`;
|
||||
feedback += `- Reason: ${decision.reason}\n`;
|
||||
@@ -279,8 +473,21 @@ export class DualAgentOrchestrator {
|
||||
if (!completed) {
|
||||
if (iterations >= this.options.maxIterations!) {
|
||||
status = 'max_iterations_reached';
|
||||
// Emit max iterations event
|
||||
this.emitProgress({
|
||||
type: 'max_iterations',
|
||||
iteration: iterations,
|
||||
maxIterations: this.options.maxIterations,
|
||||
message: `Maximum iterations (${this.options.maxIterations}) reached`,
|
||||
});
|
||||
} else if (consecutiveRejections >= this.options.maxConsecutiveRejections!) {
|
||||
status = 'max_rejections_reached';
|
||||
// Emit max rejections event
|
||||
this.emitProgress({
|
||||
type: 'max_rejections',
|
||||
iteration: iterations,
|
||||
message: `Maximum consecutive rejections (${this.options.maxConsecutiveRejections}) reached`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import * as plugins from './plugins.js';
|
||||
* Configuration options for the DualAgentOrchestrator
|
||||
*/
|
||||
export interface IDualAgentOptions extends plugins.smartai.ISmartAiOptions {
|
||||
/** Existing SmartAi instance to reuse (avoids creating duplicate providers) */
|
||||
smartAiInstance?: plugins.smartai.SmartAi;
|
||||
/** Name of the agent system */
|
||||
name?: string;
|
||||
/** Default AI provider for both Driver and Guardian */
|
||||
@@ -24,6 +26,14 @@ export interface IDualAgentOptions extends plugins.smartai.ISmartAiOptions {
|
||||
maxConsecutiveRejections?: number;
|
||||
/** Enable verbose logging */
|
||||
verbose?: boolean;
|
||||
/** Maximum characters for tool result output before truncation (default: 15000). Set to 0 to disable. */
|
||||
maxResultChars?: number;
|
||||
/** Maximum history messages to pass to API (default: 20). Set to 0 for unlimited. */
|
||||
maxHistoryMessages?: number;
|
||||
/** Optional callback for live progress updates during execution */
|
||||
onProgress?: (event: IProgressEvent) => void;
|
||||
/** Prefix for log messages (e.g., "[README]", "[Commit]"). Default: empty */
|
||||
logPrefix?: string;
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -82,6 +92,8 @@ export interface IToolExecutionResult {
|
||||
success: boolean;
|
||||
result?: unknown;
|
||||
error?: string;
|
||||
/** Optional human-readable summary for history (if provided, used instead of full result) */
|
||||
summary?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,6 +205,58 @@ export interface IDualAgentRunResult {
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Progress Event Interfaces
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* Progress event types for live feedback during agent execution
|
||||
*/
|
||||
export type TProgressEventType =
|
||||
| 'task_started'
|
||||
| 'iteration_started'
|
||||
| 'tool_proposed'
|
||||
| 'guardian_evaluating'
|
||||
| 'tool_approved'
|
||||
| 'tool_rejected'
|
||||
| 'tool_executing'
|
||||
| 'tool_completed'
|
||||
| 'task_completed'
|
||||
| 'clarification_needed'
|
||||
| 'max_iterations'
|
||||
| 'max_rejections';
|
||||
|
||||
/**
|
||||
* Log level for progress events
|
||||
*/
|
||||
export type TLogLevel = 'info' | 'warn' | 'error' | 'success';
|
||||
|
||||
/**
|
||||
* Progress event for live feedback during agent execution
|
||||
*/
|
||||
export interface IProgressEvent {
|
||||
/** Type of progress event */
|
||||
type: TProgressEventType;
|
||||
/** Current iteration number */
|
||||
iteration?: number;
|
||||
/** Maximum iterations configured */
|
||||
maxIterations?: number;
|
||||
/** Name of the tool being used */
|
||||
toolName?: string;
|
||||
/** Action being performed */
|
||||
action?: string;
|
||||
/** Reason for rejection or other explanation */
|
||||
reason?: string;
|
||||
/** Human-readable message about the event */
|
||||
message?: string;
|
||||
/** Timestamp of the event */
|
||||
timestamp: Date;
|
||||
/** Log level for this event (info, warn, error, success) */
|
||||
logLevel: TLogLevel;
|
||||
/** Pre-formatted log message ready for output */
|
||||
logMessage: string;
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Utility Types
|
||||
// ================================
|
||||
|
||||
@@ -2,6 +2,16 @@ import * as plugins from './plugins.js';
|
||||
import * as interfaces from './smartagent.interfaces.js';
|
||||
import { BaseToolWrapper } from './smartagent.tools.base.js';
|
||||
|
||||
/**
|
||||
* Options for FilesystemTool
|
||||
*/
|
||||
export interface IFilesystemToolOptions {
|
||||
/** Base path to scope all operations to. If set, all paths must be within this directory. */
|
||||
basePath?: string;
|
||||
/** Glob patterns to exclude from listings (e.g., ['.nogit/**', 'node_modules/**']) */
|
||||
excludePatterns?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filesystem tool for file and directory operations
|
||||
* Wraps @push.rocks/smartfs
|
||||
@@ -10,20 +20,66 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
public name = 'filesystem';
|
||||
public description = 'Read, write, list, and delete files and directories';
|
||||
|
||||
/** Base path to scope all operations to */
|
||||
private basePath?: string;
|
||||
/** Glob patterns to exclude from listings */
|
||||
private excludePatterns: string[];
|
||||
|
||||
constructor(options?: IFilesystemToolOptions) {
|
||||
super();
|
||||
if (options?.basePath) {
|
||||
this.basePath = plugins.path.resolve(options.basePath);
|
||||
}
|
||||
this.excludePatterns = options?.excludePatterns || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a relative path should be excluded based on exclude patterns
|
||||
*/
|
||||
private isExcluded(relativePath: string): boolean {
|
||||
if (this.excludePatterns.length === 0) return false;
|
||||
return this.excludePatterns.some(pattern =>
|
||||
plugins.minimatch(relativePath, pattern, { dot: true })
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that a path is within the allowed base path
|
||||
* @throws Error if path is outside allowed directory
|
||||
*/
|
||||
private validatePath(pathArg: string): string {
|
||||
const resolved = plugins.path.resolve(pathArg);
|
||||
if (this.basePath) {
|
||||
// Ensure the resolved path starts with the base path
|
||||
if (!resolved.startsWith(this.basePath + plugins.path.sep) && resolved !== this.basePath) {
|
||||
throw new Error(`Access denied: path "${pathArg}" is outside allowed directory "${this.basePath}"`);
|
||||
}
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
public actions: interfaces.IToolAction[] = [
|
||||
{
|
||||
name: 'read',
|
||||
description: 'Read the contents of a file',
|
||||
description: 'Read file contents (full or specific line range)',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
path: { type: 'string', description: 'Absolute path to the file' },
|
||||
path: { type: 'string', description: 'Path to the file' },
|
||||
encoding: {
|
||||
type: 'string',
|
||||
enum: ['utf8', 'binary', 'base64'],
|
||||
default: 'utf8',
|
||||
description: 'File encoding',
|
||||
},
|
||||
startLine: {
|
||||
type: 'number',
|
||||
description: 'First line to read (1-indexed, inclusive). If omitted, reads from beginning.',
|
||||
},
|
||||
endLine: {
|
||||
type: 'number',
|
||||
description: 'Last line to read (1-indexed, inclusive). If omitted, reads to end.',
|
||||
},
|
||||
},
|
||||
required: ['path'],
|
||||
},
|
||||
@@ -149,6 +205,55 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
required: ['path'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'tree',
|
||||
description: 'Show directory structure as a tree (no file contents)',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
path: { type: 'string', description: 'Root directory path' },
|
||||
maxDepth: {
|
||||
type: 'number',
|
||||
default: 3,
|
||||
description: 'Maximum depth to traverse (default: 3)',
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
description: 'Glob pattern to filter files (e.g., "*.ts")',
|
||||
},
|
||||
showSizes: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Include file sizes in output',
|
||||
},
|
||||
format: {
|
||||
type: 'string',
|
||||
enum: ['string', 'json'],
|
||||
default: 'string',
|
||||
description: 'Output format: "string" for human-readable tree, "json" for structured array',
|
||||
},
|
||||
},
|
||||
required: ['path'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'glob',
|
||||
description: 'Find files matching a glob pattern',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
pattern: {
|
||||
type: 'string',
|
||||
description: 'Glob pattern (e.g., "**/*.ts", "src/**/*.js")',
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
description: 'Base path to search from (defaults to current directory)',
|
||||
},
|
||||
},
|
||||
required: ['pattern'],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
private smartfs!: plugins.smartfs.SmartFs;
|
||||
@@ -172,25 +277,72 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
try {
|
||||
switch (action) {
|
||||
case 'read': {
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
const encoding = (params.encoding as string) || 'utf8';
|
||||
const content = await this.smartfs
|
||||
.file(params.path as string)
|
||||
const startLine = params.startLine as number | undefined;
|
||||
const endLine = params.endLine as number | undefined;
|
||||
|
||||
const fullContent = await this.smartfs
|
||||
.file(validatedPath)
|
||||
.encoding(encoding as 'utf8' | 'binary' | 'base64')
|
||||
.read();
|
||||
|
||||
const contentStr = fullContent.toString();
|
||||
const lines = contentStr.split('\n');
|
||||
const totalLines = lines.length;
|
||||
|
||||
// Apply line range if specified
|
||||
let resultContent: string;
|
||||
let resultStartLine = 1;
|
||||
let resultEndLine = totalLines;
|
||||
|
||||
if (startLine !== undefined || endLine !== undefined) {
|
||||
const start = Math.max(1, startLine ?? 1);
|
||||
const end = Math.min(totalLines, endLine ?? totalLines);
|
||||
resultStartLine = start;
|
||||
resultEndLine = end;
|
||||
|
||||
// Convert to 0-indexed for array slicing
|
||||
const selectedLines = lines.slice(start - 1, end);
|
||||
|
||||
// Add line numbers to output for context
|
||||
resultContent = selectedLines
|
||||
.map((line, idx) => `${String(start + idx).padStart(5)}│ ${line}`)
|
||||
.join('\n');
|
||||
} else {
|
||||
// No range specified - return full content but warn if large
|
||||
const MAX_LINES_WITHOUT_RANGE = 500;
|
||||
if (totalLines > MAX_LINES_WITHOUT_RANGE) {
|
||||
// Return first portion with warning
|
||||
const selectedLines = lines.slice(0, MAX_LINES_WITHOUT_RANGE);
|
||||
resultContent = selectedLines
|
||||
.map((line, idx) => `${String(idx + 1).padStart(5)}│ ${line}`)
|
||||
.join('\n');
|
||||
resultContent += `\n\n[... ${totalLines - MAX_LINES_WITHOUT_RANGE} more lines. Use startLine/endLine to read specific ranges.]`;
|
||||
resultEndLine = MAX_LINES_WITHOUT_RANGE;
|
||||
} else {
|
||||
resultContent = contentStr;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
path: params.path,
|
||||
content: content.toString(),
|
||||
content: resultContent,
|
||||
encoding,
|
||||
totalLines,
|
||||
startLine: resultStartLine,
|
||||
endLine: resultEndLine,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
case 'write': {
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
const encoding = (params.encoding as string) || 'utf8';
|
||||
await this.smartfs
|
||||
.file(params.path as string)
|
||||
.file(validatedPath)
|
||||
.encoding(encoding as 'utf8' | 'binary' | 'base64')
|
||||
.write(params.content as string);
|
||||
return {
|
||||
@@ -204,7 +356,8 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
}
|
||||
|
||||
case 'append': {
|
||||
await this.smartfs.file(params.path as string).append(params.content as string);
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
await this.smartfs.file(validatedPath).append(params.content as string);
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
@@ -215,14 +368,24 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
}
|
||||
|
||||
case 'list': {
|
||||
let dir = this.smartfs.directory(params.path as string);
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
let dir = this.smartfs.directory(validatedPath);
|
||||
if (params.recursive) {
|
||||
dir = dir.recursive();
|
||||
}
|
||||
if (params.filter) {
|
||||
dir = dir.filter(params.filter as string);
|
||||
}
|
||||
const entries = await dir.list();
|
||||
let entries = await dir.list();
|
||||
|
||||
// Filter out excluded paths
|
||||
if (this.excludePatterns.length > 0) {
|
||||
entries = entries.filter(entry => {
|
||||
const relativePath = plugins.path.relative(validatedPath, entry.path);
|
||||
return !this.isExcluded(relativePath) && !this.isExcluded(entry.name);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
@@ -234,33 +397,34 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
}
|
||||
|
||||
case 'delete': {
|
||||
const path = params.path as string;
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
// Check if it's a directory or file
|
||||
const exists = await this.smartfs.file(path).exists();
|
||||
const exists = await this.smartfs.file(validatedPath).exists();
|
||||
if (exists) {
|
||||
// Try to get stats to check if it's a directory
|
||||
try {
|
||||
const stats = await this.smartfs.file(path).stat();
|
||||
const stats = await this.smartfs.file(validatedPath).stat();
|
||||
if (stats.isDirectory && params.recursive) {
|
||||
await this.smartfs.directory(path).recursive().delete();
|
||||
await this.smartfs.directory(validatedPath).recursive().delete();
|
||||
} else {
|
||||
await this.smartfs.file(path).delete();
|
||||
await this.smartfs.file(validatedPath).delete();
|
||||
}
|
||||
} catch {
|
||||
await this.smartfs.file(path).delete();
|
||||
await this.smartfs.file(validatedPath).delete();
|
||||
}
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
path,
|
||||
path: params.path,
|
||||
deleted: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
case 'exists': {
|
||||
const exists = await this.smartfs.file(params.path as string).exists();
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
const exists = await this.smartfs.file(validatedPath).exists();
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
@@ -271,7 +435,8 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
}
|
||||
|
||||
case 'stat': {
|
||||
const stats = await this.smartfs.file(params.path as string).stat();
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
const stats = await this.smartfs.file(validatedPath).stat();
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
@@ -282,7 +447,9 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
}
|
||||
|
||||
case 'copy': {
|
||||
await this.smartfs.file(params.source as string).copy(params.destination as string);
|
||||
const validatedSource = this.validatePath(params.source as string);
|
||||
const validatedDest = this.validatePath(params.destination as string);
|
||||
await this.smartfs.file(validatedSource).copy(validatedDest);
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
@@ -294,7 +461,9 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
}
|
||||
|
||||
case 'move': {
|
||||
await this.smartfs.file(params.source as string).move(params.destination as string);
|
||||
const validatedSource = this.validatePath(params.source as string);
|
||||
const validatedDest = this.validatePath(params.destination as string);
|
||||
await this.smartfs.file(validatedSource).move(validatedDest);
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
@@ -306,7 +475,8 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
}
|
||||
|
||||
case 'mkdir': {
|
||||
let dir = this.smartfs.directory(params.path as string);
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
let dir = this.smartfs.directory(validatedPath);
|
||||
if (params.recursive !== false) {
|
||||
dir = dir.recursive();
|
||||
}
|
||||
@@ -320,6 +490,168 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
};
|
||||
}
|
||||
|
||||
case 'tree': {
|
||||
const validatedPath = this.validatePath(params.path as string);
|
||||
const maxDepth = (params.maxDepth as number) ?? 3;
|
||||
const filter = params.filter as string | undefined;
|
||||
const showSizes = (params.showSizes as boolean) ?? false;
|
||||
const format = (params.format as 'string' | 'json') ?? 'string';
|
||||
|
||||
// Collect all entries recursively up to maxDepth
|
||||
interface ITreeEntry {
|
||||
path: string;
|
||||
relativePath: string;
|
||||
isDir: boolean;
|
||||
depth: number;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
const entries: ITreeEntry[] = [];
|
||||
|
||||
const collectEntries = async (dirPath: string, depth: number, relativePath: string) => {
|
||||
if (depth > maxDepth) return;
|
||||
|
||||
let dir = this.smartfs.directory(dirPath);
|
||||
if (filter) {
|
||||
dir = dir.filter(filter);
|
||||
}
|
||||
const items = await dir.list();
|
||||
|
||||
for (const item of items) {
|
||||
// item is IDirectoryEntry with name, path, isFile, isDirectory properties
|
||||
const itemPath = item.path;
|
||||
const itemRelPath = relativePath ? `${relativePath}/${item.name}` : item.name;
|
||||
const isDir = item.isDirectory;
|
||||
|
||||
// Skip excluded paths
|
||||
if (this.isExcluded(itemRelPath) || this.isExcluded(item.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const entry: ITreeEntry = {
|
||||
path: itemPath,
|
||||
relativePath: itemRelPath,
|
||||
isDir,
|
||||
depth,
|
||||
};
|
||||
|
||||
if (showSizes && !isDir && item.stats) {
|
||||
entry.size = item.stats.size;
|
||||
}
|
||||
|
||||
entries.push(entry);
|
||||
|
||||
// Recurse into directories
|
||||
if (isDir && depth < maxDepth) {
|
||||
await collectEntries(itemPath, depth + 1, itemRelPath);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await collectEntries(validatedPath, 0, '');
|
||||
|
||||
// Sort entries by path for consistent output
|
||||
entries.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
||||
|
||||
if (format === 'json') {
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
path: params.path,
|
||||
entries: entries.map((e) => ({
|
||||
path: e.relativePath,
|
||||
isDir: e.isDir,
|
||||
depth: e.depth,
|
||||
...(e.size !== undefined ? { size: e.size } : {}),
|
||||
})),
|
||||
count: entries.length,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Format as string tree
|
||||
const formatSize = (bytes: number): string => {
|
||||
if (bytes < 1024) return `${bytes}B`;
|
||||
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
||||
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
||||
};
|
||||
|
||||
// Build tree string with proper indentation
|
||||
let treeStr = `${params.path}/\n`;
|
||||
const pathParts = new Map<string, number>(); // Track which paths are last in their parent
|
||||
|
||||
// Group by parent to determine last child
|
||||
const parentChildCount = new Map<string, number>();
|
||||
const parentCurrentChild = new Map<string, number>();
|
||||
|
||||
for (const entry of entries) {
|
||||
const parentPath = entry.relativePath.includes('/')
|
||||
? entry.relativePath.substring(0, entry.relativePath.lastIndexOf('/'))
|
||||
: '';
|
||||
parentChildCount.set(parentPath, (parentChildCount.get(parentPath) || 0) + 1);
|
||||
}
|
||||
|
||||
for (const entry of entries) {
|
||||
const parentPath = entry.relativePath.includes('/')
|
||||
? entry.relativePath.substring(0, entry.relativePath.lastIndexOf('/'))
|
||||
: '';
|
||||
parentCurrentChild.set(parentPath, (parentCurrentChild.get(parentPath) || 0) + 1);
|
||||
const isLast = parentCurrentChild.get(parentPath) === parentChildCount.get(parentPath);
|
||||
|
||||
// Build prefix based on depth
|
||||
let prefix = '';
|
||||
const parts = entry.relativePath.split('/');
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
prefix += '│ ';
|
||||
}
|
||||
prefix += isLast ? '└── ' : '├── ';
|
||||
|
||||
const name = parts[parts.length - 1];
|
||||
const suffix = entry.isDir ? '/' : '';
|
||||
const sizeStr = showSizes && entry.size !== undefined ? ` (${formatSize(entry.size)})` : '';
|
||||
|
||||
treeStr += `${prefix}${name}${suffix}${sizeStr}\n`;
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
path: params.path,
|
||||
tree: treeStr,
|
||||
count: entries.length,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
case 'glob': {
|
||||
const pattern = params.pattern as string;
|
||||
const basePath = params.path ? this.validatePath(params.path as string) : (this.basePath || process.cwd());
|
||||
|
||||
// Use smartfs to list with filter
|
||||
const dir = this.smartfs.directory(basePath).recursive().filter(pattern);
|
||||
const matches = await dir.list();
|
||||
|
||||
// Return file paths relative to base path for readability
|
||||
// Filter out excluded paths
|
||||
const files = matches
|
||||
.map((entry) => ({
|
||||
path: entry.path,
|
||||
relativePath: plugins.path.relative(basePath, entry.path),
|
||||
isDirectory: entry.isDirectory,
|
||||
}))
|
||||
.filter((file) => !this.isExcluded(file.relativePath));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
pattern,
|
||||
basePath,
|
||||
files,
|
||||
count: files.length,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
default:
|
||||
return {
|
||||
success: false,
|
||||
@@ -336,8 +668,12 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
|
||||
public getCallSummary(action: string, params: Record<string, unknown>): string {
|
||||
switch (action) {
|
||||
case 'read':
|
||||
return `Read file "${params.path}" with encoding ${params.encoding || 'utf8'}`;
|
||||
case 'read': {
|
||||
const lineRange = params.startLine || params.endLine
|
||||
? ` lines ${params.startLine || 1}-${params.endLine || 'end'}`
|
||||
: '';
|
||||
return `Read file "${params.path}"${lineRange}`;
|
||||
}
|
||||
|
||||
case 'write': {
|
||||
const content = params.content as string;
|
||||
@@ -372,6 +708,12 @@ export class FilesystemTool extends BaseToolWrapper {
|
||||
case 'mkdir':
|
||||
return `Create directory "${params.path}"${params.recursive !== false ? ' (with parents)' : ''}`;
|
||||
|
||||
case 'tree':
|
||||
return `Show tree of "${params.path}" (depth: ${params.maxDepth ?? 3}, format: ${params.format ?? 'string'})`;
|
||||
|
||||
case 'glob':
|
||||
return `Find files matching "${params.pattern}"${params.path ? ` in "${params.path}"` : ''}`;
|
||||
|
||||
default:
|
||||
return `Unknown action: ${action}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user