diff --git a/.env.example b/.env.example
index f4ffd00..7d357cc 100644
--- a/.env.example
+++ b/.env.example
@@ -26,6 +26,10 @@ APS_PORT=5199
# 默认 ~/.aps/aps.sqlite;服务端部署时显式指定
# APS_DB_PATH=
+# ---- 引擎选择 ----
+# 留空 = 有密钥就用 Pi、没密钥用假引擎;也可显式写 fake | pi
+# APS_ENGINE=
+
# ---- 开发期开关 ----
# 1=注册假 Provider(用于联调与演示;默认不注册,能力清单为空)
# APS_DEV_PROVIDER=1
\ No newline at end of file
diff --git a/.tmp-pi-sessions/2026-09-28T12-18-49-579Z_raw-probe.jsonl b/.tmp-pi-sessions/2026-09-28T12-18-49-579Z_raw-probe.jsonl
new file mode 100644
index 0000000..acd55e3
--- /dev/null
+++ b/.tmp-pi-sessions/2026-09-28T12-18-49-579Z_raw-probe.jsonl
@@ -0,0 +1,8 @@
+{"type":"session","version":3,"id":"raw-probe","timestamp":"2026-09-28T12:18:49.579Z","cwd":"D:\\workspace\\github\\aps-agent"}
+{"type":"model_change","id":"c5ce29c8","parentId":null,"timestamp":"2026-09-28T12:18:49.620Z","provider":"deepseek","modelId":"deepseek-chat"}
+{"type":"thinking_level_change","id":"d7ce43d9","parentId":"c5ce29c8","timestamp":"2026-09-28T12:18:49.620Z","thinkingLevel":"high"}
+{"type":"message","id":"9daf9ab7","parentId":"d7ce43d9","timestamp":"2026-09-28T12:18:49.642Z","message":{"role":"system","content":"","sections":{"preamble":"You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.","tools":"\n(none)\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n","rules":"\n- Be concise in your responses\n- Show file paths clearly when working with files\n","docs":"\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: D:\\workspace\\github\\aps-agent\\node_modules\\.pnpm\\@earendil-works+pi-coding-agent@0.87.1_ws@8.22.0\\node_modules\\@earendil-works\\pi-coding-agent\\README.md\n- Additional docs: D:\\workspace\\github\\aps-agent\\node_modules\\.pnpm\\@earendil-works+pi-coding-agent@0.87.1_ws@8.22.0\\node_modules\\@earendil-works\\pi-coding-agent\\docs\n- Examples: D:\\workspace\\github\\aps-agent\\node_modules\\.pnpm\\@earendil-works+pi-coding-agent@0.87.1_ws@8.22.0\\node_modules\\@earendil-works\\pi-coding-agent\\examples (extensions, custom tools, SDK)\n- When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md)\n- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)\n","cwd":"\nD:/workspace/github/aps-agent\n"},"timestamp":1790597929641}}
+{"type":"message","id":"421a57b6","parentId":"9daf9ab7","timestamp":"2026-09-28T12:18:49.642Z","message":{"role":"user","content":[{"type":"text","text":"用一句话回答:1+1 等于几"}],"timestamp":1790597929640}}
+{"type":"message","id":"5ab3ce68","parentId":"421a57b6","timestamp":"2026-09-28T12:18:49.873Z","message":{"role":"assistant","content":[],"api":"openai-completions","provider":"deepseek","model":"deepseek-chat","usage":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"totalTokens":0,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"error","timestamp":1790597929656,"errorMessage":"401: {\"message\":\"Authentication Fails, Your api key: ****-key is invalid (request_id: 91c7a4c1-9f68-4283-9b12-a1c985d6b703)\",\"type\":\"authentication_error\",\"param\":null,\"code\":\"invalid_request_error\"}"}}
+{"type":"message","id":"290decc4","parentId":"5ab3ce68","timestamp":"2026-09-28T12:19:10.278Z","message":{"role":"user","content":[{"type":"text","text":"用一句话回答:1+1 等于几"}],"timestamp":1790597950276}}
+{"type":"message","id":"a69d0b1e","parentId":"290decc4","timestamp":"2026-09-28T12:19:10.444Z","message":{"role":"assistant","content":[],"api":"openai-completions","provider":"deepseek","model":"deepseek-chat","usage":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"totalTokens":0,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"error","timestamp":1790597950292,"errorMessage":"401: {\"message\":\"Authentication Fails, Your api key: ****-key is invalid (request_id: 37c34f4b-4e59-42c6-970f-23b3cb2958ea)\",\"type\":\"authentication_error\",\"param\":null,\"code\":\"invalid_request_error\"}"}}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d27c575..c450ea4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,7 +19,7 @@ importers:
version: link:server
'@eslint/js':
specifier: ^10.0.1
- version: 10.0.1(eslint@10.11.0)
+ version: 10.0.1(eslint@10.11.0(jiti@2.7.0))
'@types/node':
specifier: ^26.6.2
version: 26.6.2
@@ -28,7 +28,7 @@ importers:
version: 8.20.0
eslint:
specifier: ^10.11.0
- version: 10.11.0
+ version: 10.11.0(jiti@2.7.0)
prettier:
specifier: ^3.9.9
version: 3.9.9
@@ -37,7 +37,7 @@ importers:
version: 6.0.3
typescript-eslint:
specifier: ^8.70.1
- version: 8.70.1(eslint@10.11.0)(typescript@6.0.3)
+ version: 8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)
client/app:
dependencies:
@@ -59,10 +59,10 @@ importers:
version: 19.3.0(@types/react@19.3.0)
'@vitejs/plugin-react':
specifier: ^5.1.0
- version: 5.2.0(vite@7.3.6(@types/node@26.6.2)(lightningcss@1.33.0))
+ version: 5.2.0(vite@7.3.6(@types/node@26.6.2)(jiti@2.7.0)(lightningcss@1.33.0)(yaml@2.9.0))
vite:
specifier: ^7.2.0
- version: 7.3.6(@types/node@26.6.2)(lightningcss@1.33.0)
+ version: 7.3.6(@types/node@26.6.2)(jiti@2.7.0)(lightningcss@1.33.0)(yaml@2.9.0)
client/desktop: {}
@@ -85,6 +85,12 @@ importers:
'@aps/provider-sdk':
specifier: workspace:*
version: link:provider-sdk
+ '@earendil-works/pi-agent-core':
+ specifier: 0.87.1
+ version: 0.87.1(ws@8.22.0)
+ '@earendil-works/pi-coding-agent':
+ specifier: 0.87.1
+ version: 0.87.1(ws@8.22.0)
server/provider-sdk:
dependencies:
@@ -94,6 +100,95 @@ importers:
packages:
+ '@anthropic-ai/sdk@0.124.0':
+ resolution: {integrity: sha512-cN5O8i9UVxHeOQAzj/XjshWXG8KiibJDw9OGpH2Z/eR3n/RBxdoLxDJOcfqAJWvjaMDFfHTBADU04hWRJVkDyA==}
+ hasBin: true
+ peerDependencies:
+ zod: ^3.25.0 || ^4.0.0
+ peerDependenciesMeta:
+ zod:
+ optional: true
+
+ '@aws-sdk/client-bedrock-runtime@3.1127.0':
+ resolution: {integrity: sha512-IDl/lrPb90aH+pZFHGNDmgH9nAUQj5PlZH1sJ3w7RikctyjHSnY3oNjZhrLoaBoQn/rNK0zsP6OHEqEhj2tdLA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/core@3.978.1':
+ resolution: {integrity: sha512-LbY9aGsEiznDWmUc30Nwv3aIX/+dbwTx8KfS0yOC3NPYMO+O91e6jkT1azf34FwjOndq8/Q+RcVVZz5xnerwdg==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-env@3.972.72':
+ resolution: {integrity: sha512-xTKO/FWJPozTIXbozVnVGoNBhaGba8TBcx+KyUjRVeOlXE+dUc7GTR1cLvu0uTdIdmemzaFbqqCshXeZA1fZew==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-http@3.972.74':
+ resolution: {integrity: sha512-u91E/hT8f4d1xy0Jl7VG4nVKJ3lxbrZkoBTeSVoJdWBiSEUMwMS/9+e0H/aJVQV//Lt5wuzP+E69v4aRSsNTmw==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-ini@3.973.17':
+ resolution: {integrity: sha512-ged4KXdBkvIC81bLvNHHuQKdKak/VXhQTR1NWYTTqW0474nlmsxy9O/vlgTIohDDWH3xpBdtVMZRyjb+DnocDA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-login@3.972.79':
+ resolution: {integrity: sha512-L+Z85anONJd8MaiuraO4wRxATCdEejBZ3K3eymzWI5JPXa9sOS9CkIm72PBKqXKX+Z9p9NGMX5AIMXm0LEflgw==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-node@3.972.84':
+ resolution: {integrity: sha512-oHt854odINVwzwsh+c5x69j0ajm4DbqqqVJ+O1ECsCIZeMDAbzFpXItaqP7UZstJj/ATdTk/KFSH0LaNAgV+kA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-process@3.972.72':
+ resolution: {integrity: sha512-rLIp2xbMjX/k9/od7APpqq1ZgXXnV0pOL1Th3ZsL8Wu0TRtBsDTVS8iPqcfRFcHakFxPvR04OSTv2ka2qOb/2A==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-sso@3.973.16':
+ resolution: {integrity: sha512-IGihaJfFZYacJJr/odqILCoK7W/mvrZ7cuK7ECn3sAu4vLC6u0V8bS7mCGbdugJ8Aum2tnvqmx0F2MRFp2rn9g==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-web-identity@3.972.78':
+ resolution: {integrity: sha512-/y9WvNtlcPBGLR0qc1a+9J/xtYZfVczvLUOuXaVWylzttH7ewsxwHtjmiJSolNrVSDorIxHGHMU61CbonRkmwA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/eventstream-handler-node@3.972.35':
+ resolution: {integrity: sha512-a8xilRoRaalvSPZdfrs0VY3/BPc0uYhXW56Z/k6nmZ5Vk430LHeowf9APIPq8utM3tMJSNGSSuJMlB9YrPsN+A==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/middleware-eventstream@3.972.30':
+ resolution: {integrity: sha512-B6gvZlcnRBNWraKgyEjKsbhv+VjtbyHmpU7hmtTHzXpDSxHPpCJnYLpglEOOsF+SFne20DbZC5IVC1aNr2Pb4A==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/middleware-websocket@3.972.54':
+ resolution: {integrity: sha512-bhESdru8u8KosziH8jcVta/NM/dNreeRz2+2aU86si5bfBYOiJ6IiqD+9U4URUcU5WJO3Yw+jO3GLDIHlscXMQ==}
+ engines: {node: '>= 14.0.0'}
+
+ '@aws-sdk/nested-clients@3.997.46':
+ resolution: {integrity: sha512-oRxtBcka/JGHGs9l9p9IVajGoTP8vTPmoAzdHGy4Qcy9P5vPnDf6nhIeM/COQNY9k/OahImTRaLkHftoXvfcmQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/signature-v4-multi-region@3.996.47':
+ resolution: {integrity: sha512-Zk08macMvQTHzQJCLJVkOlviVoqwYMrpXv4lmLN7b7sAbiMoOK7Go0NYdR5UeF+MW8LIbRmwrNy9u/5VvX1U5g==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/token-providers@3.1127.0':
+ resolution: {integrity: sha512-Dv2TMWBshJ+tF6ahs2Sy5bh4Iabsd4GAQqVvE9XZmYmnoaVbpS2QKIKE/HRacc7bTtbjEEvP+laGzHvHlf1CiQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/token-providers@3.1138.0':
+ resolution: {integrity: sha512-GpyAr0DD63YOEmYFM6Df+gJuIgC92MMTiBK4FTKfxii5MJ9ge20epR7LyroulscYlG89J+ZB2ivFDPjvfQhzdw==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/types@3.974.6':
+ resolution: {integrity: sha512-v/clNZzZnDxGyvpHMOGpJKVXFAExJzUNAAjaWGdcx8QAcXLGwTaOkw33p5SHAi0YAioK32xB3hWwOekRVfmfKg==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/xml-builder@3.972.41':
+ resolution: {integrity: sha512-ctjVSyCMegrWfXlx6VqzSBFI6UqmQ5ZlnfMhdLIiWmhoH8UAQxSCP5N3OpG7X3k4LnS7ou74C4mt20+bfTW2aQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws/lambda-invoke-store@0.3.0':
+ resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==}
+ engines: {node: '>=18.0.0'}
+
'@babel/code-frame@7.29.7':
resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
engines: {node: '>=6.9.0'}
@@ -165,6 +260,10 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/runtime@7.29.7':
+ resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/template@7.29.7':
resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
engines: {node: '>=6.9.0'}
@@ -183,6 +282,32 @@ packages:
'@cacheable/utils@2.5.0':
resolution: {integrity: sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==}
+ '@earendil-works/chord@0.87.1':
+ resolution: {integrity: sha512-bg7IkJGFcEaMqqYgOGUiq5Ky9RghpRfrlZ8I/v/1b4bBZ02A7t3E+6uhPRbadwWb/kWsnVFbZsqOKRN4a3LLCg==}
+ engines: {node: '>=22.19.0'}
+
+ '@earendil-works/pi-agent-core@0.87.1':
+ resolution: {integrity: sha512-Zev3B0HK7YS5A4EZQ2XnEqiJuirx6QBiltJ+LpmjV5a/+2IU0cfKtIfnkNkORK707XOvKBY2WRtk7cAwHpbh2Q==}
+ engines: {node: '>=22.19.0'}
+
+ '@earendil-works/pi-ai@0.87.1':
+ resolution: {integrity: sha512-X/3PfQBnnoeVdO9Cv8zHghUMglzlgNZYGNzoPnbRoGnHl3Rw3TlA2UKSUB7BRHUOxMryHXYa8dnjWZlbRheDZA==}
+ engines: {node: '>=22.19.0'}
+ hasBin: true
+
+ '@earendil-works/pi-coding-agent@0.87.1':
+ resolution: {integrity: sha512-m8ArJUtVcQMSe1lLE/Ei7vX/JV7O39sWmWBsXV2NOU70F0qCp8GubA24pT3LnwTmM6LL2xV80/h6sQg85n69ew==}
+ engines: {node: '>=22.19.0'}
+ hasBin: true
+
+ '@earendil-works/pi-telemetry@0.87.1':
+ resolution: {integrity: sha512-MC6TRQH5lgMXpcN+Vku2WMI2T8BsiUPzMQHGo81uqFZD3/9O79WWJAysEDGuzduP6R4tvtgwMLwmqIxynM10JQ==}
+ engines: {node: '>=22.19.0'}
+
+ '@earendil-works/pi-tui@0.87.1':
+ resolution: {integrity: sha512-YEH2vRyOeiO7hhN6j6AE6YwKSq2Kz2f3XR8bj1TbR+aGE/JsnY1hLPMI2pvaZfRM1n9Y00tejxFQ4zbzvF7nkQ==}
+ engines: {node: '>=22.19.0'}
+
'@esbuild/aix-ppc64@0.28.2':
resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==}
engines: {node: '>=18'}
@@ -378,6 +503,15 @@ packages:
resolution: {integrity: sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==}
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+ '@google/genai@2.21.0':
+ resolution: {integrity: sha512-+PDtco2/Z0ONdzCGekCoCT+O1VJS9xJQNN4XzQpXG/t3El/SWWMkCWlFRO1KmivOHPa4Q0VjUYu1HBKCZ/v33Q==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@modelcontextprotocol/sdk': ^1.25.2
+ peerDependenciesMeta:
+ '@modelcontextprotocol/sdk':
+ optional: true
+
'@humanfs/core@0.19.2':
resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==}
engines: {node: '>=18.18.0'}
@@ -430,6 +564,33 @@ packages:
os: [linux]
libc: [glibc]
+ '@protobufjs/aspromise@1.1.2':
+ resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
+
+ '@protobufjs/base64@1.1.2':
+ resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
+
+ '@protobufjs/codegen@2.0.5':
+ resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==}
+
+ '@protobufjs/eventemitter@1.1.1':
+ resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==}
+
+ '@protobufjs/fetch@1.1.1':
+ resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==}
+
+ '@protobufjs/float@1.0.2':
+ resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
+
+ '@protobufjs/path@1.1.2':
+ resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
+
+ '@protobufjs/pool@1.1.0':
+ resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
+
+ '@protobufjs/utf8@1.1.2':
+ resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==}
+
'@rolldown/pluginutils@1.0.0-rc.3':
resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==}
@@ -571,6 +732,36 @@ packages:
cpu: [x64]
os: [win32]
+ '@silvia-odwyer/photon-node@0.3.4':
+ resolution: {integrity: sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==}
+
+ '@smithy/core@3.35.0':
+ resolution: {integrity: sha512-zRMhfkByhT2snNdr1si24vJitU6Cr9ix2MikUfWmkAgp4jrNP0GcKSP5YvwQ+TlI8AZXER5QOGJn3JsVtSD9/A==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/credential-provider-imds@4.5.2':
+ resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/fetch-http-handler@5.8.0':
+ resolution: {integrity: sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/node-http-handler@4.12.1':
+ resolution: {integrity: sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/signature-v4@5.7.4':
+ resolution: {integrity: sha512-tHy0K0VtqNd5Y7Y41h0a0Lhh0L1GzC08dTWg0F7vRJWFtTENg7IZikf3wQkanYIRdb7ngoIPMTmqgUi401fEeQ==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/types@4.19.0':
+ resolution: {integrity: sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==}
+ engines: {node: '>=18.0.0'}
+
+ '@stablelib/base64@1.0.1':
+ resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==}
+
'@types/babel__core@7.20.5':
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
@@ -603,6 +794,9 @@ packages:
'@types/react@19.3.0':
resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==}
+ '@types/retry@0.12.0':
+ resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==}
+
'@typescript-eslint/eslint-plugin@8.70.1':
resolution: {integrity: sha512-nDNrUQ/4ruSNYbu749TRY7cfrzPtoLHEXSNBI8aaNY32LlZCajixqRf3FqcKC4p5Cam4VOHYx/t+i5+nKXvrqA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -678,6 +872,14 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
+ agent-base@9.0.0:
+ resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==}
+ engines: {node: '>= 20'}
+
ajv@6.15.0:
resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
@@ -688,11 +890,20 @@ packages:
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
engines: {node: 18 || 20 || >=22}
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
baseline-browser-mapping@2.11.25:
resolution: {integrity: sha512-gMmEShwwq7FJqMwvfRwvCl00v4kN+KOfJqXn+f4nrufak5gNHJOksd/60Dvjuz7sI8Y5WiSFBa8FEYr+zoyqCw==}
engines: {node: '>=6.0.0'}
hasBin: true
+ bignumber.js@9.3.1:
+ resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==}
+
+ bowser@2.14.1:
+ resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==}
+
brace-expansion@5.0.12:
resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==}
engines: {node: 20 || >=22}
@@ -702,12 +913,19 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ buffer-equal-constant-time@1.0.1:
+ resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
+
cacheable@2.5.0:
resolution: {integrity: sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==}
caniuse-lite@1.0.30001810:
resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==}
+ chalk@6.0.0:
+ resolution: {integrity: sha512-2uNTXIuTTxk7ciZgAU1BQcgnchcG0xXnrs6jzkQfj9SsRa9M2s5zE8WT96hS6KmG4MzWHSrvH43DF1m4XRkrFg==}
+ engines: {node: '>=22'}
+
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
@@ -718,6 +936,10 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ data-uri-to-buffer@4.0.1:
+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+ engines: {node: '>= 12'}
+
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@@ -734,6 +956,13 @@ packages:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
+ diff@8.0.4:
+ resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==}
+ engines: {node: '>=0.3.1'}
+
+ ecdsa-sig-formatter@1.0.11:
+ resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
+
electron-to-chromium@1.5.437:
resolution: {integrity: sha512-1z60R0Nb+kYPnGUrQ6PvMjTVINDGMfqQZ/mI5FJIHvTotlA6noI+YJWakbjaFM+qhLXg9WnK3RUeYSO5ixSHJA==}
@@ -792,6 +1021,9 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -801,6 +1033,9 @@ packages:
fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ fast-sha256@1.3.0:
+ resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==}
+
fast-uri@3.1.8:
resolution: {integrity: sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==}
@@ -813,6 +1048,10 @@ packages:
picomatch:
optional: true
+ fetch-blob@3.2.0:
+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+ engines: {node: ^12.20 || >= 14.13}
+
file-entry-cache@11.1.5:
resolution: {integrity: sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==}
@@ -826,29 +1065,79 @@ packages:
flatted@3.4.4:
resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==}
+ formdata-polyfill@4.0.10:
+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+ engines: {node: '>=12.20.0'}
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
+ gaxios@7.3.1:
+ resolution: {integrity: sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==}
+ engines: {node: '>=18'}
+
+ gcp-metadata@8.1.2:
+ resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==}
+ engines: {node: '>=18'}
+
gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
+ get-east-asian-width@1.6.0:
+ resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==}
+ engines: {node: '>=18'}
+
glob-parent@6.0.2:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
+ google-auth-library@10.9.1:
+ resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==}
+ engines: {node: '>=18'}
+
+ google-logging-utils@1.1.3:
+ resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==}
+ engines: {node: '>=14'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ grok-mermaid@0.2.3:
+ resolution: {integrity: sha512-/4KopAbsjvuRP9MdPtlDjOHUmUVEohOX73JNcsWpzAtFxh+bq5+Dhb6gzvRieLDwIPQIR3/vy8V1NNTuz4Zsmg==}
+ engines: {node: '>=18'}
+
hashery@1.5.1:
resolution: {integrity: sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==}
engines: {node: '>=20'}
+ highlight.js@10.7.3:
+ resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
+
hookified@1.15.1:
resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==}
hookified@2.2.0:
resolution: {integrity: sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==}
+ hosted-git-info@9.0.3:
+ resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==}
+ engines: {node: ^20.17.0 || >=22.9.0}
+
+ http-proxy-agent@9.1.0:
+ resolution: {integrity: sha512-2NxoveTT58mjYT4n3RPTEfCZGLMbidoO8XEieXfpSYxu+PQJ1qpx4ypwH6N+uF9twBPIvRRgvkvW5HUTYWENig==}
+ engines: {node: '>= 20'}
+
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
+ https-proxy-agent@9.1.0:
+ resolution: {integrity: sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==}
+ engines: {node: '>= 20'}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -857,6 +1146,10 @@ packages:
resolution: {integrity: sha512-HpbUakT7xp5miBUywCHf36ZEuAJNklBJDDsGpUIjMzOSmM8ELSfA9Sa/QDPeNeqeoN31u+UTCkL4klCOVvRm4Q==}
engines: {node: '>= 4'}
+ ignore@7.0.8:
+ resolution: {integrity: sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==}
+ engines: {node: '>= 4'}
+
imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
@@ -872,6 +1165,10 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ jiti@2.7.0:
+ resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
+ hasBin: true
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -880,6 +1177,13 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ json-bigint@1.0.0:
+ resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==}
+
+ json-schema-to-ts@3.1.1:
+ resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==}
+ engines: {node: '>=16'}
+
json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
@@ -894,6 +1198,12 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ jwa@2.0.1:
+ resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
+
+ jws@4.0.1:
+ resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
+
keyv@5.6.0:
resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==}
@@ -979,9 +1289,21 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
+ long@5.3.2:
+ resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
+
+ lru-cache@11.5.3:
+ resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==}
+ engines: {node: 20 || >=22}
+
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ marked@18.0.11:
+ resolution: {integrity: sha512-HnslJfsZkRPBDJRHvVtAaWlZHEpSu7u8LgQuJCELjRKuWR+hpq4A7sLq3p8HaI9ypVoXDXxV34CsQJEe1+J5Aw==}
+ engines: {node: '>= 20'}
+ hasBin: true
+
minimatch@10.2.6:
resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==}
engines: {node: 18 || 20 || >=22}
@@ -997,10 +1319,30 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+ deprecated: Use your platform's native DOMException instead
+
+ node-fetch@3.3.2:
+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
node-releases@2.0.56:
resolution: {integrity: sha512-x0InOIyzgdk+eyaWaRJFH5snEtiImgBgblZ2CyPrLmqqcuMQkEvcDPHbzqbD8eDsSeJbVOjn+crzyzHaM4D+/A==}
engines: {node: '>=18'}
+ openai@6.40.0:
+ resolution: {integrity: sha512-MWtTjd/gQt4jpbji61NTgFWJLoY/PdRJ6wG9/ZDRMYNMlBKrCrSlkLI+KgHP1vR1qT6LKSAyAqIxno6lcK9JiA==}
+ peerDependencies:
+ ws: ^8.18.0
+ zod: ^3.25 || ^4.0
+ peerDependenciesMeta:
+ ws:
+ optional: true
+ zod:
+ optional: true
+
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
@@ -1013,6 +1355,13 @@ packages:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
+ p-retry@4.6.2:
+ resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==}
+ engines: {node: '>=8'}
+
+ partial-json@0.1.7:
+ resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==}
+
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@@ -1041,6 +1390,22 @@ packages:
engines: {node: '>=14'}
hasBin: true
+ proper-lockfile@4.1.2:
+ resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==}
+
+ protobufjs@7.6.6:
+ resolution: {integrity: sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==}
+ engines: {node: '>=12.0.0'}
+
+ proxy-agent-negotiate@1.1.0:
+ resolution: {integrity: sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==}
+ engines: {node: '>= 20'}
+ peerDependencies:
+ kerberos: ^2.0.0
+ peerDependenciesMeta:
+ kerberos:
+ optional: true
+
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@@ -1066,11 +1431,22 @@ packages:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
+ retry@0.12.0:
+ resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
+ engines: {node: '>= 4'}
+
+ retry@0.13.1:
+ resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
+ engines: {node: '>= 4'}
+
rollup@4.63.4:
resolution: {integrity: sha512-4U0liVayNIoLp3GFl1FcI8561WepLnZ1rqfraGh7S9B3Ur5F9S283y8Futii7RUU2C/97tOBmBy7nYvhoiOpbQ==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
scheduler@0.28.0:
resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==}
@@ -1091,24 +1467,39 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
+ standardwebhooks@1.1.1:
+ resolution: {integrity: sha512-bCbX9ZEyFkWPsRz7Bl3NuQUJohmwGSev/yhr7vhaGPlc4AfIrspIRa6cPTBuI1ItmrTDJ4d/S2hCsfe4+vQGnQ==}
+
tinyglobby@0.2.17:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
engines: {node: '>=12.0.0'}
+ ts-algebra@2.0.0:
+ resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==}
+
ts-api-utils@2.5.0:
resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==}
engines: {node: '>=18.12'}
peerDependencies:
typescript: '>=4.8.4'
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
+ typebox@1.3.27:
+ resolution: {integrity: sha512-zu+jc1pcy4UiNThxikUr36f0Rybk9PEeCg/NE6adeWr/SKsdNO4EzZHYRDlv2YCVAfj3Odq3dESSo/jNyoBXzA==}
+
typescript-eslint@8.70.1:
resolution: {integrity: sha512-AcWG7KDjZ2THNXsgwttMaGmzVi0VFRlFYfqFHYQRbDpF3owuYbuiL8c7UUrd2k8s3PoSfIQrWfrGXfcElrWLYA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1124,6 +1515,10 @@ packages:
undici-types@8.9.0:
resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==}
+ undici@8.10.2:
+ resolution: {integrity: sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==}
+ engines: {node: '>=22.19.0'}
+
update-browserslist-db@1.3.3:
resolution: {integrity: sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==}
hasBin: true
@@ -1173,6 +1568,10 @@ packages:
yaml:
optional: true
+ web-streams-polyfill@3.3.3:
+ resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
+ engines: {node: '>= 8'}
+
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
@@ -1182,15 +1581,219 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
+ ws@8.22.0:
+ resolution: {integrity: sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ yaml@2.9.0:
+ resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
+
yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
snapshots:
+ '@anthropic-ai/sdk@0.124.0':
+ dependencies:
+ json-schema-to-ts: 3.1.1
+ standardwebhooks: 1.1.1
+
+ '@aws-sdk/client-bedrock-runtime@3.1127.0':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/credential-provider-node': 3.972.84
+ '@aws-sdk/eventstream-handler-node': 3.972.35
+ '@aws-sdk/middleware-eventstream': 3.972.30
+ '@aws-sdk/middleware-websocket': 3.972.54
+ '@aws-sdk/token-providers': 3.1127.0
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/fetch-http-handler': 5.8.0
+ '@smithy/node-http-handler': 4.12.1
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/core@3.978.1':
+ dependencies:
+ '@aws-sdk/types': 3.974.6
+ '@aws-sdk/xml-builder': 3.972.41
+ '@aws/lambda-invoke-store': 0.3.0
+ '@smithy/core': 3.35.0
+ '@smithy/signature-v4': 5.7.4
+ '@smithy/types': 4.19.0
+ bowser: 2.14.1
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-env@3.972.72':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-http@3.972.74':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/fetch-http-handler': 5.8.0
+ '@smithy/node-http-handler': 4.12.1
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-ini@3.973.17':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/credential-provider-env': 3.972.72
+ '@aws-sdk/credential-provider-http': 3.972.74
+ '@aws-sdk/credential-provider-login': 3.972.79
+ '@aws-sdk/credential-provider-process': 3.972.72
+ '@aws-sdk/credential-provider-sso': 3.973.16
+ '@aws-sdk/credential-provider-web-identity': 3.972.78
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/credential-provider-imds': 4.5.2
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-login@3.972.79':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-node@3.972.84':
+ dependencies:
+ '@aws-sdk/credential-provider-env': 3.972.72
+ '@aws-sdk/credential-provider-http': 3.972.74
+ '@aws-sdk/credential-provider-ini': 3.973.17
+ '@aws-sdk/credential-provider-process': 3.972.72
+ '@aws-sdk/credential-provider-sso': 3.973.16
+ '@aws-sdk/credential-provider-web-identity': 3.972.78
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/credential-provider-imds': 4.5.2
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-process@3.972.72':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-sso@3.973.16':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/token-providers': 3.1138.0
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-web-identity@3.972.78':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/eventstream-handler-node@3.972.35':
+ dependencies:
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/middleware-eventstream@3.972.30':
+ dependencies:
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/middleware-websocket@3.972.54':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/fetch-http-handler': 5.8.0
+ '@smithy/signature-v4': 5.7.4
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/nested-clients@3.997.46':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/signature-v4-multi-region': 3.996.47
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/fetch-http-handler': 5.8.0
+ '@smithy/node-http-handler': 4.12.1
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/signature-v4-multi-region@3.996.47':
+ dependencies:
+ '@aws-sdk/types': 3.974.6
+ '@smithy/signature-v4': 5.7.4
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/token-providers@3.1127.0':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/token-providers@3.1138.0':
+ dependencies:
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/types@3.974.6':
+ dependencies:
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws-sdk/xml-builder@3.972.41':
+ dependencies:
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@aws/lambda-invoke-store@0.3.0': {}
+
'@babel/code-frame@7.29.7':
dependencies:
'@babel/helper-validator-identifier': 7.29.7
@@ -1280,6 +1883,8 @@ snapshots:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.29.7
+ '@babel/runtime@7.29.7': {}
+
'@babel/template@7.29.7':
dependencies:
'@babel/code-frame': 7.29.7
@@ -1315,6 +1920,86 @@ snapshots:
hashery: 1.5.1
keyv: 5.6.0
+ '@earendil-works/chord@0.87.1':
+ dependencies:
+ esbuild: 0.28.2
+
+ '@earendil-works/pi-agent-core@0.87.1(ws@8.22.0)':
+ dependencies:
+ '@earendil-works/chord': 0.87.1
+ '@earendil-works/pi-ai': 0.87.1(ws@8.22.0)
+ '@earendil-works/pi-telemetry': 0.87.1
+ diff: 8.0.4
+ ignore: 7.0.8
+ typebox: 1.3.27
+ yaml: 2.9.0
+ transitivePeerDependencies:
+ - '@modelcontextprotocol/sdk'
+ - bufferutil
+ - kerberos
+ - supports-color
+ - utf-8-validate
+ - ws
+ - zod
+
+ '@earendil-works/pi-ai@0.87.1(ws@8.22.0)':
+ dependencies:
+ '@anthropic-ai/sdk': 0.124.0
+ '@aws-sdk/client-bedrock-runtime': 3.1127.0
+ '@earendil-works/pi-telemetry': 0.87.1
+ '@google/genai': 2.21.0
+ '@smithy/node-http-handler': 4.12.1
+ http-proxy-agent: 9.1.0
+ https-proxy-agent: 9.1.0
+ openai: 6.40.0(ws@8.22.0)
+ partial-json: 0.1.7
+ typebox: 1.3.27
+ transitivePeerDependencies:
+ - '@modelcontextprotocol/sdk'
+ - bufferutil
+ - kerberos
+ - supports-color
+ - utf-8-validate
+ - ws
+ - zod
+
+ '@earendil-works/pi-coding-agent@0.87.1(ws@8.22.0)':
+ dependencies:
+ '@earendil-works/chord': 0.87.1
+ '@earendil-works/pi-agent-core': 0.87.1(ws@8.22.0)
+ '@earendil-works/pi-ai': 0.87.1(ws@8.22.0)
+ '@earendil-works/pi-tui': 0.87.1
+ '@silvia-odwyer/photon-node': 0.3.4
+ chalk: 6.0.0
+ cross-spawn: 7.0.6
+ diff: 8.0.4
+ grok-mermaid: 0.2.3
+ highlight.js: 10.7.3
+ hosted-git-info: 9.0.3
+ ignore: 7.0.8
+ jiti: 2.7.0
+ minimatch: 10.2.6
+ proper-lockfile: 4.1.2
+ semver: 7.8.5
+ typebox: 1.3.27
+ undici: 8.10.2
+ yaml: 2.9.0
+ transitivePeerDependencies:
+ - '@modelcontextprotocol/sdk'
+ - bufferutil
+ - kerberos
+ - supports-color
+ - utf-8-validate
+ - ws
+ - zod
+
+ '@earendil-works/pi-telemetry@0.87.1': {}
+
+ '@earendil-works/pi-tui@0.87.1':
+ dependencies:
+ get-east-asian-width: 1.6.0
+ marked: 18.0.11
+
'@esbuild/aix-ppc64@0.28.2':
optional: true
@@ -1393,9 +2078,9 @@ snapshots:
'@esbuild/win32-x64@0.28.2':
optional: true
- '@eslint-community/eslint-utils@4.10.1(eslint@10.11.0)':
+ '@eslint-community/eslint-utils@4.10.1(eslint@10.11.0(jiti@2.7.0))':
dependencies:
- eslint: 10.11.0
+ eslint: 10.11.0(jiti@2.7.0)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.2': {}
@@ -1416,9 +2101,9 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
- '@eslint/js@10.0.1(eslint@10.11.0)':
+ '@eslint/js@10.0.1(eslint@10.11.0(jiti@2.7.0))':
optionalDependencies:
- eslint: 10.11.0
+ eslint: 10.11.0(jiti@2.7.0)
'@eslint/object-schema@3.0.5': {}
@@ -1427,6 +2112,17 @@ snapshots:
'@eslint/core': 1.2.1
levn: 0.4.1
+ '@google/genai@2.21.0':
+ dependencies:
+ google-auth-library: 10.9.1
+ p-retry: 4.6.2
+ protobufjs: 7.6.6
+ ws: 8.22.0
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
'@humanfs/core@0.19.2':
dependencies:
'@humanfs/types': 0.15.0
@@ -1473,6 +2169,26 @@ snapshots:
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
optional: true
+ '@protobufjs/aspromise@1.1.2': {}
+
+ '@protobufjs/base64@1.1.2': {}
+
+ '@protobufjs/codegen@2.0.5': {}
+
+ '@protobufjs/eventemitter@1.1.1': {}
+
+ '@protobufjs/fetch@1.1.1':
+ dependencies:
+ '@protobufjs/aspromise': 1.1.2
+
+ '@protobufjs/float@1.0.2': {}
+
+ '@protobufjs/path@1.1.2': {}
+
+ '@protobufjs/pool@1.1.0': {}
+
+ '@protobufjs/utf8@1.1.2': {}
+
'@rolldown/pluginutils@1.0.0-rc.3': {}
'@rollup/rollup-android-arm-eabi@4.63.4':
@@ -1550,6 +2266,43 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.63.4':
optional: true
+ '@silvia-odwyer/photon-node@0.3.4': {}
+
+ '@smithy/core@3.35.0':
+ dependencies:
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@smithy/credential-provider-imds@4.5.2':
+ dependencies:
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@smithy/fetch-http-handler@5.8.0':
+ dependencies:
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@smithy/node-http-handler@4.12.1':
+ dependencies:
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@smithy/signature-v4@5.7.4':
+ dependencies:
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
+ tslib: 2.8.1
+
+ '@smithy/types@4.19.0':
+ dependencies:
+ tslib: 2.8.1
+
+ '@stablelib/base64@1.0.1': {}
+
'@types/babel__core@7.20.5':
dependencies:
'@babel/parser': 7.29.9
@@ -1589,15 +2342,17 @@ snapshots:
dependencies:
csstype: 3.2.3
- '@typescript-eslint/eslint-plugin@8.70.1(@typescript-eslint/parser@8.70.1(eslint@10.11.0)(typescript@6.0.3))(eslint@10.11.0)(typescript@6.0.3)':
+ '@types/retry@0.12.0': {}
+
+ '@typescript-eslint/eslint-plugin@8.70.1(@typescript-eslint/parser@8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.70.1(eslint@10.11.0)(typescript@6.0.3)
+ '@typescript-eslint/parser': 8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)
'@typescript-eslint/scope-manager': 8.70.1
- '@typescript-eslint/type-utils': 8.70.1(eslint@10.11.0)(typescript@6.0.3)
- '@typescript-eslint/utils': 8.70.1(eslint@10.11.0)(typescript@6.0.3)
+ '@typescript-eslint/type-utils': 8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)
+ '@typescript-eslint/utils': 8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)
'@typescript-eslint/visitor-keys': 8.70.1
- eslint: 10.11.0
+ eslint: 10.11.0(jiti@2.7.0)
ignore: 7.0.10
natural-compare: 1.4.0
ts-api-utils: 2.5.0(typescript@6.0.3)
@@ -1605,14 +2360,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.70.1(eslint@10.11.0)(typescript@6.0.3)':
+ '@typescript-eslint/parser@8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.70.1
'@typescript-eslint/types': 8.70.1
'@typescript-eslint/typescript-estree': 8.70.1(typescript@6.0.3)
'@typescript-eslint/visitor-keys': 8.70.1
debug: 4.4.3
- eslint: 10.11.0
+ eslint: 10.11.0(jiti@2.7.0)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@@ -1635,13 +2390,13 @@ snapshots:
dependencies:
typescript: 6.0.3
- '@typescript-eslint/type-utils@8.70.1(eslint@10.11.0)(typescript@6.0.3)':
+ '@typescript-eslint/type-utils@8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)':
dependencies:
'@typescript-eslint/types': 8.70.1
'@typescript-eslint/typescript-estree': 8.70.1(typescript@6.0.3)
- '@typescript-eslint/utils': 8.70.1(eslint@10.11.0)(typescript@6.0.3)
+ '@typescript-eslint/utils': 8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)
debug: 4.4.3
- eslint: 10.11.0
+ eslint: 10.11.0(jiti@2.7.0)
ts-api-utils: 2.5.0(typescript@6.0.3)
typescript: 6.0.3
transitivePeerDependencies:
@@ -1664,13 +2419,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.70.1(eslint@10.11.0)(typescript@6.0.3)':
+ '@typescript-eslint/utils@8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.10.1(eslint@10.11.0)
+ '@eslint-community/eslint-utils': 4.10.1(eslint@10.11.0(jiti@2.7.0))
'@typescript-eslint/scope-manager': 8.70.1
'@typescript-eslint/types': 8.70.1
'@typescript-eslint/typescript-estree': 8.70.1(typescript@6.0.3)
- eslint: 10.11.0
+ eslint: 10.11.0(jiti@2.7.0)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@@ -1680,7 +2435,7 @@ snapshots:
'@typescript-eslint/types': 8.70.1
eslint-visitor-keys: 5.0.1
- '@vitejs/plugin-react@5.2.0(vite@7.3.6(@types/node@26.6.2)(lightningcss@1.33.0))':
+ '@vitejs/plugin-react@5.2.0(vite@7.3.6(@types/node@26.6.2)(jiti@2.7.0)(lightningcss@1.33.0)(yaml@2.9.0))':
dependencies:
'@babel/core': 7.29.7
'@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7)
@@ -1688,7 +2443,7 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-rc.3
'@types/babel__core': 7.20.5
react-refresh: 0.18.0
- vite: 7.3.6(@types/node@26.6.2)(lightningcss@1.33.0)
+ vite: 7.3.6(@types/node@26.6.2)(jiti@2.7.0)(lightningcss@1.33.0)(yaml@2.9.0)
transitivePeerDependencies:
- supports-color
@@ -1698,6 +2453,10 @@ snapshots:
acorn@8.18.0: {}
+ agent-base@7.1.4: {}
+
+ agent-base@9.0.0: {}
+
ajv@6.15.0:
dependencies:
fast-deep-equal: 3.1.3
@@ -1714,8 +2473,14 @@ snapshots:
balanced-match@4.0.4: {}
+ base64-js@1.5.1: {}
+
baseline-browser-mapping@2.11.25: {}
+ bignumber.js@9.3.1: {}
+
+ bowser@2.14.1: {}
+
brace-expansion@5.0.12:
dependencies:
balanced-match: 4.0.4
@@ -1728,6 +2493,8 @@ snapshots:
node-releases: 2.0.56
update-browserslist-db: 1.3.3(browserslist@4.29.0)
+ buffer-equal-constant-time@1.0.1: {}
+
cacheable@2.5.0:
dependencies:
'@cacheable/memory': 2.2.0
@@ -1738,6 +2505,8 @@ snapshots:
caniuse-lite@1.0.30001810: {}
+ chalk@6.0.0: {}
+
convert-source-map@2.0.0: {}
cross-spawn@7.0.6:
@@ -1748,6 +2517,8 @@ snapshots:
csstype@3.2.3: {}
+ data-uri-to-buffer@4.0.1: {}
+
debug@4.4.3:
dependencies:
ms: 2.1.3
@@ -1757,6 +2528,12 @@ snapshots:
detect-libc@2.1.2:
optional: true
+ diff@8.0.4: {}
+
+ ecdsa-sig-formatter@1.0.11:
+ dependencies:
+ safe-buffer: 5.2.1
+
electron-to-chromium@1.5.437: {}
esbuild@0.28.2:
@@ -1803,9 +2580,9 @@ snapshots:
eslint-visitor-keys@5.0.1: {}
- eslint@10.11.0:
+ eslint@10.11.0(jiti@2.7.0):
dependencies:
- '@eslint-community/eslint-utils': 4.10.1(eslint@10.11.0)
+ '@eslint-community/eslint-utils': 4.10.1(eslint@10.11.0(jiti@2.7.0))
'@eslint-community/regexpp': 4.12.2
'@eslint/config-array': 0.23.5
'@eslint/config-helpers': 0.7.0
@@ -1835,6 +2612,8 @@ snapshots:
minimatch: 10.2.6
natural-compare: 1.4.0
optionator: 0.9.4
+ optionalDependencies:
+ jiti: 2.7.0
transitivePeerDependencies:
- supports-color
@@ -1856,18 +2635,27 @@ snapshots:
esutils@2.0.3: {}
+ extend@3.0.2: {}
+
fast-deep-equal@3.1.3: {}
fast-json-stable-stringify@2.1.0: {}
fast-levenshtein@2.0.6: {}
+ fast-sha256@1.3.0: {}
+
fast-uri@3.1.8: {}
fdir@6.5.0(picomatch@4.0.7):
optionalDependencies:
picomatch: 4.0.7
+ fetch-blob@3.2.0:
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 3.3.3
+
file-entry-cache@11.1.5:
dependencies:
flat-cache: 6.1.23
@@ -1885,27 +2673,99 @@ snapshots:
flatted@3.4.4: {}
+ formdata-polyfill@4.0.10:
+ dependencies:
+ fetch-blob: 3.2.0
+
fsevents@2.3.3:
optional: true
+ gaxios@7.3.1:
+ dependencies:
+ extend: 3.0.2
+ https-proxy-agent: 7.0.6
+ node-fetch: 3.3.2
+ transitivePeerDependencies:
+ - supports-color
+
+ gcp-metadata@8.1.2:
+ dependencies:
+ gaxios: 7.3.1
+ google-logging-utils: 1.1.3
+ json-bigint: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+
gensync@1.0.0-beta.2: {}
+ get-east-asian-width@1.6.0: {}
+
glob-parent@6.0.2:
dependencies:
is-glob: 4.0.3
+ google-auth-library@10.9.1:
+ dependencies:
+ base64-js: 1.5.1
+ ecdsa-sig-formatter: 1.0.11
+ gaxios: 7.3.1
+ gcp-metadata: 8.1.2
+ google-logging-utils: 1.1.3
+ jws: 4.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ google-logging-utils@1.1.3: {}
+
+ graceful-fs@4.2.11: {}
+
+ grok-mermaid@0.2.3: {}
+
hashery@1.5.1:
dependencies:
hookified: 1.15.1
+ highlight.js@10.7.3: {}
+
hookified@1.15.1: {}
hookified@2.2.0: {}
+ hosted-git-info@9.0.3:
+ dependencies:
+ lru-cache: 11.5.3
+
+ http-proxy-agent@9.1.0:
+ dependencies:
+ agent-base: 9.0.0
+ debug: 4.4.3
+ proxy-agent-negotiate: 1.1.0
+ transitivePeerDependencies:
+ - kerberos
+ - supports-color
+
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ https-proxy-agent@9.1.0:
+ dependencies:
+ agent-base: 9.0.0
+ debug: 4.4.3
+ proxy-agent-negotiate: 1.1.0
+ transitivePeerDependencies:
+ - kerberos
+ - supports-color
+
ignore@5.3.2: {}
ignore@7.0.10: {}
+ ignore@7.0.8: {}
+
imurmurhash@0.1.4: {}
is-extglob@2.1.1: {}
@@ -1916,10 +2776,21 @@ snapshots:
isexe@2.0.0: {}
+ jiti@2.7.0: {}
+
js-tokens@4.0.0: {}
jsesc@3.1.0: {}
+ json-bigint@1.0.0:
+ dependencies:
+ bignumber.js: 9.3.1
+
+ json-schema-to-ts@3.1.1:
+ dependencies:
+ '@babel/runtime': 7.29.7
+ ts-algebra: 2.0.0
+
json-schema-traverse@0.4.1: {}
json-schema-traverse@1.0.0: {}
@@ -1928,6 +2799,17 @@ snapshots:
json5@2.2.3: {}
+ jwa@2.0.1:
+ dependencies:
+ buffer-equal-constant-time: 1.0.1
+ ecdsa-sig-formatter: 1.0.11
+ safe-buffer: 5.2.1
+
+ jws@4.0.1:
+ dependencies:
+ jwa: 2.0.1
+ safe-buffer: 5.2.1
+
keyv@5.6.0:
dependencies:
'@keyv/serialize': 1.1.1
@@ -1991,10 +2873,16 @@ snapshots:
dependencies:
p-locate: 5.0.0
+ long@5.3.2: {}
+
+ lru-cache@11.5.3: {}
+
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
+ marked@18.0.11: {}
+
minimatch@10.2.6:
dependencies:
brace-expansion: 5.0.12
@@ -2005,8 +2893,20 @@ snapshots:
natural-compare@1.4.0: {}
+ node-domexception@1.0.0: {}
+
+ node-fetch@3.3.2:
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+
node-releases@2.0.56: {}
+ openai@6.40.0(ws@8.22.0):
+ optionalDependencies:
+ ws: 8.22.0
+
optionator@0.9.4:
dependencies:
deep-is: 0.1.4
@@ -2024,6 +2924,13 @@ snapshots:
dependencies:
p-limit: 3.1.0
+ p-retry@4.6.2:
+ dependencies:
+ '@types/retry': 0.12.0
+ retry: 0.13.1
+
+ partial-json@0.1.7: {}
+
path-exists@4.0.0: {}
path-key@3.1.1: {}
@@ -2042,6 +2949,28 @@ snapshots:
prettier@3.9.9: {}
+ proper-lockfile@4.1.2:
+ dependencies:
+ graceful-fs: 4.2.11
+ retry: 0.12.0
+ signal-exit: 3.0.7
+
+ protobufjs@7.6.6:
+ dependencies:
+ '@protobufjs/aspromise': 1.1.2
+ '@protobufjs/base64': 1.1.2
+ '@protobufjs/codegen': 2.0.5
+ '@protobufjs/eventemitter': 1.1.1
+ '@protobufjs/fetch': 1.1.1
+ '@protobufjs/float': 1.0.2
+ '@protobufjs/path': 1.1.2
+ '@protobufjs/pool': 1.1.0
+ '@protobufjs/utf8': 1.1.2
+ '@types/node': 26.6.2
+ long: 5.3.2
+
+ proxy-agent-negotiate@1.1.0: {}
+
punycode@2.3.1: {}
qified@0.10.1:
@@ -2059,6 +2988,10 @@ snapshots:
require-from-string@2.0.2: {}
+ retry@0.12.0: {}
+
+ retry@0.13.1: {}
+
rollup@4.63.4:
dependencies:
'@types/estree': 1.0.9
@@ -2091,6 +3024,8 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.63.4
fsevents: 2.3.3
+ safe-buffer@5.2.1: {}
+
scheduler@0.28.0: {}
semver@6.3.1: {}
@@ -2103,28 +3038,41 @@ snapshots:
shebang-regex@3.0.0: {}
+ signal-exit@3.0.7: {}
+
source-map-js@1.2.1: {}
+ standardwebhooks@1.1.1:
+ dependencies:
+ '@stablelib/base64': 1.0.1
+ fast-sha256: 1.3.0
+
tinyglobby@0.2.17:
dependencies:
fdir: 6.5.0(picomatch@4.0.7)
picomatch: 4.0.7
+ ts-algebra@2.0.0: {}
+
ts-api-utils@2.5.0(typescript@6.0.3):
dependencies:
typescript: 6.0.3
+ tslib@2.8.1: {}
+
type-check@0.4.0:
dependencies:
prelude-ls: 1.2.1
- typescript-eslint@8.70.1(eslint@10.11.0)(typescript@6.0.3):
+ typebox@1.3.27: {}
+
+ typescript-eslint@8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.70.1(@typescript-eslint/parser@8.70.1(eslint@10.11.0)(typescript@6.0.3))(eslint@10.11.0)(typescript@6.0.3)
- '@typescript-eslint/parser': 8.70.1(eslint@10.11.0)(typescript@6.0.3)
+ '@typescript-eslint/eslint-plugin': 8.70.1(@typescript-eslint/parser@8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)
+ '@typescript-eslint/parser': 8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)
'@typescript-eslint/typescript-estree': 8.70.1(typescript@6.0.3)
- '@typescript-eslint/utils': 8.70.1(eslint@10.11.0)(typescript@6.0.3)
- eslint: 10.11.0
+ '@typescript-eslint/utils': 8.70.1(eslint@10.11.0(jiti@2.7.0))(typescript@6.0.3)
+ eslint: 10.11.0(jiti@2.7.0)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@@ -2133,6 +3081,8 @@ snapshots:
undici-types@8.9.0: {}
+ undici@8.10.2: {}
+
update-browserslist-db@1.3.3(browserslist@4.29.0):
dependencies:
browserslist: 4.29.0
@@ -2143,7 +3093,7 @@ snapshots:
dependencies:
punycode: 2.3.1
- vite@7.3.6(@types/node@26.6.2)(lightningcss@1.33.0):
+ vite@7.3.6(@types/node@26.6.2)(jiti@2.7.0)(lightningcss@1.33.0)(yaml@2.9.0):
dependencies:
esbuild: 0.28.2
fdir: 6.5.0(picomatch@4.0.7)
@@ -2154,7 +3104,11 @@ snapshots:
optionalDependencies:
'@types/node': 26.6.2
fsevents: 2.3.3
+ jiti: 2.7.0
lightningcss: 1.33.0
+ yaml: 2.9.0
+
+ web-streams-polyfill@3.3.3: {}
which@2.0.2:
dependencies:
@@ -2162,6 +3116,10 @@ snapshots:
word-wrap@1.2.5: {}
+ ws@8.22.0: {}
+
yallist@3.1.1: {}
+ yaml@2.9.0: {}
+
yocto-queue@0.1.0: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 4e2e70b..c2f8ba5 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -9,4 +9,7 @@ packages:
# pnpm 11:允许执行安装脚本的依赖。esbuild 是 vite 的构建依赖,需要 postinstall。
allowBuilds:
- esbuild: true
\ No newline at end of file
+ # Pi 依赖链带 postinstall;装它们是 Pi 官方推荐的接入方式(ADR-0006)
+ '@google/genai': true
+ esbuild: true
+ protobufjs: true
diff --git a/scripts/config.test.mjs b/scripts/config.test.mjs
index 5a1237d..24dc916 100644
--- a/scripts/config.test.mjs
+++ b/scripts/config.test.mjs
@@ -81,4 +81,20 @@ test('配置文件损坏时报错,不静默降级', async () => {
test('配置文件路径:默认在用户目录,可用 APS_CONFIG_FILE 覆盖', () => {
assert.equal(configFilePath({ env: {}, homeDir: 'C:/Users/test' }).replace(/\\/g, '/'), 'C:/Users/test/.aps/config.json');
assert.equal(configFilePath({ env: { APS_CONFIG_FILE: 'D:/cfg/aps.json' }, homeDir: 'C:/Users/test' }), 'D:/cfg/aps.json');
+});
+
+test('引擎选择:没密钥用假引擎,有密钥自动选 Pi,可显式覆盖', async () => {
+ await withConfigFile(undefined, async ({ dir, file }) => {
+ const noKey = loadConfig({ env: { APS_CONFIG_FILE: file }, homeDir: dir });
+ assert.equal(noKey.engine.kind, 'fake', '没有密钥时应回退到假引擎');
+ });
+
+ const content = JSON.stringify({ llm: { apiKey: 'sk-file-123' } });
+ await withConfigFile(content, async ({ dir, file }) => {
+ const withKey = loadConfig({ env: { APS_CONFIG_FILE: file }, homeDir: dir });
+ assert.equal(withKey.engine.kind, 'pi', '有密钥时应自动选 Pi');
+
+ const forced = loadConfig({ env: { APS_CONFIG_FILE: file, APS_ENGINE: 'fake' }, homeDir: dir });
+ assert.equal(forced.engine.kind, 'fake', '显式配置应覆盖自动选择');
+ });
});
\ No newline at end of file
diff --git a/scripts/pi-probe.mjs b/scripts/pi-probe.mjs
new file mode 100644
index 0000000..c706bb3
--- /dev/null
+++ b/scripts/pi-probe.mjs
@@ -0,0 +1,29 @@
+#!/usr/bin/env node
+/**
+ * Pi 子进程接线探测(开发用)。
+ *
+ * 拉起 Pi、发一句话、把映射后的事件打出来。没有配置密钥时也能跑:
+ * 它会走到"模型不可用",正好用来验证进程、协议与错误映射这三段接线。
+ *
+ * 用法:node scripts/pi-probe.mjs [提问]
+ */
+import { createPiRuntime } from '@aps/server/agent/pi/runtime';
+
+const prompt = process.argv[2] ?? '用一句话回答:1+1 等于几';
+const runtime = createPiRuntime({ provider: process.env.APS_LLM_PROVIDER ?? 'deepseek', model: process.env.APS_LLM_MODEL ?? 'deepseek-chat', apiKey: process.env.APS_LLM_API_KEY ?? '', turnTimeoutMs: 30_000 });
+
+console.log(`引擎:${runtime.name}`);
+const session = await runtime.createSession({ sessionId: 'probe-1', subject: { userId: 'probe', tenantId: 'probe' }, projectId: null, tools: [] });
+console.log(`会话已创建:${session.id}`);
+
+const controller = new AbortController();
+const started = Date.now();
+try {
+ for await (const event of session.send(prompt, { signal: controller.signal })) {
+ console.log(`[${String(Date.now() - started).padStart(5)}ms] ${event.type}`, JSON.stringify(event).slice(0, 260));
+ if (event.type === 'turn_end') break;
+ }
+} finally {
+ await session.dispose();
+ console.log('子进程已停止');
+}
\ No newline at end of file
diff --git a/scripts/pi-runtime.test.mjs b/scripts/pi-runtime.test.mjs
new file mode 100644
index 0000000..9ccb8b7
--- /dev/null
+++ b/scripts/pi-runtime.test.mjs
@@ -0,0 +1,72 @@
+/**
+ * Pi 运行时用例(任务 A3.3)。
+ *
+ * 1. 未配置密钥时必须快速失败并给出指引(不是静默挂住)
+ * 2. 真实跑一轮:需要 APS_PI_INTEGRATION=1 且提供密钥(网络调用,默认跳过)
+ * —— 密钥有效时断言收到文本;无效时断言错误被归到六分类之一;两者都必须以 turn_end 收尾
+ */
+import assert from 'node:assert/strict';
+import { test } from 'node:test';
+
+import { classifyPiFailure } from '@aps/server/agent/pi/runtime';
+
+const integrationEnabled = process.env.APS_PI_INTEGRATION === '1';
+const apiKey = process.env.APS_LLM_API_KEY ?? process.env.DEEPSEEK_API_KEY ?? '';
+
+test('未配置模型密钥时快速失败并给出配置指引', async () => {
+ // 环境变量也算配置来源,这里临时清掉,确保「真的没有密钥」
+ const saved = process.env.DEEPSEEK_API_KEY;
+ delete process.env.DEEPSEEK_API_KEY;
+ try {
+ const { createPiRuntime } = await import('@aps/server/agent/pi/runtime');
+ const runtime = createPiRuntime({ provider: 'deepseek', model: 'deepseek-chat', apiKey: '' });
+ await assert.rejects(
+ () => runtime.createSession({ sessionId: 'no-key', subject: { userId: 'u', tenantId: 't' }, projectId: null, tools: [] }),
+ /未配置模型密钥/,
+ );
+ } finally {
+ if (saved !== undefined) process.env.DEEPSEEK_API_KEY = saved;
+ }
+});
+
+test('错误文本按六分类归一', () => {
+ assert.equal(classifyPiFailure('401: Authentication Fails'), 'forbidden');
+ assert.equal(classifyPiFailure('429 rate limit exceeded'), 'rate_limited');
+ assert.equal(classifyPiFailure('connect ETIMEDOUT'), 'unavailable');
+ assert.equal(classifyPiFailure('something odd'), 'unavailable');
+});
+
+test('真实跑一轮:Pi 子进程接入', { skip: !integrationEnabled ? '需要 APS_PI_INTEGRATION=1 与密钥(会真实调用模型)' : false }, async () => {
+ const { createPiRuntime } = await import('@aps/server/agent/pi/runtime');
+ const runtime = createPiRuntime({ provider: 'deepseek', model: 'deepseek-chat', apiKey, turnTimeoutMs: 60_000 });
+ const session = await runtime.createSession({
+ sessionId: `it-${Date.now()}`,
+ subject: { userId: 'it', tenantId: 'it' },
+ projectId: null,
+ tools: [],
+ });
+
+ const events = [];
+ try {
+ for await (const event of session.send('只用一句话回答:1+1 等于几')) {
+ events.push(event);
+ if (event.type === 'turn_end') break;
+ }
+ } finally {
+ await session.dispose();
+ }
+
+ const types = events.map((event) => event.type);
+ assert.ok(types.includes('turn_end'), `必须以 turn_end 收尾,实际:${types.join(',')}`);
+ const failed = events.find((event) => event.type === 'error');
+ const text = events.filter((event) => event.type === 'text').map((event) => event.delta).join('');
+ if (failed) {
+ assert.ok(
+ ['invalid_argument', 'forbidden', 'conflict', 'rate_limited', 'unavailable', 'unknown_result'].includes(failed.kind),
+ `错误分类必须合法,实际 ${failed.kind}`,
+ );
+ console.log(`(本轮模型调用失败,已按 ${failed.kind} 归一)`);
+ } else {
+ assert.ok(text.length > 0 || types.includes('message_end'), `既没有文本也没有错误,事件:${types.join(',')}`);
+ }
+});
\ No newline at end of file
diff --git a/server/agent/pi/runtime.ts b/server/agent/pi/runtime.ts
new file mode 100644
index 0000000..0fa8a26
--- /dev/null
+++ b/server/agent/pi/runtime.ts
@@ -0,0 +1,228 @@
+/**
+ * Pi 引擎适配(任务 A3.3,ADR-0006):把 Pi 作为长驻子进程驱动。
+ *
+ * - 用官方 RpcClient 拉起 `pi --mode rpc`,协议是标准输入输出的 JSONL
+ * - 工具面:启动参数带 --no-builtin-tools / --no-extensions,Pi 自带的 read/bash/edit/write 全部关掉;
+ * 平台的工具由 Pi 侧扩展桥提供(A3.11),扩展还没接之前 Pi 手里没有工具(评测里对应场景跳过)
+ * - 事件面:把 Pi 的会话事件映射成平台的 RuntimeEvent,上层只认平台类型
+ * - 状态:平台保存会话历史;Pi 自己的 session 文件放在平台管理目录里,只作同引擎恢复用(ADR-0003)
+ */
+import { existsSync } from 'node:fs';
+import { homedir } from 'node:os';
+import { dirname, join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+import { RpcClient, type JsonAgentSessionEvent } from '@earendil-works/pi-coding-agent';
+import type { ExecutionReceipt } from '@aps/contracts';
+
+import type { AgentRuntime, CreateRuntimeSessionInput, RuntimeEvent, RuntimeSession, SendOptions } from '../runtime.js';
+
+export interface PiRuntimeOptions {
+ provider?: string;
+ model?: string;
+ apiKey?: string;
+ cwd?: string;
+ cliPath?: string;
+ /** Pi 自己的会话文件目录(默认 ~/.aps/pi-sessions) */
+ sessionDir?: string;
+ /** 额外的 CLI 参数,慎用:会覆盖不了默认的关闭项,只是追加 */
+ extraArgs?: string[];
+ /** 单回合最长等待(毫秒),超时按引擎错误处理 */
+ turnTimeoutMs?: number;
+}
+
+/** provider → 环境变量名:密钥走环境,不进命令行(命令行会被进程列表看到) */
+const API_KEY_ENV: Record = {
+ deepseek: 'DEEPSEEK_API_KEY',
+ openai: 'OPENAI_API_KEY',
+ anthropic: 'ANTHROPIC_API_KEY',
+ google: 'GEMINI_API_KEY',
+};
+
+const DEFAULT_TURN_TIMEOUT_MS = 120_000;
+const POLL_MS = 25;
+
+/**
+ * RpcClient 默认找的是包里的 dist/cli.js,实际可执行入口在 dist/bundle/cli.js,必须显式给。
+ *
+ * 三种取法依次尝试:ESM 解析(这个包的 exports 只声明了 import 条件,CJS 的 require.resolve 会失败)、
+ * 仓库根下的包目录、server 包下的包目录。
+ */
+function defaultCliPath(): string {
+ const candidates: string[] = [];
+ try {
+ const resolver = (import.meta as unknown as { resolve?: (specifier: string) => string }).resolve;
+ const resolved = resolver?.('@earendil-works/pi-coding-agent');
+ if (resolved) candidates.push(join(dirname(fileURLToPath(resolved)), 'bundle', 'cli.js'));
+ } catch {
+ /* 落到下面的候选路径 */
+ }
+ for (const root of [process.cwd(), join(process.cwd(), 'server')]) {
+ candidates.push(join(root, 'node_modules', '@earendil-works', 'pi-coding-agent', 'dist', 'bundle', 'cli.js'));
+ }
+ return candidates.find((candidate) => existsSync(candidate)) ?? '';
+}
+
+/** 把 Pi 的失败文本归到平台的六分类(实施设计 5) */
+export function classifyPiFailure(detail: string): 'forbidden' | 'rate_limited' | 'unavailable' | 'unknown_result' {
+ if (/401|403|auth|api key|unauthor/i.test(detail)) return 'forbidden';
+ if (/429|rate.?limit|too many/i.test(detail)) return 'rate_limited';
+ if (/timeout|ETIMEDOUT|ECONNRESET|ENOTFOUND|socket hang up/i.test(detail)) return 'unavailable';
+ return 'unavailable';
+}
+
+/** Pi 的事件联合很宽,这里只映射平台需要的部分,其余忽略 */
+export function mapPiEvent(event: JsonAgentSessionEvent): RuntimeEvent[] {
+ const raw = event as unknown as Record;
+ const type = String(raw.type ?? '');
+
+ switch (type) {
+ case 'message_update': {
+ const inner = raw.assistantMessageEvent as Record | undefined;
+ if (inner && inner.type === 'text_delta' && typeof inner.delta === 'string') {
+ return [{ type: 'text', delta: inner.delta }];
+ }
+ return [];
+ }
+ case 'tool_execution_start':
+ return [
+ {
+ type: 'tool_call',
+ callId: String(raw.toolCallId ?? ''),
+ capabilityId: String(raw.toolName ?? ''),
+ args: raw.args,
+ },
+ ];
+ case 'tool_execution_end': {
+ const callId = String(raw.toolCallId ?? '');
+ const receipt: ExecutionReceipt = {
+ executionId: callId,
+ status: raw.isError === true ? 'failed' : 'succeeded',
+ result: raw.result,
+ ...(raw.isError === true ? { errorKind: 'unknown_result' as const } : {}),
+ };
+ return [{ type: 'tool_result', callId, receipt }];
+ }
+ case 'message_end': {
+ // 模型调用失败不是独立事件:助手消息带 stopReason=error 与 errorMessage(实测形状)
+ const message = raw.message as { role?: string; stopReason?: string; errorMessage?: string } | undefined;
+ if (!message || message.role !== 'assistant') return [];
+ if (message.stopReason !== 'error' && message.errorMessage === undefined) return [];
+ const detail = typeof message.errorMessage === 'string' ? message.errorMessage : '';
+ return [{ type: 'error', kind: classifyPiFailure(detail), message: detail || '模型调用失败(未提供详情)' }];
+ }
+ case 'agent_settled':
+ // Pi 明确表示不会再自动继续(重试、压缩、排队都结束了)
+ return [{ type: 'turn_end', reason: 'stop' }];
+ case 'error': {
+ const reason = raw.reason ?? raw.error;
+ const detail = typeof reason === 'string' ? reason : 'Pi 报错(未提供详情)';
+ return [{ type: 'error', kind: classifyPiFailure(detail), message: detail }];
+ }
+ default:
+ return [];
+ }
+}
+
+export function createPiRuntime(options: PiRuntimeOptions = {}): AgentRuntime {
+ const provider = options.provider ?? 'deepseek';
+ const model = options.model ?? 'deepseek-chat';
+ const sessionDir = options.sessionDir ?? join(homedir(), '.aps', 'pi-sessions');
+ const turnTimeoutMs = options.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;
+
+ return {
+ name: `pi:${provider}/${model}`,
+ async createSession(input: CreateRuntimeSessionInput): Promise {
+ const env: Record = {};
+ for (const [key, value] of Object.entries(process.env)) {
+ if (value !== undefined) env[key] = value;
+ }
+ if (options.apiKey !== undefined && options.apiKey !== '') {
+ env[API_KEY_ENV[provider] ?? 'DEEPSEEK_API_KEY'] = options.apiKey;
+ }
+
+ const cliPath = options.cliPath ?? defaultCliPath();
+ const client = new RpcClient({
+ ...(cliPath === '' ? {} : { cliPath }),
+ ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
+ provider,
+ model,
+ env,
+ args: [
+ // 工具只来自能力目录:关掉内置工具与自动发现的扩展/技能(A3.11 再接扩展桥)
+ '--no-builtin-tools',
+ '--no-extensions',
+ '--no-skills',
+ '--no-prompt-templates',
+ '--no-context-files',
+ '--session-dir',
+ sessionDir,
+ '--session-id',
+ input.sessionId,
+ ...(input.system === undefined ? [] : ['--system-prompt', input.system]),
+ ...(options.extraArgs ?? []),
+ ],
+ });
+
+ if ((options.apiKey ?? '') === '' && (env[API_KEY_ENV[provider] ?? 'DEEPSEEK_API_KEY'] ?? '') === '') {
+ throw new Error(`Pi 引擎未配置模型密钥:请在 ~/.aps/config.json 的 llm.apiKey 里填写,或设置 ${API_KEY_ENV[provider] ?? 'DEEPSEEK_API_KEY'}(ADR-0011)`);
+ }
+
+ await client.start();
+
+ return {
+ id: `pi-${input.sessionId}`,
+ async *send(text: string, sendOptions?: SendOptions): AsyncIterable {
+ const queue: RuntimeEvent[] = [];
+ let wake: (() => void) | undefined;
+ let aborted = false;
+
+ const unsubscribe = client.onEvent((event) => {
+ queue.push(...mapPiEvent(event));
+ wake?.();
+ wake = undefined;
+ });
+
+ try {
+ await client.prompt(text);
+ const deadline = Date.now() + turnTimeoutMs;
+ while (Date.now() < deadline) {
+ if (sendOptions?.signal?.aborted === true && !aborted) {
+ aborted = true;
+ await client.abort();
+ }
+ while (queue.length > 0) {
+ const next = queue.shift() as RuntimeEvent;
+ if (next.type === 'turn_end') {
+ yield { type: 'turn_end', reason: aborted ? 'cancelled' : next.reason };
+ return;
+ }
+ yield next;
+ }
+ await new Promise((resolve) => {
+ wake = resolve;
+ setTimeout(resolve, POLL_MS);
+ });
+ }
+ yield { type: 'error', kind: 'unknown_result', message: `Pi 回合超过 ${turnTimeoutMs}ms 未结束` };
+ yield { type: 'turn_end', reason: 'error' };
+ } catch (error) {
+ yield { type: 'error', kind: 'unknown_result', message: error instanceof Error ? error.message : 'Pi 子进程异常' };
+ yield { type: 'turn_end', reason: 'error' };
+ } finally {
+ unsubscribe();
+ }
+ },
+ resolveToolResult(_callId: string, _receipt: ExecutionReceipt): void {
+ // 工具由 Pi 侧扩展执行(A3.11):回执要经扩展桥送回去,这里暂时无处可送
+ },
+ abort(): void {
+ void client.abort();
+ },
+ async dispose(): Promise {
+ await client.stop();
+ },
+ };
+ },
+ };
+}
\ No newline at end of file
diff --git a/server/app/turn-runner.ts b/server/app/turn-runner.ts
index 96d0d31..3365d7e 100644
--- a/server/app/turn-runner.ts
+++ b/server/app/turn-runner.ts
@@ -40,7 +40,8 @@ export async function runTurn(input: TurnRunnerInput): Promise {
const { runtimeSession, sessionId, runId, assistantMessageId, publish, invoke, signal } = input;
let emitted = '';
let toolCalls = 0;
- let finishReason: TurnResult['finishReason'] = 'stop';
+ let sawError = false;
+ let lastTurnEndReason: TurnResult['finishReason'] = 'stop';
publish({ sessionId, runId, type: 'run.state', data: { state: 'running' } });
@@ -94,11 +95,11 @@ export async function runTurn(input: TurnRunnerInput): Promise {
type: 'error',
data: { code: `engine.${event.kind}`, message: event.message, retryable: event.kind !== 'forbidden', errorKind: event.kind },
});
- finishReason = 'error';
+ sawError = true;
break;
}
case 'turn_end': {
- finishReason = event.reason;
+ lastTurnEndReason = event.reason;
break;
}
default:
@@ -106,7 +107,7 @@ export async function runTurn(input: TurnRunnerInput): Promise {
}
}
} catch (error) {
- finishReason = 'error';
+ sawError = true;
publish({
sessionId,
runId,
@@ -115,7 +116,8 @@ export async function runTurn(input: TurnRunnerInput): Promise {
});
}
- if (signal.aborted && finishReason === 'stop') finishReason = 'cancelled';
+ // 结束原因取「最严重的那个」:取消 > 错误 > 正常结束,避免被 turn_end 覆盖回 stop
+ const finishReason: TurnResult['finishReason'] = signal.aborted ? 'cancelled' : sawError ? 'error' : lastTurnEndReason;
publish({
sessionId,
runId,
diff --git a/server/config.ts b/server/config.ts
index ba48c54..63eaaa2 100644
--- a/server/config.ts
+++ b/server/config.ts
@@ -19,8 +19,14 @@ export interface LlmConfig {
apiKey: string;
}
+export interface EngineConfig {
+ /** fake = 假引擎(默认);pi = Pi 子进程(A3.3) */
+ kind: 'fake' | 'pi';
+}
+
export interface PlatformConfig {
llm: LlmConfig;
+ engine: EngineConfig;
database: { path: string };
server: { host: string; port: number };
/** 客户端构建产物目录,可覆盖(默认仓库内 client/app/dist) */
@@ -47,6 +53,7 @@ export function configFilePath(input: LoadConfigInput = {}): string {
interface FileConfig {
llm?: Partial;
+ engine?: Partial;
database?: { path?: string };
server?: { host?: string; port?: number };
clientDist?: string;
@@ -76,8 +83,15 @@ export function loadConfig(input: LoadConfigInput = {}): PlatformConfig {
const port = Number.parseInt(env.APS_PORT ?? '', 10);
+ // 引擎选择:显式配置优先;没配就按「有没有密钥」自动决定——没密钥只能用假引擎(ADR-0011)
+ const requestedEngine = (env.APS_ENGINE ?? file.engine?.kind ?? '').toLowerCase();
+ const engine: EngineConfig = {
+ kind: requestedEngine === 'pi' || requestedEngine === 'fake' ? (requestedEngine as EngineConfig['kind']) : apiKey.trim() !== '' ? 'pi' : 'fake',
+ };
+
return {
llm: { provider, baseUrl, model, apiKey },
+ engine,
database: { path: dbPath },
server: {
host: env.APS_HOST ?? file.server?.host ?? '127.0.0.1',
@@ -96,6 +110,7 @@ export function isEngineConfigured(config: PlatformConfig): boolean {
export function redactConfig(config: PlatformConfig): Record {
return {
llm: {
+ engine: { kind: config.engine.kind },
provider: config.llm.provider,
baseUrl: config.llm.baseUrl,
model: config.llm.model,
diff --git a/server/index.ts b/server/index.ts
index 0c9bbde..eb309b7 100644
--- a/server/index.ts
+++ b/server/index.ts
@@ -41,10 +41,11 @@ export async function startServer(options: StartOptions = {}): Promise 配置里的 engine.kind;选 pi 但没密钥时明确回退到假引擎 */
+async function selectRuntime(config: ReturnType): Promise {
+ if (config.engine.kind !== 'pi') {
+ const { createFakeRuntime } = await import('./agent/fake-runtime.js');
+ const { createRulePlanner, plannerToFakeTurn } = await import('./agent/rule-planner.js');
+ return createFakeRuntime({ name: 'fake', planner: plannerToFakeTurn(createRulePlanner()) });
+ }
+ if (config.llm.apiKey.trim() === '') {
+ console.error('警告:配置要求 Pi 引擎但没有模型密钥,已回退到假引擎(ADR-0011 允许未配置时降级)');
+ const { createFakeRuntime } = await import('./agent/fake-runtime.js');
+ const { createRulePlanner, plannerToFakeTurn } = await import('./agent/rule-planner.js');
+ return createFakeRuntime({ name: 'fake', planner: plannerToFakeTurn(createRulePlanner()) });
+ }
+ const { createPiRuntime } = await import('./agent/pi/runtime.js');
+ return createPiRuntime({ provider: config.llm.provider, model: config.llm.model, apiKey: config.llm.apiKey });
}
\ No newline at end of file
diff --git a/server/package.json b/server/package.json
index a6eb325..b156414 100644
--- a/server/package.json
+++ b/server/package.json
@@ -22,6 +22,10 @@
"types": "./dist/agent/fake-runtime.d.ts",
"default": "./dist/agent/fake-runtime.js"
},
+ "./agent/pi/runtime": {
+ "types": "./dist/agent/pi/runtime.d.ts",
+ "default": "./dist/agent/pi/runtime.js"
+ },
"./agent/conformance": {
"types": "./dist/agent/conformance.d.ts",
"default": "./dist/agent/conformance.js"
@@ -40,6 +44,8 @@
},
"dependencies": {
"@aps/contracts": "workspace:*",
- "@aps/provider-sdk": "workspace:*"
+ "@aps/provider-sdk": "workspace:*",
+ "@earendil-works/pi-agent-core": "0.87.1",
+ "@earendil-works/pi-coding-agent": "0.87.1"
}
}
\ No newline at end of file