diff --git a/changelog.md b/changelog.md index 15903ae..7f10b93 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,15 @@ # Changelog +## 2026-03-06 - 3.0.0 - BREAKING CHANGE(api) +Migrate public API to ai-sdk v6 and refactor core agent architecture: replace class-based DualAgent/Driver/Guardian with a single runAgent function; introduce ts_tools factories for tools, a compactMessages compaction subpath, and truncateOutput utility; simplify ToolRegistry to return ToolSet and remove legacy BaseToolWrapper/tool classes; update package exports and dependencies and bump major version. + +- Major API break: DualAgent/Driver/Guardian classes and many legacy tool wrapper classes were removed and replaced by runAgent and functional tool factories. +- Tooling refactor: new ts_tools (filesystem, shell, http, json) produce ToolSet-style tools; ToolRegistry now stores ToolSet and exposes getTools(). +- Context management: added compactMessages in ts_compaction for onContextOverflow handling and truncateOutput util to limit tool outputs. +- Package changes: package.json bumped to 2.0.0, added exports map, updated devDependencies and dependencies (@push.rocks/smartai -> ^2.0.0, ai -> ^6.0.0, zod added). +- Tests updated/added to reflect new API (unit tests and an end-to-end test added). +- Consumers must update imports/usages (e.g. import runAgent, tool, z, stepCountIs and new subpath exports) — this is a breaking change. + ## 2026-01-20 - 1.8.0 - feat(tools) add ToolRegistry, ToolSearchTool and ExpertTool to support on-demand tool visibility, discovery, activation, and expert/subagent tooling; extend DualAgentOrchestrator API and interfaces to manage tool lifecycle diff --git a/npmextra.json b/npmextra.json index 1c07711..88fe753 100644 --- a/npmextra.json +++ b/npmextra.json @@ -5,7 +5,7 @@ "githost": "code.foss.global", "gitscope": "push.rocks", "gitrepo": "smartagent", - "description": "an agentic framework built on top of @push.rocks/smartai", + "description": "Agentic loop for ai-sdk (Vercel AI SDK). Wraps streamText with stopWhen for parallel multi-step tool execution. Built on @push.rocks/smartai.", "npmPackagename": "@push.rocks/smartagent", "license": "MIT", "projectDomain": "push.rocks" diff --git a/package.json b/package.json index f3cab59..59f8697 100644 --- a/package.json +++ b/package.json @@ -1,33 +1,47 @@ { "name": "@push.rocks/smartagent", - "version": "1.8.0", + "version": "2.0.0", "private": false, - "description": "an agentic framework built on top of @push.rocks/smartai", + "description": "Agentic loop for ai-sdk (Vercel AI SDK). Wraps streamText with stopWhen for parallel multi-step tool execution. Built on @push.rocks/smartai.", "main": "dist_ts/index.js", "typings": "dist_ts/index.d.ts", "type": "module", + "exports": { + ".": { + "import": "./dist_ts/index.js", + "types": "./dist_ts/index.d.ts" + }, + "./tools": { + "import": "./dist_ts_tools/index.js", + "types": "./dist_ts_tools/index.d.ts" + }, + "./compaction": { + "import": "./dist_ts_compaction/index.js", + "types": "./dist_ts_compaction/index.d.ts" + } + }, "author": "Task Venture Capital GmbH", "license": "MIT", "scripts": { - "test": "(tstest test/ --verbose)", - "build": "(tsbuild --web --allowimplicitany)", + "test": "(tstest test/ --verbose --logfile --timeout 120)", + "build": "(tsbuild tsfolders --allowimplicitany)", "buildDocs": "(tsdoc)" }, "devDependencies": { - "@git.zone/tsbuild": "^4.0.2", - "@git.zone/tsbundle": "^2.6.3", + "@git.zone/tsbuild": "^4.3.0", + "@git.zone/tsbundle": "^2.9.1", "@git.zone/tsrun": "^2.0.1", - "@git.zone/tstest": "^3.1.3", - "@types/node": "^25.0.2" + "@git.zone/tstest": "^3.3.0", + "@push.rocks/qenv": "^6.1.3", + "@types/node": "^25.3.5" }, "dependencies": { - "@push.rocks/smartai": "^0.13.3", - "@push.rocks/smartbrowser": "^2.0.8", - "@push.rocks/smartdeno": "^1.2.0", - "@push.rocks/smartfs": "^1.2.0", + "@push.rocks/smartai": "^2.0.0", + "@push.rocks/smartfs": "^1.4.0", "@push.rocks/smartrequest": "^5.0.1", - "@push.rocks/smartshell": "^3.3.0", - "minimatch": "^10.1.1" + "@push.rocks/smartshell": "^3.3.7", + "ai": "^6.0.0", + "zod": "^3.25.0" }, "packageManager": "pnpm@10.18.1+sha512.77a884a165cbba2d8d1c19e3b4880eee6d2fcabd0d879121e282196b80042351d5eb3ca0935fa599da1dc51265cc68816ad2bddd2a2de5ea9fdf92adbec7cd34", "repository": { @@ -40,13 +54,11 @@ "homepage": "https://code.foss.global/push.rocks/smartagent#readme", "files": [ "ts/**/*", - "ts_web/**/*", + "ts_tools/**/*", + "ts_compaction/**/*", "dist/**/*", "dist_*/**/*", - "dist_ts/**/*", - "dist_ts_web/**/*", "assets/**/*", - "cli.js", "npmextra.json", "readme.md" ], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef2ec56..e19f9aa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,47 +9,111 @@ importers: .: dependencies: '@push.rocks/smartai': - specifier: ^0.13.3 - version: 0.13.3(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76) - '@push.rocks/smartbrowser': - specifier: ^2.0.8 - version: 2.0.8(typescript@5.9.3) - '@push.rocks/smartdeno': - specifier: ^1.2.0 - version: 1.2.0 + specifier: ^2.0.0 + version: 2.0.0(typescript@5.9.3)(ws@8.19.0)(zod@3.25.76) '@push.rocks/smartfs': - specifier: ^1.2.0 - version: 1.2.0 + specifier: ^1.4.0 + version: 1.4.0 '@push.rocks/smartrequest': specifier: ^5.0.1 version: 5.0.1 '@push.rocks/smartshell': - specifier: ^3.3.0 - version: 3.3.0 - minimatch: - specifier: ^10.1.1 - version: 10.1.1 + specifier: ^3.3.7 + version: 3.3.7 + ai: + specifier: ^6.0.0 + version: 6.0.116(zod@3.25.76) + zod: + specifier: ^3.25.0 + version: 3.25.76 devDependencies: '@git.zone/tsbuild': - specifier: ^4.0.2 - version: 4.0.2 + specifier: ^4.3.0 + version: 4.3.0 '@git.zone/tsbundle': - specifier: ^2.6.3 - version: 2.6.3 + specifier: ^2.9.1 + version: 2.9.1 '@git.zone/tsrun': 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) + specifier: ^3.3.0 + version: 3.3.0(@tiptap/pm@2.27.2)(socks@2.8.7)(typescript@5.9.3) + '@push.rocks/qenv': + specifier: ^6.1.3 + version: 6.1.3 '@types/node': - specifier: ^25.0.2 - version: 25.0.2 + specifier: ^25.3.5 + version: 25.3.5 packages: - '@anthropic-ai/sdk@0.71.2': - resolution: {integrity: sha512-TGNDEUuEstk/DKu0/TflXAEt+p+p/WhTlFzEnoosvbaDU2LTjm42igSdlL0VijrKpWejtOKxX0b8A7uc+XiSAQ==} + '@ai-sdk/anthropic@3.0.58': + resolution: {integrity: sha512-/53SACgmVukO4bkms4dpxpRlYhW8Ct6QZRe6sj1Pi5H00hYhxIrqfiLbZBGxkdRvjsBQeP/4TVGsXgH5rQeb8Q==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/gateway@3.0.66': + resolution: {integrity: sha512-SIQ0YY0iMuv+07HLsZ+bB990zUJ6S4ujORAh+Jv1V2KGNn73qQKnGO0JBk+w+Res8YqOFSycwDoWcFlQrVxS4A==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/google@3.0.43': + resolution: {integrity: sha512-NGCgP5g8HBxrNdxvF8Dhww+UKfqAkZAmyYBvbu9YLoBkzAmGKDBGhVptN/oXPB5Vm0jggMdoLycZ8JReQM8Zqg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/groq@3.0.29': + resolution: {integrity: sha512-I/tUoHuOvGXbIr1dJ0CLRLA7W0UPDMtrYT5mgeb3O+P+6I5BAm/7riPwr22Xw5YTzpwQxcoDQlIczOU9XDXBpA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/mistral@3.0.24': + resolution: {integrity: sha512-krBTH2KHxtX8lCkSYSL4ZKSpn2EoJ5cNmBa9BmFL62KO1h5lYY6ivEwQb93TgY/hs2pkAIe4HJFIMX5kG1XtXg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/openai-compatible@2.0.35': + resolution: {integrity: sha512-g3wA57IAQFb+3j4YuFndgkUdXyRETZVvbfAWM+UX7bZSxA3xjes0v3XKgIdKdekPtDGsh4ZX2byHD0gJIMPfiA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/openai@3.0.41': + resolution: {integrity: sha512-IZ42A+FO+vuEQCVNqlnAPYQnnUpUfdJIwn1BEDOBywiEHa23fw7PahxVtlX9zm3/zMvTW4JKPzWyvAgDu+SQ2A==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/perplexity@3.0.23': + resolution: {integrity: sha512-LyizJlT3rVJ9WgU7C8RqCf4/QuV/aZT/D3s77sa2M0FtzA9tX5VsWDBR3GN0eAKnXxbC3Lhp5PaNuvqQgoMDiw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@4.0.19': + resolution: {integrity: sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider@3.0.8': + resolution: {integrity: sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==} + engines: {node: '>=18'} + + '@ai-sdk/xai@3.0.67': + resolution: {integrity: sha512-KQQIDc91dUA5IGFMnXBuvPBeraYNTdpDC1qUS+JG8vE+/299//5sZFafI1kKYUu3f3p7LaZrKXYgZ1Ni7QIRbw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@anthropic-ai/sdk@0.78.0': + resolution: {integrity: sha512-PzQhR715td/m1UaaN5hHXjYB8Gl2lF9UVhrrGrZeysiF6Rb74Wc9GCB8hzLdzmQtBd1qe89F9OptgB9Za1Ib5w==} hasBin: true peerDependencies: zod: ^3.25.0 || ^4.0.0 @@ -66,11 +130,16 @@ packages: '@api.global/typedrequest@3.1.10': resolution: {integrity: sha512-EiCp44XVcMjBvEs4oM1nMUaeY4ySU0Pzt3+mDwVG5DNP6EV87Nwancbr2jKScvaFNel9eeDgGtgEnFBKjOnApA==} - '@api.global/typedserver@3.0.80': - resolution: {integrity: sha512-dcp0oXsjBL+XdFg1wUUP08uJQid5bQ0Yv3V3Y3lnI2QCbat0FU+Tsb0TZRnZ4+P150Vj/ITBqJUgDzFsF34grA==} + '@api.global/typedrequest@3.3.0': + resolution: {integrity: sha512-Jwobqla+9k2IBG0duwrCFtc6GU6wsvHS3f0gJJsxTrpapylBW1YSF7NnGHPGs7F9hbATsO6IoUBpR2ScoKyGJA==} - '@api.global/typedsocket@3.0.1': - resolution: {integrity: sha512-xojiAVNXtHoxkpBo8U2HHJG8FrVXXuLvDNndSHXwx4C9VslUwDn5zSCI+PdBl8iAg+ZuBmKjqkpZZ9sL6DC5yQ==} + '@api.global/typedserver@8.4.2': + resolution: {integrity: sha512-eESOcWvrbqkshR4s4OeTX1AK74bNCeGgiRebKgjxIzJ+b0+rkPQyn2DOaMtyXjFZRNgRHyytLm5Iqj5fdazeqw==} + + '@api.global/typedsocket@4.1.2': + resolution: {integrity: sha512-fZFuJY9ucFCICjF4wi6OvK8drsv6UcwVVsfamOT1HxFj7OBOYw6QHOceQ+cAQ8IrWbX817sf8gzlesl+jlG8JA==} + peerDependencies: + '@push.rocks/smartserve': '>=1.1.0' '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} @@ -250,26 +319,44 @@ packages: '@borewit/text-codec@0.1.1': resolution: {integrity: sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==} - '@cloudflare/workers-types@4.20251202.0': - resolution: {integrity: sha512-Q7m1Ivu2fbKalOPm00KLpu6GfRaq4TlrPknqugvZgp/gDH96OYKINO4x7jvCIBvCz/aK9vVoOj8tlbSQBervVA==} + '@borewit/text-codec@0.2.1': + resolution: {integrity: sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==} + + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + + '@cloudflare/workers-types@4.20260305.1': + resolution: {integrity: sha512-835BZaIcgjuYIUqgOWJSpwQxFSJ8g/X1OCZFLO7bmirM6TGmVgIGwiGItBgkjUXXCPrYzJEldsJkuFuK7ePuMw==} '@configvault.io/interfaces@1.0.17': resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==} + '@design.estate/dees-catalog@3.43.3': + resolution: {integrity: sha512-GjTePdwqNBL4isMOx4Ibei6pgK55H+DccbtgyNqjHRBz3LL14mo809ebjY2IZOVobswyzuTcNFvhfiqFP4/HLg==} + '@design.estate/dees-comms@1.0.27': resolution: {integrity: sha512-GvzTUwkV442LD60T08iqSoqvhA02Mou5lFvvqBPc4yBUiU7cZISqBx+76xvMgMIEI9Dx9JfTl4/2nW8MoVAanw==} + '@design.estate/dees-comms@1.0.30': + resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==} + '@design.estate/dees-domtools@2.3.6': resolution: {integrity: sha512-cKaPNtSpp/ZuuXVx2dXO3K2FU3/HjC4ZkqtXb8Kl6yy9rNDbgtjcI4PuOk9Ux1SJzw7FgcxqVh7OSEV60htbmg==} + '@design.estate/dees-domtools@2.3.9': + resolution: {integrity: sha512-tixdBPUbbQEg46QkUQw9XVgGH/OxVe68FwPjspczKVPDM/0CbJL76JGQuTySZTPe8F49f2Q2Ft257qEGBEEtGA==} + '@design.estate/dees-element@2.1.3': resolution: {integrity: sha512-TjXWxVcdSPaT1IOk31ckfxvAZnJLuTxhFGsNCKoh63/UE2FVf6slp8//UFvN+ADigiA9ZsY0azkY99XbJCwDDA==} - '@emnapi/core@1.7.1': - resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} + '@design.estate/dees-element@2.1.6': + resolution: {integrity: sha512-7zyHkUjB8UEQgT9VbB2IJtc/yuPt9CI5JGel3b6BxA1kecY64ceIjFvof1uIkc0QP8q2fMLLY45r1c+9zDTjzg==} - '@emnapi/runtime@1.7.1': - resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + '@design.estate/dees-wcctools@3.8.0': + resolution: {integrity: sha512-CC14iVKUrguzD9jIrdPBd9fZ4egVJEZMxl5y8iy0l7WLumeoYvGsoXj5INVkRPLRVLqziIdi4Je1hXqHt2NU+g==} + + '@emnapi/core@1.8.1': + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} '@emnapi/runtime@1.8.1': resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} @@ -283,174 +370,350 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.27.1': resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.27.1': resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==} engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.27.1': resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==} engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.27.1': resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.27.1': resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.27.1': resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.27.1': resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.27.1': resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@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-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.27.1': resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.27.1': resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.27.1': resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.27.1': resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.27.1': resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@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-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.27.1': resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.27.1': resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.27.1': resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.27.1': resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.27.1': resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.27.1': resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.27.1': resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.27.1': resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.27.1': resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.27.1': resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@git.zone/tsbuild@4.0.2': - resolution: {integrity: sha512-LcRlFnDbcUe53Pdoob585iXq9TAT90TyEaYl/wml/etFoPeBX+oQLm6GryejUPXrUP7i1opyTonadkQN1OyXOA==} + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@fortawesome/fontawesome-common-types@7.2.0': + resolution: {integrity: sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw==} + engines: {node: '>=6'} + + '@fortawesome/fontawesome-svg-core@7.2.0': + resolution: {integrity: sha512-6639htZMjEkwskf3J+e6/iar+4cTNM9qhoWuRfj9F3eJD6r7iCzV1SWnQr2Mdv0QT0suuqU8BoJCZUyCtP9R4Q==} + engines: {node: '>=6'} + + '@fortawesome/free-brands-svg-icons@7.2.0': + resolution: {integrity: sha512-VNG8xqOip1JuJcC3zsVsKRQ60oXG9+oYNDCosjoU/H9pgYmLTEwWw8pE0jhPz/JWdHeUuK6+NQ3qsM4gIbdbYQ==} + engines: {node: '>=6'} + + '@fortawesome/free-regular-svg-icons@7.2.0': + resolution: {integrity: sha512-iycmlN51EULlQ4D/UU9WZnHiN0CvjJ2TuuCrAh+1MVdzD+4ViKYH2deNAll4XAAYlZa8WAefHR5taSK8hYmSMw==} + engines: {node: '>=6'} + + '@fortawesome/free-solid-svg-icons@7.2.0': + resolution: {integrity: sha512-YTVITFGN0/24PxzXrwqCgnyd7njDuzp5ZvaCx5nq/jg55kUYd94Nj8UTchBdBofi/L0nwRfjGOg0E41d2u9T1w==} + engines: {node: '>=6'} + + '@git.zone/tsbuild@4.3.0': + resolution: {integrity: sha512-lb6eMQ8RQPaJqAB4kC++GIElOiTAH1pClmoND/q7XHuiMZxv6cXz2/U/sZt339mon2c40dXRG2tkLF2jRsP0pQ==} hasBin: true - '@git.zone/tsbundle@2.6.3': - resolution: {integrity: sha512-YD1qMYA/4eOuF57V0ccR+xo6ww1+QOYFA2K5gBPFBDNh9VdfvWxxDhOUybja8lT9PVMoli8PHG5WA5tKJkdXIQ==} + '@git.zone/tsbundle@2.9.1': + resolution: {integrity: sha512-JW1xjSv7UjAm2lwAQPxhCWs14wqs+UIq5FqIGUPuI6rrDBWIMT2d0gpP6iP6TqXqgm6XpBlfU4rHcHheUXzXbQ==} hasBin: true - '@git.zone/tspublish@1.10.3': - resolution: {integrity: sha512-o2/jvNsdLC8SRdH1kQ7JjNOQNu9el0FpJ/QOW3mgiC5C9reuTp18iU4kijsVVLgvw4KZv6Z289SoKPh3HPsS0g==} + '@git.zone/tspublish@1.11.2': + resolution: {integrity: sha512-BcGap1OzXDgXpfQXMh9W17r/CkWNhPsJ3WzjG2wrGE+ePUJCJAm9w6+J8G5WdZZcZKPqTB07cp707LbSiksc5A==} hasBin: true '@git.zone/tsrun@2.0.1': resolution: {integrity: sha512-NEcnsjvlC1o3Z6SS3VhKCf6Ev+Sh4EAinmggslrIR/ppMrvjDbXNFXoyr3PB+GLeSAR0JRZ1fGvVYjpEzjBdIg==} hasBin: true - '@git.zone/tstest@3.1.3': - resolution: {integrity: sha512-t+/cKV21JHK8X7NGAmihs5M/eMm+V+jn4R5rzfwGG97WJFAcP5qE1Os9VYtyZw3tx/NZXA2yA4abo/ELluTuRA==} + '@git.zone/tstest@3.3.0': + resolution: {integrity: sha512-+j/XW7/XM3JAhlJEvITrGWlfeq4WCq2aODxKupboPXFLJTikwv3lxojcr4T/6RJ3Y3GCWYxWfzcjjw6ELi5phg==} hasBin: true '@happy-dom/global-registrator@15.11.7': @@ -594,13 +857,61 @@ packages: cpu: [x64] os: [win32] - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} + '@inquirer/checkbox@3.0.1': + resolution: {integrity: sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ==} + engines: {node: '>=18'} - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} - engines: {node: 20 || >=22} + '@inquirer/confirm@4.0.1': + resolution: {integrity: sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w==} + engines: {node: '>=18'} + + '@inquirer/core@9.2.1': + resolution: {integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==} + engines: {node: '>=18'} + + '@inquirer/editor@3.0.1': + resolution: {integrity: sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q==} + engines: {node: '>=18'} + + '@inquirer/expand@3.0.1': + resolution: {integrity: sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ==} + engines: {node: '>=18'} + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/input@3.0.1': + resolution: {integrity: sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg==} + engines: {node: '>=18'} + + '@inquirer/number@2.0.1': + resolution: {integrity: sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ==} + engines: {node: '>=18'} + + '@inquirer/password@3.0.1': + resolution: {integrity: sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ==} + engines: {node: '>=18'} + + '@inquirer/prompts@6.0.1': + resolution: {integrity: sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==} + engines: {node: '>=18'} + + '@inquirer/rawlist@3.0.1': + resolution: {integrity: sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ==} + engines: {node: '>=18'} + + '@inquirer/search@2.0.1': + resolution: {integrity: sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg==} + engines: {node: '>=18'} + + '@inquirer/select@3.0.1': + resolution: {integrity: sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q==} + engines: {node: '>=18'} + + '@inquirer/type@2.0.0': + resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} + engines: {node: '>=18'} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -724,41 +1035,118 @@ packages: '@lit-labs/ssr-dom-shim@1.4.0': resolution: {integrity: sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==} + '@lit-labs/ssr-dom-shim@1.5.1': + resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==} + '@lit/reactive-element@2.1.1': resolution: {integrity: sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==} - '@mistralai/mistralai@1.12.0': - resolution: {integrity: sha512-oDr1hcS3wsIT/QupBG93TNiA5kilwBYoAIyl5BNYqMM2Ix/xsNq+wT8b++uhp/GTUMx44n+8Bn1mkATbwxe6bQ==} + '@lit/reactive-element@2.1.2': + resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} '@mixmark-io/domino@2.2.0': resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} - '@module-federation/error-codes@0.21.6': - resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} + '@module-federation/error-codes@0.22.0': + resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} - '@module-federation/runtime-core@0.21.6': - resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} + '@module-federation/runtime-core@0.22.0': + resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} - '@module-federation/runtime-tools@0.21.6': - resolution: {integrity: sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q==} + '@module-federation/runtime-tools@0.22.0': + resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} - '@module-federation/runtime@0.21.6': - resolution: {integrity: sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ==} + '@module-federation/runtime@0.22.0': + resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} - '@module-federation/sdk@0.21.6': - resolution: {integrity: sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw==} + '@module-federation/sdk@0.22.0': + resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} - '@module-federation/webpack-bundler-runtime@0.21.6': - resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==} + '@module-federation/webpack-bundler-runtime@0.22.0': + resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} - '@mongodb-js/saslprep@1.3.2': - resolution: {integrity: sha512-QgA5AySqB27cGTXBFmnpifAi7HxoGUeezwo6p9dI03MuDB6Pp33zgclqVb6oVK3j6I9Vesg0+oojW2XxB59SGg==} + '@mongodb-js/saslprep@1.4.6': + resolution: {integrity: sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==} + + '@napi-rs/canvas-android-arm64@0.1.96': + resolution: {integrity: sha512-ew1sPrN3dGdZ3L4FoohPfnjq0f9/Jk7o+wP7HkQZokcXgIUD6FIyICEWGhMYzv53j63wUcPvZeAwgewX58/egg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@napi-rs/canvas-darwin-arm64@0.1.96': + resolution: {integrity: sha512-Q/wOXZ5PzTqpdmA5eUOcegCf4Go/zz3aZ5DlzSeDpOjFmfwMKh8EzLAoweQ+mJVagcHQyzoJhaTEnrO68TNyNg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@napi-rs/canvas-darwin-x64@0.1.96': + resolution: {integrity: sha512-UrXiQz28tQEvGM1qvyptewOAfmUrrd5+wvi6Rzjj2VprZI8iZ2KIvBD2lTTG1bVF95AbeDeG7PJA0D9sLKaOFA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.96': + resolution: {integrity: sha512-I90ODxweD8aEP6XKU/NU+biso95MwCtQ2F46dUvhec1HesFi0tq/tAJkYic/1aBSiO/1kGKmSeD1B0duOHhEHQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@napi-rs/canvas-linux-arm64-gnu@0.1.96': + resolution: {integrity: sha512-Dx/0+RFV++w3PcRy+4xNXkghhXjA5d0Mw1bs95emn5Llinp1vihMaA6WJt3oYv2LAHc36+gnrhIBsPhUyI2SGw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@napi-rs/canvas-linux-arm64-musl@0.1.96': + resolution: {integrity: sha512-UvOi7fii3IE2KDfEfhh8m+LpzSRvhGK7o1eho99M2M0HTik11k3GX+2qgVx9EtujN3/bhFFS1kSO3+vPMaJ0Mg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@napi-rs/canvas-linux-riscv64-gnu@0.1.96': + resolution: {integrity: sha512-MBSukhGCQ5nRtf9NbFYWOU080yqkZU1PbuH4o1ROvB4CbPl12fchDR35tU83Wz8gWIM9JTn99lBn9DenPIv7Ig==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + + '@napi-rs/canvas-linux-x64-gnu@0.1.96': + resolution: {integrity: sha512-I/ccu2SstyKiV3HIeVzyBIWfrJo8cN7+MSQZPnabewWV6hfJ2nY7Df2WqOHmobBRUw84uGR6zfQHsUEio/m5Vg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@napi-rs/canvas-linux-x64-musl@0.1.96': + resolution: {integrity: sha512-H3uov7qnTl73GDT4h52lAqpJPsl1tIUyNPWJyhQ6gHakohNqqRq3uf80+NEpzcytKGEOENP1wX3yGwZxhjiWEQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@napi-rs/canvas-win32-arm64-msvc@0.1.96': + resolution: {integrity: sha512-ATp6Y+djOjYtkfV/VRH7CZ8I1MEtkUQBmKUbuWw5zWEHHqfL0cEcInE4Cxgx7zkNAhEdBbnH8HMVrqNp+/gwxA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/canvas-win32-x64-msvc@0.1.96': + resolution: {integrity: sha512-UYGdTltVd+Z8mcIuoqGmAXXUvwH5CLf2M6mIB5B0/JmX5J041jETjqtSYl7gN+aj3k1by/SG6sS0hAwCqyK7zw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@napi-rs/canvas@0.1.96': + resolution: {integrity: sha512-6NNmNxvoJKeucVjxaaRUt3La2i5jShgiAbaY3G/72s1Vp3U06XPrAIxkAjBxpDcamEn/t+WJ4OOlGmvILo4/Ew==} + engines: {node: '>= 10'} '@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==} + '@napi-rs/wasm-runtime@1.1.1': + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} '@oxc-project/types@0.99.0': resolution: {integrity: sha512-LLDEhXB7g1m5J+woRSgfKsFPS3LhR9xRhTeIoEBm5WrkwMxn6eZ0Ld0c0K5eHB57ChZX6I3uSmmLjZ8pcjlRcw==} @@ -811,8 +1199,8 @@ packages: resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} engines: {node: '>=12.22.0'} - '@pnpm/npm-conf@2.3.1': - resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} + '@pnpm/npm-conf@3.0.2': + resolution: {integrity: sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==} engines: {node: '>=12'} '@puppeteer/browsers@2.10.13': @@ -838,49 +1226,45 @@ packages: '@push.rocks/lik@6.2.2': resolution: {integrity: sha512-j64FFPPyMXeeUorjKJVF6PWaJUfiIrF3pc41iJH4lOh0UUpBAHpcNzHVxTR58orwbVA/h3Hz+DQd4b1Rq0dFDQ==} + '@push.rocks/lik@6.3.1': + resolution: {integrity: sha512-UWDwGBaVx5yPtAFXqDDBtQZCzETUOA/7myQIXb+YBsuiIw4yQuhNZ23uY2ChQH2Zn6DLqdNSgQcYC0WywMZBNQ==} + '@push.rocks/mongodump@1.1.0': resolution: {integrity: sha512-kW0ZUGyf1e4nwloVwBQjNId+MzgTcNS834C+RxH21i1NqyOubbpWZtJtPP+K+s35nSJRyCTy3ICfBMdDBTAm2w==} + '@push.rocks/npmextra@5.3.3': + resolution: {integrity: sha512-snLpSHwaQ5OXlZzF1KX/FY71W5LwajjBzor82Vue0smjEPnSeUPY5/JcVdMwtdprdJe13pc/EQQuIiL/zw4/yg==} + '@push.rocks/qenv@6.1.3': resolution: {integrity: sha512-+z2hsAU/7CIgpYLFqvda8cn9rUBMHqLdQLjsFfRn5jPoD7dJ5rFlpkbhfM4Ws8mHMniwWaxGKo+q/YBhtzRBLg==} - '@push.rocks/smartai@0.13.3': - resolution: {integrity: sha512-VDZzHs101hpGMmUaectuLfcME4kHpuOS7o5ffuGk5lYl383foyAN71+5v441jpk/gLDNf2KhDACR/d2O4n90Ag==} + '@push.rocks/smartai@2.0.0': + resolution: {integrity: sha512-7ljFKOVwqha+hMYuOkbwoSY8eA8sK2EpckrqIthOgVU3Gr6ZgL/yjQZSUUY6cHNz9G17+sb2LQ7oBk/YQqguGA==} '@push.rocks/smartarchive@4.2.4': resolution: {integrity: sha512-uiqVAXPxmr8G5rv3uZvZFMOCt8l7cZC3nzvsy4YQqKf/VkPhKIEX+b7LkAeNlxPSYUiBQUkNRoawg9+5BaMcHg==} - '@push.rocks/smartarchive@5.0.1': - resolution: {integrity: sha512-x4bie9IIdL9BZqBZLc8Pemp8xZOJGa6mXSVgKJRL4/Rw+E5N4rVHjQOYGRV75nC2mAMJh9GIbixuxLnWjj77ag==} - - '@push.rocks/smartarray@1.1.0': - resolution: {integrity: sha512-b5YgBmUdglOJH8zeUf2ZWdPCoqySgwvkycRi2BhA9zVZHkpASh39Ej0q0fxFJetlUVyYqGfVoMVjbVrLFfFV7g==} - '@push.rocks/smartbrowser@2.0.8': resolution: {integrity: sha512-0KWRZj3TuKo/sNwgPbiSE6WL+TMeR19t1JmXBZWh9n8iA2mpc4HhMrQAndEUdRCkx5ofSaHWojIRVFzGChj0Dg==} '@push.rocks/smartbucket@3.3.10': resolution: {integrity: sha512-0H2MioALspC8Aj0Q1FPCs2w4k2u9oJg7Q5yM8+1TZo7aRfrdxgM5HQ7z3apUaqC3ZEDewW6vSlttjHFHhMEC3A==} - '@push.rocks/smartbucket@4.3.0': - resolution: {integrity: sha512-4nstzEduCKou4R5ekKH6kUjDZXWfrtjA1hIQ4MJmTbtncmm2+4+ixjaFThS2nS8Aa+fHcBgOtKkBv8wTsgvK/Q==} - '@push.rocks/smartbuffer@3.0.5': resolution: {integrity: sha512-pWYF08Mn8s/KF/9nHRk7pZPzuMjmYVQay2c5gGexdayxn1W4eCSYYhWH73vR2JBfGeGq/izbRNuUuEaIEeTIKA==} '@push.rocks/smartcache@1.0.18': resolution: {integrity: sha512-3+cmLu9chbnmi4yD4kjlFP/Tn4NReaZIoicEcGTtwbcokTrSDMs3YPdJzIpDZkAs83PW7OcVSHa3Ak5KU5OWzA==} - '@push.rocks/smartchok@1.2.0': - resolution: {integrity: sha512-I5fR++k6nR1wiMQUwcTYzO0g8FwD6gN+3HwfIzpQlolrM91i6Q5TaoMlt3aysbvKCSNvkL3FlJLOfUHNGWoWkA==} - deprecated: This package has been renamed. Please use @push.rocks/smartwatch instead. - - '@push.rocks/smartcli@4.0.19': - resolution: {integrity: sha512-s1jZSgDZWi/az26AY4TJ2HPuG1qZzGC5R9fKWaECLmwnSpk6y9JXL5dnJAUohcdu50kdXCWEcRmLfYxOt81vEA==} + '@push.rocks/smartcli@4.0.20': + resolution: {integrity: sha512-gCo4ItvsPj8WoVAJw/6vkuoGA5FtIoACux2ktcCeH0nrFe7/xGR6waJ1aZcYAi7QN4gi52TlsgwuKz7BzXqhmQ==} '@push.rocks/smartclickhouse@2.0.17': resolution: {integrity: sha512-IYO8Obor/Ruam2KQ2B/+5uQ+rL0exU5KZoSgOc3jkkrfjn+zZenN2xoV8lVqavAtxZVfG7MfxFrcv6I7I9ZMmA==} + '@push.rocks/smartclickhouse@2.2.0': + resolution: {integrity: sha512-eTzKiREIPSzL1kPkVyD6vEbn+WV/DvQqDjP67VlhNlQGbRcemnJG/eLrUUR1ytmdIqnsZGEK6UYBgyj5nhzLNQ==} + '@push.rocks/smartcrypto@2.0.4': resolution: {integrity: sha512-1+/5bsjyataf5uUkUNnnVXGRAt+gHVk1KDzozjTqgqJxHvQk1d9fVDohL6CxUhUucTPtu5VR5xNBiV8YCDuGyw==} @@ -890,9 +1274,6 @@ packages: '@push.rocks/smartdelay@3.0.5': resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==} - '@push.rocks/smartdeno@1.2.0': - resolution: {integrity: sha512-6S1plCaMUVOZiRSflfoz9Fqk9phACCuKmc7Z6SfTvfl+p9VcPUmewKgaa/0QiLOpiI6ksfxdfmkS5Rw5HpYeIA==} - '@push.rocks/smartdns@7.6.1': resolution: {integrity: sha512-nnP5+A2GOt0WsHrYhtKERmjdEHUchc+QbCCBEqlyeQTn+mNfx2WZvKVI1DFRJt8lamvzxP6Hr/BSe3WHdh4Snw==} @@ -908,6 +1289,9 @@ packages: '@push.rocks/smartexit@1.0.23': resolution: {integrity: sha512-WmwKYcwbHBByoABhHHB+PAjr5475AtD/xBh1mDcqPrFsOOUOZq3BBUdpq25wI3ccu/SZB5IwaimiVzadls6HkA==} + '@push.rocks/smartexit@2.0.3': + resolution: {integrity: sha512-ZWpZ3Elorpv/rKtUcCUejUHG4BIE5B3QWysBAgb7lTcA7y0vGdFY32Y5/Q5tHpZM6PPxl/WTdUOYtSojQTq+pA==} + '@push.rocks/smartexpect@2.5.0': resolution: {integrity: sha512-yoyuCoQ3tTiAriuvF+/09fNbVfFnacudL2SwHSzPhX/ugaE7VTSWXQ9A34eKOWvil0MPyDcOY36fVZDxvrPd8A==} @@ -920,17 +1304,11 @@ packages: '@push.rocks/smartfile@11.2.7': resolution: {integrity: sha512-8Yp7/sAgPpWJBHohV92ogHWKzRomI5MEbSG6b5W2n18tqwfAmjMed0rQvsvGrSBlnEWCKgoOrYIIZbLO61+J0Q==} - '@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==} - - '@push.rocks/smartfs@1.3.1': - resolution: {integrity: sha512-ZSduVS8tM+/erbyCTvRRvc9gLWwbpqN5xdIIkMr+gub7fowSeJb7tR2rnGwySa63DyimU0q2KTp79VV9YqGLeg==} + '@push.rocks/smartfs@1.4.0': + resolution: {integrity: sha512-4PgteGOyMBiUWKLfTXOjxrZz+sXPLnvcmHeAEHY2gwZJflfp5/YDVPhodctOydersXzkynO359dIGLSCyQnnAQ==} '@push.rocks/smartguard@3.1.0': resolution: {integrity: sha512-J23q84f1O+TwFGmd4lrO9XLHUh2DaLXo9PN/9VmTWYzTkQDv5JehmifXVI0esophXcCIfbdIu6hbt7/aHlDF4A==} @@ -938,12 +1316,21 @@ packages: '@push.rocks/smarthash@3.2.6': resolution: {integrity: sha512-Mq/WNX0Tjjes3X1gHd/ZBwOOKSrAG/Z3Xoc0OcCm3P20WKpniihkMpsnlE7wGjvpHLi/ZRe/XkB3KC3d5r9X4g==} + '@push.rocks/smarti18n@1.0.4': + resolution: {integrity: sha512-bHIi9Iuzp2cbux9q79ZK5jOQYPsYJ9zDDS4p/xEPQH31gr0mcFRosLSQb1kvDQDVmUhI0ADlQMqr2ui9zEXQHA==} + + '@push.rocks/smartinteract@2.0.16': + resolution: {integrity: sha512-eltvVRRUKBKd77DSFA4DPY2g4V4teZLNe8A93CDy/WglglYcUjxMoLY/b0DFTWCWKYT+yjk6Fe6p0FRrvX9Yvg==} + '@push.rocks/smartjimp@1.2.0': resolution: {integrity: sha512-SPz8p2ZuphNqIXK/UDsNFrnpJn/jr6FbuBSMQc0V2v2ffQIF32ZqktKQpXpitiqD1K5JEYS56JAhlYHgrAu7yw==} '@push.rocks/smartjson@5.2.0': resolution: {integrity: sha512-710e8UwovRfPgUtaBHcd6unaODUjV5fjxtGcGCqtaTcmvOV6VpasdVfT66xMDzQmWH2E9ZfHDJeso9HdDQzNQA==} + '@push.rocks/smartjson@6.0.0': + resolution: {integrity: sha512-FYfJnmukt66WePn6xrVZ3BLmRQl9W82LcsICK3VU9sGW7kasig090jKXPm+yX8ibQcZAO/KyR/Q8tMIYZNxGew==} + '@push.rocks/smartlog-destination-devtools@1.0.12': resolution: {integrity: sha512-zvsIkrqByc0JRaBgIyhh+PSz2SY/e/bmhZdUcr/OW6pudgAcqe2sso68EzrKux0w9OMl1P9ZnzF3FpCZPFWD/A==} @@ -956,6 +1343,9 @@ packages: '@push.rocks/smartlog@3.1.10': resolution: {integrity: sha512-5pf5JyzOE2WTCUislNIW4EHePo1a7hiXB+jbil38+N5hW71AEwcPFe6oGxbp5w9ALlz66hV2+E+25R0SsxN+fQ==} + '@push.rocks/smartlog@3.2.1': + resolution: {integrity: sha512-x9/P59pfzY6HOGYmYrhqmoRl/pliTVx44g2Vbb8dIr/0zA39cAJHlPze1+UGncn37XKGmutK2iLSsJLEsexD0A==} + '@push.rocks/smartmanifest@2.0.2': resolution: {integrity: sha512-QGc5C9vunjfUbYsPGz5bynV/mVmPHkrQDkWp8ZO8VJtK1GZe+njgbrNyxn2SUHR0IhSAbSXl1j4JvBqYf5eTVg==} @@ -968,8 +1358,11 @@ packages: '@push.rocks/smartmime@2.0.4': resolution: {integrity: sha512-mG6lRBLr5nF+GLZmgCcdjhdDsmTtJWBFZDCa1eJ8Au9TvUzbPW0fY5aqJBb3UwfyZzH6St8Th9cJSXjagOQkYA==} - '@push.rocks/smartmongo@2.0.14': - resolution: {integrity: sha512-fvfPeCDDy5JaDBpVnsMKednsOoRzuYC0OszO8OoLOX/RaR755zIbRppCCK8Cez0hqd6eNkJGQeWdX/vXlJOPBA==} + '@push.rocks/smartmongo@2.2.0': + resolution: {integrity: sha512-ovVCNoJ3D0aBuKtoKaQWWQKvBngaGJq9fAPQigzji1EHsS1XyGpXWCpe5nq/ptGvBROOcpqZcOFEGAcrnb+OjA==} + + '@push.rocks/smartmongo@5.1.0': + resolution: {integrity: sha512-2tpKf8K+SMdLHOEpafgKPIN+ypWTLwHc33hCUDNMQ1KaL7vokkavA44+fHxQydOGPMtDi22tSMFeVMCcUSzs4w==} '@push.rocks/smartnetwork@4.4.0': resolution: {integrity: sha512-OvFtz41cvQ7lcXwaIOhghNUUlNoMxvwKDctbDvMyuZyEH08SpLjhyv2FuKbKL/mgwA/WxakTbohoC8SW7t+kiw==} @@ -995,8 +1388,8 @@ packages: '@push.rocks/smartpdf@3.3.0': resolution: {integrity: sha512-k4mBZAIl/TVBHDYQXaBZAgC8DdmHXsIZ3hRrLY3ysLr143YJ1VkwqQ2poqWh3A2SZQDrVfpKRYliUtjFRFrYVw==} - '@push.rocks/smartpdf@4.1.1': - resolution: {integrity: sha512-pC5gBDk4nk+xhRltS0ByTTSnVrwHjrrVfyrAgHYyiPKPZmYH5+Q4fZ+qzBrc6lEZSuCP8TEAeZcsGoOd3hAwvw==} + '@push.rocks/smartpdf@4.1.3': + resolution: {integrity: sha512-o0myXTRULg8HR55IXTSBIR+d0EjAlSrjwdqAnMYV3PDdUiPfxE7JE0GcDGsTKcm6mPxx/N2mg9Y/7xrlQU0z3w==} '@push.rocks/smartping@1.0.8': resolution: {integrity: sha512-Fvx1Db6hSsDOI6pdiCuS9GjtOX8ugx865YQrPg5vK2iw6Qj/srwyXcWLFYt+19WVKtvtWDJIAKbW+q3bXFsCeA==} @@ -1019,36 +1412,48 @@ packages: '@push.rocks/smartrouter@1.3.3': resolution: {integrity: sha512-1+xZEnWlhzqLWAaJ1zFNhQ0zgbfCWQl1DBT72LygLxTs+P0K8AwJKgqo/IX6CT55kGCFnPAZIYSbVJlGsgrB0w==} + '@push.rocks/smartrust@1.3.1': + resolution: {integrity: sha512-3ApbgF6yGeE2TRQxBY9Y48H1JlpcRheIp7QDBLSSfk80Uoe6fjdgBAfNz3Ir8hW3RZ3b7hA3sm1ZshCok58SEA==} + '@push.rocks/smartrx@3.0.10': resolution: {integrity: sha512-USjIYcsSfzn14cwOsxgq/bBmWDTTzy3ouWAnW5NdMyRRzEbmeNrvmy6TRqNeDlJ2PsYNTt1rr/zGUqvIy72ITg==} - '@push.rocks/smarts3@3.0.3': - resolution: {integrity: sha512-Y9nXMwurthJ9Z7yi0RwjhPFUC58aY8Mhia8kFo6Xj1tBM4LE8Oxg/ydejF7otHqQGr3QyqV5C4YrDEG17rUuzg==} + '@push.rocks/smarts3@5.3.0': + resolution: {integrity: sha512-6bo55ovCDEylbTxwPFZYDrZrz2babQEUmxHIexmVcP2j+6LYRHDbGYnWoyKdtqniqDFZ04pFkOoZ85hUzU5xCw==} - '@push.rocks/smartshell@3.3.0': - resolution: {integrity: sha512-m0w618H6YBs+vXGz1CgS4nPi5CUAnqRtckcS9/koGwfcIx1IpjqmiP47BoCTbdgcv0IPUxQVBG1IXTHPuZ8Z5g==} + '@push.rocks/smartserve@2.0.1': + resolution: {integrity: sha512-YQb2qexfCzCqOlLWBBXKMg6xG4zahCPAxomz/KEKAwHtW6wMTtuHKSTSkRTQ0vl9jssLMAmRz2OyafiL9XGJXQ==} + + '@push.rocks/smartshell@3.3.7': + resolution: {integrity: sha512-b3st2+FjHUVhZZRlXfw93+SQA0UMVlURqe55uVpWdjJX7jeGXTTeszuYygtiR99zC5iZ8WZhGDct3N2L1qc/qw==} '@push.rocks/smartsitemap@2.0.4': resolution: {integrity: sha512-76dYWG/o/EjV4vYCK7ZKM35T9xgrI+oHEiiIE6E2MDaFIU6QnSfciTfbscH5nc0vxx8Ah+I0HPEJO94BM2S39w==} - '@push.rocks/smartsocket@2.1.0': - resolution: {integrity: sha512-etOGyfiDFQz/1WJnD3jFL2N7ykujTjiudAz6qZTz82xE5oabKuKX+Cn8SdM9dOwzyWmBUKbUdll8QhovAXjn+g==} - '@push.rocks/smartspawn@3.0.3': resolution: {integrity: sha512-DyrGPV69wwOiJgKkyruk5hS3UEGZ99xFAqBE9O2nM8VXCRLbbty3xt1Ug5Z092ZZmJYaaGMSnMw3ijyZJFCT0Q==} '@push.rocks/smartstate@2.0.27': resolution: {integrity: sha512-q4UKir7GV3hakJWXQR4DoA4tUVwT5GRkJ/MtanHYF0wZLHfS19+nGmyO9y974zk3eT9hmy3+Lq5cKtU2W6+Y3w==} + '@push.rocks/smartstate@2.2.1': + resolution: {integrity: sha512-fLrilAJNI6QOs0hcBRD9eTwU2Rlo6NlDCKQo9N/zyp0VJ6AV1UVdEZcVIQILu1CO0RUHX9aBAbFunJrb2+Zrkg==} + '@push.rocks/smartstream@3.2.5': resolution: {integrity: sha512-PLGGIFDy8JLNVUnnntMSIYN4W081YSbNC7Y/sWpvUT8PAXtbEXXUiDFgK5o3gcI0ptpKQxHAwxhzNlPj0sbFVg==} + '@push.rocks/smartstream@3.4.0': + resolution: {integrity: sha512-kePb44W9n5K96zj2Ms3K4xnYbNXP5AfxDd86zZMDQ1/T10nvkIpL9m5w4lG/VJ4KAsWFs81S87BkkcjhhrY5Kw==} + '@push.rocks/smartstring@4.1.0': resolution: {integrity: sha512-Q4py/Nm3KTDhQ9EiC75yBtSTLR0KLMwhKM+8gGcutgKotZT6wJ3gncjmtD8LKFfNhb4lSaFMgPJgLrCHTOH6Iw==} '@push.rocks/smarttime@4.1.1': resolution: {integrity: sha512-Ha/3J/G+zfTl4ahpZgF6oUOZnUjpLhrBja0OQ2cloFxF9sKT8I1COaSqIfBGDtoK2Nly4UD4aTJ3JcJNOg/kgA==} + '@push.rocks/smarttime@4.2.3': + resolution: {integrity: sha512-8gMg8RUkrCG4p9NcEUZV7V6KpL24+jAMK02g7qyhfA6giz/JJWD0+8w8xjSR+G7qe16KVQ2y3RbvAL9TxmO36g==} + '@push.rocks/smartunique@3.0.9': resolution: {integrity: sha512-q6DYQgT7/dqdWi9HusvtWCjdsFzLFXY9LTtaZV6IYNJt6teZOonoygxTdNt9XLn6niBSbLYrHSKvJNTRH/uK+g==} @@ -1058,6 +1463,10 @@ packages: '@push.rocks/smartversion@3.0.5': resolution: {integrity: sha512-8MZSo1yqyaKxKq0Q5N188l4un++9GFWVbhCAX5mXJwewZHn97ujffTeL+eOQYpWFTEpUhaq1QhL4NhqObBCt1Q==} + '@push.rocks/smartwatch@6.3.0': + resolution: {integrity: sha512-TeZ1PGBoBMpC4/CK8StIj5InEiFfKp7xWJSm3aYMjB/uaoeRP0vXqv1ORIC/TKYGJuEDuAXUsit8tZVjn0qT1Q==} + engines: {node: '>=20.0.0'} + '@push.rocks/smartxml@2.0.0': resolution: {integrity: sha512-1d06zYJX4Zt8s5w5qFOUg2LAEz9ykrh9d6CQPK4WAgOBIefb1xzVEWHc7yoxicc2OkzNgC3IBCEg3s6BncZKWw==} @@ -1070,11 +1479,14 @@ packages: '@push.rocks/taskbuffer@3.4.0': resolution: {integrity: sha512-Rvwr1CzYztB9PMboojRzVSq3xGp8288kvtvWx4Mg3rvps913znMja1UOjNn52ivOxu3dHUNYE3NDSP+j84cUWQ==} + '@push.rocks/taskbuffer@3.5.0': + resolution: {integrity: sha512-Y9WwIEIyp6oVFdj06j84tfrZIvjhbMb3DF52rYxlTeYLk3W7RPhSg1bGPCbtkXWeKdBrSe37V90BkOG7Qq8Pqg==} + '@push.rocks/webrequest@3.0.37': resolution: {integrity: sha512-fLN7kP6GeHFxE4UH4r9C9pjcQb0QkJxHeAMwXvbOqB9hh0MFNKhtGU7GoaTn8SVRGRMPc9UqZVNwo6u5l8Wn0A==} - '@push.rocks/webrequest@4.0.1': - resolution: {integrity: sha512-I60XZZLVf8W5I7YdmUVVu4G92teE3rg3/aKaV00BRg8vJ3VXx3wc59Qj4em7zxQ5o0HvL8m1Aezw3RFMDPyVgA==} + '@push.rocks/webrequest@4.0.5': + resolution: {integrity: sha512-wVSCaXqJ9Vh+rbwVz0wDl46dYz4rnwwSrm5vbVXKbuH6oKTPF0YRoujeJPqRltIn64RVGdLeY9/6ix+ZCrzhsg==} '@push.rocks/websetup@3.0.19': resolution: {integrity: sha512-iKJDwXdMmQdu5siOIgziPRxM51lN1AU9HOr+yMteu1YMDkZT7HKCyisDAr4gC9WZ9a7FzsG8zgthm4dMeA8NTw==} @@ -1117,6 +1529,9 @@ packages: resolution: {integrity: sha512-TxHSar7Cj29E+GOcIj4DeZKWCNVzHKdqnrBRqcBqLqmeYZvzFosLXpFKoaCJDq7MSxuPoCvu5woSdp9YmPXyog==} deprecated: This package has been deprecated in favour of the new package at @push.rocks/smartstring + '@remirror/core-constants@3.0.0': + resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} + '@rolldown/binding-android-arm64@1.0.0-beta.52': resolution: {integrity: sha512-MBGIgysimZPqTDcLXI+i9VveijkP5C3EAncEogXhqfax6YXj1Tr2LY3DVuEOMIjWfMPMhtQSPup4fSTAmgjqIw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1203,60 +1618,60 @@ packages: '@rolldown/pluginutils@1.0.0-beta.52': resolution: {integrity: sha512-/L0htLJZbaZFL1g9OHOblTxbCYIGefErJjtYOwgl9ZqNx27P3L0SDfjhhHIss32gu5NWgnxuT2a2Hnnv6QGHKA==} - '@rspack/binding-darwin-arm64@1.6.7': - resolution: {integrity: sha512-QiIAP8JTAtht0j8/xZZEQTJRB9e+KrOm9c7JJm73CewVg55rDWRrwopiVfBNlTu1coem1ztUHJYdQhg2uXfqww==} + '@rspack/binding-darwin-arm64@1.7.7': + resolution: {integrity: sha512-eL14fHy2JqfQ0YA5YMN2hktXhbafDSZt5kthvlBCbpQZLnYB7RP7TjHManIW/xFpnzrabvxkrLUOHhuIbWixIw==} cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-x64@1.6.7': - resolution: {integrity: sha512-DpQRxxTXkMMNPmBXeJBaAB8HmWKxH2IfvHv7vU+kBhJ3xdPtXU4/xBv1W3biluoNRG11gc1WLIgjzeGgaLCxmw==} + '@rspack/binding-darwin-x64@1.7.7': + resolution: {integrity: sha512-Zt+whHag/cTw1pZfRwkv11tu5LaAHy2VkvRVCsHClwrfp81PRcNJ2oRMurOUmRt1YL0mRdpRbZTh7XjGSc6gGw==} cpu: [x64] os: [darwin] - '@rspack/binding-linux-arm64-gnu@1.6.7': - resolution: {integrity: sha512-211/XoBiooGGgUo/NxNpsrzGUXtH1d7g/4+UTtjYtfc8QHwu7ZMHcsqg0wss53fXzn/yyxd0DZ56vBHq52BiFw==} + '@rspack/binding-linux-arm64-gnu@1.7.7': + resolution: {integrity: sha512-uSq4qkvmAzSDUTKE2v4yUgHIBdTily1k3BcK5wBCGFm9OPODj5lQZpAdOHHIwu+Jxyjoa7Mb64tghhj9hZcXcA==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@1.6.7': - resolution: {integrity: sha512-0WnqAWz3WPDsXGvOOA++or7cHpoidVsH3FlqNaAfRu6ni6n7ig/s0/jKUB+C5FtXOgmGjAGkZHfFgNHsvZ0FWw==} + '@rspack/binding-linux-arm64-musl@1.7.7': + resolution: {integrity: sha512-NhWCBfiu6plpmLRP6c6D5lBUaVrBr1nvjSEc7VyQF8TGh8URo2btH0wngEiX0nWvidsSlERt1l6Y5QPGuiCl1g==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-x64-gnu@1.6.7': - resolution: {integrity: sha512-iMrE0Q4IuYpkE0MjpaOVaUDYbQFiCRI9D3EPoXzlXJj4kJSdNheODpHTBVRlWt8Xp7UAoWuIFXCvKFKcSMm3aQ==} + '@rspack/binding-linux-x64-gnu@1.7.7': + resolution: {integrity: sha512-aRvf8gCI7jDeEN9i4u9fY5coa3ZAyHzGVA4ZhTJCgZ5wWA5A9SQewMSq7khS1WAAFE1USlk1tUuPujnrGoYrGg==} cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@1.6.7': - resolution: {integrity: sha512-e7gKFxpdEQwYGk7lTC/hukTgNtaoAstBXehnZNk4k3kuU6+86WDrkn18Cd949iNqfIPtIG/wIsFNGbkHsH69hQ==} + '@rspack/binding-linux-x64-musl@1.7.7': + resolution: {integrity: sha512-ALPto4OT7snzXbYDyqkLfh1BvwDTTH1hPYXGUXBzQ0wEV7sXeyvxCC4yjH6B5MhR7W3tFuF4IfDy5Z4BxmOoGQ==} cpu: [x64] os: [linux] - '@rspack/binding-wasm32-wasi@1.6.7': - resolution: {integrity: sha512-yx88EFdE9RP3hh7VhjjW6uc6wGU0KcpOcZp8T8E/a+X8L98fX0aVrtM1IDbndhmdluIMqGbfJNap2+QqOCY9Mw==} + '@rspack/binding-wasm32-wasi@1.7.7': + resolution: {integrity: sha512-7DZvUp0v75n451qfZw1ppbPakL6NAc2gjb5e9AJcOb7KUMBHNyOxqpPo/jRYKxH7isPpLfpoId79WQGGNTTMAw==} cpu: [wasm32] - '@rspack/binding-win32-arm64-msvc@1.6.7': - resolution: {integrity: sha512-vgxVYpFK8P5ulSXQQA+EbX78R/SUU+WIf0JIY+LoUoP89gZOsise/lKAJMAybzpeTJ1t0ndLchFznDYnzq+l4Q==} + '@rspack/binding-win32-arm64-msvc@1.7.7': + resolution: {integrity: sha512-oI08KqyVDKhq1Qi/YPMdrSLDOib0DQes9Cg67NJLZISe5UXwzvgBj7zyyKpaj8TLWnIlKSq4ITr3haRnd4lOfA==} cpu: [arm64] os: [win32] - '@rspack/binding-win32-ia32-msvc@1.6.7': - resolution: {integrity: sha512-bV5RTW0Va0UQKJm9HWLt7fWNBPaBBBxCJOA2pJT3nGGm6CCXKnZSyEiVbFUk4jI/uiwBfqenlLkzaGoMRbeDhA==} + '@rspack/binding-win32-ia32-msvc@1.7.7': + resolution: {integrity: sha512-nZ/t7XpO/+tRjK6m85an27j8FwJqpYXVSBGReZbB6dVHZiS7l6psjWkIf6A3E2umn/RjA7qvHaPH9czWkH+Fhw==} cpu: [ia32] os: [win32] - '@rspack/binding-win32-x64-msvc@1.6.7': - resolution: {integrity: sha512-8xlbuJQtYktlBjZupOHlO8FeZqSIhsV3ih7xBSiOYar6LI6uQzA7XiO3I5kaPSDirBMMMKv1Z4rKCxWx10a3TQ==} + '@rspack/binding-win32-x64-msvc@1.7.7': + resolution: {integrity: sha512-+XnPOC1MoeF5Qa24Z8+DCsytQP0Q9Ifdkh+XzTWgvjpFQmGAkDynHUVfscmJL/8k/nd1l/6TyXCL1EGoqa0huQ==} cpu: [x64] os: [win32] - '@rspack/binding@1.6.7': - resolution: {integrity: sha512-7ICabuBN3gHc6PPN52+m1kruz3ogiJjg1C0gSWdLRk18m/4jlcM2aAy6wfXjgODJdB0Yh2ro/lIpBbj+AYWUGA==} + '@rspack/binding@1.7.7': + resolution: {integrity: sha512-9FqHG2Bl70Bd4gUmwA+3xUx4pYphdLO9ToIm9iMWbBINyArME0XboZg4FoEdU13LqndkWqaamkE613BR0lRF3g==} - '@rspack/core@1.6.7': - resolution: {integrity: sha512-tkd4nSzTf+pDa9OAE4INi/JEa93HNszjWy5C9+trf4ZCXLLHsHxHQFbzoreuz4Vv2PlCWajgvAdiPMV1vGIkuw==} + '@rspack/core@1.7.7': + resolution: {integrity: sha512-efwVXxAA9eYgLtYX53zcuuex6Wr8DnOXeIw3JFoA8EuyN7TINGqnvkuGDuE+F9XQxQ3KBzVueiYdMK42sVTyUw==} engines: {node: '>=18.12.0'} peerDependencies: '@swc/helpers': '>=0.5.1' @@ -1490,8 +1905,8 @@ packages: resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} engines: {node: '>=18.0.0'} - '@socket.io/component-emitter@3.1.2': - resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} '@szmarczak/http-timer@5.0.1': resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} @@ -1500,6 +1915,155 @@ packages: '@tempfix/idb@8.0.3': resolution: {integrity: sha512-hPJQKO7+oAIY+pDNImrZ9QAINbz9KmwT+yO4iRVwdPanok2YKpaUxdJzIvCUwY0YgAawlvYdffbLvRLV5hbs2g==} + '@tempfix/lenis@1.3.20': + resolution: {integrity: sha512-ypeB0FuHLHOCQXW4d0RQ69txPJJH+1CHcpsZIUdcv2t1vR0IVyQr2vHihtde9UOXhjzqEnUphWon/UcJNsa0YA==} + peerDependencies: + '@nuxt/kit': '>=3.0.0' + react: '>=17.0.0' + vue: '>=3.0.0' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + react: + optional: true + vue: + optional: true + + '@tempfix/webcontainer__api@1.6.1': + resolution: {integrity: sha512-Hgn3cwy0vPzjrVBqeVnY0jNZLaOCW7d+dxBe7Jv9YGHAjJ8udUMS+KbTywSv5paAfld3A/RN/iolmMzOwZxLTA==} + + '@tiptap/core@2.27.2': + resolution: {integrity: sha512-ABL1N6eoxzDzC1bYvkMbvyexHacszsKdVPYqhl5GwHLOvpZcv9VE9QaKwDILTyz5voCA0lGcAAXZp+qnXOk5lQ==} + peerDependencies: + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-blockquote@2.27.2': + resolution: {integrity: sha512-oIGZgiAeA4tG3YxbTDfrmENL4/CIwGuP3THtHsNhwRqwsl9SfMk58Ucopi2GXTQSdYXpRJ0ahE6nPqB5D6j/Zw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-bold@2.27.2': + resolution: {integrity: sha512-bR7J5IwjCGQ0s3CIxyMvOCnMFMzIvsc5OVZKscTN5UkXzFsaY6muUAIqtKxayBUucjtUskm5qZowJITCeCb1/A==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-bullet-list@2.27.2': + resolution: {integrity: sha512-gmFuKi97u5f8uFc/GQs+zmezjiulZmFiDYTh3trVoLRoc2SAHOjGEB7qxdx7dsqmMN7gwiAWAEVurLKIi1lnnw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-code-block@2.27.2': + resolution: {integrity: sha512-KgvdQHS4jXr79aU3wZOGBIZYYl9vCB7uDEuRFV4so2rYrfmiYMw3T8bTnlNEEGe4RUeAms1i4fdwwvQp9nR1Dw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-code@2.27.2': + resolution: {integrity: sha512-7X9AgwqiIGXoZX7uvdHQsGsjILnN/JaEVtqfXZnPECzKGaWHeK/Ao4sYvIIIffsyZJA8k5DC7ny2/0sAgr2TuA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-document@2.27.2': + resolution: {integrity: sha512-CFhAYsPnyYnosDC4639sCJnBUnYH4Cat9qH5NZWHVvdgtDwu8GZgZn2eSzaKSYXWH1vJ9DSlCK+7UyC3SNXIBA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-dropcursor@2.27.2': + resolution: {integrity: sha512-oEu/OrktNoQXq1x29NnH/GOIzQZm8ieTQl3FK27nxfBPA89cNoH4mFEUmBL5/OFIENIjiYG3qWpg6voIqzswNw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-gapcursor@2.27.2': + resolution: {integrity: sha512-/c9VF1HBxj+AP54XGVgCmD9bEGYc5w5OofYCFQgM7l7PB1J00A4vOke0oPkHJnqnOOyPlFaxO/7N6l3XwFcnKA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-hard-break@2.27.2': + resolution: {integrity: sha512-kSRVGKlCYK6AGR0h8xRkk0WOFGXHIIndod3GKgWU49APuIGDiXd8sziXsSlniUsWmqgDmDXcNnSzPcV7AQ8YNg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-heading@2.27.2': + resolution: {integrity: sha512-iM3yeRWuuQR/IRQ1djwNooJGfn9Jts9zF43qZIUf+U2NY8IlvdNsk2wTOdBgh6E0CamrStPxYGuln3ZS4fuglw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-history@2.27.2': + resolution: {integrity: sha512-+hSyqERoFNTWPiZx4/FCyZ/0eFqB9fuMdTB4AC/q9iwu3RNWAQtlsJg5230bf/qmyO6bZxRUc0k8p4hrV6ybAw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-horizontal-rule@2.27.2': + resolution: {integrity: sha512-WGWUSgX+jCsbtf9Y9OCUUgRZYuwjVoieW5n6mAUohJ9/6gc6sGIOrUpBShf+HHo6WD+gtQjRd+PssmX3NPWMpg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-italic@2.27.2': + resolution: {integrity: sha512-1OFsw2SZqfaqx5Fa5v90iNlPRcqyt+lVSjBwTDzuPxTPFY4Q0mL89mKgkq2gVHYNCiaRkXvFLDxaSvBWbmthgg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-link@2.27.2': + resolution: {integrity: sha512-bnP61qkr0Kj9Cgnop1hxn2zbOCBzNtmawxr92bVTOE31fJv6FhtCnQiD6tuPQVGMYhcmAj7eihtvuEMFfqEPcQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-list-item@2.27.2': + resolution: {integrity: sha512-eJNee7IEGXMnmygM5SdMGDC8m/lMWmwNGf9fPCK6xk0NxuQRgmZHL6uApKcdH6gyNcRPHCqvTTkhEP7pbny/fg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-ordered-list@2.27.2': + resolution: {integrity: sha512-M7A4tLGJcLPYdLC4CI2Gwl8LOrENQW59u3cMVa+KkwG1hzSJyPsbDpa1DI6oXPC2WtYiTf22zrbq3gVvH+KA2w==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-paragraph@2.27.2': + resolution: {integrity: sha512-elYVn2wHJJ+zB9LESENWOAfI4TNT0jqEN34sMA/hCtA4im1ZG2DdLHwkHIshj/c4H0dzQhmsS/YmNC5Vbqab/A==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-strike@2.27.2': + resolution: {integrity: sha512-HHIjhafLhS2lHgfAsCwC1okqMsQzR4/mkGDm4M583Yftyjri1TNA7lzhzXWRFWiiMfJxKtdjHjUAQaHuteRTZw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text-align@2.27.2': + resolution: {integrity: sha512-0Pyks6Hu+Q/+9+5/osoSv0SP6jIerdWMYbi13aaZLsJoj3lBj5WNaE11JtAwSFN5sx0IbqhDSlp1zkvRnzgZ8g==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text-style@2.27.2': + resolution: {integrity: sha512-Omk+uxjJLyEY69KStpCw5fA9asvV+MGcAX2HOxyISDFoLaL49TMrNjhGAuz09P1L1b0KGXo4ml7Q3v/Lfy4WPA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text@2.27.2': + resolution: {integrity: sha512-Xk7nYcigljAY0GO9hAQpZ65ZCxqOqaAlTPDFcKerXmlkQZP/8ndx95OgUb1Xf63kmPOh3xypurGS2is3v0MXSA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-typography@2.27.2': + resolution: {integrity: sha512-NSyqDa8PlAZoVRfTWQuxueTZ6ftOD72EV7UKVpftf3C+Heme727mvwl1YHMnagOlqVoxBhFOrl9CnSs/q5uayQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-underline@2.27.2': + resolution: {integrity: sha512-gPOsbAcw1S07ezpAISwoO8f0RxpjcSH7VsHEFDVuXm4ODE32nhvSinvHQjv2icRLOXev+bnA7oIBu7Oy859gWQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/pm@2.27.2': + resolution: {integrity: sha512-kaEg7BfiJPDQMKbjVIzEPO3wlcA+pZb2tlcK9gPrdDnEFaec2QTF1sXz2ak2IIb2curvnIrQ4yrfHgLlVA72wA==} + + '@tiptap/starter-kit@2.27.2': + resolution: {integrity: sha512-bb0gJvPoDuyRUQ/iuN52j1//EtWWttw+RXAv1uJxfR0uKf8X7uAqzaOOgwjknoCIDC97+1YHwpGdnRjpDkOBxw==} + '@tokenizer/inflate@0.4.1': resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} engines: {node: '>=18'} @@ -1534,9 +2098,6 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - '@types/cors@2.8.19': - resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} - '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -1561,8 +2122,8 @@ packages: '@types/html-minifier@4.0.6': resolution: {integrity: sha512-1Dcf38DkVMYo8SIOkUka7GxI+0BztCVsnfiG2Sxb6G8ShHDQTWQb1WKps/eb3O074HNDCn8wU7LMl5N99nNG+Q==} - '@types/http-cache-semantics@4.0.4': - resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + '@types/http-cache-semantics@4.2.0': + resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} @@ -1576,9 +2137,18 @@ packages: '@types/jsonfile@6.1.4': resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/mime-types@2.1.4': resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} @@ -1588,14 +2158,20 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/mute-stream@0.0.4': + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + '@types/node-forge@1.3.14': resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} '@types/node@16.9.1': resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==} - '@types/node@25.0.2': - resolution: {integrity: sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==} + '@types/node@22.19.15': + resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==} + + '@types/node@25.3.5': + resolution: {integrity: sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==} '@types/ping@0.4.4': resolution: {integrity: sha512-ifvo6w2f5eJYlXm+HiVx67iJe8WZp87sfa683nlqED5Vnt9Z93onkokNoWqOG21EaE8fMxyKPobE+mkPEyxsdw==} @@ -1654,6 +2230,9 @@ packages: '@types/which@3.0.4': resolution: {integrity: sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==} + '@types/wrap-ansi@3.0.0': + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} @@ -1663,14 +2242,17 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@vercel/oidc@3.1.0': + resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} + engines: {node: '>= 20'} + + '@yr/monotone-cubic-spline@1.0.3': + resolution: {integrity: sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==} + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} - accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -1687,10 +2269,20 @@ packages: resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} engines: {node: '>= 8.0.0'} + ai@6.0.116: + resolution: {integrity: sha512-7yM+cTmyRLeNIXwt4Vj+mrrJgVQ9RMIW5WO0ydoLoYkewIvsMcvUmqS4j2RJTUXaF1HphwmSKUMQ/HypNRGOmA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + ansi-256-colors@1.1.0: resolution: {integrity: sha1-kQ3lDvzHwJ49gvL4er1rcAwYgYo=} engines: {node: '>=0.10.0'} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1710,6 +2302,9 @@ packages: any-base@1.1.0: resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==} + apexcharts@5.10.1: + resolution: {integrity: sha512-BpKKRopNm5cziXmA1igmCKiJ02I2g/I4vBtjhB6/50FrrY2IH5csvCzzqiIuFCB+P+2p0MgLAGOJPKOUvXO63w==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -1745,12 +2340,24 @@ packages: react-native-b4a: optional: true + b4a@1.8.0: + resolution: {integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + bare-events@2.8.2: resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} peerDependencies: @@ -1768,6 +2375,15 @@ packages: bare-buffer: optional: true + bare-fs@4.5.5: + resolution: {integrity: sha512-XvwYM6VZqKoqDll8BmSww5luA5eflDzY0uEFfBJtFKe4PAAtxBjU3YIxzIBzhyaEQBy1VXEQBto4cpN5RZJw+w==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-os@3.6.2: resolution: {integrity: sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==} engines: {bare: '>=1.14.0'} @@ -1786,16 +2402,23 @@ packages: bare-events: optional: true + bare-stream@2.8.0: + resolution: {integrity: sha512-reUN0M2sHRqCdG4lUK3Fw8w98eeUIZHL5c3H7Mbhk2yVBL+oofgaIp0ieLfD5QXwPCypBpmEEKU2WZKzbAk8GA==} + peerDependencies: + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-events: + optional: true + bare-url@2.3.2: resolution: {integrity: sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - base64id@2.0.0: - resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} - engines: {node: ^4.5.0 || >= 5.9} - basic-ftp@5.0.5: resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} engines: {node: '>=10.0.0'} @@ -1819,9 +2442,16 @@ packages: brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@5.0.4: + resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + engines: {node: 18 || 20 || >=22} + broadcast-channel@7.2.0: resolution: {integrity: sha512-JgraikEriG/TxBUi2W/w2O0jhHjXZUtXAvCZH0Yr3whjxYVgAg0hSe6r/teM+I5H5Q/q6RhyuKdC2pHNlFyepQ==} + broadcast-channel@7.3.0: + resolution: {integrity: sha512-UHPhLBQKfQ8OmMFMpmPfO5dRakyA1vsfiDGWTYNvChYol65tbuhivPEGgZZiuetorvExdvxaWiBy/ym1Ty08yA==} + brorand@1.1.0: resolution: {integrity: sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=} @@ -1885,6 +2515,9 @@ packages: character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + chokidar@5.0.0: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} @@ -1902,6 +2535,10 @@ packages: resolution: {integrity: sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=} engines: {node: '>=4'} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1948,10 +2585,6 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - cosmiconfig@9.0.0: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} @@ -1961,6 +2594,13 @@ packages: typescript: optional: true + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + + croner@10.0.1: + resolution: {integrity: sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g==} + engines: {node: '>=18.0'} + croner@9.1.0: resolution: {integrity: sha512-p9nwwR4qyT5W996vBZhdvBCnMhicY5ytZkR4D1Xj0wuTDEiMnjwR57Q3RXYY/s0EpX6Ay3vgIcfaR+ewGHsi+g==} engines: {node: '>=18.0'} @@ -1983,15 +2623,6 @@ packages: dayjs@1.11.19: resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -2058,6 +2689,9 @@ packages: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} + dompurify@3.2.7: + resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -2084,17 +2718,6 @@ packages: end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - engine.io-client@6.6.3: - resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==} - - engine.io-parser@5.2.3: - resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} - engines: {node: '>=10.0.0'} - - engine.io@6.6.4: - resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==} - engines: {node: '>=10.2.0'} - entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -2127,6 +2750,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -2134,6 +2762,10 @@ packages: escape-html@1.0.3: resolution: {integrity: sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=} + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} @@ -2178,13 +2810,13 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} + eventsource-parser@3.0.6: + resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} + engines: {node: '>=18.0.0'} + exif-parser@0.1.12: resolution: {integrity: sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==} - express-force-ssl@0.3.2: - resolution: {integrity: sha1-AbK0mK5v0uQRUrIrV6Phc3c69n4=} - engines: {node: '>=0.2.2'} - express@5.2.1: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} @@ -2192,6 +2824,10 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + extract-zip@2.0.1: resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -2214,16 +2850,19 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - fast-xml-parser@4.5.3: - resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==} + fast-xml-builder@1.0.0: + resolution: {integrity: sha512-fpZuDogrAgnyt9oDDz+5DBz0zgPdPZz6D4IR7iESxRXElrlGTRkHJ9eEt+SACRJwT0FNFrt71DFQIUFBJfX/uQ==} + + fast-xml-parser@4.5.4: + resolution: {integrity: sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ==} hasBin: true fast-xml-parser@5.2.5: resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} hasBin: true - fast-xml-parser@5.3.2: - resolution: {integrity: sha512-n8v8b6p4Z1sMgqRmqLJm3awW4NX7NkaKPfb3uJIBTSH7Pdvufi3PQ3/lJLQrvxcMYl7JI2jnDO90siPEpD8JBA==} + fast-xml-parser@5.4.2: + resolution: {integrity: sha512-pw/6pIl4k0CSpElPEJhDppLzaixDEuWui2CUQQBH/ECDf7+y6YwA4Gf7Tyb0Rfe4DIMuZipYj4AEL0nACKglvQ==} hasBin: true fault@2.0.1: @@ -2247,8 +2886,8 @@ packages: resolution: {integrity: sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ==} engines: {node: '>=18'} - file-type@21.1.1: - resolution: {integrity: sha512-ifJXo8zUqbQ/bLbl9sFoqHNTNWbnPY1COImFfM6CCy7z+E+jC1eY9YfOKkx0fckIg+VljAy2/87T61fp0+eEkg==} + file-type@21.3.0: + resolution: {integrity: sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==} engines: {node: '>=20'} finalhandler@2.1.1: @@ -2406,6 +3045,10 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + hmac-drbg@1.0.1: resolution: {integrity: sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=} @@ -2439,6 +3082,13 @@ packages: humanize-ms@1.2.1: resolution: {integrity: sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=} + ibantools@4.5.1: + resolution: {integrity: sha512-DfKQpLlFq9yEUIEnFuCJzss3XavD7iHZTU5PyqXiAJ+rmaMp+NFP3hboumHKuK8nZjuOJg93WemTzcQ5b9jOZA==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + iconv-lite@0.7.0: resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} engines: {node: '>=0.10.0'} @@ -2462,6 +3112,10 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + inquirer@11.1.0: + resolution: {integrity: sha512-CmLAZT65GG/v30c+D2Fk8+ceP6pxD6RL+hIUOWAltCmeyEqWYwqu9v76q03OvjyZ3AB0C1Ala2stn1z/rMqGEw==} + engines: {node: '>=18'} + ip-address@10.1.0: resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} engines: {node: '>= 12'} @@ -2520,9 +3174,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} - isexe@3.1.1: - resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} - engines: {node: '>=16'} + isexe@4.0.0: + resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} + engines: {node: '>=20'} isopen@1.3.0: resolution: {integrity: sha512-AN6Q9J0UlqHFl1fN/2xJCHCBLCBCFDjZhpGBO1gh3wzgRPsFSFBUL36I2Lbfd9qkuoj58axmE7j83iejTQsk8Q==} @@ -2562,6 +3216,9 @@ packages: resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} engines: {node: '>=16'} + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} @@ -2589,55 +3246,37 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + linkifyjs@4.3.2: + resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==} + lit-element@4.2.1: resolution: {integrity: sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==} + lit-element@4.2.2: + resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} + lit-html@3.3.1: resolution: {integrity: sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==} + lit-html@3.3.2: + resolution: {integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==} + lit@3.3.1: resolution: {integrity: sha512-Ksr/8L3PTapbdXJCk+EJVB78jDodUMaP54gD24W186zGRARvwrsPfS60wae/SSCTCNZVPd1chXqio1qHQmu4NA==} + lit@3.3.2: + resolution: {integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} - lodash._baseassign@3.2.0: - resolution: {integrity: sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=} - - lodash._basecopy@3.0.1: - resolution: {integrity: sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=} - - lodash._bindcallback@3.0.1: - resolution: {integrity: sha1-5THCdkTPi1epnhftlbNcdIeJOS4=} - - lodash._createassigner@3.1.1: - resolution: {integrity: sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=} - - lodash._getnative@3.9.1: - resolution: {integrity: sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=} - - lodash._isiterateecall@3.0.9: - resolution: {integrity: sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=} - - lodash.assign@3.2.0: - resolution: {integrity: sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=} - lodash.clonedeep@4.5.0: resolution: {integrity: sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=} - lodash.isarguments@3.1.0: - resolution: {integrity: sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=} - - lodash.isarray@3.0.4: - resolution: {integrity: sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=} - - lodash.keys@3.1.2: - resolution: {integrity: sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=} - - lodash.restparam@3.6.1: - resolution: {integrity: sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -2656,6 +3295,9 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} + lucide@0.564.0: + resolution: {integrity: sha512-FasyXKHWon773WIl3HeCQpd5xS6E0aLjqxiQStlHNKktni+HDncc1sqY+6vRUbCfmDsIaKQz43EEQLAUDLZO0g==} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -2666,9 +3308,18 @@ packages: make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + markdown-it@14.1.1: + resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} + hasBin: true + markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + marked@14.0.0: + resolution: {integrity: sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==} + engines: {node: '>= 18'} + hasBin: true + matcher@5.0.0: resolution: {integrity: sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2719,6 +3370,9 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + media-typer@1.1.0: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} @@ -2851,21 +3505,24 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + mingo@7.2.0: + resolution: {integrity: sha512-UeX942qZpofn5L97h295SkS7j/ADf7Qac8gdRCMBPxi0/1m70aeB2owLFvWbyuMj1dowonlivlVRQVDx+6h+7Q==} + minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=} - minimatch@10.1.1: - resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} - engines: {node: 20 || >=22} + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} minimist@1.2.8: @@ -2878,15 +3535,18 @@ packages: mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + monaco-editor@0.55.1: + resolution: {integrity: sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==} + mongodb-connection-string-url@3.0.2: resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==} - mongodb-memory-server-core@10.3.0: - resolution: {integrity: sha512-tp+ZfTBAPqHXjROhAFg6HcVVzXaEhh/iHcbY7QPOIiLwr94OkBFAw4pixyGSfP5wI2SZeEA13lXyRmBAhugWgA==} + mongodb-memory-server-core@10.4.3: + resolution: {integrity: sha512-IPjlw73IoSYopnqBibQKxmAXMbOEPf5uGAOsBcaUiNH/TOI7V19WO+K7n5KYtnQ9FqzLGLpvwCGuPOTBSg4s5Q==} engines: {node: '>=16.20.1'} - mongodb-memory-server@10.3.0: - resolution: {integrity: sha512-dRNr2uEhMgjEe6kgqS+ITBKBbl2cz0DNBjNZ12BGUckvEOAHbhd3R7q/lFPSZrZ6AMKa2EOUJdAmFF1WlqSbsA==} + mongodb-memory-server@10.4.3: + resolution: {integrity: sha512-CDZvFisXvGIigsIw5gqH6r9NI/zxGa/uRdutgUL/isuJh+inj0YXb7Ykw6oFMFzqgTJWb7x0I5DpzrqCstBWpg==} engines: {node: '>=16.20.1'} mongodb@6.21.0: @@ -2919,15 +3579,15 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + nanoid@4.0.2: resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} engines: {node: ^14 || ^16 || >=18} hasBin: true - negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - negotiator@1.0.0: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} @@ -2947,18 +3607,18 @@ packages: resolution: {integrity: sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==} engines: {node: '>= 6.13.0'} + node-forge@1.3.3: + resolution: {integrity: sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==} + engines: {node: '>= 6.13.0'} + normalize-newline@4.1.0: resolution: {integrity: sha512-ff4jKqMI8Xl50/4Mms/9jPobzAV/UK+kXG2XJ/7AqOmxIx8mqfqTIHYxuAnEgJ2AQeBbLnlbmZ5+38Y9A0w/YA==} engines: {node: '>=12'} - normalize-url@8.1.0: - resolution: {integrity: sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==} + normalize-url@8.1.1: + resolution: {integrity: sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==} engines: {node: '>=14.16'} - object-assign@4.1.1: - resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} - engines: {node: '>=0.10.0'} - object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -2988,8 +3648,8 @@ packages: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} - openai@6.16.0: - resolution: {integrity: sha512-fZ1uBqjFUjXzbGc35fFtYKEOxd20kd9fDpFeqWtsOZWiubY8CZ1NAlXHW3iathaFvqmNtCWMIsosCuyeI7Joxg==} + openai@6.27.0: + resolution: {integrity: sha512-osTKySlrdYrLYTt0zjhY8yp0JUBmWDCN+Q+QxsV4xMQnnoVFpylgKGgxwN8sSdTNw0G4y+WUXs4eCMWpyDNWZQ==} hasBin: true peerDependencies: ws: ^8.18.0 @@ -3000,6 +3660,13 @@ packages: zod: optional: true + orderedmap@2.1.1: + resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} + + os-tmpdir@1.0.2: + resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=} + engines: {node: '>=0.10.0'} + p-cancelable@3.0.0: resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} engines: {node: '>=12.20'} @@ -3102,6 +3769,16 @@ packages: hasBin: true bundledDependencies: [] + pdf2json@4.0.2: + resolution: {integrity: sha512-iiRSuRmLihoEJ4YGkoqSq3/r4MR0OmkMTYDda0Pq7DAWqJwMylTilXu46T16gfS3DUp3fhiVuz7NtRMbk3uBhw==} + engines: {node: '>=20.18.0'} + hasBin: true + bundledDependencies: [] + + pdfjs-dist@4.10.38: + resolution: {integrity: sha512-/Y3fcFrXEAsMjJXeL9J8+ZG9U01LbuWaYypvDW2ycW1jL269L3js3DVBjDJ0Up9Np1uqDXsDrRihHANhZOlwdQ==} + engines: {node: '>=20'} + peek-readable@4.1.0: resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==} engines: {node: '>=8'} @@ -3155,6 +3832,64 @@ packages: property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + prosemirror-changeset@2.4.0: + resolution: {integrity: sha512-LvqH2v7Q2SF6yxatuPP2e8vSUKS/L+xAU7dPDC4RMyHMhZoGDfBC74mYuyYF4gLqOEG758wajtyhNnsTkuhvng==} + + prosemirror-collab@1.3.1: + resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==} + + prosemirror-commands@1.7.1: + resolution: {integrity: sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==} + + prosemirror-dropcursor@1.8.2: + resolution: {integrity: sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==} + + prosemirror-gapcursor@1.4.0: + resolution: {integrity: sha512-z00qvurSdCEWUIulij/isHaqu4uLS8r/Fi61IbjdIPJEonQgggbJsLnstW7Lgdk4zQ68/yr6B6bf7sJXowIgdQ==} + + prosemirror-history@1.5.0: + resolution: {integrity: sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==} + + prosemirror-inputrules@1.5.1: + resolution: {integrity: sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==} + + prosemirror-keymap@1.2.3: + resolution: {integrity: sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==} + + prosemirror-markdown@1.13.4: + resolution: {integrity: sha512-D98dm4cQ3Hs6EmjK500TdAOew4Z03EV71ajEFiWra3Upr7diytJsjF4mPV2dW+eK5uNectiRj0xFxYI9NLXDbw==} + + prosemirror-menu@1.3.0: + resolution: {integrity: sha512-TImyPXCHPcDsSka2/lwJ6WjTASr4re/qWq1yoTTuLOqfXucwF6VcRa2LWCkM/EyTD1UO3CUwiH8qURJoWJRxwg==} + + prosemirror-model@1.25.4: + resolution: {integrity: sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==} + + prosemirror-schema-basic@1.2.4: + resolution: {integrity: sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==} + + prosemirror-schema-list@1.5.1: + resolution: {integrity: sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==} + + prosemirror-state@1.4.4: + resolution: {integrity: sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==} + + prosemirror-tables@1.8.5: + resolution: {integrity: sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==} + + prosemirror-trailing-node@3.0.0: + resolution: {integrity: sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==} + peerDependencies: + prosemirror-model: ^1.22.1 + prosemirror-state: ^1.4.2 + prosemirror-view: ^1.33.8 + + prosemirror-transform@1.11.0: + resolution: {integrity: sha512-4I7Ce4KpygXb9bkiPS3hTEk4dSHorfRw8uI0pE8IhxlK2GXsqv5tIA7JUSxtSu7u8APVOTtbUBxTmnHIxVkIJw==} + + prosemirror-view@1.41.6: + resolution: {integrity: sha512-mxpcDG4hNQa/CPtzxjdlir5bJFDlm0/x5nGBbStB2BWX+XOQ9M8ekEG+ojqB5BcVu2Rc80/jssCMZzSstJuSYg==} + proto-list@1.2.4: resolution: {integrity: sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=} @@ -3172,6 +3907,10 @@ packages: pump@3.0.3: resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + punycode@1.4.1: resolution: {integrity: sha1-wNWmOycYgArY4esPpSachN1BhF4=} @@ -3199,6 +3938,10 @@ packages: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} + qs@6.15.0: + resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} + engines: {node: '>=0.6'} + quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -3238,8 +3981,8 @@ packages: reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} - registry-auth-token@5.1.0: - resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} + registry-auth-token@5.1.1: + resolution: {integrity: sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==} engines: {node: '>=14'} registry-url@6.0.1: @@ -3296,10 +4039,17 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rope-sequence@1.3.4: + resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} + router@2.2.0: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} + run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} @@ -3322,6 +4072,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + send@1.2.0: resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} engines: {node: '>= 18'} @@ -3380,21 +4135,6 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - socket.io-adapter@2.5.5: - resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} - - socket.io-client@4.8.1: - resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==} - engines: {node: '>=10.0.0'} - - socket.io-parser@4.2.4: - resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} - engines: {node: '>=10.0.0'} - - socket.io@4.8.1: - resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} - engines: {node: '>=10.2.0'} - socks-proxy-agent@8.0.5: resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} engines: {node: '>= 14'} @@ -3463,6 +4203,9 @@ packages: strnum@2.1.1: resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==} + strnum@2.2.0: + resolution: {integrity: sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==} + strtok3@10.3.4: resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} engines: {node: '>=18'} @@ -3493,6 +4236,12 @@ packages: tar-stream@3.1.7: resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + tar-stream@3.1.8: + resolution: {integrity: sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ==} + + teex@1.0.1: + resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} + text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -3508,6 +4257,10 @@ packages: tinycolor2@1.6.0: resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -3520,6 +4273,10 @@ packages: resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==} engines: {node: '>=14.16'} + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} + tr46@5.1.1: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} @@ -3558,6 +4315,10 @@ packages: turndown@7.2.2: resolution: {integrity: sha512-1F7db8BiExOKxjSMU2b7if62D/XOyQyZbPKq/nUwopfgnHlqXHqQ0lvfUTeUIr1lZJzOPFn43dODyMSIfvWRKQ==} + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + type-fest@2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} @@ -3578,6 +4339,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + uglify-js@3.19.3: resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} @@ -3587,8 +4351,11 @@ packages: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} - undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -3646,6 +4413,9 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + webdriver-bidi-protocol@0.3.9: resolution: {integrity: sha512-uIYvlRQ0PwtZR1EzHlTMol1G0lAlmOe6wPykF9a77AK3bkpvZHzIVxRE2ThOx5vjy2zISe0zhwf5rzuUfbo1PQ==} @@ -3666,11 +4436,15 @@ packages: engines: {node: '>= 8'} hasBin: true - which@5.0.0: - resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} - engines: {node: ^18.17.0 || >=20.5.0} + which@6.0.1: + resolution: {integrity: sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==} + engines: {node: ^20.17.0 || >=22.9.0} hasBin: true + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3682,8 +4456,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} - ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3694,8 +4468,8 @@ packages: utf-8-validate: optional: true - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3717,9 +4491,13 @@ packages: resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} engines: {node: '>=4.0'} - xmlhttprequest-ssl@2.1.2: - resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} - engines: {node: '>=0.4.0'} + xterm-addon-fit@0.8.0: + resolution: {integrity: sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==} + peerDependencies: + xterm: ^5.0.0 + + xterm@5.3.0: + resolution: {integrity: sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==} y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} @@ -3749,10 +4527,9 @@ packages: resolution: {integrity: sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==} engines: {node: '>=12'} - zod-to-json-schema@3.25.1: - resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} - peerDependencies: - zod: ^3.25 || ^4 + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} @@ -3762,7 +4539,74 @@ packages: snapshots: - '@anthropic-ai/sdk@0.71.2(zod@3.25.76)': + '@ai-sdk/anthropic@3.0.58(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/gateway@3.0.66(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + '@vercel/oidc': 3.1.0 + zod: 3.25.76 + + '@ai-sdk/google@3.0.43(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/groq@3.0.29(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/mistral@3.0.24(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/openai-compatible@2.0.35(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/openai@3.0.41(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/perplexity@3.0.23(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/provider-utils@4.0.19(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.0.6 + zod: 3.25.76 + + '@ai-sdk/provider@3.0.8': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/xai@3.0.67(zod@3.25.76)': + dependencies: + '@ai-sdk/openai-compatible': 2.0.35(zod@3.25.76) + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + + '@anthropic-ai/sdk@0.78.0(zod@3.25.76)': dependencies: json-schema-to-ts: 3.1.1 optionalDependencies: @@ -3784,21 +4628,34 @@ snapshots: '@push.rocks/webrequest': 3.0.37 '@push.rocks/webstream': 1.0.10 - '@api.global/typedserver@3.0.80': + '@api.global/typedrequest@3.3.0': dependencies: - '@api.global/typedrequest': 3.1.10 '@api.global/typedrequest-interfaces': 3.0.19 - '@api.global/typedsocket': 3.0.1 - '@cloudflare/workers-types': 4.20251202.0 - '@design.estate/dees-comms': 1.0.27 - '@push.rocks/lik': 6.2.2 - '@push.rocks/smartchok': 1.2.0 + '@push.rocks/isounique': 1.0.5 + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartbuffer': 3.0.5 '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartenv': 5.0.13 + '@push.rocks/smartguard': 3.1.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/webrequest': 4.0.5 + '@push.rocks/webstream': 1.0.10 + + '@api.global/typedserver@8.4.2(@tiptap/pm@2.27.2)': + dependencies: + '@api.global/typedrequest': 3.3.0 + '@api.global/typedrequest-interfaces': 3.0.19 + '@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.1) + '@cloudflare/workers-types': 4.20260305.1 + '@design.estate/dees-catalog': 3.43.3(@tiptap/pm@2.27.2) + '@design.estate/dees-comms': 1.0.30 + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartenv': 6.0.0 '@push.rocks/smartfeed': 1.4.0 - '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smartfile': 13.1.2 + '@push.rocks/smartfs': 1.4.0 '@push.rocks/smartjson': 5.2.0 - '@push.rocks/smartlog': 3.1.10 + '@push.rocks/smartlog': 3.2.1 '@push.rocks/smartlog-destination-devtools': 1.0.12 '@push.rocks/smartlog-interfaces': 3.0.2 '@push.rocks/smartmanifest': 2.0.2 @@ -3808,46 +4665,39 @@ snapshots: '@push.rocks/smartopen': 2.0.0 '@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartrequest': 4.4.2 + '@push.rocks/smartrequest': 5.0.1 '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartserve': 2.0.1 '@push.rocks/smartsitemap': 2.0.4 - '@push.rocks/smartstream': 3.2.5 - '@push.rocks/smarttime': 4.1.1 - '@push.rocks/taskbuffer': 3.4.0 - '@push.rocks/webrequest': 3.0.37 + '@push.rocks/smartstream': 3.4.0 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/smartwatch': 6.3.0 + '@push.rocks/taskbuffer': 3.5.0 + '@push.rocks/webrequest': 4.0.5 '@push.rocks/webstore': 2.0.20 '@tsclass/tsclass': 9.3.0 - '@types/express': 5.0.6 - body-parser: 2.2.1 - cors: 2.8.5 - express: 5.2.1 - express-force-ssl: 0.3.2 - lit: 3.3.1 + lit: 3.3.2 transitivePeerDependencies: - '@nuxt/kit' + - '@tiptap/pm' - bufferutil - react - supports-color - utf-8-validate - vue - '@api.global/typedsocket@3.0.1': + '@api.global/typedsocket@4.1.2(@push.rocks/smartserve@2.0.1)': dependencies: - '@api.global/typedrequest': 3.1.10 + '@api.global/typedrequest': 3.3.0 '@api.global/typedrequest-interfaces': 3.0.19 '@push.rocks/isohash': 2.0.1 + '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartrx': 3.0.10 - '@push.rocks/smartsocket': 2.1.0 + '@push.rocks/smartserve': 2.0.1 '@push.rocks/smartstring': 4.1.0 '@push.rocks/smarturl': 3.1.0 - transitivePeerDependencies: - - '@nuxt/kit' - - bufferutil - - react - - supports-color - - utf-8-validate - - vue '@aws-crypto/crc32@5.2.0': dependencies: @@ -4342,12 +5192,51 @@ snapshots: '@borewit/text-codec@0.1.1': {} - '@cloudflare/workers-types@4.20251202.0': {} + '@borewit/text-codec@0.2.1': {} + + '@cfworker/json-schema@4.1.1': {} + + '@cloudflare/workers-types@4.20260305.1': {} '@configvault.io/interfaces@1.0.17': dependencies: '@api.global/typedrequest-interfaces': 3.0.19 + '@design.estate/dees-catalog@3.43.3(@tiptap/pm@2.27.2)': + dependencies: + '@design.estate/dees-domtools': 2.3.9 + '@design.estate/dees-element': 2.1.6 + '@design.estate/dees-wcctools': 3.8.0 + '@fortawesome/fontawesome-svg-core': 7.2.0 + '@fortawesome/free-brands-svg-icons': 7.2.0 + '@fortawesome/free-regular-svg-icons': 7.2.0 + '@fortawesome/free-solid-svg-icons': 7.2.0 + '@push.rocks/smarti18n': 1.0.4 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartstring': 4.1.0 + '@tempfix/webcontainer__api': 1.6.1 + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/extension-link': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-text-align': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-typography': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-underline': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/starter-kit': 2.27.2 + '@tsclass/tsclass': 9.3.0 + apexcharts: 5.10.1 + highlight.js: 11.11.1 + ibantools: 4.5.1 + lucide: 0.564.0 + monaco-editor: 0.55.1 + pdfjs-dist: 4.10.38 + xterm: 5.3.0 + xterm-addon-fit: 0.8.0(xterm@5.3.0) + transitivePeerDependencies: + - '@nuxt/kit' + - '@tiptap/pm' + - react + - supports-color + - vue + '@design.estate/dees-comms@1.0.27': dependencies: '@api.global/typedrequest': 3.1.10 @@ -4355,6 +5244,13 @@ snapshots: '@push.rocks/smartdelay': 3.0.5 broadcast-channel: 7.2.0 + '@design.estate/dees-comms@1.0.30': + dependencies: + '@api.global/typedrequest': 3.3.0 + '@api.global/typedrequest-interfaces': 3.0.19 + '@push.rocks/smartdelay': 3.0.5 + broadcast-channel: 7.3.0 + '@design.estate/dees-domtools@2.3.6': dependencies: '@api.global/typedrequest': 3.1.10 @@ -4381,6 +5277,32 @@ snapshots: - supports-color - vue + '@design.estate/dees-domtools@2.3.9': + dependencies: + '@api.global/typedrequest': 3.3.0 + '@design.estate/dees-comms': 1.0.30 + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartjson': 6.0.0 + '@push.rocks/smartmarkdown': 3.0.3 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrouter': 1.3.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartstate': 2.2.1 + '@push.rocks/smartstring': 4.1.0 + '@push.rocks/smarturl': 3.1.0 + '@push.rocks/webrequest': 4.0.5 + '@push.rocks/websetup': 3.0.19 + '@push.rocks/webstore': 2.0.20 + '@tempfix/lenis': 1.3.20 + lit: 3.3.2 + sweet-scroll: 4.0.0 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + '@design.estate/dees-element@2.1.3': dependencies: '@design.estate/dees-domtools': 2.3.6 @@ -4393,17 +5315,36 @@ snapshots: - supports-color - vue - '@emnapi/core@1.7.1': + '@design.estate/dees-element@2.1.6': + dependencies: + '@design.estate/dees-domtools': 2.3.9 + '@push.rocks/isounique': 1.0.5 + '@push.rocks/smartrx': 3.0.10 + lit: 3.3.2 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + + '@design.estate/dees-wcctools@3.8.0': + dependencies: + '@design.estate/dees-domtools': 2.3.9 + '@design.estate/dees-element': 2.1.6 + '@push.rocks/smartdelay': 3.0.5 + lit: 3.3.2 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + + '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.7.1': - dependencies: - tslib: 2.8.1 - optional: true - '@emnapi/runtime@1.8.1': dependencies: tslib: 2.8.1 @@ -4417,90 +5358,186 @@ snapshots: '@esbuild/aix-ppc64@0.27.1': optional: true + '@esbuild/aix-ppc64@0.27.3': + optional: true + '@esbuild/android-arm64@0.27.1': optional: true + '@esbuild/android-arm64@0.27.3': + optional: true + '@esbuild/android-arm@0.27.1': optional: true + '@esbuild/android-arm@0.27.3': + optional: true + '@esbuild/android-x64@0.27.1': optional: true + '@esbuild/android-x64@0.27.3': + optional: true + '@esbuild/darwin-arm64@0.27.1': optional: true + '@esbuild/darwin-arm64@0.27.3': + optional: true + '@esbuild/darwin-x64@0.27.1': optional: true + '@esbuild/darwin-x64@0.27.3': + optional: true + '@esbuild/freebsd-arm64@0.27.1': optional: true + '@esbuild/freebsd-arm64@0.27.3': + optional: true + '@esbuild/freebsd-x64@0.27.1': optional: true + '@esbuild/freebsd-x64@0.27.3': + optional: true + '@esbuild/linux-arm64@0.27.1': optional: true + '@esbuild/linux-arm64@0.27.3': + optional: true + '@esbuild/linux-arm@0.27.1': optional: true + '@esbuild/linux-arm@0.27.3': + optional: true + '@esbuild/linux-ia32@0.27.1': optional: true + '@esbuild/linux-ia32@0.27.3': + optional: true + '@esbuild/linux-loong64@0.27.1': optional: true + '@esbuild/linux-loong64@0.27.3': + optional: true + '@esbuild/linux-mips64el@0.27.1': optional: true + '@esbuild/linux-mips64el@0.27.3': + optional: true + '@esbuild/linux-ppc64@0.27.1': optional: true + '@esbuild/linux-ppc64@0.27.3': + optional: true + '@esbuild/linux-riscv64@0.27.1': optional: true + '@esbuild/linux-riscv64@0.27.3': + optional: true + '@esbuild/linux-s390x@0.27.1': optional: true + '@esbuild/linux-s390x@0.27.3': + optional: true + '@esbuild/linux-x64@0.27.1': optional: true + '@esbuild/linux-x64@0.27.3': + optional: true + '@esbuild/netbsd-arm64@0.27.1': optional: true + '@esbuild/netbsd-arm64@0.27.3': + optional: true + '@esbuild/netbsd-x64@0.27.1': optional: true + '@esbuild/netbsd-x64@0.27.3': + optional: true + '@esbuild/openbsd-arm64@0.27.1': optional: true + '@esbuild/openbsd-arm64@0.27.3': + optional: true + '@esbuild/openbsd-x64@0.27.1': optional: true + '@esbuild/openbsd-x64@0.27.3': + optional: true + '@esbuild/openharmony-arm64@0.27.1': optional: true + '@esbuild/openharmony-arm64@0.27.3': + optional: true + '@esbuild/sunos-x64@0.27.1': optional: true + '@esbuild/sunos-x64@0.27.3': + optional: true + '@esbuild/win32-arm64@0.27.1': optional: true + '@esbuild/win32-arm64@0.27.3': + optional: true + '@esbuild/win32-ia32@0.27.1': optional: true + '@esbuild/win32-ia32@0.27.3': + optional: true + '@esbuild/win32-x64@0.27.1': optional: true - '@git.zone/tsbuild@4.0.2': + '@esbuild/win32-x64@0.27.3': + optional: true + + '@fortawesome/fontawesome-common-types@7.2.0': {} + + '@fortawesome/fontawesome-svg-core@7.2.0': dependencies: - '@git.zone/tspublish': 1.10.3 + '@fortawesome/fontawesome-common-types': 7.2.0 + + '@fortawesome/free-brands-svg-icons@7.2.0': + dependencies: + '@fortawesome/fontawesome-common-types': 7.2.0 + + '@fortawesome/free-regular-svg-icons@7.2.0': + dependencies: + '@fortawesome/fontawesome-common-types': 7.2.0 + + '@fortawesome/free-solid-svg-icons@7.2.0': + dependencies: + '@fortawesome/fontawesome-common-types': 7.2.0 + + '@git.zone/tsbuild@4.3.0': + dependencies: + '@git.zone/tspublish': 1.11.2 '@push.rocks/early': 4.0.4 - '@push.rocks/smartcli': 4.0.19 + '@push.rocks/smartcli': 4.0.20 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartfile': 13.1.2 - '@push.rocks/smartfs': 1.2.0 - '@push.rocks/smartlog': 3.1.10 + '@push.rocks/smartfs': 1.4.0 + '@push.rocks/smartlog': 3.2.1 '@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpromise': 4.2.3 typescript: 5.9.3 @@ -4508,47 +5545,56 @@ snapshots: - '@nuxt/kit' - aws-crt - bare-abort-controller + - bare-buffer - react - react-native-b4a - supports-color - vue - '@git.zone/tsbundle@2.6.3': + '@git.zone/tsbundle@2.9.1': dependencies: '@push.rocks/early': 4.0.4 - '@push.rocks/smartcli': 4.0.19 + '@push.rocks/npmextra': 5.3.3 + '@push.rocks/smartcli': 4.0.20 '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartfs': 1.2.0 - '@push.rocks/smartlog': 3.1.10 + '@push.rocks/smartfs': 1.4.0 + '@push.rocks/smartinteract': 2.0.16 + '@push.rocks/smartlog': 3.2.1 '@push.rocks/smartlog-destination-local': 9.0.2 '@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartspawn': 3.0.3 - '@rspack/core': 1.6.7 + '@rspack/core': 1.7.7 '@types/html-minifier': 4.0.6 - esbuild: 0.27.1 + esbuild: 0.27.3 html-minifier: 4.0.0 rolldown: 1.0.0-beta.52 typescript: 5.9.3 transitivePeerDependencies: + - '@nuxt/kit' - '@swc/helpers' + - react - supports-color + - vue - '@git.zone/tspublish@1.10.3': + '@git.zone/tspublish@1.11.2': dependencies: '@push.rocks/consolecolor': 2.0.3 - '@push.rocks/smartcli': 4.0.19 + '@push.rocks/npmextra': 5.3.3 + '@push.rocks/smartcli': 4.0.20 '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartfile': 11.2.7 - '@push.rocks/smartlog': 3.1.10 + '@push.rocks/smartfile': 13.1.2 + '@push.rocks/smartfs': 1.4.0 + '@push.rocks/smartlog': 3.2.1 '@push.rocks/smartnpm': 2.0.6 '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartrequest': 4.4.2 - '@push.rocks/smartshell': 3.3.0 + '@push.rocks/smartrequest': 5.0.1 + '@push.rocks/smartshell': 3.3.7 transitivePeerDependencies: - '@nuxt/kit' - aws-crt - bare-abort-controller + - bare-buffer - react - react-native-b4a - supports-color @@ -4557,42 +5603,43 @@ snapshots: '@git.zone/tsrun@2.0.1': dependencies: '@push.rocks/smartfile': 13.1.2 - '@push.rocks/smartshell': 3.3.0 + '@push.rocks/smartshell': 3.3.7 tsx: 4.21.0 - '@git.zone/tstest@3.1.3(socks@2.8.7)(typescript@5.9.3)': + '@git.zone/tstest@3.3.0(@tiptap/pm@2.27.2)(socks@2.8.7)(typescript@5.9.3)': dependencies: - '@api.global/typedserver': 3.0.80 - '@git.zone/tsbundle': 2.6.3 + '@api.global/typedserver': 8.4.2(@tiptap/pm@2.27.2) + '@git.zone/tsbundle': 2.9.1 '@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) - '@push.rocks/smartchok': 1.2.0 '@push.rocks/smartcrypto': 2.0.4 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartenv': 6.0.0 '@push.rocks/smartexpect': 2.5.0 - '@push.rocks/smartfile': 11.2.7 - '@push.rocks/smartjson': 5.2.0 - '@push.rocks/smartlog': 3.1.10 - '@push.rocks/smartmongo': 2.0.14(socks@2.8.7) + '@push.rocks/smartfile': 13.1.2 + '@push.rocks/smartfs': 1.4.0 + '@push.rocks/smartjson': 6.0.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartmongo': 5.1.0(socks@2.8.7) '@push.rocks/smartnetwork': 4.4.0 '@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartrequest': 5.0.1 - '@push.rocks/smarts3': 3.0.3 - '@push.rocks/smartshell': 3.3.0 - '@push.rocks/smarttime': 4.1.1 + '@push.rocks/smarts3': 5.3.0 + '@push.rocks/smartshell': 3.3.7 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/smartwatch': 6.3.0 '@types/ws': 8.18.1 figures: 6.1.0 - ws: 8.18.3 + ws: 8.19.0 transitivePeerDependencies: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' - '@nuxt/kit' - '@swc/helpers' - - aws-crt + - '@tiptap/pm' - bare-abort-controller - bare-buffer - bufferutil @@ -4708,11 +5755,101 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.0': + '@inquirer/checkbox@3.0.1': dependencies: - '@isaacs/balanced-match': 4.0.1 + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.3 + + '@inquirer/confirm@4.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/core@9.2.1': + dependencies: + '@inquirer/figures': 1.0.15 + '@inquirer/type': 2.0.0 + '@types/mute-stream': 0.0.4 + '@types/node': 22.19.15 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/editor@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + external-editor: 3.1.0 + + '@inquirer/expand@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/figures@1.0.15': {} + + '@inquirer/input@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/number@2.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/password@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + + '@inquirer/prompts@6.0.1': + dependencies: + '@inquirer/checkbox': 3.0.1 + '@inquirer/confirm': 4.0.1 + '@inquirer/editor': 3.0.1 + '@inquirer/expand': 3.0.1 + '@inquirer/input': 3.0.1 + '@inquirer/number': 2.0.1 + '@inquirer/password': 3.0.1 + '@inquirer/rawlist': 3.0.1 + '@inquirer/search': 2.0.1 + '@inquirer/select': 3.0.1 + + '@inquirer/rawlist@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/search@2.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/select@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.3 + + '@inquirer/type@2.0.0': + dependencies: + mute-stream: 1.0.0 '@isaacs/cliui@8.0.2': dependencies: @@ -4916,60 +6053,111 @@ snapshots: '@lit-labs/ssr-dom-shim@1.4.0': {} + '@lit-labs/ssr-dom-shim@1.5.1': {} + '@lit/reactive-element@2.1.1': dependencies: '@lit-labs/ssr-dom-shim': 1.4.0 - '@mistralai/mistralai@1.12.0': + '@lit/reactive-element@2.1.2': dependencies: - zod: 3.25.76 - zod-to-json-schema: 3.25.1(zod@3.25.76) + '@lit-labs/ssr-dom-shim': 1.5.1 '@mixmark-io/domino@2.2.0': {} - '@module-federation/error-codes@0.21.6': {} + '@module-federation/error-codes@0.22.0': {} - '@module-federation/runtime-core@0.21.6': + '@module-federation/runtime-core@0.22.0': dependencies: - '@module-federation/error-codes': 0.21.6 - '@module-federation/sdk': 0.21.6 + '@module-federation/error-codes': 0.22.0 + '@module-federation/sdk': 0.22.0 - '@module-federation/runtime-tools@0.21.6': + '@module-federation/runtime-tools@0.22.0': dependencies: - '@module-federation/runtime': 0.21.6 - '@module-federation/webpack-bundler-runtime': 0.21.6 + '@module-federation/runtime': 0.22.0 + '@module-federation/webpack-bundler-runtime': 0.22.0 - '@module-federation/runtime@0.21.6': + '@module-federation/runtime@0.22.0': dependencies: - '@module-federation/error-codes': 0.21.6 - '@module-federation/runtime-core': 0.21.6 - '@module-federation/sdk': 0.21.6 + '@module-federation/error-codes': 0.22.0 + '@module-federation/runtime-core': 0.22.0 + '@module-federation/sdk': 0.22.0 - '@module-federation/sdk@0.21.6': {} + '@module-federation/sdk@0.22.0': {} - '@module-federation/webpack-bundler-runtime@0.21.6': + '@module-federation/webpack-bundler-runtime@0.22.0': dependencies: - '@module-federation/runtime': 0.21.6 - '@module-federation/sdk': 0.21.6 + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 - '@mongodb-js/saslprep@1.3.2': + '@mongodb-js/saslprep@1.4.6': dependencies: sparse-bitfield: 3.0.3 + '@napi-rs/canvas-android-arm64@0.1.96': + optional: true + + '@napi-rs/canvas-darwin-arm64@0.1.96': + optional: true + + '@napi-rs/canvas-darwin-x64@0.1.96': + optional: true + + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.96': + optional: true + + '@napi-rs/canvas-linux-arm64-gnu@0.1.96': + optional: true + + '@napi-rs/canvas-linux-arm64-musl@0.1.96': + optional: true + + '@napi-rs/canvas-linux-riscv64-gnu@0.1.96': + optional: true + + '@napi-rs/canvas-linux-x64-gnu@0.1.96': + optional: true + + '@napi-rs/canvas-linux-x64-musl@0.1.96': + optional: true + + '@napi-rs/canvas-win32-arm64-msvc@0.1.96': + optional: true + + '@napi-rs/canvas-win32-x64-msvc@0.1.96': + optional: true + + '@napi-rs/canvas@0.1.96': + optionalDependencies: + '@napi-rs/canvas-android-arm64': 0.1.96 + '@napi-rs/canvas-darwin-arm64': 0.1.96 + '@napi-rs/canvas-darwin-x64': 0.1.96 + '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.96 + '@napi-rs/canvas-linux-arm64-gnu': 0.1.96 + '@napi-rs/canvas-linux-arm64-musl': 0.1.96 + '@napi-rs/canvas-linux-riscv64-gnu': 0.1.96 + '@napi-rs/canvas-linux-x64-gnu': 0.1.96 + '@napi-rs/canvas-linux-x64-musl': 0.1.96 + '@napi-rs/canvas-win32-arm64-msvc': 0.1.96 + '@napi-rs/canvas-win32-x64-msvc': 0.1.96 + optional: true + '@napi-rs/wasm-runtime@1.0.7': dependencies: - '@emnapi/core': 1.7.1 - '@emnapi/runtime': 1.7.1 + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 '@tybys/wasm-util': 0.10.1 optional: true - '@napi-rs/wasm-runtime@1.1.0': + '@napi-rs/wasm-runtime@1.1.1': dependencies: - '@emnapi/core': 1.7.1 - '@emnapi/runtime': 1.7.1 + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 '@tybys/wasm-util': 0.10.1 optional: true + '@opentelemetry/api@1.9.0': {} + '@oxc-project/types@0.99.0': {} '@pdf-lib/standard-fonts@1.0.0': @@ -5076,7 +6264,7 @@ snapshots: dependencies: graceful-fs: 4.2.10 - '@pnpm/npm-conf@2.3.1': + '@pnpm/npm-conf@3.0.2': dependencies: '@pnpm/config.env-replace': 1.1.0 '@pnpm/network.ca-file': 1.0.2 @@ -5146,9 +6334,20 @@ snapshots: '@types/symbol-tree': 3.2.5 symbol-tree: 3.2.4 + '@push.rocks/lik@6.3.1': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartmatch': 2.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smarttime': 4.2.3 + '@types/minimatch': 5.1.2 + '@types/symbol-tree': 3.2.5 + symbol-tree: 3.2.4 + '@push.rocks/mongodump@1.1.0(socks@2.8.7)': dependencies: - '@push.rocks/lik': 6.2.2 + '@push.rocks/lik': 6.3.1 '@push.rocks/smartfile': 11.2.7 '@push.rocks/smartjson': 5.2.0 '@push.rocks/smartpath': 6.0.0 @@ -5164,26 +6363,45 @@ snapshots: - snappy - socks + '@push.rocks/npmextra@5.3.3': + dependencies: + '@push.rocks/qenv': 6.1.3 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/taskbuffer': 3.5.0 + '@tsclass/tsclass': 9.3.0 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + '@push.rocks/qenv@6.1.3': dependencies: - '@api.global/typedrequest': 3.1.10 + '@api.global/typedrequest': 3.3.0 '@configvault.io/interfaces': 1.0.17 '@push.rocks/smartfile': 11.2.7 - '@push.rocks/smartlog': 3.1.10 + '@push.rocks/smartlog': 3.2.1 '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartai@0.13.3(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)': + '@push.rocks/smartai@2.0.0(typescript@5.9.3)(ws@8.19.0)(zod@3.25.76)': dependencies: - '@anthropic-ai/sdk': 0.71.2(zod@3.25.76) - '@mistralai/mistralai': 1.12.0 - '@push.rocks/smartarray': 1.1.0 - '@push.rocks/smartfs': 1.3.1 - '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartpdf': 4.1.1(typescript@5.9.3) - '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartrequest': 5.0.1 - '@push.rocks/webstream': 1.0.10 - openai: 6.16.0(ws@8.18.3)(zod@3.25.76) + '@ai-sdk/anthropic': 3.0.58(zod@3.25.76) + '@ai-sdk/google': 3.0.43(zod@3.25.76) + '@ai-sdk/groq': 3.0.29(zod@3.25.76) + '@ai-sdk/mistral': 3.0.24(zod@3.25.76) + '@ai-sdk/openai': 3.0.41(zod@3.25.76) + '@ai-sdk/perplexity': 3.0.23(zod@3.25.76) + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/xai': 3.0.67(zod@3.25.76) + '@anthropic-ai/sdk': 0.78.0(zod@3.25.76) + '@push.rocks/smartpdf': 4.1.3(typescript@5.9.3) + ai: 6.0.116(zod@3.25.76) + openai: 6.27.0(ws@8.19.0)(zod@3.25.76) transitivePeerDependencies: - '@nuxt/kit' - aws-crt @@ -5207,40 +6425,19 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartrequest': 4.4.2 '@push.rocks/smartrx': 3.0.10 - '@push.rocks/smartstream': 3.2.5 + '@push.rocks/smartstream': 3.4.0 '@push.rocks/smartunique': 3.0.9 '@push.rocks/smarturl': 3.1.0 '@types/tar-stream': 3.1.4 fflate: 0.8.2 - file-type: 21.1.1 - tar-stream: 3.1.7 + file-type: 21.3.0 + tar-stream: 3.1.8 transitivePeerDependencies: - bare-abort-controller + - bare-buffer - react-native-b4a - supports-color - '@push.rocks/smartarchive@5.0.1': - dependencies: - '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartfile': 13.1.0 - '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartrequest': 4.4.2 - '@push.rocks/smartrx': 3.0.10 - '@push.rocks/smartstream': 3.2.5 - '@push.rocks/smartunique': 3.0.9 - '@push.rocks/smarturl': 3.1.0 - '@types/tar-stream': 3.1.4 - fflate: 0.8.2 - file-type: 21.1.1 - tar-stream: 3.1.7 - transitivePeerDependencies: - - bare-abort-controller - - react-native-b4a - - supports-color - - '@push.rocks/smartarray@1.1.0': {} - '@push.rocks/smartbrowser@2.0.8(typescript@5.9.3)': dependencies: '@push.rocks/smartdelay': 3.0.5 @@ -5270,21 +6467,6 @@ snapshots: transitivePeerDependencies: - aws-crt - '@push.rocks/smartbucket@4.3.0': - dependencies: - '@aws-sdk/client-s3': 3.940.0 - '@push.rocks/smartmime': 2.0.4 - '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartrx': 3.0.10 - '@push.rocks/smartstream': 3.2.5 - '@push.rocks/smartstring': 4.1.0 - '@push.rocks/smartunique': 3.0.9 - '@tsclass/tsclass': 9.3.0 - minimatch: 10.1.1 - transitivePeerDependencies: - - aws-crt - '@push.rocks/smartbuffer@3.0.5': dependencies: uint8array-extras: 1.5.0 @@ -5297,18 +6479,10 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smarttime': 4.1.1 - '@push.rocks/smartchok@1.2.0': + '@push.rocks/smartcli@4.0.20': dependencies: - '@push.rocks/lik': 6.2.2 - '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartrx': 3.0.10 - chokidar: 5.0.0 - picomatch: 4.0.3 - - '@push.rocks/smartcli@4.0.19': - dependencies: - '@push.rocks/lik': 6.2.2 - '@push.rocks/smartlog': 3.1.10 + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartlog': 3.2.1 '@push.rocks/smartobject': 1.0.12 '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartrx': 3.0.10 @@ -5323,24 +6497,33 @@ snapshots: '@push.rocks/smarturl': 3.1.0 '@push.rocks/webrequest': 3.0.37 + '@push.rocks/smartclickhouse@2.2.0': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartobject': 1.0.12 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smarturl': 3.1.0 + '@push.rocks/webrequest': 4.0.5 + '@push.rocks/smartcrypto@2.0.4': dependencies: '@push.rocks/smartpromise': 4.2.3 '@types/node-forge': 1.3.14 - node-forge: 1.3.2 + node-forge: 1.3.3 '@push.rocks/smartdata@5.16.7(socks@2.8.7)': dependencies: - '@push.rocks/lik': 6.2.2 + '@push.rocks/lik': 6.3.1 '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartlog': 3.1.10 - '@push.rocks/smartmongo': 2.0.14(socks@2.8.7) + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartmongo': 2.2.0(socks@2.8.7) '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartrx': 3.0.10 '@push.rocks/smartstring': 4.1.0 - '@push.rocks/smarttime': 4.1.1 + '@push.rocks/smarttime': 4.2.3 '@push.rocks/smartunique': 3.0.9 - '@push.rocks/taskbuffer': 3.4.0 + '@push.rocks/taskbuffer': 3.5.0 '@tsclass/tsclass': 9.3.0 mongodb: 6.21.0(socks@2.8.7) transitivePeerDependencies: @@ -5348,6 +6531,7 @@ snapshots: - '@mongodb-js/zstd' - '@nuxt/kit' - bare-abort-controller + - bare-buffer - gcp-metadata - kerberos - mongodb-client-encryption @@ -5362,18 +6546,6 @@ snapshots: dependencies: '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartdeno@1.2.0': - dependencies: - '@push.rocks/smartarchive': 5.0.1 - '@push.rocks/smartfs': 1.2.0 - '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartshell': 3.3.0 - '@push.rocks/smartunique': 3.0.9 - transitivePeerDependencies: - - bare-abort-controller - - react-native-b4a - - supports-color - '@push.rocks/smartdns@7.6.1': dependencies: '@push.rocks/smartdelay': 3.0.5 @@ -5386,7 +6558,7 @@ snapshots: acme-client: 5.4.0 dns-packet: 5.6.1 elliptic: 6.6.1 - minimatch: 10.1.1 + minimatch: 10.2.4 transitivePeerDependencies: - supports-color @@ -5410,6 +6582,11 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 tree-kill: 1.2.2 + '@push.rocks/smartexit@2.0.3': + dependencies: + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartexpect@2.5.0': dependencies: '@push.rocks/smartdelay': 3.0.5 @@ -5419,7 +6596,7 @@ snapshots: '@push.rocks/smartfeed@1.4.0': dependencies: '@tsclass/tsclass': 9.3.0 - fast-xml-parser: 4.5.3 + fast-xml-parser: 4.5.4 '@push.rocks/smartfile-interfaces@1.0.7': {} @@ -5441,29 +6618,12 @@ snapshots: glob: 11.1.0 js-yaml: 4.1.1 - '@push.rocks/smartfile@13.1.0': - 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/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/smartfs': 1.4.0 '@push.rocks/smarthash': 3.2.6 '@push.rocks/smartjson': 5.2.0 '@push.rocks/smartmime': 2.0.4 @@ -5475,13 +6635,10 @@ snapshots: glob: 11.1.0 js-yaml: 4.1.1 - '@push.rocks/smartfs@1.2.0': - dependencies: - '@push.rocks/smartpath': 6.0.0 - - '@push.rocks/smartfs@1.3.1': + '@push.rocks/smartfs@1.4.0': dependencies: '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartrust': 1.3.1 '@push.rocks/smartguard@3.1.0': dependencies: @@ -5496,6 +6653,15 @@ snapshots: '@types/through2': 2.0.41 through2: 4.0.2 + '@push.rocks/smarti18n@1.0.4': {} + + '@push.rocks/smartinteract@2.0.16': + dependencies: + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartobject': 1.0.12 + '@push.rocks/smartpromise': 4.2.3 + inquirer: 11.1.0 + '@push.rocks/smartjimp@1.2.0': dependencies: '@push.rocks/levelcache': 3.2.0 @@ -5519,6 +6685,13 @@ snapshots: fast-json-stable-stringify: 2.1.0 lodash.clonedeep: 4.5.0 + '@push.rocks/smartjson@6.0.0': + dependencies: + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartstring': 4.1.0 + fast-json-stable-stringify: 2.1.0 + lodash.clonedeep: 4.5.0 + '@push.rocks/smartlog-destination-devtools@1.0.12': dependencies: '@push.rocks/smartlog-interfaces': 3.0.2 @@ -5547,6 +6720,19 @@ snapshots: '@push.rocks/webrequest': 3.0.37 '@tsclass/tsclass': 9.3.0 + '@push.rocks/smartlog@3.2.1': + dependencies: + '@api.global/typedrequest-interfaces': 3.0.19 + '@push.rocks/consolecolor': 2.0.3 + '@push.rocks/isounique': 1.0.5 + '@push.rocks/smartclickhouse': 2.2.0 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smarthash': 3.2.6 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/webrequest': 4.0.5 + '@tsclass/tsclass': 9.3.0 + '@push.rocks/smartmanifest@2.0.2': {} '@push.rocks/smartmarkdown@3.0.3': @@ -5574,18 +6760,50 @@ snapshots: file-type: 19.6.0 mime: 4.1.0 - '@push.rocks/smartmongo@2.0.14(socks@2.8.7)': + '@push.rocks/smartmongo@2.2.0(socks@2.8.7)': dependencies: '@push.rocks/mongodump': 1.1.0(socks@2.8.7) '@push.rocks/smartdata': 5.16.7(socks@2.8.7) + '@push.rocks/smartfs': 1.4.0 '@push.rocks/smartpath': 5.1.0 '@push.rocks/smartpromise': 4.2.3 - mongodb-memory-server: 10.3.0(socks@2.8.7) + '@push.rocks/smartrx': 3.0.10 + bson: 6.10.4 + mingo: 7.2.0 + mongodb-memory-server: 10.4.3(socks@2.8.7) transitivePeerDependencies: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' - '@nuxt/kit' - bare-abort-controller + - bare-buffer + - gcp-metadata + - kerberos + - mongodb-client-encryption + - react + - react-native-b4a + - snappy + - socks + - supports-color + - vue + + '@push.rocks/smartmongo@5.1.0(socks@2.8.7)': + dependencies: + '@push.rocks/mongodump': 1.1.0(socks@2.8.7) + '@push.rocks/smartdata': 5.16.7(socks@2.8.7) + '@push.rocks/smartfs': 1.4.0 + '@push.rocks/smartpath': 5.1.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + bson: 6.10.4 + mingo: 7.2.0 + mongodb-memory-server: 10.4.3(socks@2.8.7) + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - '@nuxt/kit' + - bare-abort-controller + - bare-buffer - gcp-metadata - kerberos - mongodb-client-encryption @@ -5616,13 +6834,14 @@ snapshots: '@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartrequest': 4.4.2 - '@push.rocks/smarttime': 4.1.1 + '@push.rocks/smarttime': 4.2.3 '@push.rocks/smartversion': 3.0.5 package-json: 8.1.1 transitivePeerDependencies: - '@nuxt/kit' - aws-crt - bare-abort-controller + - bare-buffer - react - react-native-b4a - supports-color @@ -5630,7 +6849,7 @@ snapshots: '@push.rocks/smartntml@2.0.8': dependencies: - '@design.estate/dees-element': 2.1.3 + '@design.estate/dees-element': 2.1.6 '@happy-dom/global-registrator': 15.11.7 '@push.rocks/smartpromise': 4.2.3 fake-indexeddb: 6.2.5 @@ -5643,7 +6862,7 @@ snapshots: '@push.rocks/smartobject@1.0.12': dependencies: fast-deep-equal: 3.1.3 - minimatch: 9.0.5 + minimatch: 9.0.9 '@push.rocks/smartopen@2.0.0': dependencies: @@ -5677,11 +6896,11 @@ snapshots: - typescript - utf-8-validate - '@push.rocks/smartpdf@4.1.1(typescript@5.9.3)': + '@push.rocks/smartpdf@4.1.3(typescript@5.9.3)': dependencies: '@push.rocks/smartbuffer': 3.0.5 '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smartfs': 1.4.0 '@push.rocks/smartjimp': 1.2.0 '@push.rocks/smartnetwork': 4.4.0 '@push.rocks/smartpath': 6.0.0 @@ -5692,7 +6911,7 @@ snapshots: '@types/express': 5.0.6 express: 5.2.1 pdf-lib: 1.17.1 - pdf2json: 3.2.0 + pdf2json: 4.0.2 transitivePeerDependencies: - '@nuxt/kit' - aws-crt @@ -5716,7 +6935,7 @@ snapshots: '@push.rocks/smartpuppeteer@2.0.5(typescript@5.9.3)': dependencies: '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartshell': 3.3.0 + '@push.rocks/smartshell': 3.3.7 puppeteer: 24.31.0(typescript@5.9.3) tree-kill: 1.2.2 transitivePeerDependencies: @@ -5759,29 +6978,41 @@ snapshots: '@push.rocks/smartrx': 3.0.10 path-to-regexp: 8.3.0 + '@push.rocks/smartrust@1.3.1': + dependencies: + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartrx@3.0.10': dependencies: '@push.rocks/smartpromise': 4.2.3 rxjs: 7.8.2 - '@push.rocks/smarts3@3.0.3': + '@push.rocks/smarts3@5.3.0': dependencies: - '@push.rocks/smartbucket': 4.3.0 - '@push.rocks/smartfs': 1.2.0 '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartxml': 2.0.0 + '@push.rocks/smartrust': 1.3.1 '@tsclass/tsclass': 9.3.0 - transitivePeerDependencies: - - aws-crt - '@push.rocks/smartshell@3.3.0': + '@push.rocks/smartserve@2.0.1': + dependencies: + '@api.global/typedrequest': 3.3.0 + '@cfworker/json-schema': 4.1.1 + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpath': 6.0.0 + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@push.rocks/smartshell@3.3.7': dependencies: '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartexit': 1.0.23 + '@push.rocks/smartexit': 2.0.3 '@push.rocks/smartpromise': 4.2.3 '@types/which': 3.0.4 - tree-kill: 1.2.2 - which: 5.0.0 + which: 6.0.1 '@push.rocks/smartsitemap@2.0.4': dependencies: @@ -5789,34 +7020,9 @@ snapshots: '@push.rocks/smartfeed': 1.4.0 '@push.rocks/smartxml': 2.0.0 '@push.rocks/smartyaml': 3.0.4 - '@push.rocks/webrequest': 4.0.1 + '@push.rocks/webrequest': 4.0.5 '@tsclass/tsclass': 9.3.0 - '@push.rocks/smartsocket@2.1.0': - dependencies: - '@api.global/typedrequest-interfaces': 3.0.19 - '@api.global/typedserver': 3.0.80 - '@push.rocks/isohash': 2.0.1 - '@push.rocks/isounique': 1.0.5 - '@push.rocks/lik': 6.2.2 - '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartenv': 5.0.13 - '@push.rocks/smartjson': 5.2.0 - '@push.rocks/smartlog': 3.1.10 - '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartrx': 3.0.10 - '@push.rocks/smarttime': 4.1.1 - engine.io: 6.6.4 - socket.io: 4.8.1 - socket.io-client: 4.8.1 - transitivePeerDependencies: - - '@nuxt/kit' - - bufferutil - - react - - supports-color - - utf-8-validate - - vue - '@push.rocks/smartspawn@3.0.3': dependencies: '@push.rocks/smartpromise': 4.2.3 @@ -5835,6 +7041,14 @@ snapshots: '@push.rocks/smartrx': 3.0.10 '@push.rocks/webstore': 2.0.20 + '@push.rocks/smartstate@2.2.1': + dependencies: + '@push.rocks/smarthash': 3.2.6 + '@push.rocks/smartjson': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/webstore': 2.0.20 + '@push.rocks/smartstream@3.2.5': dependencies: '@push.rocks/lik': 6.2.2 @@ -5842,6 +7056,13 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartstream@3.4.0': + dependencies: + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartstring@4.1.0': dependencies: '@push.rocks/isounique': 1.0.5 @@ -5857,6 +7078,17 @@ snapshots: is-nan: 1.3.2 pretty-ms: 9.3.0 + '@push.rocks/smarttime@4.2.3': + dependencies: + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartpromise': 4.2.3 + croner: 10.0.1 + date-fns: 4.1.0 + dayjs: 1.11.19 + is-nan: 1.3.2 + pretty-ms: 9.3.0 + '@push.rocks/smartunique@3.0.9': dependencies: '@types/uuid': 9.0.8 @@ -5868,11 +7100,20 @@ snapshots: '@push.rocks/smartversion@3.0.5': dependencies: '@types/semver': 7.7.1 - semver: 7.7.3 + semver: 7.7.4 + + '@push.rocks/smartwatch@6.3.0': + dependencies: + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + chokidar: 5.0.0 + picomatch: 4.0.3 '@push.rocks/smartxml@2.0.0': dependencies: - fast-xml-parser: 5.3.2 + fast-xml-parser: 5.4.2 '@push.rocks/smartyaml@2.0.5': dependencies: @@ -5899,6 +7140,22 @@ snapshots: - supports-color - vue + '@push.rocks/taskbuffer@3.5.0': + dependencies: + '@design.estate/dees-element': 2.1.6 + '@push.rocks/lik': 6.3.1 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/smartunique': 3.0.9 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + '@push.rocks/webrequest@3.0.37': dependencies: '@push.rocks/smartdelay': 3.0.5 @@ -5907,11 +7164,11 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 '@push.rocks/webstore': 2.0.20 - '@push.rocks/webrequest@4.0.1': + '@push.rocks/webrequest@4.0.5': dependencies: '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartenv': 5.0.13 - '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartjson': 6.0.0 '@push.rocks/smartpromise': 4.2.3 '@push.rocks/webstore': 2.0.20 @@ -5978,6 +7235,8 @@ snapshots: strip-indent: 4.1.1 url: 0.11.4 + '@remirror/core-constants@3.0.0': {} + '@rolldown/binding-android-arm64@1.0.0-beta.52': optional: true @@ -6010,7 +7269,7 @@ snapshots: '@rolldown/binding-wasm32-wasi@1.0.0-beta.52': dependencies: - '@napi-rs/wasm-runtime': 1.1.0 + '@napi-rs/wasm-runtime': 1.1.1 optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.52': @@ -6024,55 +7283,55 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.52': {} - '@rspack/binding-darwin-arm64@1.6.7': + '@rspack/binding-darwin-arm64@1.7.7': optional: true - '@rspack/binding-darwin-x64@1.6.7': + '@rspack/binding-darwin-x64@1.7.7': optional: true - '@rspack/binding-linux-arm64-gnu@1.6.7': + '@rspack/binding-linux-arm64-gnu@1.7.7': optional: true - '@rspack/binding-linux-arm64-musl@1.6.7': + '@rspack/binding-linux-arm64-musl@1.7.7': optional: true - '@rspack/binding-linux-x64-gnu@1.6.7': + '@rspack/binding-linux-x64-gnu@1.7.7': optional: true - '@rspack/binding-linux-x64-musl@1.6.7': + '@rspack/binding-linux-x64-musl@1.7.7': optional: true - '@rspack/binding-wasm32-wasi@1.6.7': + '@rspack/binding-wasm32-wasi@1.7.7': dependencies: '@napi-rs/wasm-runtime': 1.0.7 optional: true - '@rspack/binding-win32-arm64-msvc@1.6.7': + '@rspack/binding-win32-arm64-msvc@1.7.7': optional: true - '@rspack/binding-win32-ia32-msvc@1.6.7': + '@rspack/binding-win32-ia32-msvc@1.7.7': optional: true - '@rspack/binding-win32-x64-msvc@1.6.7': + '@rspack/binding-win32-x64-msvc@1.7.7': optional: true - '@rspack/binding@1.6.7': + '@rspack/binding@1.7.7': optionalDependencies: - '@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/binding-darwin-arm64': 1.7.7 + '@rspack/binding-darwin-x64': 1.7.7 + '@rspack/binding-linux-arm64-gnu': 1.7.7 + '@rspack/binding-linux-arm64-musl': 1.7.7 + '@rspack/binding-linux-x64-gnu': 1.7.7 + '@rspack/binding-linux-x64-musl': 1.7.7 + '@rspack/binding-wasm32-wasi': 1.7.7 + '@rspack/binding-win32-arm64-msvc': 1.7.7 + '@rspack/binding-win32-ia32-msvc': 1.7.7 + '@rspack/binding-win32-x64-msvc': 1.7.7 - '@rspack/core@1.6.7': + '@rspack/core@1.7.7': dependencies: - '@module-federation/runtime-tools': 0.21.6 - '@rspack/binding': 1.6.7 + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.7 '@rspack/lite-tapable': 1.1.0 '@rspack/lite-tapable@1.1.0': {} @@ -6419,7 +7678,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@socket.io/component-emitter@3.1.2': {} + '@standard-schema/spec@1.1.0': {} '@szmarczak/http-timer@5.0.1': dependencies: @@ -6427,6 +7686,158 @@ snapshots: '@tempfix/idb@8.0.3': {} + '@tempfix/lenis@1.3.20': {} + + '@tempfix/webcontainer__api@1.6.1': {} + + '@tiptap/core@2.27.2(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-blockquote@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-bold@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-bullet-list@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-code-block@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-code@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-document@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-dropcursor@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-gapcursor@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-hard-break@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-heading@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-history@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-horizontal-rule@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-italic@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-link@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + linkifyjs: 4.3.2 + + '@tiptap/extension-list-item@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-ordered-list@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-paragraph@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-strike@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-text-align@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-text-style@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-text@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-typography@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-underline@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/pm@2.27.2': + dependencies: + prosemirror-changeset: 2.4.0 + prosemirror-collab: 1.3.1 + prosemirror-commands: 1.7.1 + prosemirror-dropcursor: 1.8.2 + prosemirror-gapcursor: 1.4.0 + prosemirror-history: 1.5.0 + prosemirror-inputrules: 1.5.1 + prosemirror-keymap: 1.2.3 + prosemirror-markdown: 1.13.4 + prosemirror-menu: 1.3.0 + prosemirror-model: 1.25.4 + prosemirror-schema-basic: 1.2.4 + prosemirror-schema-list: 1.5.1 + prosemirror-state: 1.4.4 + prosemirror-tables: 1.8.5 + prosemirror-trailing-node: 3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6) + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + + '@tiptap/starter-kit@2.27.2': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/extension-blockquote': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-bold': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-bullet-list': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-code': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-code-block': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-document': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-dropcursor': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-gapcursor': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-hard-break': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-heading': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-history': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-horizontal-rule': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-italic': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-list-item': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-ordered-list': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-paragraph': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-strike': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-text': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-text-style': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/pm': 2.27.2 + '@tokenizer/inflate@0.4.1': dependencies: debug: 4.4.3 @@ -6453,27 +7864,23 @@ snapshots: '@types/bn.js@5.2.0': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/buffer-json@2.0.3': {} '@types/clean-css@4.2.11': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 source-map: 0.6.1 '@types/connect@3.4.38': dependencies: - '@types/node': 25.0.2 - - '@types/cors@2.8.19': - dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/debug@4.1.12': dependencies: @@ -6481,7 +7888,7 @@ snapshots: '@types/dns-packet@5.6.5': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/elliptic@6.4.18': dependencies: @@ -6489,7 +7896,7 @@ snapshots: '@types/express-serve-static-core@5.1.0': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -6503,7 +7910,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/hast@3.0.4': dependencies: @@ -6515,7 +7922,7 @@ snapshots: '@types/relateurl': 0.2.33 '@types/uglify-js': 3.17.5 - '@types/http-cache-semantics@4.0.4': {} + '@types/http-cache-semantics@4.2.0': {} '@types/http-errors@2.0.5': {} @@ -6525,27 +7932,44 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 + + '@types/linkify-it@5.0.0': {} + + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 + '@types/mdurl@2.0.0': {} + '@types/mime-types@2.1.4': {} '@types/minimatch@5.1.2': {} '@types/ms@2.1.0': {} + '@types/mute-stream@0.0.4': + dependencies: + '@types/node': 25.3.5 + '@types/node-forge@1.3.14': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/node@16.9.1': {} - '@types/node@25.0.2': + '@types/node@22.19.15': dependencies: - undici-types: 7.16.0 + undici-types: 6.21.0 + + '@types/node@25.3.5': + dependencies: + undici-types: 7.18.2 '@types/ping@0.4.4': {} @@ -6561,22 +7985,22 @@ snapshots: '@types/send@1.2.1': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/serve-static@2.2.0': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/symbol-tree@3.2.5': {} '@types/tar-stream@3.1.4': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/through2@2.0.41': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/trusted-types@2.0.7': {} @@ -6598,26 +8022,27 @@ snapshots: '@types/which@3.0.4': {} + '@types/wrap-ansi@3.0.0': {} + '@types/ws@8.18.1': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 '@types/yauzl@2.10.3': dependencies: - '@types/node': 25.0.2 + '@types/node': 25.3.5 optional: true '@ungap/structured-clone@1.3.0': {} + '@vercel/oidc@3.1.0': {} + + '@yr/monotone-cubic-spline@1.0.3': {} + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 - accepts@1.3.8: - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - accepts@2.0.0: dependencies: mime-types: 3.0.2 @@ -6639,8 +8064,20 @@ snapshots: dependencies: humanize-ms: 1.2.1 + ai@6.0.116(zod@3.25.76): + dependencies: + '@ai-sdk/gateway': 3.0.66(zod@3.25.76) + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + '@opentelemetry/api': 1.9.0 + zod: 3.25.76 + ansi-256-colors@1.1.0: {} + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -6653,6 +8090,10 @@ snapshots: any-base@1.1.0: {} + apexcharts@5.10.1: + dependencies: + '@yr/monotone-cubic-spline': 1.0.3 + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -6687,10 +8128,14 @@ snapshots: b4a@1.7.3: {} + b4a@1.8.0: {} + bail@2.0.2: {} balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + bare-events@2.8.2: {} bare-fs@4.5.2: @@ -6705,13 +8150,22 @@ snapshots: - react-native-b4a optional: true - bare-os@3.6.2: - optional: true + bare-fs@4.5.5: + dependencies: + bare-events: 2.8.2 + bare-path: 3.0.0 + bare-stream: 2.8.0(bare-events@2.8.2) + bare-url: 2.3.2 + fast-fifo: 1.3.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + bare-os@3.6.2: {} bare-path@3.0.0: dependencies: bare-os: 3.6.2 - optional: true bare-stream@2.7.0(bare-events@2.8.2): dependencies: @@ -6723,15 +8177,22 @@ snapshots: - react-native-b4a optional: true + bare-stream@2.8.0(bare-events@2.8.2): + dependencies: + streamx: 2.23.0 + teex: 1.0.1 + optionalDependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + bare-url@2.3.2: dependencies: bare-path: 3.0.0 - optional: true base64-js@1.5.1: {} - base64id@2.0.0: {} - basic-ftp@5.0.5: {} bmp-ts@1.0.9: {} @@ -6763,6 +8224,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.4: + dependencies: + balanced-match: 4.0.4 + broadcast-channel@7.2.0: dependencies: '@babel/runtime': 7.28.4 @@ -6770,6 +8235,13 @@ snapshots: p-queue: 6.6.2 unload: 2.4.1 + broadcast-channel@7.3.0: + dependencies: + '@babel/runtime': 7.28.6 + oblivious-set: 2.0.0 + p-queue: 6.6.2 + unload: 2.4.1 + brorand@1.1.0: {} bson@6.10.4: {} @@ -6789,12 +8261,12 @@ snapshots: cacheable-request@10.2.14: dependencies: - '@types/http-cache-semantics': 4.0.4 + '@types/http-cache-semantics': 4.2.0 get-stream: 6.0.1 http-cache-semantics: 4.2.0 keyv: 4.5.4 mimic-response: 4.0.0 - normalize-url: 8.1.0 + normalize-url: 8.1.1 responselike: 3.0.0 call-bind-apply-helpers@1.0.2: @@ -6831,6 +8303,8 @@ snapshots: character-entities@2.0.2: {} + chardet@0.7.0: {} + chokidar@5.0.0: dependencies: readdirp: 5.0.0 @@ -6847,6 +8321,8 @@ snapshots: clean-stack@1.3.0: {} + cli-width@4.1.0: {} + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -6884,11 +8360,6 @@ snapshots: cookie@0.7.2: {} - cors@2.8.5: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - cosmiconfig@9.0.0(typescript@5.9.3): dependencies: env-paths: 2.2.1 @@ -6898,6 +8369,10 @@ snapshots: optionalDependencies: typescript: 5.9.3 + crelt@1.0.6: {} + + croner@10.0.1: {} + croner@9.1.0: {} cross-spawn@7.0.6: @@ -6916,10 +8391,6 @@ snapshots: dayjs@1.11.19: {} - debug@4.3.7: - dependencies: - ms: 2.1.3 - debug@4.4.3: dependencies: ms: 2.1.3 @@ -6974,6 +8445,10 @@ snapshots: dependencies: '@leichtgewicht/ip-codec': 2.0.5 + dompurify@3.2.7: + optionalDependencies: + '@types/trusted-types': 2.0.7 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -7004,36 +8479,6 @@ snapshots: dependencies: once: 1.4.0 - engine.io-client@6.6.3: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 - engine.io-parser: 5.2.3 - ws: 8.17.1 - xmlhttprequest-ssl: 2.1.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - engine.io-parser@5.2.3: {} - - engine.io@6.6.4: - dependencies: - '@types/cors': 2.8.19 - '@types/node': 25.0.2 - accepts: 1.3.8 - base64id: 2.0.0 - cookie: 0.7.2 - cors: 2.8.5 - debug: 4.3.7 - engine.io-parser: 5.2.3 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - entities@4.5.0: {} env-paths@2.2.1: {} @@ -7086,10 +8531,41 @@ snapshots: '@esbuild/win32-ia32': 0.27.1 '@esbuild/win32-x64': 0.27.1 + esbuild@0.27.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 + escalade@3.2.0: {} escape-html@1.0.3: {} + escape-string-regexp@4.0.0: {} + escape-string-regexp@5.0.0: {} escodegen@2.1.0: @@ -7122,11 +8598,9 @@ snapshots: events@3.3.0: {} - exif-parser@0.1.12: {} + eventsource-parser@3.0.6: {} - express-force-ssl@0.3.2: - dependencies: - lodash.assign: 3.2.0 + exif-parser@0.1.12: {} express@5.2.1: dependencies: @@ -7163,6 +8637,12 @@ snapshots: extend@3.0.2: {} + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + extract-zip@2.0.1: dependencies: debug: 4.4.3 @@ -7183,7 +8663,9 @@ snapshots: fast-json-stable-stringify@2.1.0: {} - fast-xml-parser@4.5.3: + fast-xml-builder@1.0.0: {} + + fast-xml-parser@4.5.4: dependencies: strnum: 1.1.2 @@ -7191,9 +8673,10 @@ snapshots: dependencies: strnum: 2.1.1 - fast-xml-parser@5.3.2: + fast-xml-parser@5.4.2: dependencies: - strnum: 2.1.1 + fast-xml-builder: 1.0.0 + strnum: 2.2.0 fault@2.0.1: dependencies: @@ -7222,11 +8705,11 @@ snapshots: token-types: 6.1.1 uint8array-extras: 1.5.0 - file-type@21.1.1: + file-type@21.3.0: dependencies: '@tokenizer/inflate': 0.4.1 strtok3: 10.3.4 - token-types: 6.1.1 + token-types: 6.1.2 uint8array-extras: 1.5.0 transitivePeerDependencies: - supports-color @@ -7348,7 +8831,7 @@ snapshots: dependencies: foreground-child: 3.3.1 jackspeak: 4.1.1 - minimatch: 10.1.1 + minimatch: 10.2.4 minipass: 7.1.2 package-json-from-dist: 1.0.1 path-scurry: 2.0.1 @@ -7358,7 +8841,7 @@ snapshots: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.1.2 + minimatch: 3.1.5 once: 1.4.0 path-is-absolute: 1.0.1 @@ -7433,6 +8916,8 @@ snapshots: he@1.2.0: {} + highlight.js@11.11.1: {} + hmac-drbg@1.0.1: dependencies: hash.js: 1.1.7 @@ -7484,6 +8969,12 @@ snapshots: dependencies: ms: 2.1.3 + ibantools@4.5.1: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.7.0: dependencies: safer-buffer: 2.1.2 @@ -7508,6 +8999,17 @@ snapshots: ini@1.3.8: {} + inquirer@11.1.0: + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/prompts': 6.0.1 + '@inquirer/type': 2.0.0 + '@types/mute-stream': 0.0.4 + ansi-escapes: 4.3.2 + mute-stream: 1.0.0 + run-async: 3.0.0 + rxjs: 7.8.2 + ip-address@10.1.0: {} ipaddr.js@1.9.1: {} @@ -7543,7 +9045,7 @@ snapshots: isexe@2.0.0: {} - isexe@3.1.1: {} + isexe@4.0.0: {} isopen@1.3.0: {} @@ -7605,6 +9107,8 @@ snapshots: '@babel/runtime': 7.28.6 ts-algebra: 2.0.0 + json-schema@0.4.0: {} + jsonfile@6.2.0: dependencies: universalify: 2.0.1 @@ -7621,65 +9125,50 @@ snapshots: lines-and-columns@1.2.4: {} + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + linkifyjs@4.3.2: {} + lit-element@4.2.1: dependencies: '@lit-labs/ssr-dom-shim': 1.4.0 '@lit/reactive-element': 2.1.1 lit-html: 3.3.1 + lit-element@4.2.2: + dependencies: + '@lit-labs/ssr-dom-shim': 1.5.1 + '@lit/reactive-element': 2.1.2 + lit-html: 3.3.2 + lit-html@3.3.1: dependencies: '@types/trusted-types': 2.0.7 + lit-html@3.3.2: + dependencies: + '@types/trusted-types': 2.0.7 + lit@3.3.1: dependencies: '@lit/reactive-element': 2.1.1 lit-element: 4.2.1 lit-html: 3.3.1 + lit@3.3.2: + dependencies: + '@lit/reactive-element': 2.1.2 + lit-element: 4.2.2 + lit-html: 3.3.2 + locate-path@5.0.0: dependencies: p-locate: 4.1.0 - lodash._baseassign@3.2.0: - dependencies: - lodash._basecopy: 3.0.1 - lodash.keys: 3.1.2 - - lodash._basecopy@3.0.1: {} - - lodash._bindcallback@3.0.1: {} - - lodash._createassigner@3.1.1: - dependencies: - lodash._bindcallback: 3.0.1 - lodash._isiterateecall: 3.0.9 - lodash.restparam: 3.6.1 - - lodash._getnative@3.9.1: {} - - lodash._isiterateecall@3.0.9: {} - - lodash.assign@3.2.0: - dependencies: - lodash._baseassign: 3.2.0 - lodash._createassigner: 3.1.1 - lodash.keys: 3.1.2 - lodash.clonedeep@4.5.0: {} - lodash.isarguments@3.1.0: {} - - lodash.isarray@3.0.4: {} - - lodash.keys@3.1.2: - dependencies: - lodash._getnative: 3.9.1 - lodash.isarguments: 3.1.0 - lodash.isarray: 3.0.4 - - lodash.restparam@3.6.1: {} - longest-streak@3.1.0: {} lower-case@1.1.4: {} @@ -7690,6 +9179,8 @@ snapshots: lru-cache@7.18.3: {} + lucide@0.564.0: {} + make-dir@3.1.0: dependencies: semver: 6.3.1 @@ -7700,8 +9191,19 @@ snapshots: make-error@1.3.6: {} + markdown-it@14.1.1: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + markdown-table@3.0.4: {} + marked@14.0.0: {} + matcher@5.0.0: dependencies: escape-string-regexp: 5.0.0 @@ -7835,6 +9337,8 @@ snapshots: dependencies: '@types/mdast': 4.0.4 + mdurl@2.0.0: {} + media-typer@1.1.0: {} memory-pager@1.5.0: {} @@ -8059,19 +9563,21 @@ snapshots: mimic-response@4.0.0: {} + mingo@7.2.0: {} + minimalistic-assert@1.0.1: {} minimalistic-crypto-utils@1.0.1: {} - minimatch@10.1.1: + minimatch@10.2.4: dependencies: - '@isaacs/brace-expansion': 5.0.0 + brace-expansion: 5.0.4 - minimatch@3.1.2: + minimatch@3.1.5: dependencies: brace-expansion: 1.1.12 - minimatch@9.0.5: + minimatch@9.0.9: dependencies: brace-expansion: 2.0.2 @@ -8081,12 +9587,17 @@ snapshots: mitt@3.0.1: {} + monaco-editor@0.55.1: + dependencies: + dompurify: 3.2.7 + marked: 14.0.0 + mongodb-connection-string-url@3.0.2: dependencies: '@types/whatwg-url': 11.0.5 whatwg-url: 14.2.0 - mongodb-memory-server-core@10.3.0(socks@2.8.7): + mongodb-memory-server-core@10.4.3(socks@2.8.7): dependencies: async-mutex: 0.5.0 camelcase: 6.3.0 @@ -8096,14 +9607,15 @@ snapshots: https-proxy-agent: 7.0.6 mongodb: 6.21.0(socks@2.8.7) new-find-package-json: 2.0.0 - semver: 7.7.3 - tar-stream: 3.1.7 + semver: 7.7.4 + tar-stream: 3.1.8 tslib: 2.8.1 yauzl: 3.2.0 transitivePeerDependencies: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' - bare-abort-controller + - bare-buffer - gcp-metadata - kerberos - mongodb-client-encryption @@ -8112,14 +9624,15 @@ snapshots: - socks - supports-color - mongodb-memory-server@10.3.0(socks@2.8.7): + mongodb-memory-server@10.4.3(socks@2.8.7): dependencies: - mongodb-memory-server-core: 10.3.0(socks@2.8.7) + mongodb-memory-server-core: 10.4.3(socks@2.8.7) tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' - bare-abort-controller + - bare-buffer - gcp-metadata - kerberos - mongodb-client-encryption @@ -8130,7 +9643,7 @@ snapshots: mongodb@6.21.0(socks@2.8.7): dependencies: - '@mongodb-js/saslprep': 1.3.2 + '@mongodb-js/saslprep': 1.4.6 bson: 6.10.4 mongodb-connection-string-url: 3.0.2 optionalDependencies: @@ -8138,9 +9651,9 @@ snapshots: ms@2.1.3: {} - nanoid@4.0.2: {} + mute-stream@1.0.0: {} - negotiator@0.6.3: {} + nanoid@4.0.2: {} negotiator@1.0.0: {} @@ -8158,13 +9671,13 @@ snapshots: node-forge@1.3.2: {} + node-forge@1.3.3: {} + normalize-newline@4.1.0: dependencies: replace-buffer: 1.2.1 - normalize-url@8.1.0: {} - - object-assign@4.1.1: {} + normalize-url@8.1.1: {} object-inspect@1.13.4: {} @@ -8190,11 +9703,15 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 - openai@6.16.0(ws@8.18.3)(zod@3.25.76): + openai@6.27.0(ws@8.19.0)(zod@3.25.76): optionalDependencies: - ws: 8.18.3 + ws: 8.19.0 zod: 3.25.76 + orderedmap@2.1.1: {} + + os-tmpdir@1.0.2: {} + p-cancelable@3.0.0: {} p-finally@1.0.0: {} @@ -8241,9 +9758,9 @@ snapshots: package-json@8.1.1: dependencies: got: 12.6.1 - registry-auth-token: 5.1.0 + registry-auth-token: 5.1.1 registry-url: 6.0.1 - semver: 7.7.3 + semver: 7.7.4 pako@1.0.11: {} @@ -8297,6 +9814,12 @@ snapshots: pdf2json@3.2.0: {} + pdf2json@4.0.2: {} + + pdfjs-dist@4.10.38: + optionalDependencies: + '@napi-rs/canvas': 0.1.96 + peek-readable@4.1.0: {} peek-readable@5.4.2: {} @@ -8331,6 +9854,109 @@ snapshots: property-information@7.1.0: {} + prosemirror-changeset@2.4.0: + dependencies: + prosemirror-transform: 1.11.0 + + prosemirror-collab@1.3.1: + dependencies: + prosemirror-state: 1.4.4 + + prosemirror-commands@1.7.1: + dependencies: + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + + prosemirror-dropcursor@1.8.2: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + + prosemirror-gapcursor@1.4.0: + dependencies: + prosemirror-keymap: 1.2.3 + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-view: 1.41.6 + + prosemirror-history@1.5.0: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + rope-sequence: 1.3.4 + + prosemirror-inputrules@1.5.1: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + + prosemirror-keymap@1.2.3: + dependencies: + prosemirror-state: 1.4.4 + w3c-keyname: 2.2.8 + + prosemirror-markdown@1.13.4: + dependencies: + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.1 + prosemirror-model: 1.25.4 + + prosemirror-menu@1.3.0: + dependencies: + crelt: 1.0.6 + prosemirror-commands: 1.7.1 + prosemirror-history: 1.5.0 + prosemirror-state: 1.4.4 + + prosemirror-model@1.25.4: + dependencies: + orderedmap: 2.1.1 + + prosemirror-schema-basic@1.2.4: + dependencies: + prosemirror-model: 1.25.4 + + prosemirror-schema-list@1.5.1: + dependencies: + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + + prosemirror-state@1.4.4: + dependencies: + prosemirror-model: 1.25.4 + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + + prosemirror-tables@1.8.5: + dependencies: + prosemirror-keymap: 1.2.3 + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + + prosemirror-trailing-node@3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6): + dependencies: + '@remirror/core-constants': 3.0.0 + escape-string-regexp: 4.0.0 + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-view: 1.41.6 + + prosemirror-transform@1.11.0: + dependencies: + prosemirror-model: 1.25.4 + + prosemirror-view@1.41.6: + dependencies: + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + proto-list@1.2.4: {} proxy-addr@2.0.7: @@ -8358,6 +9984,8 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 + punycode.js@2.3.1: {} + punycode@1.4.1: {} punycode@2.3.1: {} @@ -8406,6 +10034,10 @@ snapshots: dependencies: side-channel: 1.1.0 + qs@6.15.0: + dependencies: + side-channel: 1.1.0 + quick-lru@5.1.1: {} randomatic@3.1.1: @@ -8452,9 +10084,9 @@ snapshots: reflect-metadata@0.2.2: {} - registry-auth-token@5.1.0: + registry-auth-token@5.1.1: dependencies: - '@pnpm/npm-conf': 2.3.1 + '@pnpm/npm-conf': 3.0.2 registry-url@6.0.1: dependencies: @@ -8543,6 +10175,8 @@ snapshots: '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.52 '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.52 + rope-sequence@1.3.4: {} + router@2.2.0: dependencies: debug: 4.4.3 @@ -8553,6 +10187,8 @@ snapshots: transitivePeerDependencies: - supports-color + run-async@3.0.0: {} + rxjs@7.8.2: dependencies: tslib: 2.8.1 @@ -8567,6 +10203,8 @@ snapshots: semver@7.7.3: {} + semver@7.7.4: {} + send@1.2.0: dependencies: debug: 4.4.3 @@ -8607,7 +10245,7 @@ snapshots: dependencies: '@img/colour': 1.0.0 detect-libc: 2.1.2 - semver: 7.7.3 + semver: 7.7.4 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.5 '@img/sharp-darwin-x64': 0.34.5 @@ -8676,47 +10314,6 @@ snapshots: smart-buffer@4.2.0: {} - socket.io-adapter@2.5.5: - dependencies: - debug: 4.3.7 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - socket.io-client@4.8.1: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 - engine.io-client: 6.6.3 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - socket.io-parser@4.2.4: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - - socket.io@4.8.1: - dependencies: - accepts: 1.3.8 - base64id: 2.0.0 - cors: 2.8.5 - debug: 4.3.7 - engine.io: 6.6.4 - socket.io-adapter: 2.5.5 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.4 @@ -8797,6 +10394,8 @@ snapshots: strnum@2.1.1: {} + strnum@2.2.0: {} + strtok3@10.3.4: dependencies: '@tokenizer/token': 0.3.0 @@ -8838,6 +10437,24 @@ snapshots: - bare-abort-controller - react-native-b4a + tar-stream@3.1.8: + dependencies: + b4a: 1.8.0 + bare-fs: 4.5.5 + fast-fifo: 1.3.2 + streamx: 2.23.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + + teex@1.0.1: + dependencies: + streamx: 2.23.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + text-decoder@1.2.3: dependencies: b4a: 1.7.3 @@ -8865,6 +10482,10 @@ snapshots: tinycolor2@1.6.0: {} + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + toidentifier@1.0.1: {} token-types@4.2.1: @@ -8878,6 +10499,12 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.1 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + tr46@5.1.1: dependencies: punycode: 2.3.1 @@ -8911,6 +10538,8 @@ snapshots: dependencies: '@mixmark-io/domino': 2.2.0 + type-fest@0.21.3: {} + type-fest@2.19.0: {} type-fest@4.41.0: {} @@ -8925,11 +10554,15 @@ snapshots: typescript@5.9.3: {} + uc.micro@2.1.0: {} + uglify-js@3.19.3: {} uint8array-extras@1.5.0: {} - undici-types@7.16.0: {} + undici-types@6.21.0: {} + + undici-types@7.18.2: {} unified@11.0.5: dependencies: @@ -8975,7 +10608,7 @@ snapshots: url@0.11.4: dependencies: punycode: 1.4.1 - qs: 6.14.0 + qs: 6.15.0 utif2@4.1.0: dependencies: @@ -8997,6 +10630,8 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 + w3c-keyname@2.2.8: {} + webdriver-bidi-protocol@0.3.9: {} webidl-conversions@7.0.0: {} @@ -9012,9 +10647,15 @@ snapshots: dependencies: isexe: 2.0.0 - which@5.0.0: + which@6.0.1: dependencies: - isexe: 3.1.1 + isexe: 4.0.0 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 wrap-ansi@7.0.0: dependencies: @@ -9030,10 +10671,10 @@ snapshots: wrappy@1.0.2: {} - ws@8.17.1: {} - ws@8.18.3: {} + ws@8.19.0: {} + xml-parse-from-string@1.0.1: {} xml2js@0.5.0: @@ -9043,7 +10684,11 @@ snapshots: xmlbuilder@11.0.1: {} - xmlhttprequest-ssl@2.1.2: {} + xterm-addon-fit@0.8.0(xterm@5.3.0): + dependencies: + xterm: 5.3.0 + + xterm@5.3.0: {} y18n@5.0.8: {} @@ -9073,9 +10718,7 @@ snapshots: buffer-crc32: 0.2.13 pend: 1.2.0 - zod-to-json-schema@3.25.1(zod@3.25.76): - dependencies: - zod: 3.25.76 + yoctocolors-cjs@2.1.3: {} zod@3.25.76: {} diff --git a/readme.hints.md b/readme.hints.md index b11f84b..cae5101 100644 --- a/readme.hints.md +++ b/readme.hints.md @@ -1,97 +1,51 @@ # Project Readme Hints ## Overview -`@push.rocks/smartagent` is a dual-agent agentic framework built on top of `@push.rocks/smartai`. It implements a Driver/Guardian architecture where the Driver proposes tool calls and the Guardian evaluates them against security policies. +`@push.rocks/smartagent` v2.0.0 is an agentic loop built on Vercel AI SDK v6 via `@push.rocks/smartai`. It wraps `streamText` with `stopWhen: stepCountIs(n)` for parallel multi-step tool execution. -## Architecture -- **DualAgentOrchestrator**: Main entry point, coordinates Driver and Guardian agents -- **DriverAgent**: Reasons about tasks, plans steps, proposes tool calls (supports both XML and native tool calling) -- **GuardianAgent**: Evaluates tool calls against configured policies -- **ToolRegistry**: Manages tool lifecycle, visibility, and discovery -- **BaseToolWrapper**: Base class for creating custom tools -- **plugins.ts**: Imports and re-exports smartai and other dependencies +## Architecture (v2) +- **`runAgent()`**: Pure async function — the core agentic loop. No class state. +- **`ToolRegistry`**: Lightweight helper for collecting tools into a `ToolSet`. +- **`truncateOutput()`**: Utility to prevent tool output from bloating context. +- **`compactMessages()`**: Context overflow handler (separate subpath export). -## Standard Tools (via registerStandardTools) -1. **FilesystemTool** - File operations with scoping and exclusion patterns -2. **HttpTool** - HTTP requests -3. **ShellTool** - Secure shell commands (no injection possible) -4. **BrowserTool** - Web page interaction via Puppeteer -5. **DenoTool** - Sandboxed TypeScript/JavaScript execution - -## Additional Tools (must register manually) -6. **JsonValidatorTool** - JSON validation and formatting (NOT in registerStandardTools) -7. **ToolSearchTool** - AI-facing interface for tool discovery and activation -8. **ExpertTool** - Wraps a DualAgentOrchestrator as a specialized expert tool - -## Tool Visibility System -Tools can be registered with visibility modes: -- **initial**: Always visible to Driver, included in system prompt (default) -- **on-demand**: Only discoverable via search, must be activated before use - -```typescript -// Register with visibility options -orchestrator.registerTool(myTool, { - visibility: 'on-demand', - tags: ['database', 'sql'], - category: 'data' -}); +## Source Layout +``` +ts/ → core: runAgent, ToolRegistry, truncateOutput, interfaces +ts_tools/ → built-in tool factories (filesystem, shell, http, json) +ts_compaction/ → compactMessages helper for onContextOverflow ``` -## Expert/SubAgent System -Experts are specialized agents wrapped as tools, enabling hierarchical agent architectures: - -```typescript -orchestrator.registerExpert({ - name: 'code_reviewer', - description: 'Reviews code for quality and best practices', - systemMessage: 'You are a code review expert...', - guardianPolicy: 'Allow read-only file access', - tools: [new FilesystemTool()], - visibility: 'on-demand', - tags: ['code', 'review'] -}); -``` - -## Tool Search -Enable tool discovery for the Driver: - -```typescript -orchestrator.enableToolSearch(); -// Driver can now use: -// - tools.search({"query": "database"}) -// - tools.list({}) -// - tools.activate({"name": "database_expert"}) -// - tools.details({"name": "filesystem"}) -``` - -## Key Features -- Token streaming support (`onToken` callback) -- Vision support (pass images as base64) -- Progress events (`onProgress` callback) -- Scoped filesystem with exclusion patterns -- Result truncation with configurable limits -- History windowing to manage token usage -- **Native tool calling mode** (`useNativeToolCalling: true`) for providers like Ollama -- **Tool visibility system** (initial vs on-demand) -- **Expert/SubAgent system** for hierarchical agents -- **Tool search and discovery** via ToolSearchTool - -## Native Tool Calling -When `useNativeToolCalling` is enabled: -- Uses provider's built-in tool calling API instead of XML parsing -- Tool names become `toolName_actionName` (e.g., `json_validate`) -- Streaming includes `[THINKING]` and `[OUTPUT]` markers -- More efficient for models that support it +## Built-in Tools (ts_tools/) +Each exports a factory returning a flat `ToolSet` (Record): +1. **filesystemTool()** → `read_file`, `write_file`, `list_directory`, `delete_file` +2. **shellTool()** → `run_command` +3. **httpTool()** → `http_get`, `http_post` +4. **jsonTool()** → `json_validate`, `json_transform` ## Key Dependencies -- `@push.rocks/smartai`: Multi-provider AI interface -- `@push.rocks/smartfs`: Filesystem operations -- `@push.rocks/smartshell`: Shell command execution -- `@push.rocks/smartbrowser`: Browser automation -- `@push.rocks/smartdeno`: Deno code execution -- `@push.rocks/smartrequest`: HTTP requests -- `minimatch`: Glob pattern matching for exclusions +- `@push.rocks/smartai` ^2.0.0 — provider registry, `getModel()`, re-exports `tool`, `jsonSchema` +- `ai` ^6.0.0 — Vercel AI SDK v6 (`streamText`, `stepCountIs`, `ModelMessage`, `ToolSet`) +- `zod` ^3.25.0 — tool input schema definitions +- `@push.rocks/smartfs`, `smartshell`, `smartrequest` — tool implementations + +## AI SDK v6 Key APIs +- `streamText({ model, messages, tools, stopWhen: stepCountIs(20) })` — agentic loop +- `tool({ description, inputSchema: z.object({...}), execute })` — define tools +- `ModelMessage` — message type (replaces v4's `CoreMessage`) +- `LanguageModelV3` — model type from `@ai-sdk/provider` +- Result is `StreamTextResult` with PromiseLike properties (`await result.text`, etc.) + +## Package Exports +- `.` → core (runAgent, ToolRegistry, truncateOutput, re-exports) +- `./tools` → built-in tool factories +- `./compaction` → compactMessages + +## Build +- `pnpm build` → `tsbuild tsfolders --allowimplicitany` +- Cross-folder imports via each folder's `plugins.ts` (tsbuild unpack resolves them) ## Test Structure - Tests use `@git.zone/tstest/tapbundle` -- Tests must end with `export default tap.start();` +- Tests must end with `export default tap.start()` +- `pnpm test` → `tstest test/ --verbose` diff --git a/readme.md b/readme.md index c25532b..df7fb16 100644 --- a/readme.md +++ b/readme.md @@ -1,12 +1,10 @@ # @push.rocks/smartagent -A dual-agent agentic framework with **Driver** and **Guardian** agents for safe, policy-controlled AI task execution. 🤖🛡️ +A lightweight agentic loop built on **Vercel AI SDK v6** via `@push.rocks/smartai`. Register tools, get a model, call `runAgent()` — done. 🚀 ## Install ```bash -npm install @push.rocks/smartagent -# or pnpm install @push.rocks/smartagent ``` @@ -16,788 +14,362 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community ## Overview -SmartAgent implements a **dual-agent architecture** where AI safety isn't just an afterthought—it's baked into the core design: +`@push.rocks/smartagent` wraps the AI SDK's `streamText` with `stopWhen: stepCountIs(n)` for **parallel multi-step tool execution**. No classes to instantiate, no lifecycle to manage — just one async function: -- **🎯 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 +```typescript +import { runAgent, tool, z } from '@push.rocks/smartagent'; +import { getModel } from '@push.rocks/smartai'; -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. +const model = getModel({ + provider: 'anthropic', + model: 'claude-sonnet-4-5-20250929', + apiKey: process.env.ANTHROPIC_TOKEN, +}); -### Why Dual-Agent? +const result = await runAgent({ + model, + prompt: 'What is 7 + 35?', + system: 'You are a helpful assistant. Use tools when asked.', + tools: { + calculator: tool({ + description: 'Perform arithmetic', + inputSchema: z.object({ + operation: z.enum(['add', 'subtract', 'multiply', 'divide']), + a: z.number(), + b: z.number(), + }), + execute: async ({ operation, a, b }) => { + const ops = { add: a + b, subtract: a - b, multiply: a * b, divide: a / b }; + return String(ops[operation]); + }, + }), + }, + maxSteps: 10, +}); -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. +console.log(result.text); // "7 + 35 = 42" +console.log(result.steps); // number of agentic steps taken +console.log(result.usage); // { promptTokens, completionTokens, totalTokens } +``` ## Architecture -```mermaid -flowchart TB - subgraph Input - Task["User Task"] - Policy["Guardian Policy Prompt"] - end - - subgraph Orchestrator["DualAgentOrchestrator"] - Registry["ToolRegistry
Visibility & Lifecycle"] - Driver["Driver Agent
Reason + Plan"] - Guardian["Guardian Agent
Evaluate against policy"] - - Driver -->|"tool call proposal"| Guardian - Guardian -->|"approve / reject + feedback"| Driver - Registry -->|"visible tools"| Driver - end - - subgraph Tools["Tools"] - Initial["Initial Tools
Always visible"] - OnDemand["On-Demand Tools
Discoverable via search"] - Experts["Expert SubAgents
Specialized agents as tools"] - end - - Task --> Orchestrator - Policy --> Guardian - Driver -->|"execute
(if approved)"| Tools - Tools -->|"result"| Driver +``` +┌─────────────────────────────────────────────────┐ +│ runAgent({ model, prompt, tools, maxSteps }) │ +│ │ +│ ┌───────────┐ ┌──────────┐ ┌───────────┐ │ +│ │ Messages │──▶│ streamText│──▶│ Tools │ │ +│ │ (history) │◀──│ (AI SDK) │◀──│ (ToolSet) │ │ +│ └───────────┘ └──────────┘ └───────────┘ │ +│ │ +│ stopWhen: stepCountIs(maxSteps) │ +│ + retry with backoff on 429/529/503 │ +│ + context overflow detection & recovery │ +│ + tool call repair (case-insensitive matching) │ +└─────────────────────────────────────────────────┘ ``` -## Quick Start +**Key features:** + +- 🔄 **Multi-step agentic loop** — the model calls tools, sees results, and continues reasoning until done +- ⚡ **Parallel tool execution** — multiple tool calls in a single step are executed concurrently +- 🔧 **Auto-retry with backoff** — handles 429/529/503 errors with header-aware retry delays +- 🩹 **Tool call repair** — case-insensitive name matching + invalid tool sink prevents crashes +- 📊 **Token streaming** — `onToken` and `onToolCall` callbacks for real-time progress +- 💥 **Context overflow handling** — detects overflow and invokes your `onContextOverflow` callback + +## Core API + +### `runAgent(options): Promise` + +The single entry point. Options: + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `model` | `LanguageModelV3` | *required* | Model from `@push.rocks/smartai`'s `getModel()` | +| `prompt` | `string` | *required* | The user's task/question | +| `system` | `string` | `undefined` | System prompt | +| `tools` | `ToolSet` | `{}` | Tools the agent can call | +| `maxSteps` | `number` | `20` | Max agentic steps before stopping | +| `messages` | `ModelMessage[]` | `[]` | Conversation history (for multi-turn) | +| `maxRetries` | `number` | `5` | Max retries on rate-limit/server errors | +| `onToken` | `(delta: string) => void` | — | Streaming token callback | +| `onToolCall` | `(name: string) => void` | — | Called when a tool is invoked | +| `onContextOverflow` | `(messages) => messages` | — | Handle context overflow (e.g., compact messages) | + +### `IAgentRunResult` ```typescript -import { DualAgentOrchestrator } from '@push.rocks/smartagent'; - -// Create orchestrator with Guardian policy -const orchestrator = new DualAgentOrchestrator({ - openaiToken: 'sk-...', - defaultProvider: 'openai', - guardianPolicyPrompt: ` - FILE SYSTEM POLICY: - - ONLY allow reading/writing within /tmp or the current working directory - - REJECT operations on system directories or sensitive files - - SHELL POLICY: - - Allow read-only commands (ls, cat, grep, echo) - - REJECT destructive commands (rm, mv, chmod) without explicit justification - - FLAG any attempt to expose secrets or credentials. - `, -}); - -// Register standard tools -orchestrator.registerStandardTools(); - -// Start the orchestrator (initializes all tools) -await orchestrator.start(); - -// Run a task -const result = await orchestrator.run('List all TypeScript files in the current directory'); - -console.log('Success:', result.success); -console.log('Result:', result.result); -console.log('Iterations:', result.iterations); - -// Cleanup -await orchestrator.stop(); +interface IAgentRunResult { + text: string; // Final response text + finishReason: string; // 'stop', 'tool-calls', 'length', etc. + steps: number; // Number of agentic steps taken + messages: ModelMessage[]; // Full conversation for multi-turn + usage: { + promptTokens: number; + completionTokens: number; + totalTokens: number; + }; +} ``` -## Standard Tools +## Defining Tools 🛠️ -SmartAgent comes with five battle-tested tools out of the box via `registerStandardTools()`: - -### 🗂️ FilesystemTool - -File and directory operations powered by `@push.rocks/smartfs`. - -**Actions**: `read`, `write`, `append`, `list`, `delete`, `exists`, `stat`, `copy`, `move`, `mkdir` +Tools use Vercel AI SDK's `tool()` helper with Zod schemas: ```typescript -// Example tool call by Driver - - filesystem - read - {"path": "/tmp/config.json"} - Need to read the configuration file to understand the settings - -``` - -**Scoped Filesystem**: Lock file operations to a specific directory with optional exclusion patterns: - -```typescript -// Only allow access within a specific directory -orchestrator.registerScopedFilesystemTool('/home/user/workspace'); - -// With exclusion patterns (glob syntax) -orchestrator.registerScopedFilesystemTool('/home/user/workspace', [ - '.nogit/**', - 'node_modules/**', - '*.secret', -]); -``` - -**Line-range Reading**: Read specific portions of large files: - -```typescript - - filesystem - read - {"path": "/var/log/app.log", "startLine": 100, "endLine": 150} - Reading only the relevant log section to avoid token overload - -``` - -### 🌐 HttpTool - -HTTP requests using `@push.rocks/smartrequest`. - -**Actions**: `get`, `post`, `put`, `patch`, `delete` - -```typescript - - http - get - {"url": "https://api.example.com/data", "headers": {"Authorization": "Bearer token"}} - Fetching data from the API endpoint - -``` - -### 💻 ShellTool - -Secure shell command execution using `@push.rocks/smartshell` with `execSpawn` (no shell injection possible). - -**Actions**: `execute`, `which` - -```typescript - - shell - execute - {"command": "ls", "args": ["-la", "/tmp"]} - Listing directory contents to find relevant files - -``` - -> 🔒 **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` - -```typescript - - browser - getPageContent - {"url": "https://example.com"} - Extracting text content from the webpage - -``` - -### 🦕 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 and are subject to Guardian approval. - -```typescript -// Simple code execution (sandboxed, no permissions) - - deno - execute - {"code": "console.log('Hello from Deno!')"} - Running a simple script to verify the environment - - -// Code with network permission - - deno - execute - { - "code": "const resp = await fetch('https://api.example.com/data'); console.log(await resp.json());", - "permissions": ["net"] - } - Fetching data from API using Deno's fetch - - -// Execute and parse JSON result - - deno - executeWithResult - { - "code": "const result = { sum: 2 + 2, date: new Date().toISOString() }; console.log(JSON.stringify(result));" - } - Computing values and returning structured data - -``` - -## Additional Tools - -### 📋 JsonValidatorTool - -Validate and format JSON data. Perfect for agents to self-check their JSON output before completing tasks. - -**Actions**: `validate`, `format` - -```typescript -import { JsonValidatorTool } from '@push.rocks/smartagent'; - -// Register the JSON validator tool (not included in registerStandardTools) -orchestrator.registerTool(new JsonValidatorTool()); -``` - -```typescript -// Validate JSON with required field checking - - json - validate - { - "jsonString": "{\"name\": \"test\", \"version\": \"1.0.0\"}", - "requiredFields": ["name", "version", "description"] - } - Ensuring the config has all required fields before saving - - -// Pretty-print JSON - - json - format - {"jsonString": "{\"compact\":true,\"data\":[1,2,3]}"} - Formatting JSON for readable output - -``` - -### 🔍 ToolSearchTool - -Enable the Driver to discover and activate on-demand tools at runtime. - -**Actions**: `search`, `list`, `activate`, `details` - -```typescript -// Enable tool search (adds the 'tools' tool) -orchestrator.enableToolSearch(); -``` - -```typescript -// Search for tools by capability - - tools - search - {"query": "database"} - - -// List all available tools - - tools - list - {} - - -// Activate an on-demand tool - - tools - activate - {"name": "database_expert"} - - -// Get detailed information about a tool - - tools - details - {"name": "filesystem"} - -``` - -### 🧠 ExpertTool (SubAgents) - -Create specialized sub-agents that can be invoked as tools. Experts are complete `DualAgentOrchestrator` instances wrapped as tools, enabling hierarchical agent architectures. - -**Actions**: `consult` - -```typescript -// Register an expert for code review -orchestrator.registerExpert({ - name: 'code_reviewer', - description: 'Reviews code for quality, bugs, and best practices', - systemMessage: `You are an expert code reviewer. Analyze code for: - - Bugs and potential issues - - Code style and best practices - - Performance concerns - - Security vulnerabilities`, - guardianPolicy: 'Allow read-only file access within the workspace', - tools: [new FilesystemTool()], - visibility: 'on-demand', // Only available via tool search - tags: ['code', 'review', 'quality'], - category: 'expert', -}); -``` - -```typescript -// Consult an expert - - code_reviewer - consult - { - "task": "Review this function for potential issues", - "context": "This is a user authentication handler" - } - -``` - -## 🎯 Tool Visibility System - -SmartAgent supports **tool visibility modes** for scalable agent architectures: - -- **`initial`** (default): Tool is visible to the Driver from the start, included in the system prompt -- **`on-demand`**: Tool is hidden until explicitly activated via `tools.activate()` - -This enables you to have many specialized tools/experts without overwhelming the Driver's context. - -```typescript -// Register a tool with on-demand visibility -orchestrator.registerTool(new MySpecializedTool(), { - visibility: 'on-demand', - tags: ['specialized', 'database'], - category: 'data', -}); - -// Enable tool search so Driver can discover and activate on-demand tools -orchestrator.enableToolSearch(); - -// The Driver can now: -// 1. tools.search({"query": "database"}) -> finds MySpecializedTool -// 2. tools.activate({"name": "myspecialized"}) -> enables it -// 3. myspecialized.action({...}) -> use the tool -``` - -### Expert SubAgent Example - -```typescript -const orchestrator = new DualAgentOrchestrator({ - openaiToken: 'sk-...', - defaultProvider: 'openai', - guardianPolicyPrompt: 'Allow safe operations...', -}); - -orchestrator.registerStandardTools(); -orchestrator.enableToolSearch(); - -// Initial expert (always visible) -orchestrator.registerExpert({ - name: 'code_assistant', - description: 'Helps with coding tasks and code generation', - systemMessage: 'You are a helpful coding assistant...', - guardianPolicy: 'Allow read-only file access', - tools: [new FilesystemTool()], -}); - -// On-demand experts (discoverable via search) -orchestrator.registerExpert({ - name: 'database_expert', - description: 'Database design, optimization, and query analysis', - systemMessage: 'You are a database expert...', - guardianPolicy: 'Allow read-only operations', - visibility: 'on-demand', - tags: ['database', 'sql', 'optimization'], -}); - -orchestrator.registerExpert({ - name: 'security_auditor', - description: 'Security vulnerability assessment and best practices', - systemMessage: 'You are a security expert...', - guardianPolicy: 'Allow read-only file access', - visibility: 'on-demand', - tags: ['security', 'audit', 'vulnerabilities'], -}); - -await orchestrator.start(); - -// Now the Driver can: -// - Use code_assistant directly -// - Search for "database" and activate database_expert when needed -// - Search for "security" and activate security_auditor when needed -``` - -## 🎥 Streaming Support - -SmartAgent supports token-by-token streaming for real-time output during LLM generation: - -```typescript -const orchestrator = new DualAgentOrchestrator({ - openaiToken: 'sk-...', - defaultProvider: 'openai', - guardianPolicyPrompt: '...', - - // Token streaming callback - onToken: (token, source) => { - // source is 'driver' or 'guardian' - process.stdout.write(token); +import { tool, z } from '@push.rocks/smartagent'; + +const myTool = tool({ + description: 'Describe what this tool does', + inputSchema: z.object({ + param1: z.string().describe('What this parameter is for'), + param2: z.number().optional(), + }), + execute: async ({ param1, param2 }) => { + // Do work, return a string + return `Result: ${param1}`; }, }); ``` -This is perfect for CLI applications or UIs that need to show progress as the agent thinks. - -## 🖼️ Vision Support - -Pass images to vision-capable models for multimodal tasks: +Pass tools as a flat object to `runAgent()`: ```typescript -import { readFileSync } from 'fs'; - -// Load image as base64 -const imageBase64 = readFileSync('screenshot.png').toString('base64'); - -// Run task with images -const result = await orchestrator.run( - 'Analyze this UI screenshot and describe any usability issues', - { images: [imageBase64] } -); +await runAgent({ + model, + prompt: 'Do the thing', + tools: { myTool, anotherTool }, + maxSteps: 10, +}); ``` -## 📊 Progress Events +## ToolRegistry -Get real-time feedback on task execution with the `onProgress` callback: +A lightweight helper for collecting tools: ```typescript -const orchestrator = new DualAgentOrchestrator({ - openaiToken: 'sk-...', - guardianPolicyPrompt: '...', - logPrefix: '[MyAgent]', // Optional prefix for log messages +import { ToolRegistry, tool, z } from '@push.rocks/smartagent'; - onProgress: (event) => { - // Pre-formatted log message ready for output - console.log(event.logMessage); +const registry = new ToolRegistry(); - // Or handle specific event types - switch (event.type) { - case 'tool_proposed': - console.log(`Proposing: ${event.toolName}.${event.action}`); - break; - case 'tool_approved': - console.log(`✓ Approved`); - break; - case 'tool_rejected': - console.log(`✗ Rejected: ${event.reason}`); - break; - case 'task_completed': - console.log(`Done in ${event.iteration} iterations`); - break; - } +registry.register('random_number', tool({ + description: 'Generate a random integer between min and max', + inputSchema: z.object({ + min: z.number(), + max: z.number(), + }), + execute: async ({ min, max }) => { + return String(Math.floor(Math.random() * (max - min + 1)) + min); + }, +})); + +registry.register('is_even', tool({ + description: 'Check if a number is even', + inputSchema: z.object({ number: z.number() }), + execute: async ({ number: n }) => n % 2 === 0 ? 'Yes' : 'No', +})); + +const result = await runAgent({ + model, + prompt: 'Generate a random number and tell me if it is even', + tools: registry.getTools(), + maxSteps: 10, +}); +``` + +## Built-in Tool Factories 🧰 + +Import from the `@push.rocks/smartagent/tools` subpath: + +```typescript +import { filesystemTool, shellTool, httpTool, jsonTool } from '@push.rocks/smartagent/tools'; +``` + +### `filesystemTool(options?)` + +Returns: `read_file`, `write_file`, `list_directory`, `delete_file` + +```typescript +const tools = filesystemTool({ rootDir: '/home/user/workspace' }); + +await runAgent({ + model, + prompt: 'Create a file called hello.txt with "Hello World"', + tools, + maxSteps: 5, +}); +``` + +Options: +- `rootDir` — restrict all file operations to this directory. Paths outside it throw `Access denied`. + +### `shellTool(options?)` + +Returns: `run_command` + +```typescript +const tools = shellTool({ cwd: '/tmp', allowedCommands: ['ls', 'echo', 'cat'] }); + +await runAgent({ + model, + prompt: 'List all files in /tmp', + tools, + maxSteps: 5, +}); +``` + +Options: +- `cwd` — working directory for commands +- `allowedCommands` — whitelist of allowed commands (if set, others are rejected) + +### `httpTool()` + +Returns: `http_get`, `http_post` + +```typescript +const tools = httpTool(); + +await runAgent({ + model, + prompt: 'Fetch the data from https://api.example.com/status', + tools, + maxSteps: 5, +}); +``` + +### `jsonTool()` + +Returns: `json_validate`, `json_transform` + +```typescript +const tools = jsonTool(); + +// Direct usage: +const result = await tools.json_validate.execute({ + jsonString: '{"name":"test","value":42}', + requiredFields: ['name', 'value'], +}); +// → "Valid JSON: object with 2 keys" +``` + +## Streaming & Callbacks 🎥 + +Monitor the agent in real-time: + +```typescript +const result = await runAgent({ + model, + prompt: 'Analyze this data...', + tools, + maxSteps: 10, + + // Token-by-token streaming + onToken: (delta) => process.stdout.write(delta), + + // Tool call notifications + onToolCall: (toolName) => console.log(`\n🔧 Calling: ${toolName}`), +}); +``` + +## Context Overflow Handling 💥 + +For long-running agents that might exceed the model's context window, use the compaction subpath: + +```typescript +import { runAgent } from '@push.rocks/smartagent'; +import { compactMessages } from '@push.rocks/smartagent/compaction'; + +const result = await runAgent({ + model, + prompt: 'Process all 500 files...', + tools, + maxSteps: 100, + + onContextOverflow: async (messages) => { + // Summarize the conversation to free up context space + return await compactMessages(model, messages); }, }); ``` -**Event Types**: `task_started`, `iteration_started`, `tool_proposed`, `guardian_evaluating`, `tool_approved`, `tool_rejected`, `tool_executing`, `tool_completed`, `task_completed`, `clarification_needed`, `max_iterations`, `max_rejections` +## Output Truncation ✂️ -## 🔧 Native Tool Calling - -For providers that support native tool calling (like Ollama with certain models), SmartAgent can use the provider's built-in tool calling API instead of XML parsing: +Prevent large tool outputs from consuming too much context: ```typescript -const orchestrator = new DualAgentOrchestrator({ - ollamaToken: 'http://localhost:11434', // Ollama endpoint - defaultProvider: 'ollama', - guardianPolicyPrompt: '...', +import { truncateOutput } from '@push.rocks/smartagent'; - // Enable native tool calling - useNativeToolCalling: true, +const { content, truncated, notice } = truncateOutput(hugeOutput, { + maxLines: 2000, // default + maxBytes: 50_000, // default }); ``` -When `useNativeToolCalling` is enabled: -- Tools are converted to JSON schema format automatically -- The provider handles tool call parsing natively -- Streaming still works with `[THINKING]` and `[OUTPUT]` markers for supported models -- Tool calls appear as `toolName_actionName` (e.g., `json_validate`) +The built-in tool factories use `truncateOutput` internally. -This is more efficient for models that support it and avoids potential XML parsing issues. +## Multi-Turn Conversations 💬 -## Guardian Policy Examples - -The Guardian's power comes from your policy. Here are battle-tested examples: - -### 🔐 Strict Security Policy +Pass the returned `messages` back for multi-turn interactions: ```typescript -const securityPolicy = ` -SECURITY POLICY: -1. REJECT any file operations outside /home/user/workspace -2. REJECT any shell commands that could modify system state -3. REJECT any HTTP requests to internal/private IP ranges -4. REJECT any attempts to read environment variables or credentials -5. FLAG and REJECT obfuscated code execution - -When rejecting, always explain: -- What policy was violated -- What would be a safer alternative -`; -``` - -### 🛠️ Development Environment Policy - -```typescript -const devPolicy = ` -DEVELOPMENT POLICY: -- Allow file operations only within the project directory -- Allow npm/pnpm commands for package management -- Allow git commands for version control -- Allow HTTP requests to public APIs only -- REJECT direct database modifications -- REJECT commands that could affect other users - -Always verify: -- File paths are relative or within project bounds -- Commands don't have dangerous flags (--force, -rf) -`; -``` - -### 🦕 Deno Code Execution Policy - -```typescript -const denoPolicy = ` -DENO CODE EXECUTION POLICY: -- ONLY allow 'read' permission for files within the workspace -- REJECT 'all' permission unless explicitly justified for the task -- REJECT 'run' permission (subprocess execution) without specific justification -- REJECT code that attempts to: - - Access credentials or environment secrets (even with 'env' permission) - - Make network requests to internal/private IP ranges - - Write to system directories -- FLAG obfuscated or encoded code (base64, eval with dynamic strings) -- Prefer sandboxed execution (no permissions) when possible - -When evaluating code: -- Review the actual code content, not just permissions -- Consider what data the code could exfiltrate -- Verify network endpoints are legitimate public APIs -`; -``` - -## Configuration Options - -```typescript -interface IDualAgentOptions { - // Provider tokens (from @push.rocks/smartai) - openaiToken?: string; - anthropicToken?: string; - perplexityToken?: string; - groqToken?: string; - xaiToken?: string; - ollamaToken?: string; // URL for Ollama endpoint - - // 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 - - // Agent configuration - driverSystemMessage?: string; // Custom system message for Driver - guardianPolicyPrompt: string; // REQUIRED: Policy for Guardian to enforce - name?: string; // Agent system name - verbose?: boolean; // Enable verbose logging - - // Native tool calling - useNativeToolCalling?: boolean; // Use provider's native tool calling API (default: false) - - // Limits - maxIterations?: number; // Max task iterations (default: 20) - maxConsecutiveRejections?: number; // Abort after N rejections (default: 3) - maxResultChars?: number; // Max chars for tool results before truncation (default: 15000) - maxHistoryMessages?: number; // Max history messages for API (default: 20) - - // Callbacks - onProgress?: (event: IProgressEvent) => void; // Progress event callback - onToken?: (token: string, source: 'driver' | 'guardian') => void; // Streaming callback - logPrefix?: string; // Prefix for log messages -} -``` - -## Result Interface - -```typescript -interface IDualAgentRunResult { - success: boolean; // Whether task completed successfully - completed: boolean; // Task completion status - result: string; // Final result or response - iterations: number; // Number of iterations taken - history: IAgentMessage[]; // Full conversation history - status: TDualAgentRunStatus; // 'completed' | 'max_iterations_reached' | etc. - toolCallCount?: number; // Number of tool calls made - rejectionCount?: number; // Number of Guardian rejections - toolLog?: IToolExecutionLog[]; // Detailed tool execution log - error?: string; // Error message if status is 'error' -} - -type TDualAgentRunStatus = - | 'completed' - | 'in_progress' - | 'max_iterations_reached' - | 'max_rejections_reached' - | 'clarification_needed' - | 'error'; -``` - -## Custom Tools - -Create custom tools by extending `BaseToolWrapper`: - -```typescript -import { BaseToolWrapper, IToolAction, IToolExecutionResult } from '@push.rocks/smartagent'; - -class MyCustomTool extends BaseToolWrapper { - public name = 'custom'; - public description = 'My custom tool for specific operations'; - - public actions: IToolAction[] = [ - { - name: 'myAction', - description: 'Performs a custom action', - parameters: { - type: 'object', - properties: { - input: { type: 'string', description: 'Input for the action' }, - }, - required: ['input'], - }, - }, - ]; - - public async initialize(): Promise { - // Setup your tool (called when orchestrator.start() runs) - this.isInitialized = true; - } - - public async cleanup(): Promise { - // Cleanup resources (called when orchestrator.stop() runs) - this.isInitialized = false; - } - - public async execute(action: string, params: Record): Promise { - this.validateAction(action); - this.ensureInitialized(); - - if (action === 'myAction') { - return { - success: true, - result: { processed: params.input }, - summary: `Processed input: ${params.input}`, // Optional human-readable summary - }; - } - - return { success: false, error: 'Unknown action' }; - } - - // Human-readable summary for Guardian evaluation - public getCallSummary(action: string, params: Record): string { - return `Custom action "${action}" with input "${params.input}"`; - } -} - -// Register custom tool -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: '...', +// First turn +const turn1 = await runAgent({ + model, + prompt: 'Create a project structure', + tools, + maxSteps: 10, }); -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 | ✅ | ✅ | -| 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: '...', +// Second turn — continues the conversation +const turn2 = await runAgent({ + model, + prompt: 'Now add a README to the project', + tools, + maxSteps: 10, + messages: turn1.messages, // pass history }); ``` -## API Reference +## Exports -### DualAgentOrchestrator +### Main (`@push.rocks/smartagent`) -| Method | Description | -|--------|-------------| -| `start()` | Initialize all tools and AI providers | -| `stop()` | Cleanup all tools and resources | -| `run(task, options?)` | Execute a task with optional images for vision | -| `continueTask(input)` | Continue a task with user input | -| `registerTool(tool, options?)` | Register a custom tool with optional visibility settings | -| `registerStandardTools()` | Register all built-in tools (Filesystem, HTTP, Shell, Browser, Deno) | -| `registerScopedFilesystemTool(basePath, excludePatterns?)` | Register filesystem tool with path restriction | -| `registerExpert(config)` | Register a specialized sub-agent as a tool | -| `enableToolSearch()` | Enable tool discovery and activation for the Driver | -| `setGuardianPolicy(policy)` | Update Guardian policy at runtime | -| `getHistory()` | Get conversation history | -| `getToolNames()` | Get list of registered tool names | -| `getRegistry()` | Get the ToolRegistry for advanced operations | -| `isActive()` | Check if orchestrator is running | +| Export | Type | Description | +|--------|------|-------------| +| `runAgent` | function | Core agentic loop | +| `ToolRegistry` | class | Tool collection helper | +| `truncateOutput` | function | Output truncation utility | +| `ContextOverflowError` | class | Error type for context overflow | +| `tool` | function | Re-exported from `@push.rocks/smartai` | +| `z` | object | Re-exported Zod for schema definitions | +| `stepCountIs` | function | Re-exported from AI SDK | +| `jsonSchema` | function | Re-exported from `@push.rocks/smartai` | -### Exports +### Tools (`@push.rocks/smartagent/tools`) -```typescript -// Main classes -export { DualAgentOrchestrator } from '@push.rocks/smartagent'; -export { DriverAgent } from '@push.rocks/smartagent'; -export { GuardianAgent } from '@push.rocks/smartagent'; +| Export | Type | Description | +|--------|------|-------------| +| `filesystemTool` | factory | File operations (read, write, list, delete) | +| `shellTool` | factory | Shell command execution | +| `httpTool` | factory | HTTP GET/POST requests | +| `jsonTool` | factory | JSON validation and transformation | -// Tool Registry -export { ToolRegistry } from '@push.rocks/smartagent'; +### Compaction (`@push.rocks/smartagent/compaction`) -// Tools -export { BaseToolWrapper } from '@push.rocks/smartagent'; -export { FilesystemTool, type IFilesystemToolOptions } from '@push.rocks/smartagent'; -export { HttpTool } from '@push.rocks/smartagent'; -export { ShellTool } from '@push.rocks/smartagent'; -export { BrowserTool } from '@push.rocks/smartagent'; -export { DenoTool, type TDenoPermission } from '@push.rocks/smartagent'; -export { JsonValidatorTool } from '@push.rocks/smartagent'; -export { ToolSearchTool } from '@push.rocks/smartagent'; -export { ExpertTool } from '@push.rocks/smartagent'; +| Export | Type | Description | +|--------|------|-------------| +| `compactMessages` | function | Summarize message history to free context | -// Types and interfaces -export * from '@push.rocks/smartagent'; // All interfaces (IExpertConfig, IToolMetadata, etc.) +## Dependencies -// Re-exported from @push.rocks/smartai -export { type ISmartAiOptions, type TProvider, type ChatMessage, type ChatOptions, type ChatResponse }; -``` +- **[`@push.rocks/smartai`](https://code.foss.global/push.rocks/smartai)** — Provider registry, `getModel()`, re-exports `tool`/`jsonSchema` +- **[`ai`](https://www.npmjs.com/package/ai)** v6 — Vercel AI SDK (`streamText`, `stepCountIs`, `ModelMessage`) +- **[`zod`](https://www.npmjs.com/package/zod)** — Tool input schema definitions +- **[`@push.rocks/smartfs`](https://code.foss.global/push.rocks/smartfs)** — Filesystem tool implementation +- **[`@push.rocks/smartshell`](https://code.foss.global/push.rocks/smartshell)** — Shell tool implementation +- **[`@push.rocks/smartrequest`](https://code.foss.global/push.rocks/smartrequest)** — HTTP tool implementation ## License and Legal Information diff --git a/test/test.agent-e2e.ts b/test/test.agent-e2e.ts new file mode 100644 index 0000000..59581cf --- /dev/null +++ b/test/test.agent-e2e.ts @@ -0,0 +1,239 @@ +import { expect, tap } from '@git.zone/tstest/tapbundle'; +import * as qenv from '@push.rocks/qenv'; +import * as path from 'path'; +import * as fs from 'fs'; +import { runAgent, tool, z, ToolRegistry } from '../ts/index.js'; +import { filesystemTool, shellTool } from '../ts_tools/index.js'; + +const testQenv = new qenv.Qenv('./', './.nogit/'); + +let model: any; +const workDir = '/tmp/smartagent-e2e-' + Date.now(); + +tap.test('setup: create model and workspace', async () => { + const apiKey = await testQenv.getEnvVarOnDemand('ANTHROPIC_TOKEN'); + if (!apiKey) { + console.log('ANTHROPIC_TOKEN not set — skipping all E2E tests'); + process.exit(0); + } + + const { getModel } = await import('@push.rocks/smartai'); + model = getModel({ + provider: 'anthropic', + model: 'claude-sonnet-4-5-20250929', + apiKey, + }); + + fs.mkdirSync(workDir, { recursive: true }); + console.log(` Workspace: ${workDir}`); +}); + +// ============================================================ +// Test 1: Simple tool call +// ============================================================ + +tap.test('agent should call a single tool and incorporate the result', async () => { + let toolCalled = false; + + const result = await runAgent({ + model, + prompt: 'What is the current time? Use the get_time tool.', + system: 'You are a helpful assistant. Use tools when asked.', + tools: { + get_time: tool({ + description: 'Returns the current ISO timestamp', + inputSchema: z.object({}), + execute: async () => { + toolCalled = true; + return new Date().toISOString(); + }, + }), + }, + maxSteps: 5, + }); + + console.log(` Response: ${result.text.substring(0, 150)}`); + console.log(` Steps: ${result.steps}, Tokens: ${result.usage.totalTokens}`); + + expect(toolCalled).toBeTrue(); + expect(result.text).toBeTruthy(); + expect(result.usage.totalTokens).toBeGreaterThan(0); +}); + +// ============================================================ +// Test 2: Multiple tools — agent chooses which to use +// ============================================================ + +tap.test('agent should pick the right tool from multiple options', async () => { + const callLog: string[] = []; + + const result = await runAgent({ + model, + prompt: 'Add 7 and 35 using the calculator tool.', + system: 'You are a helpful assistant. Use the appropriate tool to answer.', + tools: { + calculator: tool({ + description: 'Perform arithmetic. Supports add, subtract, multiply, divide.', + inputSchema: z.object({ + operation: z.enum(['add', 'subtract', 'multiply', 'divide']), + a: z.number(), + b: z.number(), + }), + execute: async ({ operation, a, b }: { operation: string; a: number; b: number }) => { + callLog.push(`calculator:${operation}(${a}, ${b})`); + switch (operation) { + case 'add': return String(a + b); + case 'subtract': return String(a - b); + case 'multiply': return String(a * b); + case 'divide': return b !== 0 ? String(a / b) : 'Error: division by zero'; + default: return 'Unknown operation'; + } + }, + }), + get_weather: tool({ + description: 'Get current weather for a city', + inputSchema: z.object({ city: z.string() }), + execute: async () => { + callLog.push('get_weather'); + return 'Sunny, 22°C'; + }, + }), + }, + maxSteps: 5, + }); + + console.log(` Tool calls: ${callLog.join(', ')}`); + console.log(` Response: ${result.text.substring(0, 150)}`); + + expect(callLog.some((c) => c.startsWith('calculator:add'))).toBeTrue(); + expect(callLog).not.toContain('get_weather'); + expect(result.text).toInclude('42'); +}); + +// ============================================================ +// Test 3: Multi-step — agent uses filesystem tools +// ============================================================ + +tap.test('agent should use filesystem tools for a multi-step task', async () => { + const fsTools = filesystemTool({ rootDir: workDir }); + + const result = await runAgent({ + model, + prompt: `Create a file called "greeting.txt" in ${workDir} with the content "Hello from smartagent!". Then read it back and tell me what it says.`, + system: 'You are a helpful assistant that works with files. Use the provided tools.', + tools: fsTools, + maxSteps: 10, + }); + + console.log(` Steps: ${result.steps}`); + console.log(` Response: ${result.text.substring(0, 200)}`); + + // Verify the file was actually created + const filePath = path.join(workDir, 'greeting.txt'); + expect(fs.existsSync(filePath)).toBeTrue(); + const content = fs.readFileSync(filePath, 'utf-8'); + expect(content).toInclude('Hello from smartagent'); + expect(result.steps).toBeGreaterThanOrEqual(2); +}); + +// ============================================================ +// Test 4: ToolRegistry usage +// ============================================================ + +tap.test('agent should work with ToolRegistry', async () => { + const registry = new ToolRegistry(); + + registry.register('random_number', tool({ + description: 'Generate a random integer between min and max (inclusive)', + inputSchema: z.object({ + min: z.number().describe('Minimum value'), + max: z.number().describe('Maximum value'), + }), + execute: async ({ min, max }: { min: number; max: number }) => { + const value = Math.floor(Math.random() * (max - min + 1)) + min; + return String(value); + }, + })); + + registry.register('is_even', tool({ + description: 'Check if a number is even', + inputSchema: z.object({ number: z.number() }), + execute: async ({ number: n }: { number: number }) => { + return n % 2 === 0 ? 'Yes, it is even' : 'No, it is odd'; + }, + })); + + const result = await runAgent({ + model, + prompt: 'Generate a random number between 1 and 100, then check if it is even or odd. Tell me both the number and whether it is even.', + system: 'You are a helpful assistant. Use tools step by step.', + tools: registry.getTools(), + maxSteps: 10, + }); + + console.log(` Response: ${result.text.substring(0, 200)}`); + expect(result.text).toBeTruthy(); + expect(result.steps).toBeGreaterThanOrEqual(2); +}); + +// ============================================================ +// Test 5: Streaming callbacks +// ============================================================ + +tap.test('agent should fire onToken and onToolCall callbacks', async () => { + const tokens: string[] = []; + const toolCalls: string[] = []; + + const result = await runAgent({ + model, + prompt: 'Use the echo tool to echo "test123".', + system: 'You are a helpful assistant. Use tools when asked.', + tools: { + echo: tool({ + description: 'Echo back the provided text', + inputSchema: z.object({ text: z.string() }), + execute: async ({ text }: { text: string }) => text, + }), + }, + maxSteps: 5, + onToken: (delta) => tokens.push(delta), + onToolCall: (name) => toolCalls.push(name), + }); + + console.log(` Streamed ${tokens.length} token chunks`); + console.log(` Tool calls observed: ${toolCalls.join(', ')}`); + + expect(tokens.length).toBeGreaterThan(0); + expect(toolCalls).toContain('echo'); + expect(result.text).toInclude('test123'); +}); + +// ============================================================ +// Test 6: Shell tool integration +// ============================================================ + +tap.test('agent should use shell tool to run a command', async () => { + const tools = shellTool(); + + const result = await runAgent({ + model, + prompt: `Run the command "echo hello_smartagent" and tell me what it outputs.`, + system: 'You are a helpful assistant that can run shell commands.', + tools, + maxSteps: 5, + }); + + console.log(` Response: ${result.text.substring(0, 200)}`); + expect(result.text).toInclude('hello_smartagent'); +}); + +// ============================================================ +// Cleanup +// ============================================================ + +tap.test('cleanup: remove workspace', async () => { + fs.rmSync(workDir, { recursive: true, force: true }); + console.log(` Cleaned up ${workDir}`); +}); + +export default tap.start(); diff --git a/test/test.ts b/test/test.ts index 1828362..9ab5f1d 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,150 +1,188 @@ import { expect, tap } from '@git.zone/tstest/tapbundle'; import * as smartagent from '../ts/index.js'; +import { filesystemTool, shellTool, httpTool, jsonTool, truncateOutput } from '../ts_tools/index.js'; +import { compactMessages } from '../ts_compaction/index.js'; -// Test exports -tap.test('should export DualAgentOrchestrator class', async () => { - expect(smartagent.DualAgentOrchestrator).toBeTypeOf('function'); +// ============================================================ +// Core exports +// ============================================================ + +tap.test('should export runAgent function', async () => { + expect(smartagent.runAgent).toBeTypeOf('function'); }); -tap.test('should export DriverAgent class', async () => { - expect(smartagent.DriverAgent).toBeTypeOf('function'); +tap.test('should export ToolRegistry class', async () => { + expect(smartagent.ToolRegistry).toBeTypeOf('function'); }); -tap.test('should export GuardianAgent class', async () => { - expect(smartagent.GuardianAgent).toBeTypeOf('function'); +tap.test('should export ContextOverflowError class', async () => { + expect(smartagent.ContextOverflowError).toBeTypeOf('function'); }); -tap.test('should export BaseToolWrapper class', async () => { - expect(smartagent.BaseToolWrapper).toBeTypeOf('function'); +tap.test('should export truncateOutput function', async () => { + expect(smartagent.truncateOutput).toBeTypeOf('function'); }); -// Test standard tools exports -tap.test('should export FilesystemTool class', async () => { - expect(smartagent.FilesystemTool).toBeTypeOf('function'); +tap.test('should re-export tool helper', async () => { + expect(smartagent.tool).toBeTypeOf('function'); }); -tap.test('should export HttpTool class', async () => { - expect(smartagent.HttpTool).toBeTypeOf('function'); +tap.test('should re-export z (zod)', async () => { + expect(smartagent.z).toBeTruthy(); }); -tap.test('should export ShellTool class', async () => { - expect(smartagent.ShellTool).toBeTypeOf('function'); +tap.test('should re-export stepCountIs', async () => { + expect(smartagent.stepCountIs).toBeTypeOf('function'); }); -tap.test('should export BrowserTool class', async () => { - expect(smartagent.BrowserTool).toBeTypeOf('function'); -}); +// ============================================================ +// ToolRegistry +// ============================================================ -tap.test('should export DenoTool class', async () => { - expect(smartagent.DenoTool).toBeTypeOf('function'); -}); - -// Test tool instantiation -tap.test('should be able to instantiate FilesystemTool', async () => { - const fsTool = new smartagent.FilesystemTool(); - expect(fsTool.name).toEqual('filesystem'); - expect(fsTool.actions).toBeTypeOf('object'); - expect(fsTool.actions.length).toBeGreaterThan(0); -}); - -tap.test('should be able to instantiate HttpTool', async () => { - const httpTool = new smartagent.HttpTool(); - expect(httpTool.name).toEqual('http'); - expect(httpTool.actions).toBeTypeOf('object'); -}); - -tap.test('should be able to instantiate ShellTool', async () => { - const shellTool = new smartagent.ShellTool(); - expect(shellTool.name).toEqual('shell'); - expect(shellTool.actions).toBeTypeOf('object'); -}); - -tap.test('should be able to instantiate BrowserTool', async () => { - const browserTool = new smartagent.BrowserTool(); - expect(browserTool.name).toEqual('browser'); - expect(browserTool.actions).toBeTypeOf('object'); -}); - -tap.test('should be able to instantiate DenoTool', async () => { - const denoTool = new smartagent.DenoTool(); - expect(denoTool.name).toEqual('deno'); - expect(denoTool.actions).toBeTypeOf('object'); -}); - -// Test tool descriptions -tap.test('FilesystemTool should have required actions', async () => { - const fsTool = new smartagent.FilesystemTool(); - const actionNames = fsTool.actions.map((a) => a.name); - expect(actionNames).toContain('read'); - expect(actionNames).toContain('write'); - expect(actionNames).toContain('list'); - expect(actionNames).toContain('delete'); - expect(actionNames).toContain('exists'); -}); - -tap.test('HttpTool should have required actions', async () => { - const httpTool = new smartagent.HttpTool(); - const actionNames = httpTool.actions.map((a) => a.name); - expect(actionNames).toContain('get'); - expect(actionNames).toContain('post'); - expect(actionNames).toContain('put'); - expect(actionNames).toContain('delete'); -}); - -tap.test('ShellTool should have required actions', async () => { - const shellTool = new smartagent.ShellTool(); - const actionNames = shellTool.actions.map((a) => a.name); - expect(actionNames).toContain('execute'); - expect(actionNames).toContain('which'); -}); - -tap.test('BrowserTool should have required actions', async () => { - const browserTool = new smartagent.BrowserTool(); - const actionNames = browserTool.actions.map((a) => a.name); - expect(actionNames).toContain('screenshot'); - expect(actionNames).toContain('pdf'); - expect(actionNames).toContain('evaluate'); - expect(actionNames).toContain('getPageContent'); -}); - -tap.test('DenoTool should have required actions', async () => { - const denoTool = new smartagent.DenoTool(); - const actionNames = denoTool.actions.map((a) => a.name); - expect(actionNames).toContain('execute'); - expect(actionNames).toContain('executeWithResult'); -}); - -// Test getCallSummary -tap.test('FilesystemTool should generate call summaries', async () => { - const fsTool = new smartagent.FilesystemTool(); - const summary = fsTool.getCallSummary('read', { path: '/tmp/test.txt' }); - expect(summary).toBeTypeOf('string'); - expect(summary).toInclude('/tmp/test.txt'); -}); - -tap.test('HttpTool should generate call summaries', async () => { - const httpTool = new smartagent.HttpTool(); - const summary = httpTool.getCallSummary('get', { url: 'https://example.com' }); - expect(summary).toBeTypeOf('string'); - expect(summary).toInclude('example.com'); -}); - -tap.test('DenoTool should generate call summaries', async () => { - const denoTool = new smartagent.DenoTool(); - const summary = denoTool.getCallSummary('execute', { code: 'console.log("hello");' }); - expect(summary).toBeTypeOf('string'); - expect(summary).toInclude('sandboxed'); -}); - -tap.test('DenoTool should show permissions in call summary', async () => { - const denoTool = new smartagent.DenoTool(); - const summary = denoTool.getCallSummary('execute', { - code: 'console.log("hello");', - permissions: ['net', 'read'] +tap.test('ToolRegistry should register and return tools', async () => { + const registry = new smartagent.ToolRegistry(); + const echoTool = smartagent.tool({ + description: 'Echo tool', + inputSchema: smartagent.z.object({ text: smartagent.z.string() }), + execute: async ({ text }: { text: string }) => text, }); - expect(summary).toBeTypeOf('string'); - expect(summary).toInclude('permissions'); - expect(summary).toInclude('net'); + registry.register('echo', echoTool); + const tools = registry.getTools(); + expect(Object.keys(tools)).toContain('echo'); +}); + +// ============================================================ +// Truncation +// ============================================================ + +tap.test('truncateOutput should not truncate short strings', async () => { + const result = truncateOutput('hello world'); + expect(result.truncated).toBeFalse(); + expect(result.content).toEqual('hello world'); +}); + +tap.test('truncateOutput should truncate strings over maxLines', async () => { + const lines = Array.from({ length: 3000 }, (_, i) => `line ${i}`).join('\n'); + const result = truncateOutput(lines, { maxLines: 100 }); + expect(result.truncated).toBeTrue(); + expect(result.notice).toBeTruthy(); + expect(result.content).toInclude('[Output truncated'); +}); + +tap.test('truncateOutput should truncate strings over maxBytes', async () => { + const big = 'x'.repeat(100_000); + const result = truncateOutput(big, { maxBytes: 1000 }); + expect(result.truncated).toBeTrue(); +}); + +// ============================================================ +// Tool factories +// ============================================================ + +tap.test('filesystemTool returns expected tool names', async () => { + const tools = filesystemTool(); + const names = Object.keys(tools); + expect(names).toContain('read_file'); + expect(names).toContain('write_file'); + expect(names).toContain('list_directory'); + expect(names).toContain('delete_file'); +}); + +tap.test('shellTool returns expected tool names', async () => { + const tools = shellTool(); + const names = Object.keys(tools); + expect(names).toContain('run_command'); +}); + +tap.test('httpTool returns expected tool names', async () => { + const tools = httpTool(); + const names = Object.keys(tools); + expect(names).toContain('http_get'); + expect(names).toContain('http_post'); +}); + +tap.test('jsonTool returns expected tool names', async () => { + const tools = jsonTool(); + const names = Object.keys(tools); + expect(names).toContain('json_validate'); + expect(names).toContain('json_transform'); +}); + +tap.test('json_validate tool should validate valid JSON', async () => { + const tools = jsonTool(); + const result = await (tools.json_validate as any).execute({ + jsonString: '{"name":"test","value":42}', + }); + expect(result).toInclude('Valid JSON'); +}); + +tap.test('json_validate tool should detect invalid JSON', async () => { + const tools = jsonTool(); + const result = await (tools.json_validate as any).execute({ + jsonString: '{invalid json', + }); + expect(result).toInclude('Invalid JSON'); +}); + +tap.test('json_validate tool should check required fields', async () => { + const tools = jsonTool(); + const result = await (tools.json_validate as any).execute({ + jsonString: '{"name":"test"}', + requiredFields: ['name', 'missing_field'], + }); + expect(result).toInclude('missing_field'); +}); + +tap.test('json_transform tool should pretty-print JSON', async () => { + const tools = jsonTool(); + const result = await (tools.json_transform as any).execute({ + jsonString: '{"a":1,"b":2}', + }); + expect(result).toInclude(' "a": 1'); +}); + +// ============================================================ +// Compaction export +// ============================================================ + +tap.test('compactMessages should be a function', async () => { + expect(compactMessages).toBeTypeOf('function'); +}); + +// ============================================================ +// Filesystem tool read/write round-trip +// ============================================================ + +tap.test('filesystem tool should write and read a file', async () => { + const tmpDir = '/tmp/smartagent-test-' + Date.now(); + const tools = filesystemTool({ rootDir: tmpDir }); + + await (tools.write_file as any).execute({ + path: tmpDir + '/hello.txt', + content: 'Hello, world!', + }); + + const content = await (tools.read_file as any).execute({ + path: tmpDir + '/hello.txt', + }); + expect(content).toInclude('Hello, world!'); + + // Cleanup + await (tools.delete_file as any).execute({ + path: tmpDir + '/hello.txt', + }); +}); + +tap.test('filesystem tool should enforce rootDir restriction', async () => { + const tools = filesystemTool({ rootDir: '/tmp/restricted' }); + let threw = false; + try { + await (tools.read_file as any).execute({ path: '/etc/passwd' }); + } catch (e) { + threw = true; + expect((e as Error).message).toInclude('Access denied'); + } + expect(threw).toBeTrue(); }); export default tap.start(); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 0ae1061..b62b374 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartagent', - version: '1.8.0', - description: 'an agentic framework built on top of @push.rocks/smartai' + version: '3.0.0', + description: 'Agentic loop for ai-sdk (Vercel AI SDK). Wraps streamText with stopWhen for parallel multi-step tool execution. Built on @push.rocks/smartai.' } diff --git a/ts/index.ts b/ts/index.ts index ff94c9e..e18822e 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -1,38 +1,11 @@ -import * as plugins from './plugins.js'; - -// Export the dual-agent orchestrator (main entry point) -export { DualAgentOrchestrator } from './smartagent.classes.dualagent.js'; - -// Export individual agents -export { DriverAgent } from './smartagent.classes.driveragent.js'; -export { GuardianAgent } from './smartagent.classes.guardianagent.js'; - -// Export tool registry and related classes +export { runAgent } from './smartagent.classes.agent.js'; export { ToolRegistry } from './smartagent.classes.toolregistry.js'; +export { truncateOutput } from './smartagent.utils.truncation.js'; +export type { ITruncateResult } from './smartagent.utils.truncation.js'; +export { ContextOverflowError } from './smartagent.interfaces.js'; +export type { IAgentRunOptions, IAgentRunResult } from './smartagent.interfaces.js'; -// Export base tool class for custom tool creation -export { BaseToolWrapper } from './smartagent.tools.base.js'; - -// Export standard tools -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'; -export { DenoTool, type TDenoPermission } from './smartagent.tools.deno.js'; -export { JsonValidatorTool } from './smartagent.tools.json.js'; - -// Export tool search and expert tools -export { ToolSearchTool } from './smartagent.tools.search.js'; -export { ExpertTool } from './smartagent.tools.expert.js'; - -// Export all interfaces -export * from './smartagent.interfaces.js'; - -// Re-export useful types from smartai -export { - type ISmartAiOptions, - type TProvider, - type ChatMessage, - type ChatOptions, - type ChatResponse, -} from '@push.rocks/smartai'; +// Re-export tool() and z so consumers can define tools without extra imports +export { tool, jsonSchema } from '@push.rocks/smartai'; +export { z } from 'zod'; +export { stepCountIs } from 'ai'; diff --git a/ts/plugins.ts b/ts/plugins.ts index e42752b..a778fc2 100644 --- a/ts/plugins.ts +++ b/ts/plugins.ts @@ -3,24 +3,25 @@ import * as path from 'path'; export { path }; -// third party -import { minimatch } from 'minimatch'; +// ai-sdk core +import { streamText, generateText, stepCountIs } from 'ai'; -export { minimatch }; +export { streamText, generateText, stepCountIs }; -// @push.rocks scope -import * as smartai from '@push.rocks/smartai'; -import * as smartdeno from '@push.rocks/smartdeno'; -import * as smartfs from '@push.rocks/smartfs'; -import * as smartrequest from '@push.rocks/smartrequest'; -import * as smartbrowser from '@push.rocks/smartbrowser'; -import * as smartshell from '@push.rocks/smartshell'; +export type { + ModelMessage, + ToolSet, + StreamTextResult, +} from 'ai'; -export { - smartai, - smartdeno, - smartfs, - smartrequest, - smartbrowser, - smartshell, -}; +// @push.rocks/smartai +import { tool, jsonSchema } from '@push.rocks/smartai'; + +export { tool, jsonSchema }; + +export type { LanguageModelV3 } from '@push.rocks/smartai'; + +// zod +import { z } from 'zod'; + +export { z }; diff --git a/ts/smartagent.classes.agent.ts b/ts/smartagent.classes.agent.ts new file mode 100644 index 0000000..2849a85 --- /dev/null +++ b/ts/smartagent.classes.agent.ts @@ -0,0 +1,198 @@ +// Retry backoff and context overflow logic derived from opencode (MIT) — https://github.com/sst/opencode + +import * as plugins from './plugins.js'; +import type { IAgentRunOptions, IAgentRunResult } from './smartagent.interfaces.js'; +import { ContextOverflowError } from './smartagent.interfaces.js'; + +// Retry constants +const RETRY_INITIAL_DELAY = 2000; +const RETRY_BACKOFF_FACTOR = 2; +const RETRY_MAX_DELAY = 30_000; +const MAX_RETRY_ATTEMPTS = 8; + +function retryDelay(attempt: number, headers?: Record): number { + if (headers) { + const ms = headers['retry-after-ms']; + if (ms) { + const n = parseFloat(ms); + if (!isNaN(n)) return n; + } + const after = headers['retry-after']; + if (after) { + const secs = parseFloat(after); + if (!isNaN(secs)) return Math.ceil(secs * 1000); + const date = Date.parse(after) - Date.now(); + if (!isNaN(date) && date > 0) return Math.ceil(date); + } + } + return Math.min( + RETRY_INITIAL_DELAY * Math.pow(RETRY_BACKOFF_FACTOR, attempt - 1), + RETRY_MAX_DELAY, + ); +} + +async function sleep(ms: number, signal?: AbortSignal): Promise { + return new Promise((resolve, reject) => { + if (signal?.aborted) { + reject(new DOMException('Aborted', 'AbortError')); + return; + } + const t = setTimeout(resolve, ms); + signal?.addEventListener( + 'abort', + () => { + clearTimeout(t); + reject(new DOMException('Aborted', 'AbortError')); + }, + { once: true }, + ); + }); +} + +function isRetryableError(err: unknown): boolean { + const status = (err as any)?.status ?? (err as any)?.statusCode; + if (status === 429 || status === 529 || status === 503) return true; + if (err instanceof Error) { + const msg = err.message.toLowerCase(); + if (msg.includes('rate limit') || msg.includes('overloaded') || msg.includes('too many requests')) { + return true; + } + } + return false; +} + +function isContextOverflow(err: unknown): boolean { + if (err instanceof Error) { + const msg = err.message.toLowerCase(); + return ( + msg.includes('context_length_exceeded') || + msg.includes('context window') || + msg.includes('maximum context length') || + msg.includes('too many tokens') || + msg.includes('input is too long') || + (err as any)?.name === 'AI_ContextWindowExceededError' + ); + } + return false; +} + +export async function runAgent(options: IAgentRunOptions): Promise { + let stepCount = 0; + let attempt = 0; + let totalInput = 0; + let totalOutput = 0; + + const tools = options.tools ?? {}; + + // Add a no-op sink for repaired-but-unrecognised tool calls + const allTools: plugins.ToolSet = { + ...tools, + invalid: plugins.tool({ + description: 'Sink for unrecognised tool calls — returns an error message to the model', + inputSchema: plugins.z.object({ + tool: plugins.z.string(), + error: plugins.z.string(), + }), + execute: async ({ tool, error }: { tool: string; error: string }) => + `Unknown tool "${tool}": ${error}`, + }), + }; + + // Build messages — streamText requires either prompt OR messages, not both + let messages: plugins.ModelMessage[] = options.messages + ? [...options.messages, { role: 'user' as const, content: options.prompt }] + : [{ role: 'user' as const, content: options.prompt }]; + + while (true) { + try { + const result = plugins.streamText({ + model: options.model, + system: options.system, + messages, + tools: allTools, + stopWhen: plugins.stepCountIs(options.maxSteps ?? 20), + maxRetries: 0, // handled manually below + abortSignal: options.abort, + + experimental_repairToolCall: async ({ toolCall, tools: availableTools, error }) => { + const lower = toolCall.toolName.toLowerCase(); + if (lower !== toolCall.toolName && (availableTools as any)[lower]) { + return { ...toolCall, toolName: lower }; + } + return { + ...toolCall, + toolName: 'invalid', + args: JSON.stringify({ + tool: toolCall.toolName, + error: String(error), + }), + }; + }, + + onChunk: ({ chunk }) => { + if (chunk.type === 'text-delta' && options.onToken) { + options.onToken((chunk as any).textDelta ?? (chunk as any).text ?? ''); + } + }, + + experimental_onToolCallStart: options.onToolCall + ? ({ toolCall }) => { + options.onToolCall!(toolCall.toolName, (toolCall as any).input ?? (toolCall as any).args); + } + : undefined, + + experimental_onToolCallFinish: options.onToolResult + ? ({ toolCall }) => { + options.onToolResult!(toolCall.toolName, (toolCall as any).result); + } + : undefined, + + onStepFinish: ({ usage }) => { + stepCount++; + totalInput += usage?.inputTokens ?? 0; + totalOutput += usage?.outputTokens ?? 0; + }, + }); + + // Consume the stream and collect results + const text = await result.text; + const finishReason = await result.finishReason; + const responseData = await result.response; + + attempt = 0; // reset on success + + return { + text, + messages: responseData.messages as plugins.ModelMessage[], + steps: stepCount, + finishReason, + usage: { + inputTokens: totalInput, + outputTokens: totalOutput, + totalTokens: totalInput + totalOutput, + }, + }; + } catch (err: unknown) { + // Abort — don't retry + if (err instanceof DOMException && err.name === 'AbortError') throw err; + + // Rate limit / overload — retry with backoff + if (isRetryableError(err) && attempt < MAX_RETRY_ATTEMPTS) { + attempt++; + const headers = (err as any)?.responseHeaders ?? (err as any)?.headers; + const delay = retryDelay(attempt, headers); + await sleep(delay, options.abort); + continue; + } + + // Context overflow — compact and retry if handler provided + if (isContextOverflow(err)) { + if (!options.onContextOverflow) throw new ContextOverflowError(); + messages = await options.onContextOverflow(messages); + continue; + } + + throw err; + } + } +} diff --git a/ts/smartagent.classes.driveragent.ts b/ts/smartagent.classes.driveragent.ts deleted file mode 100644 index ab2a011..0000000 --- a/ts/smartagent.classes.driveragent.ts +++ /dev/null @@ -1,775 +0,0 @@ -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; - /** Callback fired for each token during LLM generation */ - onToken?: (token: string) => void; -} - -/** - * DriverAgent - Executes tasks by reasoning and proposing tool calls - * Works in conjunction with GuardianAgent for approval - */ -export class DriverAgent { - private provider: plugins.smartai.MultiModalModel; - private systemMessage: string; - private maxHistoryMessages: number; - private messageHistory: plugins.smartai.ChatMessage[] = []; - private tools: Map = new Map(); - private onToken?: (token: string) => void; - private isInThinkingMode = false; // Track thinking/content state for markers - - constructor( - provider: plugins.smartai.MultiModalModel, - options?: IDriverAgentOptions | string - ) { - this.provider = provider; - - // 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; - this.onToken = options?.onToken; - } - } - - /** - * Set the token callback for streaming mode - * @param callback Function to call for each generated token - */ - public setOnToken(callback: (token: string) => void): void { - this.onToken = callback; - } - - /** - * Register a tool for use by the driver - */ - public registerTool(tool: BaseToolWrapper): void { - this.tools.set(tool.name, tool); - } - - /** - * Get all registered tools - */ - public getTools(): Map { - return this.tools; - } - - /** - * Initialize a new conversation for a task - * @param task The task description - * @param images Optional base64-encoded images for vision tasks - */ - public async startTask(task: string, images?: string[]): Promise { - // Reset message history - this.messageHistory = []; - - // 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 your output here tags.`; - } - - // Add to history - this.messageHistory.push({ - role: 'user', - content: userMessage, - }); - - // 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 - use streaming if available and callback is set - let response: plugins.smartai.ChatResponse; - - if (this.onToken && typeof (this.provider as any).chatStreaming === 'function') { - // Use streaming mode with token callback - response = await (this.provider as any).chatStreaming({ - systemMessage: fullSystemMessage, - userMessage: userMessage, - messageHistory: [], - images: images, - onToken: this.onToken, - }); - } else { - // Fallback to non-streaming mode - response = await this.provider.chat({ - systemMessage: fullSystemMessage, - userMessage: userMessage, - messageHistory: [], - images: images, - }); - } - - // Add assistant response to history (store images if provided, preserve reasoning for GPT-OSS) - const historyMessage: plugins.smartai.ChatMessage = { - role: 'assistant', - content: response.message, - reasoning: response.reasoning, - }; - this.messageHistory.push(historyMessage); - - return { - role: 'assistant', - content: response.message, - }; - } - - /** - * Continue the conversation with feedback or results - */ - public async continueWithMessage(message: string): Promise { - // Add the new message to history - this.messageHistory.push({ - role: 'user', - content: message, - }); - - // 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 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; - } - - // Get response from provider - use streaming if available and callback is set - let response: plugins.smartai.ChatResponse; - - if (this.onToken && typeof (this.provider as any).chatStreaming === 'function') { - // Use streaming mode with token callback - response = await (this.provider as any).chatStreaming({ - systemMessage: fullSystemMessage, - userMessage: message, - messageHistory: historyForChat, - onToken: this.onToken, - }); - } else { - // Fallback to non-streaming mode - response = await this.provider.chat({ - systemMessage: fullSystemMessage, - userMessage: message, - messageHistory: historyForChat, - }); - } - - // Add assistant response to history (preserve reasoning for GPT-OSS) - this.messageHistory.push({ - role: 'assistant', - content: response.message, - reasoning: response.reasoning, - }); - - return { - role: 'assistant', - content: response.message, - }; - } - - /** - * Parse tool call proposals from assistant response - */ - public parseToolCallProposals(response: string): interfaces.IToolCallProposal[] { - const proposals: interfaces.IToolCallProposal[] = []; - - // Match ... blocks - const toolCallRegex = /([\s\S]*?)<\/tool_call>/g; - let match; - - while ((match = toolCallRegex.exec(response)) !== null) { - const content = match[1]; - - try { - const proposal = this.parseToolCallContent(content); - if (proposal) { - proposals.push(proposal); - } - } catch (error) { - // Skip malformed tool calls - console.warn('Failed to parse tool call:', error); - } - } - - return proposals; - } - - /** - * Parse the content inside a tool_call block - */ - private parseToolCallContent(content: string): interfaces.IToolCallProposal | null { - // Extract tool name - const toolMatch = content.match(/(.*?)<\/tool>/s); - if (!toolMatch) return null; - const toolName = toolMatch[1].trim(); - - // Extract action - const actionMatch = content.match(/(.*?)<\/action>/s); - if (!actionMatch) return null; - const action = actionMatch[1].trim(); - - // Extract params (JSON) - const paramsMatch = content.match(/([\s\S]*?)<\/params>/); - let params: Record = {}; - if (paramsMatch) { - try { - params = JSON.parse(paramsMatch[1].trim()); - } catch { - // Try to extract individual parameters if JSON fails - params = this.extractParamsFromXml(paramsMatch[1]); - } - } - - // Extract reasoning (optional) - const reasoningMatch = content.match(/([\s\S]*?)<\/reasoning>/); - const reasoning = reasoningMatch ? reasoningMatch[1].trim() : undefined; - - return { - proposalId: this.generateProposalId(), - toolName, - action, - params, - reasoning, - }; - } - - /** - * Extract parameters from XML-like format when JSON parsing fails - */ - private extractParamsFromXml(content: string): Record { - const params: Record = {}; - const paramRegex = /<(\w+)>([\s\S]*?)<\/\1>/g; - let match; - - while ((match = paramRegex.exec(content)) !== null) { - const key = match[1]; - let value: unknown = match[2].trim(); - - // Try to parse as JSON for arrays/objects - try { - value = JSON.parse(value as string); - } catch { - // Keep as string if not valid JSON - } - - params[key] = value; - } - - return params; - } - - /** - * Check if the response indicates task completion - */ - public isTaskComplete(response: string): boolean { - // Check for explicit completion markers - const completionMarkers = [ - '', - '', - 'TASK COMPLETE', - 'Task completed successfully', - ]; - - const lowerResponse = response.toLowerCase(); - return completionMarkers.some(marker => - lowerResponse.includes(marker.toLowerCase()) - ); - } - - /** - * Check if the response needs clarification or user input - */ - public needsClarification(response: string): boolean { - const clarificationMarkers = [ - '', - '', - 'please clarify', - 'could you specify', - 'what do you mean by', - ]; - - const lowerResponse = response.toLowerCase(); - return clarificationMarkers.some(marker => - lowerResponse.includes(marker.toLowerCase()) - ); - } - - /** - * Extract the final result from a completed task - */ - public extractTaskResult(response: string): string | null { - // Try to extract from result tags - const resultMatch = response.match(/([\s\S]*?)<\/task_result>/); - if (resultMatch) { - return resultMatch[1].trim(); - } - - const completeMatch = response.match(/([\s\S]*?)<\/task_complete>/); - if (completeMatch) { - return completeMatch[1].trim(); - } - - return null; - } - - /** - * Build tool descriptions for the system message - */ - private buildToolDescriptions(): string { - const descriptions: string[] = []; - - for (const tool of this.tools.values()) { - descriptions.push(tool.getFullDescription()); - } - - return descriptions.join('\n\n'); - } - - /** - * Generate a unique proposal ID - */ - private generateProposalId(): string { - return `prop_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`; - } - - /** - * Get the default system message for the driver - */ - private getDefaultSystemMessage(): string { - return `You are an AI assistant that executes tasks by using available tools. - -## Your Role -You analyze tasks, break them down into steps, and use tools to accomplish goals. - -## CRITICAL: Tool Usage Format -To use a tool, you MUST literally write out the XML tags in your response. The system parses your output looking for these exact tags. Do NOT just describe or mention the tool call - you must OUTPUT the actual XML. - -CORRECT (the XML is in the output): - - json - validate - {"jsonString": "{\\"key\\":\\"value\\"}"} - - -WRONG (just describing, no actual XML): -"I will call json.validate now" or "Let me use the tool" - -## Guidelines -1. Think step by step about what needs to be done -2. When you need a tool, OUTPUT the XML tags - do not just mention them -3. Only propose ONE tool call at a time -4. Wait for the result before proposing the next action -5. When the task is complete, OUTPUT: - - -Your final result here - - -## Important -- The and tags MUST appear literally in your response -- If you just say "I'll call the tool" without the actual XML, it will NOT work -- If you need clarification, ask using your question`; - } - - /** - * 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: - - -Your complete output here - - -## Guidelines -1. Analyze the task requirements carefully -2. Provide a complete and accurate response -3. Always wrap your final output in tags -4. If you need clarification, ask using your question`; - } - - /** - * Reset the conversation state - */ - public reset(): void { - this.messageHistory = []; - } - - // ================================ - // Native Tool Calling Support - // ================================ - - /** - * Start a task with native tool calling support - * Uses Ollama's native tool calling API instead of XML parsing - * @param task The task description - * @param images Optional base64-encoded images for vision tasks - * @returns Response with content, reasoning, and any tool calls - */ - public async startTaskWithNativeTools( - task: string, - images?: string[] - ): Promise<{ message: interfaces.IAgentMessage; toolCalls?: interfaces.INativeToolCall[] }> { - // Reset message history - this.messageHistory = []; - - // Build simple user message (no XML instructions needed for native tool calling) - const userMessage = `TASK: ${task}\n\nComplete this task using the available tools. When done, provide your final output.`; - - // Add to history - this.messageHistory.push({ - role: 'user', - content: userMessage, - }); - - // Build system message for native tool calling - const fullSystemMessage = this.getNativeToolsSystemMessage(); - - // Get tools in JSON schema format - const tools = this.getToolsAsJsonSchema(); - - // Check if provider supports native tool calling (Ollama) - const provider = this.provider as any; - if (typeof provider.collectStreamResponse !== 'function') { - throw new Error('Provider does not support native tool calling. Use startTask() instead.'); - } - - // Use collectStreamResponse for streaming support with tools - const response = await provider.collectStreamResponse( - { - systemMessage: fullSystemMessage, - userMessage: userMessage, - messageHistory: [], - images: images, - tools: tools.length > 0 ? tools : undefined, - }, - // Pass onToken callback through onChunk for streaming with thinking markers - this.onToken ? (chunk: any) => { - if (chunk.thinking && this.onToken) { - // Add marker only when transitioning INTO thinking mode - if (!this.isInThinkingMode) { - this.onToken('\n[THINKING] '); - this.isInThinkingMode = true; - } - this.onToken(chunk.thinking); - } - if (chunk.content && this.onToken) { - // Add marker when transitioning OUT of thinking mode - if (this.isInThinkingMode) { - this.onToken('\n[OUTPUT] '); - this.isInThinkingMode = false; - } - this.onToken(chunk.content); - } - } : undefined - ); - - // Reset thinking state after response completes - this.isInThinkingMode = false; - - // Add assistant response to history - const historyMessage: any = { - role: 'assistant', - content: response.message || '', - reasoning: response.thinking || response.reasoning, - }; - - // CRITICAL: Preserve tool_calls in history for native tool calling - // Without this, the model doesn't know it already called a tool and loops forever - if (response.toolCalls && response.toolCalls.length > 0) { - historyMessage.tool_calls = response.toolCalls.map((tc: any) => ({ - function: { - name: tc.function.name, - arguments: tc.function.arguments, - }, - })); - } - - this.messageHistory.push(historyMessage as unknown as plugins.smartai.ChatMessage); - - // Convert Ollama tool calls to our format - let toolCalls: interfaces.INativeToolCall[] | undefined; - if (response.toolCalls && response.toolCalls.length > 0) { - toolCalls = response.toolCalls.map((tc: any) => ({ - function: { - name: tc.function.name, - arguments: tc.function.arguments, - index: tc.function.index, - }, - })); - } - - return { - message: { - role: 'assistant', - content: response.message || '', - }, - toolCalls, - }; - } - - /** - * Continue conversation with native tool calling support - * @param message The message to continue with (e.g., tool result) - * @param toolName Optional tool name - when provided, message is added as role: 'tool' instead of 'user' - * @returns Response with content, reasoning, and any tool calls - */ - public async continueWithNativeTools( - message: string, - toolName?: string - ): Promise<{ message: interfaces.IAgentMessage; toolCalls?: interfaces.INativeToolCall[] }> { - // Add the new message to history - if (toolName) { - // Tool result - must use role: 'tool' for native tool calling - // The 'tool' role is supported by providers but not in the ChatMessage type - this.messageHistory.push({ - role: 'tool', - content: message, - toolName: toolName, - } as unknown as plugins.smartai.ChatMessage); - } else { - // Regular user message - this.messageHistory.push({ - role: 'user', - content: message, - }); - } - - // Build system message - const fullSystemMessage = this.getNativeToolsSystemMessage(); - - // Get tools in JSON schema format - const tools = this.getToolsAsJsonSchema(); - - // Get response from provider with history windowing - // For tool results, include the full history (with tool message) - // For regular user messages, exclude the last message (it becomes userMessage) - let historyForChat: plugins.smartai.ChatMessage[]; - const fullHistory = toolName - ? this.messageHistory // Include tool result in history - : this.messageHistory.slice(0, -1); // Exclude last user message - - if (this.maxHistoryMessages > 0 && fullHistory.length > this.maxHistoryMessages) { - historyForChat = [ - fullHistory[0], - ...fullHistory.slice(-(this.maxHistoryMessages - 1)), - ]; - } else { - historyForChat = fullHistory; - } - - // Check if provider supports native tool calling - const provider = this.provider as any; - if (typeof provider.collectStreamResponse !== 'function') { - throw new Error('Provider does not support native tool calling. Use continueWithMessage() instead.'); - } - - // For tool results, use a continuation prompt instead of repeating the result - const userMessage = toolName - ? 'Continue with the task. The tool result has been provided above.' - : message; - - // Use collectStreamResponse for streaming support with tools - const response = await provider.collectStreamResponse( - { - systemMessage: fullSystemMessage, - userMessage: userMessage, - messageHistory: historyForChat, - tools: tools.length > 0 ? tools : undefined, - }, - // Pass onToken callback through onChunk for streaming with thinking markers - this.onToken ? (chunk: any) => { - if (chunk.thinking && this.onToken) { - // Add marker only when transitioning INTO thinking mode - if (!this.isInThinkingMode) { - this.onToken('\n[THINKING] '); - this.isInThinkingMode = true; - } - this.onToken(chunk.thinking); - } - if (chunk.content && this.onToken) { - // Add marker when transitioning OUT of thinking mode - if (this.isInThinkingMode) { - this.onToken('\n[OUTPUT] '); - this.isInThinkingMode = false; - } - this.onToken(chunk.content); - } - } : undefined - ); - - // Reset thinking state after response completes - this.isInThinkingMode = false; - - // Add assistant response to history - const historyMessage: any = { - role: 'assistant', - content: response.message || '', - reasoning: response.thinking || response.reasoning, - }; - - // CRITICAL: Preserve tool_calls in history for native tool calling - // Without this, the model doesn't know it already called a tool and loops forever - if (response.toolCalls && response.toolCalls.length > 0) { - historyMessage.tool_calls = response.toolCalls.map((tc: any) => ({ - function: { - name: tc.function.name, - arguments: tc.function.arguments, - }, - })); - } - - this.messageHistory.push(historyMessage as unknown as plugins.smartai.ChatMessage); - - // Convert Ollama tool calls to our format - let toolCalls: interfaces.INativeToolCall[] | undefined; - if (response.toolCalls && response.toolCalls.length > 0) { - toolCalls = response.toolCalls.map((tc: any) => ({ - function: { - name: tc.function.name, - arguments: tc.function.arguments, - index: tc.function.index, - }, - })); - } - - return { - message: { - role: 'assistant', - content: response.message || '', - }, - toolCalls, - }; - } - - /** - * Get system message for native tool calling mode - * Simplified prompt that lets the model use tools naturally - */ - private getNativeToolsSystemMessage(): string { - return `You are an AI assistant that executes tasks by using available tools. - -## Your Role -You analyze tasks, break them down into steps, and use tools to accomplish goals. - -## Guidelines -1. Think step by step about what needs to be done -2. Use the available tools to complete the task -3. Process tool results and continue until the task is complete -4. When the task is complete, provide a final summary - -## Important -- Use tools when needed to gather information or perform actions -- If you need clarification, ask the user -- Always verify your work before marking the task complete`; - } - - /** - * Convert registered tools to Ollama JSON Schema format for native tool calling - * Each tool action becomes a separate function with name format: "toolName_actionName" - * @returns Array of IOllamaTool compatible tool definitions - */ - public getToolsAsJsonSchema(): plugins.smartai.IOllamaTool[] { - const tools: plugins.smartai.IOllamaTool[] = []; - - for (const tool of this.tools.values()) { - for (const action of tool.actions) { - // Build the tool definition in Ollama format - const toolDef: plugins.smartai.IOllamaTool = { - type: 'function', - function: { - name: `${tool.name}_${action.name}`, // e.g., "json_validate" - description: `[${tool.name}] ${action.description}`, - parameters: action.parameters as plugins.smartai.IOllamaTool['function']['parameters'], - }, - }; - tools.push(toolDef); - } - } - - return tools; - } - - /** - * Parse native tool calls from provider response into IToolCallProposal format - * @param toolCalls Array of native tool calls from the provider - * @returns Array of IToolCallProposal ready for execution - */ - public parseNativeToolCalls( - toolCalls: interfaces.INativeToolCall[] - ): interfaces.IToolCallProposal[] { - return toolCalls.map(tc => { - // Split "json_validate" -> toolName="json", action="validate" - const fullName = tc.function.name; - const underscoreIndex = fullName.indexOf('_'); - - let toolName: string; - let action: string; - - if (underscoreIndex > 0) { - toolName = fullName.substring(0, underscoreIndex); - action = fullName.substring(underscoreIndex + 1); - } else { - // Fallback: treat entire name as tool name with empty action - toolName = fullName; - action = ''; - } - - return { - proposalId: this.generateProposalId(), - toolName, - action, - params: tc.function.arguments, - }; - }); - } -} diff --git a/ts/smartagent.classes.dualagent.ts b/ts/smartagent.classes.dualagent.ts deleted file mode 100644 index 1e7651f..0000000 --- a/ts/smartagent.classes.dualagent.ts +++ /dev/null @@ -1,692 +0,0 @@ -import * as plugins from './plugins.js'; -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; -import { DriverAgent } from './smartagent.classes.driveragent.js'; -import { GuardianAgent } from './smartagent.classes.guardianagent.js'; -import { FilesystemTool } from './smartagent.tools.filesystem.js'; -import { HttpTool } from './smartagent.tools.http.js'; -import { ShellTool } from './smartagent.tools.shell.js'; -import { BrowserTool } from './smartagent.tools.browser.js'; -import { DenoTool } from './smartagent.tools.deno.js'; -import { ToolRegistry } from './smartagent.classes.toolregistry.js'; -import { ToolSearchTool } from './smartagent.tools.search.js'; -import { ExpertTool } from './smartagent.tools.expert.js'; - -/** - * DualAgentOrchestrator - Coordinates Driver and Guardian agents - * Manages the complete lifecycle of task execution with tool approval - */ -export class DualAgentOrchestrator { - private options: interfaces.IDualAgentOptions; - private smartai: plugins.smartai.SmartAi; - private driverProvider: plugins.smartai.MultiModalModel; - private guardianProvider: plugins.smartai.MultiModalModel; - private driver: DriverAgent; - private guardian: GuardianAgent; - private registry: ToolRegistry = new ToolRegistry(); - 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, - }; - - // 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 - } - - /** - * Get provider by name - */ - private getProviderByName(providerName: plugins.smartai.TProvider): plugins.smartai.MultiModalModel { - switch (providerName) { - case 'openai': - return this.smartai.openaiProvider; - case 'anthropic': - return this.smartai.anthropicProvider; - case 'perplexity': - return this.smartai.perplexityProvider; - case 'ollama': - return this.smartai.ollamaProvider; - case 'groq': - return this.smartai.groqProvider; - case 'xai': - return this.smartai.xaiProvider; - case 'exo': - return this.smartai.exoProvider; - default: - return this.smartai.openaiProvider; - } - } - - /** - * Emit a progress event if callback is configured - */ - private emitProgress(event: Omit): 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, - 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 with optional visibility settings - */ - public registerTool( - tool: BaseToolWrapper, - options?: interfaces.IToolRegistrationOptions - ): void { - this.registry.register(tool, options); - - // If initial visibility and agents exist, register with them - const visibility = options?.visibility ?? 'initial'; - if (visibility === 'initial') { - if (this.driver) { - this.driver.registerTool(tool); - } - if (this.guardian) { - this.guardian.registerTool(tool); - } - } - } - - /** - * Register an expert (subagent) as a tool - */ - public registerExpert(config: interfaces.IExpertConfig): void { - const expert = new ExpertTool(config, this.smartai); - this.registerTool(expert, { - visibility: config.visibility, - tags: config.tags, - category: config.category ?? 'expert', - }); - } - - /** - * Enable tool search functionality - * This adds a 'tools' tool that allows the Driver to discover and activate on-demand tools - */ - public enableToolSearch(): void { - const searchTool = new ToolSearchTool(this.registry, (tool) => { - // Callback when an on-demand tool is activated - if (this.driver) { - this.driver.registerTool(tool); - } - if (this.guardian) { - this.guardian.registerTool(tool); - } - }); - this.registerTool(searchTool); // Always initial visibility - } - - /** - * Register all standard tools - */ - public registerStandardTools(): void { - const standardTools = [ - new FilesystemTool(), - new HttpTool(), - new ShellTool(), - new BrowserTool(), - new DenoTool(), - ]; - - for (const tool of standardTools) { - this.registerTool(tool); - } - } - - /** - * 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 { - // 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 - // Set up token callback wrapper if streaming is enabled - const driverOnToken = this.options.onToken - ? (token: string) => this.options.onToken!(token, 'driver') - : undefined; - - this.driver = new DriverAgent(this.driverProvider, { - systemMessage: this.options.driverSystemMessage, - maxHistoryMessages: this.options.maxHistoryMessages, - onToken: driverOnToken, - }); - this.guardian = new GuardianAgent(this.guardianProvider, this.options.guardianPolicyPrompt); - - // Register visible tools with agents - for (const tool of this.registry.getVisibleTools()) { - this.driver.registerTool(tool); - this.guardian.registerTool(tool); - } - - // Initialize visible tools - await this.registry.initializeVisibleTools(); - this.isRunning = true; - } - - /** - * Cleanup all tools - */ - public async stop(): Promise { - await this.registry.cleanup(); - - // Only stop smartai if we created it (don't stop external instances) - if (this.ownsSmartAi) { - await this.smartai.stop(); - } - - this.isRunning = false; - if (this.driver) { - this.driver.reset(); - } - } - - /** - * Run a task through the dual-agent system - * @param task The task description - * @param options Optional task run options (e.g., images for vision tasks) - */ - public async run(task: string, options?: interfaces.ITaskRunOptions): Promise { - if (!this.isRunning) { - throw new Error('Orchestrator not started. Call start() first.'); - } - - // Use native tool calling if enabled - const useNativeTools = this.options.useNativeToolCalling === true; - - this.conversationHistory = []; - let iterations = 0; - let consecutiveRejections = 0; - let completed = false; - let finalResult: string | null = null; - - // Track pending native tool calls - let pendingNativeToolCalls: interfaces.INativeToolCall[] | undefined; - - // Extract images from options - const images = options?.images; - - // Add initial task to history - this.conversationHistory.push({ - role: 'user', - content: task, - }); - - // Start the driver with the task and optional images - let driverResponse: interfaces.IAgentMessage; - - if (useNativeTools) { - // Native tool calling mode - const result = await this.driver.startTaskWithNativeTools(task, images); - driverResponse = result.message; - pendingNativeToolCalls = result.toolCalls; - } else { - // XML parsing mode - driverResponse = await this.driver.startTask(task, images); - } - 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! && - !completed - ) { - iterations++; - - // Emit iteration started event - this.emitProgress({ - type: 'iteration_started', - iteration: iterations, - maxIterations: this.options.maxIterations, - }); - - // Check if task is complete (for native mode, no pending tool calls and has content) - const isComplete = useNativeTools - ? (!pendingNativeToolCalls || pendingNativeToolCalls.length === 0) && driverResponse.content.length > 0 - : this.driver.isTaskComplete(driverResponse.content); - - if (isComplete) { - completed = true; - finalResult = useNativeTools - ? driverResponse.content - : (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, - completed: false, - result: driverResponse.content, - iterations, - history: this.conversationHistory, - status: 'clarification_needed', - }; - } - - // Parse tool call proposals - native mode uses pendingNativeToolCalls, XML mode parses content - let proposals: interfaces.IToolCallProposal[]; - - if (useNativeTools && pendingNativeToolCalls && pendingNativeToolCalls.length > 0) { - // Native tool calling mode - convert native tool calls to proposals - proposals = this.driver.parseNativeToolCalls(pendingNativeToolCalls); - pendingNativeToolCalls = undefined; // Clear after processing - } else if (!useNativeTools) { - // XML parsing mode - proposals = this.driver.parseToolCallProposals(driverResponse.content); - } else { - proposals = []; - } - - if (proposals.length === 0) { - if (useNativeTools) { - // Native mode: no tool calls and no content means we should continue - const result = await this.driver.continueWithNativeTools( - 'Please continue with the task. Use the available tools or provide your final output.' - ); - driverResponse = result.message; - pendingNativeToolCalls = result.toolCalls; - this.conversationHistory.push(driverResponse); - continue; - } else { - // XML mode: remind the model of the exact XML format - driverResponse = await this.driver.continueWithMessage( - `No valid tool call was found in your response. To use a tool, you MUST output the exact XML format: - - - tool_name - action_name - {"param1": "value1"} - - -For example, to validate JSON: - - json - validate - {"jsonString": "{\\"key\\":\\"value\\"}", "requiredFields": ["key"]} - - -Or to complete the task: -your final JSON output here - -Please output the exact XML format above.` - ); - this.conversationHistory.push(driverResponse); - continue; - } - } - - // 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; - - 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); - } - - 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.registry.getTool(proposal.toolName); - if (!tool) { - const errorMessage = `Tool "${proposal.toolName}" not found.`; - driverResponse = await this.driver.continueWithMessage( - `TOOL ERROR: ${errorMessage}\n\nPlease try a different approach.` - ); - this.conversationHistory.push(driverResponse); - continue; - } - - 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); - - // 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', - content: resultMessage, - toolCall: proposal, - toolResult: result, - }); - - // Continue with appropriate method based on mode - if (useNativeTools) { - const toolNameForHistory = `${proposal.toolName}_${proposal.action}`; - const continueResult = await this.driver.continueWithNativeTools(resultMessage, toolNameForHistory); - driverResponse = continueResult.message; - pendingNativeToolCalls = continueResult.toolCalls; - } else { - driverResponse = await this.driver.continueWithMessage(resultMessage); - } - this.conversationHistory.push(driverResponse); - } catch (error) { - const errorMessage = `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`; - if (useNativeTools) { - const toolNameForHistory = `${proposal.toolName}_${proposal.action}`; - const continueResult = await this.driver.continueWithNativeTools( - `TOOL ERROR: ${errorMessage}\n\nPlease try a different approach.`, - toolNameForHistory - ); - driverResponse = continueResult.message; - pendingNativeToolCalls = continueResult.toolCalls; - } else { - driverResponse = await this.driver.continueWithMessage( - `TOOL ERROR: ${errorMessage}\n\nPlease try a different approach.` - ); - } - this.conversationHistory.push(driverResponse); - } - } else { - // 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`; - - if (decision.concerns && decision.concerns.length > 0) { - feedback += `- Concerns:\n${decision.concerns.map(c => ` - ${c}`).join('\n')}\n`; - } - - if (decision.suggestions) { - feedback += `- Suggestions: ${decision.suggestions}\n`; - } - - feedback += `\nPlease adapt your approach based on this feedback.`; - - this.conversationHistory.push({ - role: 'system', - content: feedback, - toolCall: proposal, - guardianDecision: decision, - }); - - // Continue with appropriate method based on mode - if (useNativeTools) { - const continueResult = await this.driver.continueWithNativeTools(feedback); - driverResponse = continueResult.message; - pendingNativeToolCalls = continueResult.toolCalls; - } else { - driverResponse = await this.driver.continueWithMessage(feedback); - } - this.conversationHistory.push(driverResponse); - } - } - - // Determine final status - let status: interfaces.TDualAgentRunStatus = 'completed'; - 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`, - }); - } - } - - return { - success: completed, - completed, - result: finalResult || driverResponse.content, - iterations, - history: this.conversationHistory, - status, - }; - } - - /** - * Continue an existing task with user input - */ - public async continueTask(userInput: string): Promise { - if (!this.isRunning) { - throw new Error('Orchestrator not started. Call start() first.'); - } - - this.conversationHistory.push({ - role: 'user', - content: userInput, - }); - - const driverResponse = await this.driver.continueWithMessage(userInput); - this.conversationHistory.push(driverResponse); - - // Continue the run loop - // For simplicity, we return the current state - full continuation would need refactoring - return { - success: false, - completed: false, - result: driverResponse.content, - iterations: 1, - history: this.conversationHistory, - status: 'in_progress', - }; - } - - /** - * Get the conversation history - */ - public getHistory(): interfaces.IAgentMessage[] { - return [...this.conversationHistory]; - } - - /** - * Update the guardian policy - */ - public setGuardianPolicy(policyPrompt: string): void { - this.guardian.setPolicy(policyPrompt); - } - - /** - * Check if orchestrator is running - */ - public isActive(): boolean { - return this.isRunning; - } - - /** - * Get registered tool names - */ - public getToolNames(): string[] { - return this.registry.getAllMetadata().map((m) => m.name); - } - - /** - * Get the tool registry for advanced operations - */ - public getRegistry(): ToolRegistry { - return this.registry; - } -} diff --git a/ts/smartagent.classes.guardianagent.ts b/ts/smartagent.classes.guardianagent.ts deleted file mode 100644 index 015c841..0000000 --- a/ts/smartagent.classes.guardianagent.ts +++ /dev/null @@ -1,241 +0,0 @@ -import * as plugins from './plugins.js'; -import * as interfaces from './smartagent.interfaces.js'; -import type { BaseToolWrapper } from './smartagent.tools.base.js'; - -/** - * GuardianAgent - Evaluates tool call proposals against a policy - * Uses AI reasoning to approve or reject tool calls - */ -export class GuardianAgent { - private provider: plugins.smartai.MultiModalModel; - private policyPrompt: string; - private tools: Map = new Map(); - - constructor( - provider: plugins.smartai.MultiModalModel, - policyPrompt: string - ) { - this.provider = provider; - this.policyPrompt = policyPrompt; - } - - /** - * Register a tool for reference during evaluation - */ - public registerTool(tool: BaseToolWrapper): void { - this.tools.set(tool.name, tool); - } - - /** - * Evaluate a tool call proposal against the policy - */ - public async evaluate( - proposal: interfaces.IToolCallProposal, - taskContext: string - ): Promise { - // Get the tool to generate a human-readable summary - const tool = this.tools.get(proposal.toolName); - let callSummary = `${proposal.toolName}.${proposal.action}(${JSON.stringify(proposal.params)})`; - - if (tool) { - try { - callSummary = tool.getCallSummary(proposal.action, proposal.params); - } catch { - // Fallback to basic summary - } - } - - // Build the evaluation prompt - const evaluationPrompt = this.buildEvaluationPrompt( - proposal, - callSummary, - taskContext - ); - - // Get response from provider - const response = await this.provider.chat({ - systemMessage: this.buildGuardianSystemMessage(), - userMessage: evaluationPrompt, - messageHistory: [], - }); - - // Parse the decision from the response - return this.parseDecision(response.message, proposal); - } - - /** - * Build the system message for the Guardian - */ - private buildGuardianSystemMessage(): string { - return `You are a Guardian AI responsible for evaluating tool call proposals. - -## Your Role -You evaluate whether proposed tool calls are safe and aligned with the policy. - -## Policy to Enforce -${this.policyPrompt} - -## Response Format -For EVERY evaluation, respond with a decision in this exact format: - - - approve OR reject - Your detailed explanation - List any concerns, even if approving - Alternative approaches if rejecting - - -## Guidelines -1. Carefully analyze what the tool call will do -2. Consider security implications -3. Check against the policy requirements -4. If uncertain, err on the side of caution (reject) -5. Provide actionable feedback when rejecting`; - } - - /** - * Build the evaluation prompt for a specific proposal - */ - private buildEvaluationPrompt( - proposal: interfaces.IToolCallProposal, - callSummary: string, - taskContext: string - ): string { - const toolInfo = this.tools.get(proposal.toolName); - const toolDescription = toolInfo ? toolInfo.getFullDescription() : 'Unknown tool'; - - return `## Task Context -${taskContext} - -## Tool Being Used -${toolDescription} - -## Proposed Tool Call -- **Tool**: ${proposal.toolName} -- **Action**: ${proposal.action} -- **Parameters**: ${JSON.stringify(proposal.params, null, 2)} - -## Human-Readable Summary -${callSummary} - -## Driver's Reasoning -${proposal.reasoning || 'No reasoning provided'} - ---- - -Evaluate this tool call against the policy. Should it be approved or rejected?`; - } - - /** - * Parse the guardian decision from the response - */ - private parseDecision( - response: string, - proposal: interfaces.IToolCallProposal - ): interfaces.IGuardianDecision { - // Try to extract from XML tags - const decisionMatch = response.match(/(.*?)<\/decision>/s); - const reasonMatch = response.match(/([\s\S]*?)<\/reason>/); - const concernsMatch = response.match(/([\s\S]*?)<\/concerns>/); - const suggestionsMatch = response.match(/([\s\S]*?)<\/suggestions>/); - - // Determine decision - let decision: 'approve' | 'reject' = 'reject'; - if (decisionMatch) { - const decisionText = decisionMatch[1].trim().toLowerCase(); - decision = decisionText.includes('approve') ? 'approve' : 'reject'; - } else { - // Fallback: look for approval keywords in the response - const lowerResponse = response.toLowerCase(); - if ( - lowerResponse.includes('approved') || - lowerResponse.includes('i approve') || - lowerResponse.includes('looks safe') - ) { - decision = 'approve'; - } - } - - // Extract reason - let reason = reasonMatch ? reasonMatch[1].trim() : ''; - if (!reason) { - // Use the full response as reason if no tag found - reason = response.substring(0, 500); - } - - // Extract concerns - const concerns: string[] = []; - if (concernsMatch) { - const concernsText = concernsMatch[1].trim(); - if (concernsText && concernsText.toLowerCase() !== 'none') { - // Split by newlines or bullet points - const concernLines = concernsText.split(/[\n\r]+/).map(l => l.trim()).filter(l => l); - concerns.push(...concernLines); - } - } - - // Extract suggestions - const suggestions = suggestionsMatch ? suggestionsMatch[1].trim() : undefined; - - return { - decision, - reason, - concerns: concerns.length > 0 ? concerns : undefined, - suggestions: suggestions && suggestions.toLowerCase() !== 'none' ? suggestions : undefined, - }; - } - - /** - * Quick validation without AI (for obviously safe/unsafe operations) - * Returns null if AI evaluation is needed - */ - public quickValidate(proposal: interfaces.IToolCallProposal): interfaces.IGuardianDecision | null { - // Check if tool exists - if (!this.tools.has(proposal.toolName)) { - return { - decision: 'reject', - reason: `Unknown tool: ${proposal.toolName}`, - }; - } - - // Check if action exists - const tool = this.tools.get(proposal.toolName)!; - const validAction = tool.actions.find(a => a.name === proposal.action); - if (!validAction) { - return { - decision: 'reject', - reason: `Unknown action "${proposal.action}" for tool "${proposal.toolName}". Available actions: ${tool.actions.map(a => a.name).join(', ')}`, - }; - } - - // Check required parameters - const schema = validAction.parameters; - if (schema && schema.required && Array.isArray(schema.required)) { - for (const requiredParam of schema.required as string[]) { - if (!(requiredParam in proposal.params)) { - return { - decision: 'reject', - reason: `Missing required parameter: ${requiredParam}`, - }; - } - } - } - - // Needs full AI evaluation - return null; - } - - /** - * Update the policy prompt - */ - public setPolicy(policyPrompt: string): void { - this.policyPrompt = policyPrompt; - } - - /** - * Get current policy - */ - public getPolicy(): string { - return this.policyPrompt; - } -} diff --git a/ts/smartagent.classes.toolregistry.ts b/ts/smartagent.classes.toolregistry.ts index bc67582..d9a0a7d 100644 --- a/ts/smartagent.classes.toolregistry.ts +++ b/ts/smartagent.classes.toolregistry.ts @@ -1,188 +1,20 @@ -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; +import type { ToolSet } from './plugins.js'; -/** - * ToolRegistry - Manages tool registration, visibility, and lifecycle - * - * Responsibilities: - * - Track all registered tools with their metadata - * - Manage visibility (initial vs on-demand) - * - Handle activation of on-demand tools - * - Provide search functionality - */ export class ToolRegistry { - private tools: Map = new Map(); - private metadata: Map = new Map(); - private activated: Set = new Set(); + private tools: ToolSet = {}; /** - * Register a tool with optional visibility settings + * Register a tool. + * @param name Tool name (must be unique, snake_case recommended) + * @param def Tool definition created with ai-sdk's tool() helper */ - register(tool: BaseToolWrapper, options: interfaces.IToolRegistrationOptions = {}): void { - const visibility = options.visibility ?? 'initial'; - - this.tools.set(tool.name, tool); - this.metadata.set(tool.name, { - name: tool.name, - description: tool.description, - actions: tool.actions, - visibility, - isActivated: visibility === 'initial', - isInitialized: false, - tags: options.tags, - category: options.category, - }); - - if (visibility === 'initial') { - this.activated.add(tool.name); - } + public register(name: string, def: ToolSet[string]): this { + this.tools[name] = def; + return this; } - /** - * Get tools visible to the Driver (initial + activated on-demand) - */ - getVisibleTools(): BaseToolWrapper[] { - return Array.from(this.tools.entries()) - .filter(([name]) => this.activated.has(name)) - .map(([, tool]) => tool); - } - - /** - * Get all tools (for search results) - */ - getAllTools(): BaseToolWrapper[] { - return Array.from(this.tools.values()); - } - - /** - * Get a specific tool by name - */ - getTool(name: string): BaseToolWrapper | undefined { - return this.tools.get(name); - } - - /** - * Get metadata for a tool - */ - getMetadata(name: string): interfaces.IToolMetadata | undefined { - return this.metadata.get(name); - } - - /** - * Get all metadata - */ - getAllMetadata(): interfaces.IToolMetadata[] { - return Array.from(this.metadata.values()); - } - - /** - * Search tools by query (matches name, description, tags, action names) - */ - search(query: string): interfaces.IToolMetadata[] { - const q = query.toLowerCase(); - return this.getAllMetadata().filter((meta) => { - if (meta.name.toLowerCase().includes(q)) return true; - if (meta.description.toLowerCase().includes(q)) return true; - if (meta.tags?.some((t) => t.toLowerCase().includes(q))) return true; - if (meta.category?.toLowerCase().includes(q)) return true; - if ( - meta.actions.some( - (a) => a.name.toLowerCase().includes(q) || a.description.toLowerCase().includes(q) - ) - ) - return true; - return false; - }); - } - - /** - * Activate an on-demand tool - */ - async activate(name: string): Promise<{ success: boolean; error?: string }> { - const tool = this.tools.get(name); - const meta = this.metadata.get(name); - - if (!tool || !meta) { - return { success: false, error: `Tool "${name}" not found` }; - } - - if (this.activated.has(name)) { - return { success: true }; // Already activated - } - - // Initialize if not already initialized - if (!meta.isInitialized) { - await tool.initialize(); - meta.isInitialized = true; - } - - this.activated.add(name); - meta.isActivated = true; - - return { success: true }; - } - - /** - * Check if a tool is activated - */ - isActivated(name: string): boolean { - return this.activated.has(name); - } - - /** - * Initialize all initial (visible) tools - */ - async initializeVisibleTools(): Promise { - const promises: Promise[] = []; - - for (const [name, tool] of this.tools) { - const meta = this.metadata.get(name); - if (meta && this.activated.has(name) && !meta.isInitialized) { - promises.push( - tool.initialize().then(() => { - meta.isInitialized = true; - }) - ); - } - } - - await Promise.all(promises); - } - - /** - * Cleanup all initialized tools - */ - async cleanup(): Promise { - const promises: Promise[] = []; - - for (const [name, tool] of this.tools) { - const meta = this.metadata.get(name); - if (meta?.isInitialized) { - promises.push(tool.cleanup()); - } - } - - await Promise.all(promises); - } - - /** - * Check if a tool exists in the registry - */ - has(name: string): boolean { - return this.tools.has(name); - } - - /** - * Get the number of registered tools - */ - get size(): number { - return this.tools.size; - } - - /** - * Get the number of activated tools - */ - get activatedCount(): number { - return this.activated.size; + /** Get the full ToolSet for passing to runAgent */ + public getTools(): ToolSet { + return { ...this.tools }; } } diff --git a/ts/smartagent.interfaces.ts b/ts/smartagent.interfaces.ts index a193e73..02239f7 100644 --- a/ts/smartagent.interfaces.ts +++ b/ts/smartagent.interfaces.ts @@ -1,366 +1,54 @@ -import * as plugins from './plugins.js'; +import type { ToolSet, ModelMessage, LanguageModelV3 } from './plugins.js'; -// ================================ -// Tool Visibility & Registry Types -// ================================ - -/** - * Tool visibility mode - * - 'initial': Conveyed to model in system prompt AND discoverable via search - * - 'on-demand': Only discoverable via search, must be activated before use - */ -export type TToolVisibility = 'initial' | 'on-demand'; - -/** - * Tool metadata for discovery and management - */ -export interface IToolMetadata { - name: string; - description: string; - actions: IToolAction[]; - visibility: TToolVisibility; - isActivated: boolean; - isInitialized: boolean; - tags?: string[]; - category?: string; -} - -/** - * Options when registering a tool - */ -export interface IToolRegistrationOptions { - visibility?: TToolVisibility; - tags?: string[]; - category?: string; -} - -/** - * Configuration for creating an Expert (SubAgent) - */ -export interface IExpertConfig { - /** Unique name for the expert */ - name: string; - /** Description of the expert's capabilities */ - description: string; - /** System message defining expert behavior */ - systemMessage: string; - /** Guardian policy for the expert's inner agent */ - guardianPolicy: string; - /** AI provider (defaults to parent's provider) */ - provider?: plugins.smartai.TProvider; - /** Tools available to this expert */ - tools?: IAgentToolWrapper[]; - /** Max iterations for expert tasks (default: 10) */ - maxIterations?: number; - /** Visibility mode (default: 'initial') */ - visibility?: TToolVisibility; - /** Searchable tags */ - tags?: string[]; - /** Category for grouping */ - category?: string; -} - -// ================================ -// Task Run Options -// ================================ - -/** - * Options for running a task with the DualAgentOrchestrator - */ -export interface ITaskRunOptions { - /** Base64-encoded images to include with the task (for vision-capable models) */ - images?: string[]; -} - -// ================================ -// Agent Configuration Interfaces -// ================================ - -/** - * 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 */ - defaultProvider?: plugins.smartai.TProvider; - /** Optional separate provider for Guardian (for cost optimization) */ - guardianProvider?: plugins.smartai.TProvider; - /** System message for the Driver agent */ - driverSystemMessage?: string; - /** Policy prompt for the Guardian agent - REQUIRED */ - guardianPolicyPrompt: string; - /** Maximum iterations for task completion (default: 20) */ - maxIterations?: number; - /** Maximum consecutive rejections before aborting (default: 3) */ - 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; - /** Callback fired for each token during LLM generation (streaming mode) */ - onToken?: (token: string, source: 'driver' | 'guardian') => void; +export interface IAgentRunOptions { + /** The LanguageModelV3 to use — from smartai.getModel() */ + model: LanguageModelV3; + /** Initial user message or task description */ + prompt: string; + /** System prompt override */ + system?: string; + /** Tools available to the agent */ + tools?: ToolSet; /** - * Enable native tool calling mode (default: false) - * When enabled, uses Ollama's native tool calling API instead of XML parsing - * This is more efficient for models that support it (e.g., GPT-OSS with Harmony format) + * Maximum number of LLM↔tool round trips. + * Each step may execute multiple tools in parallel. + * Default: 20 */ - useNativeToolCalling?: boolean; + maxSteps?: number; + /** Prior conversation messages to include */ + messages?: ModelMessage[]; + /** Called for each streamed text delta */ + onToken?: (delta: string) => void; + /** Called when a tool call starts */ + onToolCall?: (toolName: string, input: unknown) => void; + /** Called when a tool call completes */ + onToolResult?: (toolName: string, result: unknown) => void; + /** + * Called when total token usage approaches the model's context limit. + * Receives the full message history and must return a compacted replacement. + * If not provided, runAgent throws a ContextOverflowError instead. + */ + onContextOverflow?: (messages: ModelMessage[]) => Promise; + /** AbortSignal to cancel the run mid-flight */ + abort?: AbortSignal; } -// ================================ -// Message Interfaces -// ================================ - -/** - * Represents a message in the agent's conversation history - */ -export interface IAgentMessage { - role: 'system' | 'user' | 'assistant' | 'tool' | 'guardian'; - content: string; - toolName?: string; - toolResult?: unknown; - toolCall?: IToolCallProposal; - guardianDecision?: IGuardianDecision; - timestamp?: Date; +export interface IAgentRunResult { + /** Final text output from the model */ + text: string; + /** All messages in the completed conversation */ + messages: ModelMessage[]; + /** Total steps taken */ + steps: number; + /** Finish reason from the final step */ + finishReason: string; + /** Accumulated token usage across all steps */ + usage: { inputTokens: number; outputTokens: number; totalTokens: number }; } -// ================================ -// Tool Interfaces -// ================================ - -/** - * Represents an action that a tool can perform - */ -export interface IToolAction { - /** Action name (e.g., 'read', 'write', 'delete') */ - name: string; - /** Description of what this action does */ - description: string; - /** JSON schema for action parameters */ - parameters: Record; -} - -/** - * Native tool call from provider (matches Ollama's tool calling format) - * Format: function name is "toolName_actionName" (e.g., "json_validate") - */ -export interface INativeToolCall { - function: { - name: string; // Format: "toolName_actionName" - arguments: Record; - index?: number; - }; -} - -/** - * Proposed tool call from the Driver - */ -export interface IToolCallProposal { - /** Unique ID for this proposal */ - proposalId: string; - /** Name of the tool */ - toolName: string; - /** Specific action to perform */ - action: string; - /** Parameters for the action */ - params: Record; - /** Driver's reasoning for this call */ - reasoning?: string; -} - -/** - * Result of tool execution - */ -export interface IToolExecutionResult { - success: boolean; - result?: unknown; - error?: string; - /** Optional human-readable summary for history (if provided, used instead of full result) */ - summary?: string; -} - -/** - * Base interface for wrapped tools - */ -export interface IAgentToolWrapper { - /** Tool name */ - name: string; - /** Tool description */ - description: string; - /** Available actions */ - actions: IToolAction[]; - /** Initialize the tool */ - initialize(): Promise; - /** Cleanup resources */ - cleanup(): Promise; - /** Execute an action */ - execute(action: string, params: Record): Promise; - /** Get a summary for Guardian review */ - getCallSummary(action: string, params: Record): string; -} - -// ================================ -// Guardian Interfaces -// ================================ - -/** - * Request for Guardian evaluation - */ -export interface IGuardianEvaluationRequest { - /** The proposed tool call */ - proposal: IToolCallProposal; - /** Current task context */ - taskContext: string; - /** Recent conversation history (last N messages) */ - recentHistory: IAgentMessage[]; - /** Summary of what the tool call will do */ - callSummary: string; -} - -/** - * Guardian's decision - */ -export interface IGuardianDecision { - /** Approve or reject */ - decision: 'approve' | 'reject'; - /** Explanation of the decision */ - reason: string; - /** Specific concerns if rejected */ - concerns?: string[]; - /** Suggestions for the Driver if rejected */ - suggestions?: string; - /** Confidence level (0-1) */ - confidence?: number; -} - -// ================================ -// Result Interfaces -// ================================ - -/** - * Log entry for tool executions - */ -export interface IToolExecutionLog { - timestamp: Date; - toolName: string; - action: string; - params: Record; - guardianDecision: 'approved' | 'rejected'; - guardianReason: string; - executionResult?: unknown; - executionError?: string; -} - -/** - * Status of a dual-agent run - */ -export type TDualAgentRunStatus = - | 'completed' - | 'in_progress' - | 'max_iterations_reached' - | 'max_rejections_reached' - | 'clarification_needed' - | 'error'; - -/** - * Result of a dual-agent run - */ -export interface IDualAgentRunResult { - /** Whether the task was successful */ - success: boolean; - /** Whether the task is completed */ - completed: boolean; - /** Final result or response */ - result: string; - /** Total iterations taken */ - iterations: number; - /** Full conversation history */ - history: IAgentMessage[]; - /** Current status */ - status: TDualAgentRunStatus; - /** Number of tool calls made */ - toolCallCount?: number; - /** Number of Guardian rejections */ - rejectionCount?: number; - /** Tool execution log */ - toolLog?: IToolExecutionLog[]; - /** Error message if status is 'error' */ - 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 -// ================================ - -/** - * Available tool names - */ -export type TToolName = 'filesystem' | 'http' | 'browser' | 'shell'; - -/** - * Generate a unique proposal ID - */ -export function generateProposalId(): string { - return `proposal_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; +export class ContextOverflowError extends Error { + constructor(message = 'Agent context limit reached and no onContextOverflow handler provided') { + super(message); + this.name = 'ContextOverflowError'; + } } diff --git a/ts/smartagent.tools.base.ts b/ts/smartagent.tools.base.ts deleted file mode 100644 index 690dac7..0000000 --- a/ts/smartagent.tools.base.ts +++ /dev/null @@ -1,83 +0,0 @@ -import * as interfaces from './smartagent.interfaces.js'; - -/** - * Abstract base class for tool wrappers - * All tool implementations should extend this class - */ -export abstract class BaseToolWrapper implements interfaces.IAgentToolWrapper { - abstract name: string; - abstract description: string; - abstract actions: interfaces.IToolAction[]; - - protected isInitialized = false; - - /** - * Initialize the tool and any required resources - */ - abstract initialize(): Promise; - - /** - * Cleanup any resources used by the tool - */ - abstract cleanup(): Promise; - - /** - * Execute an action with the given parameters - */ - abstract execute( - action: string, - params: Record - ): Promise; - - /** - * Generate a human-readable summary of what the action will do - * This is used by the Guardian to understand the proposed action - */ - abstract getCallSummary(action: string, params: Record): string; - - /** - * Get a comprehensive explanation of this tool for LLM consumption. - * Tools should implement this to provide detailed usage instructions with examples. - * This includes parameter schemas and concrete XML examples. - */ - abstract getToolExplanation(): string; - - /** - * Validate that an action exists for this tool - * @throws Error if the action is not valid - */ - protected validateAction(action: string): void { - const validAction = this.actions.find((a) => a.name === action); - if (!validAction) { - const availableActions = this.actions.map((a) => a.name).join(', '); - throw new Error( - `Unknown action "${action}" for tool "${this.name}". Available actions: ${availableActions}` - ); - } - } - - /** - * Check if the tool is initialized - */ - protected ensureInitialized(): void { - if (!this.isInitialized) { - throw new Error(`Tool "${this.name}" is not initialized. Call initialize() first.`); - } - } - - /** - * Get the full tool description including all actions - * Used for Driver's tool awareness - now delegates to getToolExplanation() - */ - public getFullDescription(): string { - return this.getToolExplanation(); - } - - /** - * Get the JSON schema for a specific action - */ - public getActionSchema(action: string): Record | undefined { - const actionDef = this.actions.find((a) => a.name === action); - return actionDef?.parameters; - } -} diff --git a/ts/smartagent.tools.browser.ts b/ts/smartagent.tools.browser.ts deleted file mode 100644 index 4b30ebf..0000000 --- a/ts/smartagent.tools.browser.ts +++ /dev/null @@ -1,253 +0,0 @@ -import * as plugins from './plugins.js'; -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; - -/** - * Browser tool for web page interaction - * Wraps @push.rocks/smartbrowser (Puppeteer-based) - */ -export class BrowserTool extends BaseToolWrapper { - public name = 'browser'; - public description = - 'Interact with web pages - take screenshots, generate PDFs, and execute JavaScript on pages'; - - public actions: interfaces.IToolAction[] = [ - { - name: 'screenshot', - description: 'Take a screenshot of a webpage', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL of the page to screenshot' }, - }, - required: ['url'], - }, - }, - { - name: 'pdf', - description: 'Generate a PDF from a webpage', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL of the page to convert to PDF' }, - }, - required: ['url'], - }, - }, - { - name: 'evaluate', - description: - 'Execute JavaScript code on a webpage and return the result. The script runs in the browser context.', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL of the page to run the script on' }, - script: { - type: 'string', - description: - 'JavaScript code to execute. Must be a valid expression or statements that return a value.', - }, - }, - required: ['url', 'script'], - }, - }, - { - name: 'getPageContent', - description: 'Get the text content and title of a webpage', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL of the page to get content from' }, - }, - required: ['url'], - }, - }, - ]; - - private smartbrowser!: plugins.smartbrowser.SmartBrowser; - - public async initialize(): Promise { - this.smartbrowser = new plugins.smartbrowser.SmartBrowser(); - await this.smartbrowser.start(); - this.isInitialized = true; - } - - public async cleanup(): Promise { - if (this.smartbrowser) { - await this.smartbrowser.stop(); - } - this.isInitialized = false; - } - - public async execute( - action: string, - params: Record - ): Promise { - this.validateAction(action); - this.ensureInitialized(); - - try { - switch (action) { - case 'screenshot': { - const result = await this.smartbrowser.screenshotFromPage(params.url as string); - return { - success: true, - result: { - url: params.url, - name: result.name, - id: result.id, - bufferBase64: Buffer.from(result.buffer).toString('base64'), - bufferLength: result.buffer.length, - type: 'screenshot', - }, - }; - } - - case 'pdf': { - const result = await this.smartbrowser.pdfFromPage(params.url as string); - return { - success: true, - result: { - url: params.url, - name: result.name, - id: result.id, - bufferBase64: Buffer.from(result.buffer).toString('base64'), - bufferLength: result.buffer.length, - type: 'pdf', - }, - }; - } - - case 'evaluate': { - const script = params.script as string; - // Create an async function from the script - // The script should be valid JavaScript that returns a value - const result = await this.smartbrowser.evaluateOnPage(params.url as string, async () => { - // This runs in the browser context - // We need to evaluate the script string dynamically - // eslint-disable-next-line no-eval - return eval(script); - }); - - return { - success: true, - result: { - url: params.url, - script: script.substring(0, 200) + (script.length > 200 ? '...' : ''), - evaluationResult: result, - }, - }; - } - - case 'getPageContent': { - const result = await this.smartbrowser.evaluateOnPage(params.url as string, async () => { - return { - title: document.title, - textContent: document.body?.innerText || '', - url: window.location.href, - }; - }); - - return { - success: true, - result: { - url: params.url, - title: result.title, - textContent: - result.textContent.length > 10000 - ? result.textContent.substring(0, 10000) + '... [truncated]' - : result.textContent, - actualUrl: result.url, - }, - }; - } - - default: - return { - success: false, - error: `Unknown action: ${action}`, - }; - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : String(error), - }; - } - } - - public getToolExplanation(): string { - return `## Tool: browser -Interact with web pages - take screenshots, generate PDFs, and execute JavaScript on pages. - -### Actions: - -**screenshot** - Take a screenshot of a webpage -Parameters: - - url (required): URL of the page to screenshot - -Example: - - browser - screenshot - {"url": "https://example.com"} - - -**pdf** - Generate a PDF from a webpage -Parameters: - - url (required): URL of the page to convert to PDF - -Example: - - browser - pdf - {"url": "https://example.com/report"} - - -**evaluate** - Execute JavaScript code on a webpage and return the result -Parameters: - - url (required): URL of the page to run the script on - - script (required): JavaScript code to execute (must return a value) - -Example: - - browser - evaluate - {"url": "https://example.com", "script": "document.querySelectorAll('a').length"} - - -**getPageContent** - Get the text content and title of a webpage -Parameters: - - url (required): URL of the page to get content from - -Example: - - browser - getPageContent - {"url": "https://example.com"} - -`; - } - - public getCallSummary(action: string, params: Record): string { - switch (action) { - case 'screenshot': - return `Take screenshot of "${params.url}"`; - - case 'pdf': - return `Generate PDF from "${params.url}"`; - - case 'evaluate': { - const script = params.script as string; - const preview = script.length > 100 ? script.substring(0, 100) + '...' : script; - return `Execute JavaScript on "${params.url}": "${preview}"`; - } - - case 'getPageContent': - return `Get text content and title from "${params.url}"`; - - default: - return `Unknown action: ${action}`; - } - } -} diff --git a/ts/smartagent.tools.deno.ts b/ts/smartagent.tools.deno.ts deleted file mode 100644 index c77aae9..0000000 --- a/ts/smartagent.tools.deno.ts +++ /dev/null @@ -1,230 +0,0 @@ -import * as plugins from './plugins.js'; -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; - -/** - * Deno permission types for sandboxed code execution - */ -export type TDenoPermission = - | 'all' - | 'env' - | 'ffi' - | 'hrtime' - | 'net' - | 'read' - | 'run' - | 'sys' - | 'write'; - -/** - * Deno tool for executing TypeScript/JavaScript code in a sandboxed environment - * Wraps @push.rocks/smartdeno - */ -export class DenoTool extends BaseToolWrapper { - public name = 'deno'; - public description = - 'Execute TypeScript/JavaScript code in a sandboxed Deno environment with fine-grained permission control'; - - public actions: interfaces.IToolAction[] = [ - { - name: 'execute', - description: - 'Execute TypeScript/JavaScript code and return stdout/stderr. Code runs in Deno sandbox with specified permissions.', - parameters: { - type: 'object', - properties: { - code: { - type: 'string', - description: 'TypeScript/JavaScript code to execute', - }, - permissions: { - type: 'array', - items: { - type: 'string', - enum: ['all', 'env', 'ffi', 'hrtime', 'net', 'read', 'run', 'sys', 'write'], - }, - description: - 'Deno permissions to grant. Default: none (fully sandboxed). Options: all, env, net, read, write, run, sys, ffi, hrtime', - }, - }, - required: ['code'], - }, - }, - { - name: 'executeWithResult', - description: - 'Execute code that outputs JSON on the last line of stdout. The JSON is parsed and returned as the result.', - parameters: { - type: 'object', - properties: { - code: { - type: 'string', - description: - 'Code that console.logs a JSON value on the final line. This JSON will be parsed and returned.', - }, - permissions: { - type: 'array', - items: { - type: 'string', - enum: ['all', 'env', 'ffi', 'hrtime', 'net', 'read', 'run', 'sys', 'write'], - }, - description: 'Deno permissions to grant', - }, - }, - required: ['code'], - }, - }, - ]; - - private smartdeno!: plugins.smartdeno.SmartDeno; - - public async initialize(): Promise { - this.smartdeno = new plugins.smartdeno.SmartDeno(); - await this.smartdeno.start(); - this.isInitialized = true; - } - - public async cleanup(): Promise { - if (this.smartdeno) { - await this.smartdeno.stop(); - } - this.isInitialized = false; - } - - public async execute( - action: string, - params: Record - ): Promise { - this.validateAction(action); - this.ensureInitialized(); - - try { - const code = params.code as string; - const permissions = (params.permissions as TDenoPermission[]) || []; - - // Execute the script - const result = await this.smartdeno.executeScript(code, { - permissions, - }); - - switch (action) { - case 'execute': { - return { - success: result.exitCode === 0, - result: { - exitCode: result.exitCode, - stdout: result.stdout, - stderr: result.stderr, - permissions, - }, - }; - } - - case 'executeWithResult': { - if (result.exitCode !== 0) { - return { - success: false, - error: `Script failed with exit code ${result.exitCode}: ${result.stderr}`, - }; - } - - // Parse the last line of stdout as JSON - const lines = result.stdout.trim().split('\n'); - const lastLine = lines[lines.length - 1]; - - try { - const parsedResult = JSON.parse(lastLine); - return { - success: true, - result: { - parsed: parsedResult, - stdout: result.stdout, - stderr: result.stderr, - }, - }; - } catch (parseError) { - return { - success: false, - error: `Failed to parse JSON from last line of output: ${lastLine}`, - }; - } - } - - default: - return { - success: false, - error: `Unknown action: ${action}`, - }; - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : String(error), - }; - } - } - - public getToolExplanation(): string { - return `## Tool: deno -Execute TypeScript/JavaScript code in a sandboxed Deno environment with fine-grained permission control. - -### Actions: - -**execute** - Execute TypeScript/JavaScript code and return stdout/stderr -Parameters: - - code (required): TypeScript/JavaScript code to execute - - permissions (optional): Array of Deno permissions to grant. Options: "all", "env", "net", "read", "write", "run", "sys", "ffi", "hrtime". Default: none (fully sandboxed) - -Example - Simple execution: - - deno - execute - {"code": "console.log('Hello from Deno!');"} - - -Example - With network permission: - - deno - execute - {"code": "const resp = await fetch('https://api.example.com/data');\\nconsole.log(await resp.text());", "permissions": ["net"]} - - -**executeWithResult** - Execute code that outputs JSON on the last line of stdout -Parameters: - - code (required): Code that console.logs a JSON value on the final line - - permissions (optional): Array of Deno permissions to grant - -Example: - - deno - executeWithResult - {"code": "const result = { sum: 1 + 2, product: 2 * 3 };\\nconsole.log(JSON.stringify(result));"} - -`; - } - - public getCallSummary(action: string, params: Record): string { - const code = params.code as string; - const permissions = (params.permissions as string[]) || []; - - // Create a preview of the code (first 100 chars) - const codePreview = code.length > 100 ? code.substring(0, 100) + '...' : code; - // Escape newlines for single-line display - const cleanPreview = codePreview.replace(/\n/g, '\\n'); - - const permissionInfo = permissions.length > 0 - ? ` [permissions: ${permissions.join(', ')}]` - : ' [sandboxed - no permissions]'; - - switch (action) { - case 'execute': - return `Execute Deno code${permissionInfo}: "${cleanPreview}"`; - - case 'executeWithResult': - return `Execute Deno code and parse JSON result${permissionInfo}: "${cleanPreview}"`; - - default: - return `Unknown action: ${action}`; - } - } -} diff --git a/ts/smartagent.tools.expert.ts b/ts/smartagent.tools.expert.ts deleted file mode 100644 index a8be7ae..0000000 --- a/ts/smartagent.tools.expert.ts +++ /dev/null @@ -1,144 +0,0 @@ -import * as plugins from './plugins.js'; -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; - -// Forward declaration to avoid circular import at module load time -// The actual import happens lazily in initialize() -let DualAgentOrchestrator: typeof import('./smartagent.classes.dualagent.js').DualAgentOrchestrator; - -/** - * ExpertTool - A specialized agent wrapped as a tool - * - * Enables hierarchical agent architectures where the Driver can delegate - * complex tasks to specialized experts with their own tools and policies. - */ -export class ExpertTool extends BaseToolWrapper { - public name: string; - public description: string; - public actions: interfaces.IToolAction[] = [ - { - name: 'consult', - description: 'Delegate a task or question to this expert', - parameters: { - type: 'object', - properties: { - task: { type: 'string', description: 'The task or question for the expert' }, - context: { type: 'string', description: 'Additional context to help the expert' }, - }, - required: ['task'], - }, - }, - ]; - - private config: interfaces.IExpertConfig; - private smartAi: plugins.smartai.SmartAi; - private inner?: InstanceType; - - constructor(config: interfaces.IExpertConfig, smartAi: plugins.smartai.SmartAi) { - super(); - this.config = config; - this.smartAi = smartAi; - this.name = config.name; - this.description = config.description; - } - - async initialize(): Promise { - // Lazy import to avoid circular dependency - if (!DualAgentOrchestrator) { - const module = await import('./smartagent.classes.dualagent.js'); - DualAgentOrchestrator = module.DualAgentOrchestrator; - } - - this.inner = new DualAgentOrchestrator({ - smartAiInstance: this.smartAi, // Share SmartAi instance - defaultProvider: this.config.provider, - driverSystemMessage: this.config.systemMessage, - guardianPolicyPrompt: this.config.guardianPolicy, - maxIterations: this.config.maxIterations ?? 10, - }); - - // Register expert's tools - if (this.config.tools) { - for (const tool of this.config.tools) { - // Tools in the config are IAgentToolWrapper, but we need BaseToolWrapper - // Since all our tools extend BaseToolWrapper, this cast is safe - this.inner.registerTool(tool as BaseToolWrapper); - } - } - - await this.inner.start(); - this.isInitialized = true; - } - - async cleanup(): Promise { - if (this.inner) { - await this.inner.stop(); - this.inner = undefined; - } - this.isInitialized = false; - } - - async execute( - action: string, - params: Record - ): Promise { - this.validateAction(action); - this.ensureInitialized(); - - const task = params.task as string; - const context = params.context as string | undefined; - - const fullTask = context ? `Context: ${context}\n\nTask: ${task}` : task; - - try { - const result = await this.inner!.run(fullTask); - - return { - success: result.success, - result: { - response: result.result, - iterations: result.iterations, - status: result.status, - }, - summary: result.success - ? `Expert "${this.name}" completed (${result.iterations} iterations)` - : `Expert "${this.name}" failed: ${result.status}`, - }; - } catch (error) { - return { - success: false, - error: `Expert error: ${error instanceof Error ? error.message : String(error)}`, - }; - } - } - - getCallSummary(action: string, params: Record): string { - const task = params.task as string; - const preview = task.length > 60 ? task.substring(0, 60) + '...' : task; - return `Consult ${this.name}: "${preview}"`; - } - - getToolExplanation(): string { - return `## Expert: ${this.name} -${this.description} - -### Usage: -Delegate tasks to this expert when you need specialized help. - -\`\`\` - - ${this.name} - consult - {"task": "Your question or task", "context": "Optional background"} - -\`\`\` -`; - } - - /** - * Get the expert's configuration - */ - getConfig(): interfaces.IExpertConfig { - return this.config; - } -} diff --git a/ts/smartagent.tools.filesystem.ts b/ts/smartagent.tools.filesystem.ts deleted file mode 100644 index 27673c1..0000000 --- a/ts/smartagent.tools.filesystem.ts +++ /dev/null @@ -1,885 +0,0 @@ -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 - */ -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 file contents (full or specific line range)', - parameters: { - type: 'object', - properties: { - 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'], - }, - }, - { - name: 'write', - description: 'Write content to a file (creates or overwrites)', - parameters: { - type: 'object', - properties: { - path: { type: 'string', description: 'Absolute path to the file' }, - content: { type: 'string', description: 'Content to write' }, - encoding: { - type: 'string', - enum: ['utf8', 'binary', 'base64'], - default: 'utf8', - description: 'File encoding', - }, - }, - required: ['path', 'content'], - }, - }, - { - name: 'append', - description: 'Append content to a file', - parameters: { - type: 'object', - properties: { - path: { type: 'string', description: 'Absolute path to the file' }, - content: { type: 'string', description: 'Content to append' }, - }, - required: ['path', 'content'], - }, - }, - { - name: 'list', - description: 'List files and directories in a path', - parameters: { - type: 'object', - properties: { - path: { type: 'string', description: 'Directory path to list' }, - recursive: { type: 'boolean', default: false, description: 'List recursively' }, - filter: { type: 'string', description: 'Glob pattern to filter results (e.g., "*.ts")' }, - }, - required: ['path'], - }, - }, - { - name: 'delete', - description: 'Delete a file or directory', - parameters: { - type: 'object', - properties: { - path: { type: 'string', description: 'Path to delete' }, - recursive: { - type: 'boolean', - default: false, - description: 'For directories, delete recursively', - }, - }, - required: ['path'], - }, - }, - { - name: 'exists', - description: 'Check if a file or directory exists', - parameters: { - type: 'object', - properties: { - path: { type: 'string', description: 'Path to check' }, - }, - required: ['path'], - }, - }, - { - name: 'stat', - description: 'Get file or directory statistics (size, dates, etc.)', - parameters: { - type: 'object', - properties: { - path: { type: 'string', description: 'Path to get stats for' }, - }, - required: ['path'], - }, - }, - { - name: 'copy', - description: 'Copy a file to a new location', - parameters: { - type: 'object', - properties: { - source: { type: 'string', description: 'Source file path' }, - destination: { type: 'string', description: 'Destination file path' }, - }, - required: ['source', 'destination'], - }, - }, - { - name: 'move', - description: 'Move a file to a new location', - parameters: { - type: 'object', - properties: { - source: { type: 'string', description: 'Source file path' }, - destination: { type: 'string', description: 'Destination file path' }, - }, - required: ['source', 'destination'], - }, - }, - { - name: 'mkdir', - description: 'Create a directory', - parameters: { - type: 'object', - properties: { - path: { type: 'string', description: 'Directory path to create' }, - recursive: { - type: 'boolean', - default: true, - description: 'Create parent directories if needed', - }, - }, - 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; - - public async initialize(): Promise { - this.smartfs = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode()); - this.isInitialized = true; - } - - public async cleanup(): Promise { - this.isInitialized = false; - } - - public async execute( - action: string, - params: Record - ): Promise { - this.validateAction(action); - this.ensureInitialized(); - - try { - switch (action) { - case 'read': { - const validatedPath = this.validatePath(params.path as string); - const encoding = (params.encoding as string) || 'utf8'; - 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: 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(validatedPath) - .encoding(encoding as 'utf8' | 'binary' | 'base64') - .write(params.content as string); - return { - success: true, - result: { - path: params.path, - written: true, - bytesWritten: (params.content as string).length, - }, - }; - } - - case 'append': { - const validatedPath = this.validatePath(params.path as string); - await this.smartfs.file(validatedPath).append(params.content as string); - return { - success: true, - result: { - path: params.path, - appended: true, - }, - }; - } - - case 'list': { - 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); - } - 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: { - path: params.path, - entries, - count: entries.length, - }, - }; - } - - case 'delete': { - const validatedPath = this.validatePath(params.path as string); - // Check if it's a directory or file - 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(validatedPath).stat(); - if (stats.isDirectory && params.recursive) { - await this.smartfs.directory(validatedPath).recursive().delete(); - } else { - await this.smartfs.file(validatedPath).delete(); - } - } catch { - await this.smartfs.file(validatedPath).delete(); - } - } - return { - success: true, - result: { - path: params.path, - deleted: true, - }, - }; - } - - case 'exists': { - const validatedPath = this.validatePath(params.path as string); - const exists = await this.smartfs.file(validatedPath).exists(); - return { - success: true, - result: { - path: params.path, - exists, - }, - }; - } - - case 'stat': { - const validatedPath = this.validatePath(params.path as string); - const stats = await this.smartfs.file(validatedPath).stat(); - return { - success: true, - result: { - path: params.path, - stats, - }, - }; - } - - case 'copy': { - 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: { - source: params.source, - destination: params.destination, - copied: true, - }, - }; - } - - case 'move': { - 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: { - source: params.source, - destination: params.destination, - moved: true, - }, - }; - } - - case 'mkdir': { - const validatedPath = this.validatePath(params.path as string); - let dir = this.smartfs.directory(validatedPath); - if (params.recursive !== false) { - dir = dir.recursive(); - } - await dir.create(); - return { - success: true, - result: { - path: params.path, - created: true, - }, - }; - } - - 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(); // Track which paths are last in their parent - - // Group by parent to determine last child - const parentChildCount = new Map(); - const parentCurrentChild = new Map(); - - 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, - error: `Unknown action: ${action}`, - }; - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : String(error), - }; - } - } - - public getToolExplanation(): string { - return `## Tool: filesystem -Read, write, list, and delete files and directories. - -### Actions: - -**read** - Read file contents (full or specific line range) -Parameters: - - path (required): Path to the file - - encoding (optional): File encoding - "utf8" (default), "binary", or "base64" - - startLine (optional): First line to read (1-indexed, inclusive) - - endLine (optional): Last line to read (1-indexed, inclusive) - -Example: - - filesystem - read - {"path": "/path/to/file.txt"} - - -Example with line range: - - filesystem - read - {"path": "/path/to/file.txt", "startLine": 10, "endLine": 20} - - -**write** - Write content to a file (creates or overwrites) -Parameters: - - path (required): Absolute path to the file - - content (required): Content to write - - encoding (optional): File encoding - "utf8" (default), "binary", or "base64" - -Example: - - filesystem - write - {"path": "/path/to/output.txt", "content": "Hello, World!"} - - -**list** - List files and directories in a path -Parameters: - - path (required): Directory path to list - - recursive (optional): List recursively (default: false) - - filter (optional): Glob pattern to filter results (e.g., "*.ts") - -Example: - - filesystem - list - {"path": "/path/to/dir", "recursive": true, "filter": "*.ts"} - - -**exists** - Check if a file or directory exists -Parameters: - - path (required): Path to check - -Example: - - filesystem - exists - {"path": "/path/to/check"} - - -**mkdir** - Create a directory -Parameters: - - path (required): Directory path to create - - recursive (optional): Create parent directories if needed (default: true) - -Example: - - filesystem - mkdir - {"path": "/path/to/new/dir"} - - -**delete** - Delete a file or directory -Parameters: - - path (required): Path to delete - - recursive (optional): For directories, delete recursively (default: false) - -Example: - - filesystem - delete - {"path": "/path/to/delete", "recursive": true} - - -**copy** - Copy a file to a new location -Parameters: - - source (required): Source file path - - destination (required): Destination file path - -Example: - - filesystem - copy - {"source": "/path/to/source.txt", "destination": "/path/to/dest.txt"} - - -**move** - Move a file to a new location -Parameters: - - source (required): Source file path - - destination (required): Destination file path - -Example: - - filesystem - move - {"source": "/path/to/old.txt", "destination": "/path/to/new.txt"} - - -**stat** - Get file or directory statistics (size, dates, etc.) -Parameters: - - path (required): Path to get stats for - -Example: - - filesystem - stat - {"path": "/path/to/file.txt"} - - -**append** - Append content to a file -Parameters: - - path (required): Absolute path to the file - - content (required): Content to append - -Example: - - filesystem - append - {"path": "/path/to/log.txt", "content": "New log entry\\n"} - - -**tree** - Show directory structure as a tree -Parameters: - - path (required): Root directory path - - maxDepth (optional): Maximum depth to traverse (default: 3) - - filter (optional): Glob pattern to filter files - - showSizes (optional): Include file sizes in output (default: false) - - format (optional): Output format - "string" (default) or "json" - -Example: - - filesystem - tree - {"path": "/path/to/dir", "maxDepth": 2} - - -**glob** - Find files matching a glob pattern -Parameters: - - pattern (required): Glob pattern (e.g., "**/*.ts", "src/**/*.js") - - path (optional): Base path to search from - -Example: - - filesystem - glob - {"pattern": "**/*.ts", "path": "/path/to/project"} - -`; - } - - public getCallSummary(action: string, params: Record): string { - switch (action) { - 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; - const preview = content.length > 100 ? content.substring(0, 100) + '...' : content; - return `Write ${content.length} bytes to "${params.path}". Content preview: "${preview}"`; - } - - case 'append': { - const content = params.content as string; - const preview = content.length > 100 ? content.substring(0, 100) + '...' : content; - return `Append ${content.length} bytes to "${params.path}". Content preview: "${preview}"`; - } - - case 'list': - return `List directory "${params.path}"${params.recursive ? ' recursively' : ''}${params.filter ? ` with filter "${params.filter}"` : ''}`; - - case 'delete': - return `Delete "${params.path}"${params.recursive ? ' recursively' : ''}`; - - case 'exists': - return `Check if "${params.path}" exists`; - - case 'stat': - return `Get statistics for "${params.path}"`; - - case 'copy': - return `Copy "${params.source}" to "${params.destination}"`; - - case 'move': - return `Move "${params.source}" to "${params.destination}"`; - - 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}`; - } - } -} diff --git a/ts/smartagent.tools.http.ts b/ts/smartagent.tools.http.ts deleted file mode 100644 index 9e2f2ba..0000000 --- a/ts/smartagent.tools.http.ts +++ /dev/null @@ -1,283 +0,0 @@ -import * as plugins from './plugins.js'; -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; - -/** - * HTTP tool for making web requests - * Wraps @push.rocks/smartrequest - */ -export class HttpTool extends BaseToolWrapper { - public name = 'http'; - public description = 'Make HTTP requests to web APIs and services'; - - public actions: interfaces.IToolAction[] = [ - { - name: 'get', - description: 'Make a GET request', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL to request' }, - headers: { type: 'object', description: 'Request headers (key-value pairs)' }, - query: { type: 'object', description: 'Query parameters (key-value pairs)' }, - timeout: { type: 'number', description: 'Timeout in milliseconds' }, - }, - required: ['url'], - }, - }, - { - name: 'post', - description: 'Make a POST request with JSON body', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL to request' }, - body: { type: 'object', description: 'JSON body to send' }, - headers: { type: 'object', description: 'Request headers (key-value pairs)' }, - query: { type: 'object', description: 'Query parameters (key-value pairs)' }, - timeout: { type: 'number', description: 'Timeout in milliseconds' }, - }, - required: ['url'], - }, - }, - { - name: 'put', - description: 'Make a PUT request with JSON body', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL to request' }, - body: { type: 'object', description: 'JSON body to send' }, - headers: { type: 'object', description: 'Request headers (key-value pairs)' }, - timeout: { type: 'number', description: 'Timeout in milliseconds' }, - }, - required: ['url', 'body'], - }, - }, - { - name: 'patch', - description: 'Make a PATCH request with JSON body', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL to request' }, - body: { type: 'object', description: 'JSON body to send' }, - headers: { type: 'object', description: 'Request headers (key-value pairs)' }, - timeout: { type: 'number', description: 'Timeout in milliseconds' }, - }, - required: ['url', 'body'], - }, - }, - { - name: 'delete', - description: 'Make a DELETE request', - parameters: { - type: 'object', - properties: { - url: { type: 'string', description: 'URL to request' }, - headers: { type: 'object', description: 'Request headers (key-value pairs)' }, - timeout: { type: 'number', description: 'Timeout in milliseconds' }, - }, - required: ['url'], - }, - }, - ]; - - public async initialize(): Promise { - // SmartRequest is stateless, no initialization needed - this.isInitialized = true; - } - - public async cleanup(): Promise { - this.isInitialized = false; - } - - public async execute( - action: string, - params: Record - ): Promise { - this.validateAction(action); - this.ensureInitialized(); - - try { - let request = plugins.smartrequest.SmartRequest.create().url(params.url as string); - - // Add headers - if (params.headers && typeof params.headers === 'object') { - for (const [key, value] of Object.entries(params.headers as Record)) { - request = request.header(key, value); - } - } - - // Add query parameters - if (params.query && typeof params.query === 'object') { - request = request.query(params.query as Record); - } - - // Add timeout - if (params.timeout) { - request = request.timeout(params.timeout as number); - } - - // Add JSON body for POST, PUT, PATCH - if (params.body && ['post', 'put', 'patch'].includes(action)) { - request = request.json(params.body); - } - - // Execute the request - let response; - switch (action) { - case 'get': - response = await request.get(); - break; - case 'post': - response = await request.post(); - break; - case 'put': - response = await request.put(); - break; - case 'patch': - response = await request.patch(); - break; - case 'delete': - response = await request.delete(); - break; - default: - return { success: false, error: `Unknown action: ${action}` }; - } - - // Parse response body - let body: unknown; - const contentType = response.headers?.['content-type'] || ''; - - try { - if (contentType.includes('application/json')) { - body = await response.json(); - } else { - body = await response.text(); - } - } catch { - body = null; - } - - return { - success: response.ok, - result: { - url: params.url, - method: action.toUpperCase(), - status: response.status, - statusText: response.statusText, - ok: response.ok, - headers: response.headers, - body, - }, - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : String(error), - }; - } - } - - public getToolExplanation(): string { - return `## Tool: http -Make HTTP requests to web APIs and services. - -### Actions: - -**get** - Make a GET request -Parameters: - - url (required): URL to request - - headers (optional): Request headers (key-value object) - - query (optional): Query parameters (key-value object) - - timeout (optional): Timeout in milliseconds - -Example: - - http - get - {"url": "https://api.example.com/data", "headers": {"Authorization": "Bearer token123"}} - - -**post** - Make a POST request with JSON body -Parameters: - - url (required): URL to request - - body (optional): JSON body to send - - headers (optional): Request headers (key-value object) - - query (optional): Query parameters (key-value object) - - timeout (optional): Timeout in milliseconds - -Example: - - http - post - {"url": "https://api.example.com/submit", "body": {"name": "test", "value": 123}} - - -**put** - Make a PUT request with JSON body -Parameters: - - url (required): URL to request - - body (required): JSON body to send - - headers (optional): Request headers (key-value object) - - timeout (optional): Timeout in milliseconds - -Example: - - http - put - {"url": "https://api.example.com/resource/1", "body": {"name": "updated"}} - - -**patch** - Make a PATCH request with JSON body -Parameters: - - url (required): URL to request - - body (required): JSON body to send - - headers (optional): Request headers (key-value object) - - timeout (optional): Timeout in milliseconds - -Example: - - http - patch - {"url": "https://api.example.com/resource/1", "body": {"status": "active"}} - - -**delete** - Make a DELETE request -Parameters: - - url (required): URL to request - - headers (optional): Request headers (key-value object) - - timeout (optional): Timeout in milliseconds - -Example: - - http - delete - {"url": "https://api.example.com/resource/1"} - -`; - } - - public getCallSummary(action: string, params: Record): string { - const method = action.toUpperCase(); - let summary = `${method} request to "${params.url}"`; - - if (params.query && Object.keys(params.query as object).length > 0) { - const queryStr = JSON.stringify(params.query); - summary += ` with query: ${queryStr.length > 50 ? queryStr.substring(0, 50) + '...' : queryStr}`; - } - - if (params.body) { - const bodyStr = JSON.stringify(params.body); - const preview = bodyStr.length > 100 ? bodyStr.substring(0, 100) + '...' : bodyStr; - summary += ` with body: ${preview}`; - } - - if (params.headers && Object.keys(params.headers as object).length > 0) { - const headerKeys = Object.keys(params.headers as object).join(', '); - summary += ` with headers: [${headerKeys}]`; - } - - return summary; - } -} diff --git a/ts/smartagent.tools.json.ts b/ts/smartagent.tools.json.ts deleted file mode 100644 index 510aaeb..0000000 --- a/ts/smartagent.tools.json.ts +++ /dev/null @@ -1,224 +0,0 @@ -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; - -/** - * JsonValidatorTool - Validates and formats JSON data - * Useful for agents to self-validate their JSON output before completing a task - */ -export class JsonValidatorTool extends BaseToolWrapper { - public name = 'json'; - public description = 'Validate and format JSON data. Use this to verify your JSON output is valid before completing a task.'; - - public actions: interfaces.IToolAction[] = [ - { - name: 'validate', - description: 'Validate that a string is valid JSON and optionally check required fields', - parameters: { - type: 'object', - properties: { - jsonString: { - type: 'string', - description: 'The JSON string to validate', - }, - requiredFields: { - type: 'array', - items: { type: 'string' }, - description: 'Optional list of field names that must be present at the root level', - }, - }, - required: ['jsonString'], - }, - }, - { - name: 'format', - description: 'Parse and pretty-print JSON string', - parameters: { - type: 'object', - properties: { - jsonString: { - type: 'string', - description: 'The JSON string to format', - }, - }, - required: ['jsonString'], - }, - }, - ]; - - async initialize(): Promise { - this.isInitialized = true; - } - - async cleanup(): Promise { - this.isInitialized = false; - } - - async execute( - action: string, - params: Record - ): Promise { - this.validateAction(action); - - switch (action) { - case 'validate': - return this.validateJson(params); - case 'format': - return this.formatJson(params); - default: - return { success: false, error: `Unknown action: ${action}` }; - } - } - - /** - * Validate JSON string and optionally check for required fields - */ - private validateJson(params: Record): interfaces.IToolExecutionResult { - const jsonString = params.jsonString as string; - const requiredFields = params.requiredFields as string[] | undefined; - - if (!jsonString || typeof jsonString !== 'string') { - return { - success: false, - error: 'jsonString parameter is required and must be a string', - }; - } - - try { - const parsed = JSON.parse(jsonString); - - // Check required fields if specified - if (requiredFields && Array.isArray(requiredFields)) { - const missingFields = requiredFields.filter((field) => { - if (typeof parsed !== 'object' || parsed === null) { - return true; - } - return !(field in parsed); - }); - - if (missingFields.length > 0) { - return { - success: false, - error: `Missing required fields: ${missingFields.join(', ')}`, - result: { - valid: false, - missingFields, - presentFields: Object.keys(parsed || {}), - }, - }; - } - } - - return { - success: true, - result: { - valid: true, - parsed, - type: Array.isArray(parsed) ? 'array' : typeof parsed, - fieldCount: typeof parsed === 'object' && parsed !== null ? Object.keys(parsed).length : undefined, - }, - summary: `JSON is valid (${Array.isArray(parsed) ? 'array' : typeof parsed})`, - }; - } catch (error) { - const errorMessage = (error as Error).message; - - // Extract position from error message if available - const posMatch = errorMessage.match(/position\s*(\d+)/i); - const position = posMatch ? parseInt(posMatch[1]) : undefined; - - // Provide context around the error position - let context: string | undefined; - if (position !== undefined) { - const start = Math.max(0, position - 20); - const end = Math.min(jsonString.length, position + 20); - context = jsonString.substring(start, end); - } - - return { - success: false, - error: `Invalid JSON: ${errorMessage}`, - result: { - valid: false, - errorPosition: position, - errorContext: context, - }, - }; - } - } - - /** - * Format/pretty-print JSON string - */ - private formatJson(params: Record): interfaces.IToolExecutionResult { - const jsonString = params.jsonString as string; - - if (!jsonString || typeof jsonString !== 'string') { - return { - success: false, - error: 'jsonString parameter is required and must be a string', - }; - } - - try { - const parsed = JSON.parse(jsonString); - const formatted = JSON.stringify(parsed, null, 2); - - return { - success: true, - result: formatted, - summary: `Formatted JSON (${formatted.length} chars)`, - }; - } catch (error) { - return { - success: false, - error: `Cannot format invalid JSON: ${(error as Error).message}`, - }; - } - } - - public getToolExplanation(): string { - return `## Tool: json -Validate and format JSON data. Use this to verify your JSON output is valid before completing a task. - -### Actions: - -**validate** - Validate that a string is valid JSON and optionally check required fields -Parameters: - - jsonString (required): The JSON string to validate - - requiredFields (optional): Array of field names that must be present - -Example: - - json - validate - {"jsonString": "{\\"invoice_number\\":\\"INV-001\\",\\"total\\":99.99}", "requiredFields": ["invoice_number", "total"]} - - -**format** - Parse and pretty-print JSON string -Parameters: - - jsonString (required): The JSON string to format - -Example: - - json - format - {"jsonString": "{\\"name\\":\\"test\\",\\"value\\":123}"} - -`; - } - - getCallSummary(action: string, params: Record): string { - const jsonStr = (params.jsonString as string) || ''; - const preview = jsonStr.length > 50 ? jsonStr.substring(0, 50) + '...' : jsonStr; - - switch (action) { - case 'validate': - const fields = params.requiredFields as string[] | undefined; - const fieldInfo = fields ? ` (checking fields: ${fields.join(', ')})` : ''; - return `Validate JSON: ${preview}${fieldInfo}`; - case 'format': - return `Format JSON: ${preview}`; - default: - return `JSON ${action}: ${preview}`; - } - } -} diff --git a/ts/smartagent.tools.search.ts b/ts/smartagent.tools.search.ts deleted file mode 100644 index 72e18a1..0000000 --- a/ts/smartagent.tools.search.ts +++ /dev/null @@ -1,237 +0,0 @@ -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; -import { ToolRegistry } from './smartagent.classes.toolregistry.js'; - -/** - * ToolSearchTool - AI-facing interface for discovering and activating tools - * - * This tool enables the Driver to: - * - Search for tools by capability - * - List all available tools - * - Activate on-demand tools - * - Get detailed information about specific tools - */ -export class ToolSearchTool extends BaseToolWrapper { - public name = 'tools'; - public description = - 'Search for and activate available tools and experts. Use this to discover specialized capabilities.'; - - public actions: interfaces.IToolAction[] = [ - { - name: 'search', - description: 'Search for tools by name, description, tags, or capabilities', - parameters: { - type: 'object', - properties: { - query: { type: 'string', description: 'Search query' }, - }, - required: ['query'], - }, - }, - { - name: 'list', - description: 'List all available tools grouped by visibility', - parameters: { type: 'object', properties: {} }, - }, - { - name: 'activate', - description: 'Activate an on-demand tool to make it available for use', - parameters: { - type: 'object', - properties: { - name: { type: 'string', description: 'Name of the tool to activate' }, - }, - required: ['name'], - }, - }, - { - name: 'details', - description: 'Get detailed information about a specific tool', - parameters: { - type: 'object', - properties: { - name: { type: 'string', description: 'Name of the tool' }, - }, - required: ['name'], - }, - }, - ]; - - private registry: ToolRegistry; - private onToolActivated?: (tool: BaseToolWrapper) => void; - - constructor(registry: ToolRegistry, onToolActivated?: (tool: BaseToolWrapper) => void) { - super(); - this.registry = registry; - this.onToolActivated = onToolActivated; - } - - async initialize(): Promise { - this.isInitialized = true; - } - - async cleanup(): Promise { - this.isInitialized = false; - } - - async execute( - action: string, - params: Record - ): Promise { - this.validateAction(action); - - switch (action) { - case 'search': - return this.handleSearch(params.query as string); - case 'list': - return this.handleList(); - case 'activate': - return this.handleActivate(params.name as string); - case 'details': - return this.handleDetails(params.name as string); - default: - return { success: false, error: `Unknown action: ${action}` }; - } - } - - private handleSearch(query: string): interfaces.IToolExecutionResult { - const results = this.registry.search(query); - return { - success: true, - result: results.map((m) => ({ - name: m.name, - description: m.description, - visibility: m.visibility, - isActivated: m.isActivated, - category: m.category, - tags: m.tags, - actionCount: m.actions.length, - })), - summary: `Found ${results.length} tools matching "${query}"`, - }; - } - - private handleList(): interfaces.IToolExecutionResult { - const all = this.registry.getAllMetadata(); - const initial = all.filter((m) => m.visibility === 'initial'); - const onDemand = all.filter((m) => m.visibility === 'on-demand'); - - return { - success: true, - result: { - initial: initial.map((m) => ({ - name: m.name, - description: m.description, - category: m.category, - })), - onDemand: onDemand.map((m) => ({ - name: m.name, - description: m.description, - category: m.category, - isActivated: m.isActivated, - })), - summary: `${initial.length} initial, ${onDemand.length} on-demand`, - }, - }; - } - - private async handleActivate(name: string): Promise { - const result = await this.registry.activate(name); - - if (result.success && this.onToolActivated) { - const tool = this.registry.getTool(name); - if (tool) { - this.onToolActivated(tool); - } - } - - return { - success: result.success, - result: result.success ? { name, message: `Tool "${name}" is now available` } : undefined, - error: result.error, - summary: result.success ? `Activated: ${name}` : result.error, - }; - } - - private handleDetails(name: string): interfaces.IToolExecutionResult { - const tool = this.registry.getTool(name); - const meta = this.registry.getMetadata(name); - - if (!tool || !meta) { - return { success: false, error: `Tool "${name}" not found` }; - } - - return { - success: true, - result: { - name: meta.name, - description: meta.description, - visibility: meta.visibility, - isActivated: meta.isActivated, - category: meta.category, - tags: meta.tags, - actions: meta.actions, - fullExplanation: tool.getToolExplanation(), - }, - }; - } - - getCallSummary(action: string, params: Record): string { - switch (action) { - case 'search': - return `Search tools: "${params.query}"`; - case 'list': - return 'List all tools'; - case 'activate': - return `Activate tool: ${params.name}`; - case 'details': - return `Get details: ${params.name}`; - default: - return `tools.${action}`; - } - } - - getToolExplanation(): string { - return `## Tool: tools -Search for and manage available tools and experts. - -### Actions: - -**search** - Find tools by capability -\`\`\` - - tools - search - {"query": "database"} - -\`\`\` - -**list** - List all tools grouped by visibility -\`\`\` - - tools - list - {} - -\`\`\` - -**activate** - Activate an on-demand tool -\`\`\` - - tools - activate - {"name": "database_expert"} - -\`\`\` - -**details** - Get full information about a tool -\`\`\` - - tools - details - {"name": "filesystem"} - -\`\`\` -`; - } -} diff --git a/ts/smartagent.tools.shell.ts b/ts/smartagent.tools.shell.ts deleted file mode 100644 index bbabb8a..0000000 --- a/ts/smartagent.tools.shell.ts +++ /dev/null @@ -1,230 +0,0 @@ -import * as plugins from './plugins.js'; -import * as interfaces from './smartagent.interfaces.js'; -import { BaseToolWrapper } from './smartagent.tools.base.js'; - -/** - * Shell tool for executing commands securely - * Wraps @push.rocks/smartshell with execSpawn for safety (no shell injection) - */ -export class ShellTool extends BaseToolWrapper { - public name = 'shell'; - public description = - 'Execute shell commands securely. Uses execSpawn (shell:false) to prevent command injection.'; - - public actions: interfaces.IToolAction[] = [ - { - name: 'execute', - description: - 'Execute a command with arguments (secure, no shell injection possible). Command and args are passed separately.', - parameters: { - type: 'object', - properties: { - command: { - type: 'string', - description: 'The command to execute (e.g., "ls", "cat", "grep", "node")', - }, - args: { - type: 'array', - items: { type: 'string' }, - description: 'Array of arguments (each argument is properly escaped)', - }, - cwd: { type: 'string', description: 'Working directory for the command' }, - timeout: { type: 'number', description: 'Timeout in milliseconds' }, - env: { - type: 'object', - description: 'Additional environment variables (key-value pairs)', - }, - }, - required: ['command'], - }, - }, - { - name: 'which', - description: 'Check if a command exists and get its path', - parameters: { - type: 'object', - properties: { - command: { type: 'string', description: 'Command name to look up (e.g., "node", "git")' }, - }, - required: ['command'], - }, - }, - ]; - - private smartshell!: plugins.smartshell.Smartshell; - - public async initialize(): Promise { - this.smartshell = new plugins.smartshell.Smartshell({ - executor: 'bash', - }); - this.isInitialized = true; - } - - public async cleanup(): Promise { - this.isInitialized = false; - } - - public async execute( - action: string, - params: Record - ): Promise { - this.validateAction(action); - this.ensureInitialized(); - - try { - switch (action) { - case 'execute': { - const command = params.command as string; - const args = (params.args as string[]) || []; - - // Build options - const options: { - timeout?: number; - env?: NodeJS.ProcessEnv; - cwd?: string; - } = {}; - - if (params.timeout) { - options.timeout = params.timeout as number; - } - - if (params.env) { - options.env = { - ...process.env, - ...(params.env as NodeJS.ProcessEnv), - }; - } - - // Use execSpawn for security - no shell injection possible - const result = await this.smartshell.execSpawn(command, args, options); - - return { - success: result.exitCode === 0, - result: { - command, - args, - exitCode: result.exitCode, - stdout: result.stdout, - stderr: result.stderr, - signal: result.signal, - }, - }; - } - - case 'which': { - try { - const commandPath = await plugins.smartshell.which(params.command as string); - return { - success: true, - result: { - command: params.command, - path: commandPath, - exists: true, - }, - }; - } catch { - return { - success: true, - result: { - command: params.command, - path: null, - exists: false, - }, - }; - } - } - - default: - return { - success: false, - error: `Unknown action: ${action}`, - }; - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : String(error), - }; - } - } - - public getToolExplanation(): string { - return `## Tool: shell -Execute shell commands securely. Uses execSpawn (shell:false) to prevent command injection. - -### Actions: - -**execute** - Execute a command with arguments (secure, no shell injection possible) -Parameters: - - command (required): The command to execute (e.g., "ls", "cat", "grep", "node") - - args (optional): Array of arguments (each argument is properly escaped) - - cwd (optional): Working directory for the command - - timeout (optional): Timeout in milliseconds - - env (optional): Additional environment variables (key-value object) - -Example - List files: - - shell - execute - {"command": "ls", "args": ["-la", "/path/to/dir"]} - - -Example - Run Node script: - - shell - execute - {"command": "node", "args": ["script.js"], "cwd": "/path/to/project"} - - -Example - Search in files: - - shell - execute - {"command": "grep", "args": ["-r", "pattern", "src/"]} - - -**which** - Check if a command exists and get its path -Parameters: - - command (required): Command name to look up (e.g., "node", "git") - -Example: - - shell - which - {"command": "node"} - -`; - } - - public getCallSummary(action: string, params: Record): string { - switch (action) { - case 'execute': { - const command = params.command as string; - const args = (params.args as string[]) || []; - const fullCommand = [command, ...args].join(' '); - let summary = `Execute: ${fullCommand}`; - - if (params.cwd) { - summary += ` (in ${params.cwd})`; - } - - if (params.timeout) { - summary += ` [timeout: ${params.timeout}ms]`; - } - - if (params.env && Object.keys(params.env as object).length > 0) { - const envKeys = Object.keys(params.env as object).join(', '); - summary += ` [env: ${envKeys}]`; - } - - return summary; - } - - case 'which': - return `Check if command "${params.command}" exists and get its path`; - - default: - return `Unknown action: ${action}`; - } - } -} diff --git a/ts/smartagent.utils.truncation.ts b/ts/smartagent.utils.truncation.ts new file mode 100644 index 0000000..77f44b9 --- /dev/null +++ b/ts/smartagent.utils.truncation.ts @@ -0,0 +1,39 @@ +// Truncation logic derived from opencode (MIT) — https://github.com/sst/opencode + +const MAX_LINES = 2000; +const MAX_BYTES = 50 * 1024; // 50 KB + +export interface ITruncateResult { + content: string; + truncated: boolean; + /** Set when truncated: describes what was dropped */ + notice?: string; +} + +export function truncateOutput( + text: string, + options?: { maxLines?: number; maxBytes?: number }, +): ITruncateResult { + const maxLines = options?.maxLines ?? MAX_LINES; + const maxBytes = options?.maxBytes ?? MAX_BYTES; + const lines = text.split('\n'); + const totalBytes = Buffer.byteLength(text, 'utf-8'); + + if (lines.length <= maxLines && totalBytes <= maxBytes) { + return { content: text, truncated: false }; + } + + const out: string[] = []; + let bytes = 0; + for (let i = 0; i < lines.length && i < maxLines; i++) { + const size = Buffer.byteLength(lines[i], 'utf-8') + (i > 0 ? 1 : 0); + if (bytes + size > maxBytes) break; + out.push(lines[i]); + bytes += size; + } + + const kept = out.length; + const dropped = lines.length - kept; + const notice = `\n[Output truncated: showing ${kept}/${lines.length} lines. ${dropped} lines omitted.]`; + return { content: out.join('\n') + notice, truncated: true, notice }; +} diff --git a/ts_compaction/index.ts b/ts_compaction/index.ts new file mode 100644 index 0000000..f2af9cd --- /dev/null +++ b/ts_compaction/index.ts @@ -0,0 +1 @@ +export { compactMessages } from './smartagent.compaction.js'; diff --git a/ts_compaction/plugins.ts b/ts_compaction/plugins.ts new file mode 100644 index 0000000..eb43068 --- /dev/null +++ b/ts_compaction/plugins.ts @@ -0,0 +1,6 @@ +import { generateText } from 'ai'; + +export { generateText }; + +export type { ModelMessage } from 'ai'; +export type { LanguageModelV3 } from '@push.rocks/smartai'; diff --git a/ts_compaction/smartagent.compaction.ts b/ts_compaction/smartagent.compaction.ts new file mode 100644 index 0000000..b7022e8 --- /dev/null +++ b/ts_compaction/smartagent.compaction.ts @@ -0,0 +1,51 @@ +import * as plugins from './plugins.js'; + +const COMPACTION_PROMPT = `Provide a detailed prompt for continuing our conversation above. +Focus on information that would be helpful for continuing the conversation, including what we did, what we're doing, which files we're working on, and what we're going to do next. +The summary that you construct will be used so that another agent can read it and continue the work. + +When constructing the summary, try to stick to this template: +--- +## Goal +[What goal(s) is the user trying to accomplish?] + +## Instructions +- [What important instructions did the user give you that are relevant] + +## Discoveries +[What notable things were learned during this conversation that would be useful for the next agent to know] + +## Accomplished +[What work has been completed, what work is still in progress, and what work is left?] + +## Relevant files / directories +[A structured list of relevant files that have been read, edited, or created] +---`; + +/** + * Compacts a message history into a summary. + * Pass this as the onContextOverflow handler in IAgentRunOptions. + * + * @param model The same model used by runAgent, or a cheaper small model + * @param messages The full message history that overflowed + * @returns A minimal ModelMessage[] containing the summary as context + */ +export async function compactMessages( + model: plugins.LanguageModelV3, + messages: plugins.ModelMessage[], +): Promise { + const result = await plugins.generateText({ + model, + messages: [ + ...messages, + { role: 'user', content: COMPACTION_PROMPT }, + ], + }); + + return [ + { + role: 'user', + content: `[Previous conversation summary]\n\n${result.text}\n\n[End of summary. Continue from here.]`, + }, + ]; +} diff --git a/ts_tools/index.ts b/ts_tools/index.ts new file mode 100644 index 0000000..9dc8fb6 --- /dev/null +++ b/ts_tools/index.ts @@ -0,0 +1,8 @@ +export { filesystemTool } from './tool.filesystem.js'; +export type { IFilesystemToolOptions } from './tool.filesystem.js'; +export { shellTool } from './tool.shell.js'; +export type { IShellToolOptions } from './tool.shell.js'; +export { httpTool } from './tool.http.js'; +export { jsonTool } from './tool.json.js'; +export { truncateOutput } from './plugins.js'; +export type { ITruncateResult } from './plugins.js'; diff --git a/ts_tools/plugins.ts b/ts_tools/plugins.ts new file mode 100644 index 0000000..1a29c58 --- /dev/null +++ b/ts_tools/plugins.ts @@ -0,0 +1,30 @@ +// node native +import * as path from 'path'; +import * as fs from 'fs'; + +export { path, fs }; + +// zod +import { z } from 'zod'; + +export { z }; + +// ai-sdk +import { tool } from '@push.rocks/smartai'; + +export { tool }; + +export type { ToolSet } from 'ai'; + +// @push.rocks scope +import * as smartfs from '@push.rocks/smartfs'; +import * as smartshell from '@push.rocks/smartshell'; +import * as smartrequest from '@push.rocks/smartrequest'; + +export { smartfs, smartshell, smartrequest }; + +// cross-folder import +import { truncateOutput } from '../ts/smartagent.utils.truncation.js'; + +export { truncateOutput }; +export type { ITruncateResult } from '../ts/smartagent.utils.truncation.js'; diff --git a/ts_tools/tool.filesystem.ts b/ts_tools/tool.filesystem.ts new file mode 100644 index 0000000..4bdff13 --- /dev/null +++ b/ts_tools/tool.filesystem.ts @@ -0,0 +1,131 @@ +import * as plugins from './plugins.js'; + +export interface IFilesystemToolOptions { + /** Restrict file access to this directory. Default: process.cwd() */ + rootDir?: string; +} + +function validatePath(filePath: string, rootDir?: string): string { + const resolved = plugins.path.resolve(filePath); + if (rootDir) { + const resolvedRoot = plugins.path.resolve(rootDir); + if (!resolved.startsWith(resolvedRoot + plugins.path.sep) && resolved !== resolvedRoot) { + throw new Error(`Access denied: "${filePath}" is outside allowed root "${rootDir}"`); + } + } + return resolved; +} + +export function filesystemTool(options?: IFilesystemToolOptions): plugins.ToolSet { + const rootDir = options?.rootDir; + + return { + read_file: plugins.tool({ + description: + 'Read file contents. Returns the full text or a specified line range.', + inputSchema: plugins.z.object({ + path: plugins.z.string().describe('Absolute path to the file'), + startLine: plugins.z + .number() + .optional() + .describe('First line (1-indexed, inclusive)'), + endLine: plugins.z + .number() + .optional() + .describe('Last line (1-indexed, inclusive)'), + }), + execute: async ({ + path: filePath, + startLine, + endLine, + }: { + path: string; + startLine?: number; + endLine?: number; + }) => { + const resolved = validatePath(filePath, rootDir); + const content = plugins.fs.readFileSync(resolved, 'utf-8'); + + if (startLine !== undefined || endLine !== undefined) { + const lines = content.split('\n'); + const start = (startLine ?? 1) - 1; + const end = endLine ?? lines.length; + const sliced = lines.slice(start, end).join('\n'); + return plugins.truncateOutput(sliced).content; + } + + return plugins.truncateOutput(content).content; + }, + }), + + write_file: plugins.tool({ + description: + 'Write content to a file (creates parent dirs if needed, overwrites existing).', + inputSchema: plugins.z.object({ + path: plugins.z.string().describe('Absolute path to the file'), + content: plugins.z.string().describe('Content to write'), + }), + execute: async ({ path: filePath, content }: { path: string; content: string }) => { + const resolved = validatePath(filePath, rootDir); + const dir = plugins.path.dirname(resolved); + plugins.fs.mkdirSync(dir, { recursive: true }); + plugins.fs.writeFileSync(resolved, content, 'utf-8'); + return `Written ${content.length} characters to ${filePath}`; + }, + }), + + list_directory: plugins.tool({ + description: 'List files and directories at the given path.', + inputSchema: plugins.z.object({ + path: plugins.z.string().describe('Directory path to list'), + recursive: plugins.z + .boolean() + .optional() + .describe('List recursively (default: false)'), + }), + execute: async ({ + path: dirPath, + recursive, + }: { + path: string; + recursive?: boolean; + }) => { + const resolved = validatePath(dirPath, rootDir); + + function listDir(dir: string, prefix: string = ''): string[] { + const entries = plugins.fs.readdirSync(dir, { withFileTypes: true }); + const result: string[] = []; + for (const entry of entries) { + const rel = prefix ? `${prefix}/${entry.name}` : entry.name; + const indicator = entry.isDirectory() ? '/' : ''; + result.push(`${rel}${indicator}`); + if (recursive && entry.isDirectory()) { + result.push(...listDir(plugins.path.join(dir, entry.name), rel)); + } + } + return result; + } + + const entries = listDir(resolved); + return plugins.truncateOutput(entries.join('\n')).content; + }, + }), + + delete_file: plugins.tool({ + description: 'Delete a file or empty directory.', + inputSchema: plugins.z.object({ + path: plugins.z.string().describe('Path to delete'), + }), + execute: async ({ path: filePath }: { path: string }) => { + const resolved = validatePath(filePath, rootDir); + const stat = plugins.fs.statSync(resolved); + if (stat.isDirectory()) { + plugins.fs.rmdirSync(resolved); + } else { + plugins.fs.unlinkSync(resolved); + } + return `Deleted ${filePath}`; + }, + }), + }; +} diff --git a/ts_tools/tool.http.ts b/ts_tools/tool.http.ts new file mode 100644 index 0000000..102c902 --- /dev/null +++ b/ts_tools/tool.http.ts @@ -0,0 +1,78 @@ +import * as plugins from './plugins.js'; + +export function httpTool(): plugins.ToolSet { + return { + http_get: plugins.tool({ + description: 'Make an HTTP GET request and return the response.', + inputSchema: plugins.z.object({ + url: plugins.z.string().describe('URL to request'), + headers: plugins.z + .record(plugins.z.string()) + .optional() + .describe('Request headers'), + }), + execute: async ({ + url, + headers, + }: { + url: string; + headers?: Record; + }) => { + let req = plugins.smartrequest.default.create().url(url); + if (headers) { + req = req.headers(headers); + } + const response = await req.get(); + let body: string; + try { + const json = await response.json(); + body = JSON.stringify(json, null, 2); + } catch { + body = await response.text(); + } + return plugins.truncateOutput(`HTTP ${response.status}\n${body}`).content; + }, + }), + + http_post: plugins.tool({ + description: 'Make an HTTP POST request with a JSON body.', + inputSchema: plugins.z.object({ + url: plugins.z.string().describe('URL to request'), + body: plugins.z + .record(plugins.z.unknown()) + .optional() + .describe('JSON body to send'), + headers: plugins.z + .record(plugins.z.string()) + .optional() + .describe('Request headers'), + }), + execute: async ({ + url, + body, + headers, + }: { + url: string; + body?: Record; + headers?: Record; + }) => { + let req = plugins.smartrequest.default.create().url(url); + if (headers) { + req = req.headers(headers); + } + if (body) { + req = req.json(body); + } + const response = await req.post(); + let responseBody: string; + try { + const json = await response.json(); + responseBody = JSON.stringify(json, null, 2); + } catch { + responseBody = await response.text(); + } + return plugins.truncateOutput(`HTTP ${response.status}\n${responseBody}`).content; + }, + }), + }; +} diff --git a/ts_tools/tool.json.ts b/ts_tools/tool.json.ts new file mode 100644 index 0000000..6236329 --- /dev/null +++ b/ts_tools/tool.json.ts @@ -0,0 +1,53 @@ +import * as plugins from './plugins.js'; + +export function jsonTool(): plugins.ToolSet { + return { + json_validate: plugins.tool({ + description: + 'Validate a JSON string and optionally check for required fields.', + inputSchema: plugins.z.object({ + jsonString: plugins.z.string().describe('JSON string to validate'), + requiredFields: plugins.z + .array(plugins.z.string()) + .optional() + .describe('Fields that must exist at the top level'), + }), + execute: async ({ + jsonString, + requiredFields, + }: { + jsonString: string; + requiredFields?: string[]; + }) => { + try { + const parsed = JSON.parse(jsonString); + if (requiredFields?.length) { + const missing = requiredFields.filter((f) => !(f in parsed)); + if (missing.length) { + return `Invalid: missing required fields: ${missing.join(', ')}`; + } + } + const type = Array.isArray(parsed) ? 'array' : typeof parsed; + return `Valid JSON (${type})`; + } catch (e) { + return `Invalid JSON: ${(e as Error).message}`; + } + }, + }), + + json_transform: plugins.tool({ + description: 'Parse a JSON string and return it pretty-printed.', + inputSchema: plugins.z.object({ + jsonString: plugins.z.string().describe('JSON string to format'), + }), + execute: async ({ jsonString }: { jsonString: string }) => { + try { + const parsed = JSON.parse(jsonString); + return JSON.stringify(parsed, null, 2); + } catch (e) { + return `Error parsing JSON: ${(e as Error).message}`; + } + }, + }), + }; +} diff --git a/ts_tools/tool.shell.ts b/ts_tools/tool.shell.ts new file mode 100644 index 0000000..122388e --- /dev/null +++ b/ts_tools/tool.shell.ts @@ -0,0 +1,62 @@ +import * as plugins from './plugins.js'; + +export interface IShellToolOptions { + /** Allowed commands whitelist. If empty, all commands are allowed. */ + allowedCommands?: string[]; + /** Working directory for shell execution */ + cwd?: string; +} + +export function shellTool(options?: IShellToolOptions): plugins.ToolSet { + const smartshell = new plugins.smartshell.Smartshell({ executor: 'bash' }); + + return { + run_command: plugins.tool({ + description: + 'Execute a shell command. Provide the full command string. stdout and stderr are returned.', + inputSchema: plugins.z.object({ + command: plugins.z.string().describe('The shell command to execute'), + cwd: plugins.z + .string() + .optional() + .describe('Working directory for the command'), + timeout: plugins.z + .number() + .optional() + .describe('Timeout in milliseconds'), + }), + execute: async ({ + command, + cwd, + timeout, + }: { + command: string; + cwd?: string; + timeout?: number; + }) => { + // Validate against allowed commands whitelist + if (options?.allowedCommands?.length) { + const baseCommand = command.split(/\s+/)[0]; + if (!options.allowedCommands.includes(baseCommand)) { + return `Command "${baseCommand}" is not in the allowed commands list: ${options.allowedCommands.join(', ')}`; + } + } + + // Build full command string with cd prefix if cwd specified + const effectiveCwd = cwd ?? options?.cwd; + const fullCommand = effectiveCwd + ? `cd ${JSON.stringify(effectiveCwd)} && ${command}` + : command; + + const execResult = await smartshell.exec(fullCommand); + + const output = + execResult.exitCode === 0 + ? execResult.stdout + : `Exit code: ${execResult.exitCode}\nstdout:\n${execResult.stdout}\nstderr:\n${execResult.stderr ?? ''}`; + + return plugins.truncateOutput(output).content; + }, + }), + }; +}