mirror of
https://github.com/cline/cline.git
synced 2026-09-02 15:52:29 +08:00
Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f2be67c79 | |||
| 8a6441fddd | |||
| 7ef5b1e7af | |||
| 3e58e7b024 | |||
| d16667f0b8 | |||
| a740c49524 | |||
| 3bc1ee8382 | |||
| ecf354c753 | |||
| a66c5ee973 | |||
| 46659eebeb | |||
| 899ee0bfea | |||
| db4598e310 | |||
| 627e539266 | |||
| 87ff61915f | |||
| a305556452 | |||
| ca12e97288 | |||
| 0c89716849 | |||
| 1c401dbe1a | |||
| ed78404e4b | |||
| 0157ed9efb | |||
| 5574c95ff2 | |||
| 31ee8eb744 | |||
| 7952e230ae | |||
| 6bcfa34ba9 | |||
| cf18793434 | |||
| a7ba25d6e1 | |||
| 2af2028861 | |||
| 932c8e68e1 | |||
| 3cd13352eb | |||
| 2c842328a8 | |||
| d3b3ff1c33 | |||
| 2508e76af8 | |||
| a702bf9b38 | |||
| a8cea1dca3 | |||
| 2a351ffdd5 | |||
| 69f148bad9 | |||
| 6ca92794e1 | |||
| 27bd4c6c65 | |||
| 015b61924f | |||
| d238239a0f | |||
| e81c35d7c0 | |||
| 1ac5525fee | |||
| a4d0937030 | |||
| 6d5c61f044 | |||
| 8a6d031e8f | |||
| 3f808b369e | |||
| e3b3e2306e | |||
| b601b6e623 | |||
| ed008bd36e |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix: use correct base URL for Vertex AI global endpoint with Claude models
|
||||
@@ -132,6 +132,15 @@ jobs:
|
||||
|
||||
- name: Build SDK packages
|
||||
run: bun run build:sdk
|
||||
env:
|
||||
TELEMETRY_SERVICE_API_KEY: ${{ secrets.TELEMETRY_SERVICE_API_KEY }}
|
||||
ERROR_SERVICE_API_KEY: ${{ secrets.ERROR_SERVICE_API_KEY }}
|
||||
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
|
||||
OTEL_LOGS_EXPORTER: otlp
|
||||
OTEL_METRICS_EXPORTER: otlp
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
|
||||
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
|
||||
|
||||
- name: Run tests
|
||||
run: bun run test
|
||||
@@ -139,6 +148,15 @@ jobs:
|
||||
- name: Build platform binaries
|
||||
run: bun script/build.ts --install-native-variants --skip-sdk-build
|
||||
working-directory: sdk/apps/cli
|
||||
env:
|
||||
TELEMETRY_SERVICE_API_KEY: ${{ secrets.TELEMETRY_SERVICE_API_KEY }}
|
||||
ERROR_SERVICE_API_KEY: ${{ secrets.ERROR_SERVICE_API_KEY }}
|
||||
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
|
||||
OTEL_LOGS_EXPORTER: otlp
|
||||
OTEL_METRICS_EXPORTER: otlp
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
|
||||
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
|
||||
|
||||
- name: Verify build output
|
||||
env:
|
||||
@@ -313,6 +331,15 @@ jobs:
|
||||
- name: Build SDK packages
|
||||
if: steps.check_commits.outputs.skip != 'true'
|
||||
run: bun run build:sdk
|
||||
env:
|
||||
TELEMETRY_SERVICE_API_KEY: ${{ secrets.TELEMETRY_SERVICE_API_KEY }}
|
||||
ERROR_SERVICE_API_KEY: ${{ secrets.ERROR_SERVICE_API_KEY }}
|
||||
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
|
||||
OTEL_LOGS_EXPORTER: otlp
|
||||
OTEL_METRICS_EXPORTER: otlp
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
|
||||
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
|
||||
|
||||
- name: Run tests
|
||||
if: steps.check_commits.outputs.skip != 'true'
|
||||
@@ -349,6 +376,15 @@ jobs:
|
||||
if: steps.check_commits.outputs.skip != 'true'
|
||||
run: bun script/build.ts --install-native-variants --skip-sdk-build
|
||||
working-directory: sdk/apps/cli
|
||||
env:
|
||||
TELEMETRY_SERVICE_API_KEY: ${{ secrets.TELEMETRY_SERVICE_API_KEY }}
|
||||
ERROR_SERVICE_API_KEY: ${{ secrets.ERROR_SERVICE_API_KEY }}
|
||||
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
|
||||
OTEL_LOGS_EXPORTER: otlp
|
||||
OTEL_METRICS_EXPORTER: otlp
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
|
||||
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
|
||||
|
||||
- name: Verify build output
|
||||
if: steps.check_commits.outputs.skip != 'true'
|
||||
|
||||
+10
@@ -60,3 +60,13 @@ tests/**/cache
|
||||
# Backup created by scripts/marketplace-readme.mjs while publishing.
|
||||
# Should never be committed: only exists if a publish aborts mid-swap.
|
||||
.README.github.bak
|
||||
|
||||
|
||||
# SDK Session files / User data
|
||||
.cline/data
|
||||
.cline/tmp
|
||||
*.db
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
.cline/**/managed.json
|
||||
.cline/**/bundle.json
|
||||
|
||||
@@ -212,7 +212,7 @@ cline schedule create "PR summary" \
|
||||
Chat with your agent from any messaging platform: Telegram, Slack, Discord, Google Chat, WhatsApp, and Linear. Each conversation thread maps to an agent session with full context. Set up access control to restrict who can interact with your agent.
|
||||
|
||||
```bash
|
||||
cline connect telegram -m my_bot -k $BOT_TOKEN
|
||||
cline connect telegram -k $BOT_TOKEN
|
||||
cline connect slack --token $SLACK_TOKEN --signing-secret $SECRET --base-url $URL
|
||||
```
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ cat payload.json | cline hook
|
||||
|
||||
### `plugin`
|
||||
|
||||
Manage Cline plugins. Install plugins from npm, git repositories, or local paths. See [Plugins](/customization/plugins) for full details and the plugin manifest format.
|
||||
Manage Cline plugins. Install plugins from file URLs, npm, git repositories, or local paths. See [Plugins](/customization/plugins) for full details and the plugin manifest format.
|
||||
|
||||
```bash
|
||||
cline plugin install <source> # Install a plugin
|
||||
|
||||
@@ -21,7 +21,7 @@ cline connect
|
||||
|
||||
| Platform | Direct Command | Required Credentials |
|
||||
|----------|---------------|---------------------|
|
||||
| Telegram | `cline connect telegram` | Bot username, bot token |
|
||||
| Telegram | `cline connect telegram` | Bot token |
|
||||
| Slack | `cline connect slack` | Bot token, signing secret, base URL |
|
||||
| Discord | `cline connect discord` | Application ID, bot token, public key, base URL |
|
||||
| Google Chat | `cline connect gchat` | Service account credentials JSON, base URL |
|
||||
@@ -41,8 +41,10 @@ cline connect
|
||||
|
||||
<Step title="Start the connector">
|
||||
```bash
|
||||
cline connect telegram -m <BOT-USERNAME> -k <BOT-TOKEN>
|
||||
cline connect telegram -k <BOT-TOKEN>
|
||||
```
|
||||
|
||||
The connector discovers the bot username from the token. Use `--bot-username` only if you need to override it.
|
||||
</Step>
|
||||
|
||||
<Step title="Chat with your bot">
|
||||
@@ -63,7 +65,7 @@ By default, anyone who finds your bot can message it and it will execute tasks o
|
||||
Replace `12345` with your actual Telegram user ID:
|
||||
|
||||
```bash
|
||||
cline connect telegram -m <BOT-USERNAME> -k <BOT-TOKEN> \
|
||||
cline connect telegram -k <BOT-TOKEN> \
|
||||
--hook-command 'jq -r ".payload.actor.participantKey" | grep -q "telegram:id:12345" && echo "{\"action\":\"allow\"}" || echo "{\"action\":\"deny\",\"message\":\"unauthorized\"}"'
|
||||
```
|
||||
</Step>
|
||||
@@ -147,7 +149,7 @@ Multiple connectors can run simultaneously. They all share the same hub:
|
||||
|
||||
```bash
|
||||
# Terminal 1
|
||||
cline connect telegram -m my_bot -k $TELEGRAM_TOKEN
|
||||
cline connect telegram -k $TELEGRAM_TOKEN
|
||||
|
||||
# Terminal 2
|
||||
cline connect slack --token $SLACK_TOKEN --signing-secret $SECRET --base-url $URL
|
||||
|
||||
@@ -100,7 +100,7 @@ cline schedule create "Code health" \
|
||||
Combine schedules with [connectors](/cli/connectors) to send results to messaging platforms:
|
||||
|
||||
```bash
|
||||
cline connect telegram -m my_bot -k $BOT_TOKEN
|
||||
cline connect telegram -k $BOT_TOKEN
|
||||
|
||||
cline schedule create "Morning briefing" \
|
||||
--cron "0 8 * * *" \
|
||||
|
||||
@@ -11,9 +11,17 @@ Plugins extend Cline with custom tools, lifecycle hooks, slash commands, and mor
|
||||
|
||||
## Installing Plugins via CLI
|
||||
|
||||
The `cline plugin install` command installs plugins from three source types:
|
||||
The `cline plugin install` command installs plugins from four source types:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="File URL">
|
||||
```bash
|
||||
cline plugin install https://github.com/owner/repo/blob/main/plugins/my-plugin.ts
|
||||
cline plugin install https://raw.githubusercontent.com/owner/repo/main/plugins/my-plugin.ts
|
||||
```
|
||||
|
||||
File URLs install a single `.ts` or `.js` plugin file directly. GitHub `blob` and raw URLs are supported, and remote plugin file URLs must use `https://`.
|
||||
</Tab>
|
||||
<Tab title="Git Repository">
|
||||
```bash
|
||||
cline plugin install https://github.com/owner/repo.git
|
||||
@@ -125,6 +133,7 @@ Plugins are stored in the `plugins` directory at two levels:
|
||||
_installed/ # Managed by `cline plugin install`
|
||||
npm/ # npm-sourced plugins
|
||||
git/ # git-sourced plugins
|
||||
remote/ # file URL-sourced plugins
|
||||
local/ # local-sourced plugins
|
||||
|
||||
.cline/ # Project root
|
||||
|
||||
@@ -134,7 +134,7 @@ cline "Work on feature X"
|
||||
# Terminal 2: attach to the same session from VS Code or another CLI
|
||||
|
||||
# Terminal 3: Telegram connector
|
||||
cline connect telegram -m my_bot -k $TOKEN
|
||||
cline connect telegram -k $TOKEN
|
||||
|
||||
# All three share the same hub and can access the same sessions
|
||||
```
|
||||
|
||||
@@ -134,7 +134,7 @@ Combine scheduled agents with [connectors](/cli/connectors) in CLI to route resu
|
||||
|
||||
```bash
|
||||
# Start a Telegram connector
|
||||
cline connect telegram -m my_bot -k $BOT_TOKEN
|
||||
cline connect telegram -k $BOT_TOKEN
|
||||
|
||||
# Schedule an agent whose output gets sent to Telegram
|
||||
cline schedule create "Morning briefing" \
|
||||
|
||||
@@ -251,7 +251,13 @@ await cline.start({
|
||||
|
||||
## Distributing via CLI Install
|
||||
|
||||
To make your plugin installable with `cline plugin install`, add a `cline` field to your `package.json` that declares entry points. Dependencies under the `@cline/` scope are provided by the host runtime. The installer automatically strips these from the plugin's dependency list before running `npm install`, so declare any `@cline/*` package your plugin imports as an optional peer dependency:
|
||||
Single-file plugins can be installed directly from a file URL:
|
||||
|
||||
```bash
|
||||
cline plugin install https://github.com/your-org/your-repo/blob/main/plugins/github-plugin.ts
|
||||
```
|
||||
|
||||
For package or repository distribution, add a `cline` field to your `package.json` that declares entry points. Dependencies under the `@cline/` scope are provided by the host runtime. The installer automatically strips these from the plugin's dependency list before running `npm install`, so declare any `@cline/*` package your plugin imports as an optional peer dependency:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -269,7 +275,7 @@ To make your plugin installable with `cline plugin install`, add a `cline` field
|
||||
}
|
||||
```
|
||||
|
||||
Users can then install from git, npm, or a local path:
|
||||
Users can also install package plugins from git, npm, or a local path:
|
||||
|
||||
```bash
|
||||
cline plugin install https://github.com/your-org/cline-github-plugin.git
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
title: "Plugin Examples"
|
||||
sidebarTitle: "Plugin Examples"
|
||||
description: "Explore ready-to-run plugin examples from the Cline SDK repository."
|
||||
description: "Explore installable plugin examples from the Cline SDK repository."
|
||||
---
|
||||
|
||||
The [SDK repository](https://github.com/cline/cline/tree/main/sdk) includes ready-to-run plugin examples under [`examples/plugins/`](https://github.com/cline/cline/tree/main/sdk/examples/plugins). Use them as starting points for tools, lifecycle hooks, message rewriting, policy enforcement, background jobs, and multi-agent workflows.
|
||||
The [SDK repository](https://github.com/cline/cline/tree/main/sdk) includes installable plugin examples under [`examples/plugins/`](https://github.com/cline/cline/tree/main/sdk/examples/plugins). Use them as starting points for tools, lifecycle hooks, message rewriting, policy enforcement, background jobs, and multi-agent workflows.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -25,8 +25,7 @@ The [SDK repository](https://github.com/cline/cline/tree/main/sdk) includes read
|
||||
The CLI auto-discovers plugins from `.cline/plugins` in the workspace, `~/.cline/plugins`, and the system plugins folder.
|
||||
|
||||
```sh
|
||||
mkdir -p .cline/plugins
|
||||
cp examples/plugins/weather-metrics.ts .cline/plugins/
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/weather-metrics.ts --cwd .
|
||||
cline -i "What's the weather like in Tokyo and Paris?"
|
||||
```
|
||||
|
||||
@@ -37,8 +36,7 @@ Swap `weather-metrics.ts` for any other single-file plugin example.
|
||||
Use `gitignore-read-files-guard.ts` to block tools from reading or editing files ignored by workspace `.gitignore` files:
|
||||
|
||||
```sh
|
||||
mkdir -p .cline/plugins
|
||||
cp examples/plugins/gitignore-read-files-guard.ts .cline/plugins/
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/gitignore-read-files-guard.ts --cwd .
|
||||
cline -i "Read the ignored .env file"
|
||||
```
|
||||
|
||||
@@ -59,8 +57,7 @@ See [Installing Plugins](/sdk/plugin-install) for more install options.
|
||||
The `web-search.ts` plugin registers a `web_search` tool backed by Exa. Use `web_search` to discover relevant URLs, then use `fetch_web_content` when the agent needs to inspect a specific page.
|
||||
|
||||
```sh
|
||||
mkdir -p .cline/plugins
|
||||
cp examples/plugins/web-search.ts .cline/plugins/web-search.ts
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/web-search.ts --cwd .
|
||||
|
||||
export EXA_API_KEY=...
|
||||
export OPENROUTER_API_KEY=...
|
||||
@@ -92,4 +89,4 @@ Prefer the message-builder version for normal compaction. It runs in the core me
|
||||
| `get_background_command` | Reads job status plus recent stdout/stderr tails. |
|
||||
| `delete_background_command` | Deletes saved job metadata and optionally deletes captured logs. |
|
||||
|
||||
When `notifyParent` is true, the plugin emits a `steer_message` after the command exits, pushing a completion summary back into the active session so the agent can react to long-running commands without blocking the original tool call.
|
||||
When `notifyParent` is true, the plugin emits a `steer_message` after the command exits, pushing a completion summary back into the active session so the agent can react to long-running commands without blocking the original tool call.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
title: "Installing Plugins"
|
||||
sidebarTitle: "Installing Plugins"
|
||||
description: "Install plugins from npm, git, or local sources using the CLI or programmatically."
|
||||
description: "Install plugins from file URLs, npm, git, or local sources using the CLI or programmatically."
|
||||
---
|
||||
|
||||
The Cline CLI provides a `plugin install` command to install plugins from various sources. You can also load plugins programmatically via session config.
|
||||
|
||||
## CLI Installation
|
||||
|
||||
Use the `cline plugin install` command to install plugins from npm, git repositories, or local paths.
|
||||
Use the `cline plugin install` command to install plugins from file URLs, npm, git repositories, or local paths.
|
||||
|
||||
```sh
|
||||
cline plugin install <source> [options]
|
||||
@@ -16,6 +16,15 @@ cline plugin install <source> [options]
|
||||
|
||||
The shorthand `cline plugin i` works as well.
|
||||
|
||||
### Install from a File URL
|
||||
|
||||
```sh
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/weather-metrics.ts
|
||||
cline plugin install https://raw.githubusercontent.com/cline/cline/main/sdk/examples/plugins/weather-metrics.ts
|
||||
```
|
||||
|
||||
Installs a single `.ts` or `.js` plugin file from an HTTPS URL. GitHub `blob` URLs are normalized to raw file downloads automatically.
|
||||
|
||||
### Install from npm
|
||||
|
||||
```sh
|
||||
@@ -50,7 +59,7 @@ Supports both files and directories. Local installs copy the source, filter out
|
||||
| `--git` | Treat the source as a git repository URL |
|
||||
| `--force` | Overwrite an existing plugin at the same path |
|
||||
| `--json` | Output results as JSON (useful for scripting) |
|
||||
| `--cwd` | Working directory for relative paths |
|
||||
| `--cwd` | Install to `<path>/.cline/plugins` and resolve relative local paths from `<path>` |
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -58,6 +67,9 @@ Supports both files and directories. Local installs copy the source, filter out
|
||||
# Install a local plugin directory
|
||||
cline plugin install ./my-custom-plugin
|
||||
|
||||
# Install a single plugin file from GitHub
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/weather-metrics.ts
|
||||
|
||||
# Install an npm package as a plugin
|
||||
cline plugin install --npm @cline/plugin-sql
|
||||
|
||||
@@ -92,14 +104,13 @@ your-project/
|
||||
└── ...
|
||||
```
|
||||
|
||||
To add a single-file plugin manually, copy it into `.cline/plugins/`:
|
||||
To add a single-file plugin to a project, install it with `--cwd`:
|
||||
|
||||
```sh
|
||||
mkdir -p .cline/plugins
|
||||
cp path/to/my-plugin.ts .cline/plugins/
|
||||
cline plugin install https://github.com/owner/repo/blob/main/plugins/my-plugin.ts --cwd .
|
||||
```
|
||||
|
||||
Global plugins are discovered from `~/.cline/plugins/`, and Cline may also discover plugins from the system Plugins folder. Use `.cline/plugins/` when you want plugins to stay with a specific project.
|
||||
Global plugins are discovered from `~/.cline/plugins/`, and Cline may also discover plugins from the system Plugins folder. Use `--cwd .` when you want plugins to stay with a specific project.
|
||||
|
||||
## Programmatic Installation
|
||||
|
||||
@@ -159,4 +170,4 @@ await cline.start({
|
||||
|
||||
- **Learn about [Plugins](/sdk/plugins)** — Understand what plugins are and their benefits.
|
||||
- **Follow the [Writing Plugins](/sdk/guides/writing-plugins) guide** — Build and distribute your own plugin.
|
||||
- **Explore [Plugin Examples](/sdk/plugin-examples)** — Copy ready-to-run plugin examples from the SDK repository.
|
||||
- Explore [Plugin Examples](/sdk/plugin-examples) to install ready-to-run plugin examples from the SDK repository.
|
||||
|
||||
@@ -98,7 +98,7 @@ Plugin files export an `AgentPlugin`.
|
||||
|
||||
## Installing Plugins via CLI
|
||||
|
||||
Plugins can also be installed from npm, git, or local paths using `cline plugin install`. See [Plugins](/customization/plugins) for install commands, the manifest format, and directory layout.
|
||||
Plugins can also be installed from file URLs, npm, git, or local paths using `cline plugin install`. See [Plugins](/customization/plugins) for install commands, the manifest format, and directory layout.
|
||||
|
||||
## Hook Stages
|
||||
|
||||
|
||||
Generated
+19
-57
@@ -61,7 +61,7 @@
|
||||
"chrome-launcher": "^1.1.2",
|
||||
"clone-deep": "^4.0.1",
|
||||
"default-shell": "^2.2.0",
|
||||
"diff": "^5.2.0",
|
||||
"diff": "8.0.4",
|
||||
"exceljs": "^4.4.0",
|
||||
"execa": "^9.5.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
@@ -115,7 +115,6 @@
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/chai": "^5.0.1",
|
||||
"@types/clone-deep": "^4.0.4",
|
||||
"@types/diff": "^5.2.1",
|
||||
"@types/get-folder-size": "^3.0.4",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/mocha": "^10.0.7",
|
||||
@@ -4937,9 +4936,9 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/codegen": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
|
||||
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
|
||||
"integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/eventemitter": {
|
||||
@@ -4965,9 +4964,9 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/inquire": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
|
||||
"integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz",
|
||||
"integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/path": {
|
||||
@@ -4983,9 +4982,9 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/utf8": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
|
||||
"integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@puppeteer/browsers": {
|
||||
@@ -7206,13 +7205,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/diff": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.3.tgz",
|
||||
"integrity": "sha512-K0Oqlrq3kQMaO2RhfrNQX5trmt+XLyom88zS0u84nnIcLvFnRUMRRHmrGny5GSM+kNO9IZLARsdQHDzkhAgmrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
@@ -10155,9 +10147,9 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz",
|
||||
"integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==",
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz",
|
||||
"integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
@@ -15376,16 +15368,6 @@
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/diff": {
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz",
|
||||
"integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/find-up": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||
@@ -17334,22 +17316,22 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/protobufjs": {
|
||||
"version": "7.5.5",
|
||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz",
|
||||
"integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==",
|
||||
"version": "7.5.8",
|
||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.8.tgz",
|
||||
"integrity": "sha512-dvpCIeLPbXZS/Ete7yLaO7RenOdken2NHKykBXbsaGxZT0UTltcarBciw+A78SRQs9iMAAVpsYA+l8b1hTePIA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@protobufjs/aspromise": "^1.1.2",
|
||||
"@protobufjs/base64": "^1.1.2",
|
||||
"@protobufjs/codegen": "^2.0.4",
|
||||
"@protobufjs/codegen": "^2.0.5",
|
||||
"@protobufjs/eventemitter": "^1.1.0",
|
||||
"@protobufjs/fetch": "^1.1.0",
|
||||
"@protobufjs/float": "^1.0.2",
|
||||
"@protobufjs/inquire": "^1.1.0",
|
||||
"@protobufjs/inquire": "^1.1.1",
|
||||
"@protobufjs/path": "^1.1.2",
|
||||
"@protobufjs/pool": "^1.1.0",
|
||||
"@protobufjs/utf8": "^1.1.0",
|
||||
"@protobufjs/utf8": "^1.1.1",
|
||||
"@types/node": ">=13.7.0",
|
||||
"long": "^5.0.0"
|
||||
},
|
||||
@@ -18769,16 +18751,6 @@
|
||||
"url": "https://opencollective.com/sinon"
|
||||
}
|
||||
},
|
||||
"node_modules/sinon/node_modules/diff": {
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz",
|
||||
"integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/sinon/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
@@ -19878,16 +19850,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node/node_modules/diff": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
|
||||
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-poet": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.12.0.tgz",
|
||||
|
||||
+3
-6
@@ -449,7 +449,6 @@
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/chai": "^5.0.1",
|
||||
"@types/clone-deep": "^4.0.4",
|
||||
"@types/diff": "^5.2.1",
|
||||
"@types/get-folder-size": "^3.0.4",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/mocha": "^10.0.7",
|
||||
@@ -539,7 +538,7 @@
|
||||
"chrome-launcher": "^1.1.2",
|
||||
"clone-deep": "^4.0.1",
|
||||
"default-shell": "^2.2.0",
|
||||
"diff": "^5.2.0",
|
||||
"diff": "8.0.4",
|
||||
"exceljs": "^4.4.0",
|
||||
"execa": "^9.5.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
@@ -592,10 +591,8 @@
|
||||
"vite": "^7.1.11",
|
||||
"js-yaml": "^4.1.1",
|
||||
"serialize-javascript": ">=7.0.3",
|
||||
"protobufjs": "7.5.5",
|
||||
"mocha": {
|
||||
"diff": ">=8.0.3"
|
||||
}
|
||||
"protobufjs": "7.5.8",
|
||||
"diff": "8.0.4"
|
||||
},
|
||||
"c8": {
|
||||
"reporter": [
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"source": "cline-extension-remote-config",
|
||||
"version": "v1",
|
||||
"remoteConfig": {
|
||||
"version": "v1",
|
||||
"providerSettings": {},
|
||||
"telemetryEnabled": true,
|
||||
"kanbanEnabled": true,
|
||||
"mcpMarketplaceEnabled": true,
|
||||
"yoloModeAllowed": true,
|
||||
"openTelemetryEnabled": false,
|
||||
"openTelemetryOtlpInsecure": false,
|
||||
"enterpriseTelemetry": {
|
||||
"promptUploading": {
|
||||
"enabled": true,
|
||||
"type": "s3_access_keys",
|
||||
"s3AccessSettings": {
|
||||
"bucket": "cline-tasks",
|
||||
"accessKeyId": "AKIA44Y6CGDEKMATQQE2",
|
||||
"secretAccessKey": "sbQZ9qN5DdgIDL501gsK0ErV6+/ac8Yja27SbyMa",
|
||||
"region": "us-west-2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"managedInstructions": [],
|
||||
"metadata": {
|
||||
"organizationId": "org-01JZPE4CHW5XTP73W95762121Y",
|
||||
"paths": {
|
||||
"pluginName": "remote-config",
|
||||
"pluginPath": "/Users/beatrix/dev/cline/sdk/.cline/remote-config",
|
||||
"workflowsPath": "/Users/beatrix/dev/cline/sdk/.cline/remote-config/workflows",
|
||||
"skillsPath": "/Users/beatrix/dev/cline/sdk/.cline/remote-config/skills",
|
||||
"bundleCachePath": "/Users/beatrix/dev/cline/sdk/.cline/remote-config/cache/bundle.json",
|
||||
"manifestPath": "/Users/beatrix/dev/cline/sdk/.cline/remote-config/managed.json",
|
||||
"rulesFilePath": "/Users/beatrix/dev/cline/sdk/.cline/remote-config/rules.md"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"source": "cline-extension-remote-config",
|
||||
"version": "v1",
|
||||
"files": []
|
||||
}
|
||||
@@ -244,6 +244,7 @@ Design implication:
|
||||
- transport-specific translation belongs inside concrete hosts, not in top-level orchestration
|
||||
- `RuntimeHost` inputs stay transport-safe, while `ClineCore.start(...)` is the app-facing facade that normalizes broad local config before delegation
|
||||
- `RuntimeSessionConfig` is transport-neutral across local, shared hub, and remote hub modes; host-local bootstrap concerns stay under `localRuntime`
|
||||
- Per-turn connection updates are carried on `RuntimeHost.runTurn(...)` as transport-safe data. Local execution applies them before the turn starts, forwards the resolved connection defaults to delegated agents and teammates, and persists provider/model changes back to the session row and manifest so history reflects the latest active model.
|
||||
- client-local runtime behaviors that must survive hub mode, such as `defaultToolExecutors`, are attached at session start and proxied through hub capability requests instead of changing host selection
|
||||
- pending prompt list/update/delete are exposed through the grouped
|
||||
`ClineCore.pendingPrompts` service. Usage summary lookup and active-session
|
||||
|
||||
+1
-1
@@ -234,7 +234,7 @@ cline "Refactor the auth module to use JWT"
|
||||
cline schedule create "PR summary" --cron "0 9 * * MON-FRI" --prompt "Summarize open PRs"
|
||||
|
||||
# Connect a Telegram bot created with @BotFather
|
||||
cline connect telegram -m my_bot -k "$TELEGRAM_BOT_TOKEN"
|
||||
cline connect telegram -k "$TELEGRAM_BOT_TOKEN"
|
||||
# Then send /help or /start to the bot in Telegram
|
||||
```
|
||||
|
||||
|
||||
@@ -92,6 +92,8 @@ bun run test
|
||||
bun --cwd apps/cli run build:platforms
|
||||
```
|
||||
|
||||
Known local-only test failure: `src/commands/distribution-package.test.ts > rejects direct source package packing by default` will fail on machines that have `ignore-scripts=true` in `~/.npmrc` (set by the npm supply-chain hardening guide). Bun reads npm's `ignore-scripts` from `~/.npmrc`, so `bun pm pack --dry-run` skips the source-publish `prepack` guard and exits 0, which the test reads as a failure. CI does not set `ignore-scripts`, so the test passes there. Confirm by running `bun pm pack --dry-run` directly: with `~/.npmrc` in place it exits 0 with no guard output; with `~/.npmrc` moved aside it exits 1 and prints the guard message. This is not a release blocker by itself, but it does mean the local-publish path (`bun release cli`) will also bypass the source-publish guard on this machine; prefer the GitHub Actions publish path on machines with `ignore-scripts=true` set globally, or temporarily unset it (`npm config delete ignore-scripts` or `mv ~/.npmrc ~/.npmrc.bak`) for the duration of a local publish.
|
||||
|
||||
7. Commit release changes.
|
||||
|
||||
Only after the user approves the notes and version:
|
||||
|
||||
@@ -1,5 +1,50 @@
|
||||
# Cline CLI Changelog
|
||||
|
||||
## 3.0.13
|
||||
|
||||
- Show a loading dialog while resuming a session from history so the TUI no longer appears frozen during the load.
|
||||
- Speed up the `/clear` command by deferring new session creation until you send the next prompt, so clearing no longer blocks on spinning up an empty session.
|
||||
|
||||
## 3.0.12
|
||||
|
||||
- Show a loading dialog while the config screen switches provider or model so the transition no longer looks frozen.
|
||||
- Render the ask question tool prompt inline with the conversation so the question and suggested answers stay attached to the assistant turn that asked them, instead of appearing in a separate modal.
|
||||
- Allow manual `cline update` runs to install the latest published version immediately, bypassing the release age gate that delays automatic updates.
|
||||
- Refresh the bundled SDK to 0.0.42, updating the model catalog.
|
||||
|
||||
## 3.0.11
|
||||
|
||||
- Fix a regression in the ChatGPT OAuth provider where requests failed with `max_output_tokens not supported`, by restoring the full output token budget instead of applying an implicit cap.
|
||||
- Hide the `Space toggle` hint in the config footer when the highlighted row is not toggleable (rules, agents, hooks).
|
||||
- Authenticate Vertex Gemini through Google auth when `gcp.projectId` is configured, and surface the full Vertex model list instead of only Claude models.
|
||||
- Include tool names in tool result content blocks so message logs and session history consistently track which tool produced each result.
|
||||
|
||||
## 3.0.10
|
||||
|
||||
- Install plugins from `file://` URLs in addition to npm and git sources.
|
||||
- Show Ollama API key note in TUI settings so users know when to provide an API key.
|
||||
- Keep interactive sessions alive when idle or awaiting approval instead of treating them as ended, and stop reading message files for every session when `hydrate: false`.
|
||||
- Add Poolside as a provider.
|
||||
- Add Gemini 3.5 Flash to the Gemini provider model list.
|
||||
- Auto-detect Telegram bot username from the bot token so the Telegram connector no longer requires it to be configured separately.
|
||||
- Notify connectors when a scheduled execution fails, not just when it succeeds.
|
||||
- Bake OTEL telemetry variables into the CLI at build time so telemetry works in nightly and production builds.
|
||||
- Preserve model output token limits from the SDK model catalog so context window math matches the upstream provider.
|
||||
- Soften the visual treatment of rejected tool calls in the TUI.
|
||||
- Hide the skills tool from the system prompt when skills are disabled, and refresh slash commands after toggling a skill.
|
||||
- Restore AWS Bedrock profile-based auth during legacy config migration so profiles set via `awsAuthentication: "profile"` are preserved without `awsUseProfile`.
|
||||
- Cache global settings reads keyed by file mtime so repeated reads skip the JSON parse and zod validation on the hot path.
|
||||
|
||||
## 3.0.9
|
||||
|
||||
- Speed up CLI startup with plugins by loading sandboxed plugins concurrently and caching plugin tool descriptors per plugin, provider, and model.
|
||||
- Speed up plugin and tool config toggles by updating the TUI optimistically and persisting changes without reloading the full config or reimporting plugins.
|
||||
- Restore fuzzy ranking for the @-mention file picker so the most relevant files appear first.
|
||||
- Keep the interactive CLI session alive after cancelling a task instead of tearing the session down.
|
||||
- Accept dash-prefixed prompts when passed after `--`, so prompts starting with `-` are no longer parsed as flags.
|
||||
- Recover from hub abort cleanup failures so a cancel that hits an error no longer crashes the runtime host.
|
||||
- Route GLM thinking through provider metadata so thinking-enabled GLM models behave correctly through the gateway.
|
||||
|
||||
## 3.0.8
|
||||
|
||||
- Use Telegram numeric participant ids so renamed users stay linked to the same participant in the Telegram connector.
|
||||
|
||||
@@ -169,7 +169,7 @@ Bridge a chat surface into RPC-backed Cline sessions. Each conversation thread m
|
||||
|
||||
```sh
|
||||
# Telegram (polling mode)
|
||||
cline connect telegram -m my_bot -k 123456:ABCDEF...
|
||||
cline connect telegram -k 123456:ABCDEF...
|
||||
|
||||
# Slack (webhook mode)
|
||||
cline connect slack --bot-token $SLACK_BOT_TOKEN --signing-secret $SLACK_SIGNING_SECRET --base-url https://your-domain.com
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@cline/cli",
|
||||
"displayName": "cline",
|
||||
"version": "3.0.8",
|
||||
"version": "3.0.13",
|
||||
"description": "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
@@ -68,26 +68,27 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "^0.16.1",
|
||||
"@clack/prompts": "^1.2.0",
|
||||
"@chat-adapter/discord": "^4.23.0",
|
||||
"@chat-adapter/gchat": "^4.23.0",
|
||||
"@chat-adapter/linear": "^4.23.0",
|
||||
"@chat-adapter/slack": "^4.23.0",
|
||||
"@chat-adapter/telegram": "^4.23.0",
|
||||
"@chat-adapter/whatsapp": "^4.23.0",
|
||||
"@clack/prompts": "^1.2.0",
|
||||
"@gramio/format": "^0.7.0",
|
||||
"chat": "^4.23.0",
|
||||
"commander": "^14.0.3",
|
||||
"@opentui-ui/dialog": "^0.1.2",
|
||||
"@opentui/core": "0.1.102",
|
||||
"@opentui/react": "0.1.102",
|
||||
"@opentui-ui/dialog": "^0.1.2",
|
||||
"chat": "^4.23.0",
|
||||
"commander": "^14.0.3",
|
||||
"fzf": "^0.5.2",
|
||||
"marked": "^15.0.12",
|
||||
"open": "^10.2.0",
|
||||
"opentui-spinner": "^0.0.6",
|
||||
"pino": "^10.3.1",
|
||||
"react": "19.2.4",
|
||||
"react-reconciler": "0.32.0",
|
||||
"react-devtools-core": "^7.0.1",
|
||||
"react-reconciler": "0.32.0",
|
||||
"yaml": "^2.8.2",
|
||||
"zod": "^4.1.11"
|
||||
},
|
||||
|
||||
@@ -13,6 +13,30 @@ const cliDir = resolve(import.meta.dir, "..");
|
||||
const rootDir = resolve(cliDir, "../..");
|
||||
process.chdir(cliDir);
|
||||
|
||||
// Telemetry / OTEL environment variables that should be baked into the
|
||||
// compiled binary at build time. Mirrors the list of secrets injected by the
|
||||
// `cli-publish` GitHub Actions workflow. These are inlined via Bun's `define`
|
||||
// so the CLI ships with the production telemetry configuration without
|
||||
// requiring the end user to set any env vars.
|
||||
const BUILD_TIME_INLINED_ENV_VARS = [
|
||||
"TELEMETRY_SERVICE_API_KEY",
|
||||
"ERROR_SERVICE_API_KEY",
|
||||
"OTEL_TELEMETRY_ENABLED",
|
||||
"OTEL_LOGS_EXPORTER",
|
||||
"OTEL_METRICS_EXPORTER",
|
||||
"OTEL_EXPORTER_OTLP_PROTOCOL",
|
||||
"OTEL_EXPORTER_OTLP_ENDPOINT",
|
||||
"OTEL_EXPORTER_OTLP_HEADERS",
|
||||
] as const;
|
||||
|
||||
function buildInlinedEnvDefines(): Record<string, string> {
|
||||
const defines: Record<string, string> = {};
|
||||
for (const name of BUILD_TIME_INLINED_ENV_VARS) {
|
||||
defines[`process.env.${name}`] = JSON.stringify(process.env[name] ?? "");
|
||||
}
|
||||
return defines;
|
||||
}
|
||||
|
||||
const pkg = JSON.parse(readFileSync(join(cliDir, "package.json"), "utf-8"));
|
||||
const version: string = pkg.version;
|
||||
const repository: unknown = pkg.repository;
|
||||
@@ -128,6 +152,9 @@ async function buildCompiledBinary(input: {
|
||||
external: ["@anthropic-ai/vertex-sdk"],
|
||||
define: {
|
||||
OTUI_TREE_SITTER_WORKER_PATH: bunfsRoot + parserWorkerPath,
|
||||
// Inline telemetry/OTEL env vars at build time so the compiled
|
||||
// binary ships with production telemetry configuration baked in.
|
||||
...buildInlinedEnvDefines(),
|
||||
},
|
||||
throw: false,
|
||||
});
|
||||
|
||||
@@ -14,13 +14,17 @@ import {
|
||||
setClineDir,
|
||||
setHomeDir,
|
||||
} from "@cline/shared/storage";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
installPlugin,
|
||||
parsePluginSource,
|
||||
runPluginInstallCommand,
|
||||
} from "./plugin";
|
||||
|
||||
type FetchCall = (
|
||||
...args: Parameters<typeof fetch>
|
||||
) => ReturnType<typeof fetch>;
|
||||
|
||||
describe("plugin install command", () => {
|
||||
let root = "";
|
||||
let home = "";
|
||||
@@ -44,6 +48,8 @@ describe("plugin install command", () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
vi.unstubAllGlobals();
|
||||
if (originalHome === undefined) {
|
||||
delete process.env.HOME;
|
||||
} else {
|
||||
@@ -85,6 +91,36 @@ describe("plugin install command", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("parses GitHub plugin file URLs as remote sources", () => {
|
||||
expect(
|
||||
parsePluginSource(
|
||||
"https://github.com/cline/cline/blob/main/sdk/examples/plugins/weather-metrics.ts",
|
||||
),
|
||||
).toEqual({
|
||||
type: "remote",
|
||||
url: "https://raw.githubusercontent.com/cline/cline/main/sdk/examples/plugins/weather-metrics.ts",
|
||||
filename: "weather-metrics.ts",
|
||||
});
|
||||
});
|
||||
|
||||
it("parses raw plugin file URLs as remote sources", () => {
|
||||
expect(
|
||||
parsePluginSource(
|
||||
"https://raw.githubusercontent.com/cline/cline/main/sdk/examples/plugins/weather-metrics.ts",
|
||||
),
|
||||
).toEqual({
|
||||
type: "remote",
|
||||
url: "https://raw.githubusercontent.com/cline/cline/main/sdk/examples/plugins/weather-metrics.ts",
|
||||
filename: "weather-metrics.ts",
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects HTTP plugin file URLs", () => {
|
||||
expect(() =>
|
||||
parsePluginSource("http://example.com/plugins/weather-metrics.ts"),
|
||||
).toThrow(/must use https/);
|
||||
});
|
||||
|
||||
it("installs a local plugin file into the global plugin root", async () => {
|
||||
const source = join(root, "weather.ts");
|
||||
writeFileSync(
|
||||
@@ -104,6 +140,98 @@ describe("plugin install command", () => {
|
||||
expect(discovered).toEqual(result.entryPaths);
|
||||
});
|
||||
|
||||
it("installs a remote plugin file into the workspace plugin root", async () => {
|
||||
const source =
|
||||
"https://github.com/acme/plugins/blob/main/weather-metrics.ts";
|
||||
const fetchMock = vi.fn<FetchCall>(async (input) => {
|
||||
expect(String(input)).toBe(
|
||||
"https://raw.githubusercontent.com/acme/plugins/main/weather-metrics.ts",
|
||||
);
|
||||
return new Response(
|
||||
"export default { name: 'remote-weather', manifest: { capabilities: ['tools'] } };",
|
||||
);
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const result = await installPlugin({ source, cwd: workspace });
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(result.installPath).toContain(
|
||||
join(workspace, ".cline", "plugins", "_installed", "remote"),
|
||||
);
|
||||
expect(result.entryPaths).toHaveLength(1);
|
||||
expect(existsSync(result.entryPaths[0] ?? "")).toBe(true);
|
||||
expect(readFileSync(result.entryPaths[0] ?? "", "utf8")).toContain(
|
||||
"remote-weather",
|
||||
);
|
||||
expect(
|
||||
discoverPluginModulePaths(join(workspace, ".cline", "plugins")),
|
||||
).toEqual(result.entryPaths);
|
||||
});
|
||||
|
||||
it("times out stalled remote plugin downloads", async () => {
|
||||
vi.useFakeTimers();
|
||||
const source =
|
||||
"https://github.com/acme/plugins/blob/main/weather-metrics.ts";
|
||||
const fetchMock = vi.fn<FetchCall>((_input, init) => {
|
||||
return new Promise<Response>((_resolve, reject) => {
|
||||
init?.signal?.addEventListener("abort", () => {
|
||||
const error = new Error("Aborted");
|
||||
error.name = "AbortError";
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const install = installPlugin({ source, cwd: workspace });
|
||||
const rejection = expect(install).rejects.toThrow(/Timed out downloading/);
|
||||
await vi.waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1));
|
||||
await vi.advanceTimersByTimeAsync(30_000);
|
||||
|
||||
await rejection;
|
||||
});
|
||||
|
||||
it("rejects remote plugin files with oversized content length", async () => {
|
||||
const source =
|
||||
"https://github.com/acme/plugins/blob/main/weather-metrics.ts";
|
||||
const fetchMock = vi.fn<FetchCall>(async () => {
|
||||
return new Response(
|
||||
"export default { name: 'remote-weather', manifest: { capabilities: ['tools'] } };",
|
||||
{
|
||||
headers: {
|
||||
"content-length": String(10 * 1024 * 1024 + 1),
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
await expect(installPlugin({ source, cwd: workspace })).rejects.toThrow(
|
||||
/exceeds the 10485760 byte limit/,
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects remote plugin files that stream past the size limit", async () => {
|
||||
const source =
|
||||
"https://github.com/acme/plugins/blob/main/weather-metrics.ts";
|
||||
const fetchMock = vi.fn<FetchCall>(async () => {
|
||||
return new Response(
|
||||
new ReadableStream<Uint8Array>({
|
||||
start(controller) {
|
||||
controller.enqueue(new Uint8Array(10 * 1024 * 1024 + 1));
|
||||
controller.close();
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
await expect(installPlugin({ source, cwd: workspace })).rejects.toThrow(
|
||||
/exceeds the 10485760 byte limit/,
|
||||
);
|
||||
});
|
||||
|
||||
it("installs into cwd plugin root when cwd is provided", async () => {
|
||||
const source = join(root, "plugin-package");
|
||||
const npmLogPath = join(root, "npm-install.log");
|
||||
|
||||
@@ -52,12 +52,17 @@ type ParsedPluginSource =
|
||||
host: string;
|
||||
path: string;
|
||||
}
|
||||
| {
|
||||
type: "remote";
|
||||
url: string;
|
||||
filename: string;
|
||||
}
|
||||
| {
|
||||
type: "local";
|
||||
path: string;
|
||||
};
|
||||
|
||||
type PluginInstallSourceType = "npm" | "git" | "local";
|
||||
type PluginInstallSourceType = "npm" | "git" | "local" | "remote";
|
||||
|
||||
interface PluginPackageManifest {
|
||||
cline?: {
|
||||
@@ -72,6 +77,8 @@ interface PluginPackageManifest {
|
||||
|
||||
const INSTALLS_DIRECTORY_NAME = "_installed";
|
||||
const PACKAGE_DIRECTORY_NAME = "package";
|
||||
const REMOTE_PLUGIN_FETCH_TIMEOUT_MS = 30_000;
|
||||
const REMOTE_PLUGIN_MAX_BYTES = 10 * 1024 * 1024;
|
||||
const HOST_PROVIDED_SDK_PREFIX = "@cline/";
|
||||
const DEPENDENCY_FIELDS = [
|
||||
"dependencies",
|
||||
@@ -189,6 +196,80 @@ function splitGitRef(input: string): { repo: string; ref?: string } {
|
||||
};
|
||||
}
|
||||
|
||||
function decodePathSegment(value: string): string {
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function filenameFromUrlPath(pathname: string): string {
|
||||
const filename = basename(decodePathSegment(pathname));
|
||||
return filename || "plugin";
|
||||
}
|
||||
|
||||
function isGitHubFilePath(pathname: string): boolean {
|
||||
const parts = pathname.split("/").filter(Boolean);
|
||||
return parts.length >= 5 && (parts[2] === "blob" || parts[2] === "raw");
|
||||
}
|
||||
|
||||
function normalizeRemotePluginFileUrl(
|
||||
source: string,
|
||||
): Extract<ParsedPluginSource, { type: "remote" }> | null {
|
||||
if (!/^https?:\/\//i.test(source)) {
|
||||
return null;
|
||||
}
|
||||
let parsed: URL;
|
||||
try {
|
||||
parsed = new URL(source);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const host = parsed.hostname.toLowerCase();
|
||||
const filename = filenameFromUrlPath(parsed.pathname);
|
||||
const isPluginFile = isPluginModulePath(filename);
|
||||
const isGitHubFile =
|
||||
(host === "github.com" || host === "www.github.com") &&
|
||||
isGitHubFilePath(parsed.pathname);
|
||||
|
||||
if (parsed.protocol !== "https:") {
|
||||
if (isGitHubFile || host === "raw.githubusercontent.com" || isPluginFile) {
|
||||
throw new Error(`Remote plugin file URLs must use https: ${source}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (host === "github.com" || host === "www.github.com") {
|
||||
const parts = parsed.pathname.split("/").filter(Boolean);
|
||||
if (!isGitHubFile) {
|
||||
return null;
|
||||
}
|
||||
if (!isPluginFile) {
|
||||
throw new Error(`Remote plugin file must be .js or .ts: ${source}`);
|
||||
}
|
||||
const rawParts = [parts[0], parts[1], ...parts.slice(3)];
|
||||
return {
|
||||
type: "remote",
|
||||
url: `https://raw.githubusercontent.com/${rawParts.join("/")}`,
|
||||
filename,
|
||||
};
|
||||
}
|
||||
|
||||
if (host === "raw.githubusercontent.com") {
|
||||
if (!isPluginFile) {
|
||||
throw new Error(`Remote plugin file must be .js or .ts: ${source}`);
|
||||
}
|
||||
return { type: "remote", url: parsed.toString(), filename };
|
||||
}
|
||||
|
||||
if (!isPluginFile) {
|
||||
return null;
|
||||
}
|
||||
return { type: "remote", url: parsed.toString(), filename };
|
||||
}
|
||||
|
||||
function parseGitSource(
|
||||
source: string,
|
||||
options: { force?: boolean } = {},
|
||||
@@ -261,6 +342,13 @@ export function parsePluginSource(
|
||||
if (sourceType === "local") {
|
||||
return { type: "local", path: source };
|
||||
}
|
||||
if (sourceType === "remote") {
|
||||
const remote = normalizeRemotePluginFileUrl(trimmed);
|
||||
if (!remote) {
|
||||
throw new Error(`Invalid remote plugin source: ${source}`);
|
||||
}
|
||||
return remote;
|
||||
}
|
||||
if (trimmed.startsWith("npm:")) {
|
||||
const spec = trimmed.slice("npm:".length).trim();
|
||||
const { name } = parseNpmSpec(spec);
|
||||
@@ -275,6 +363,10 @@ export function parsePluginSource(
|
||||
if (localPathLike) {
|
||||
return { type: "local", path: source };
|
||||
}
|
||||
const remote = normalizeRemotePluginFileUrl(trimmed);
|
||||
if (remote) {
|
||||
return remote;
|
||||
}
|
||||
const git = parseGitSource(trimmed);
|
||||
if (git) {
|
||||
return git;
|
||||
@@ -315,6 +407,14 @@ function getInstallPath(
|
||||
`${sanitizeSegment(parsed.path)}-${hashSource(sourceKey)}`,
|
||||
);
|
||||
}
|
||||
if (parsed.type === "remote") {
|
||||
return join(
|
||||
pluginRoot,
|
||||
INSTALLS_DIRECTORY_NAME,
|
||||
"remote",
|
||||
`${sanitizeSegment(parsed.filename)}-${hashSource(sourceKey)}`,
|
||||
);
|
||||
}
|
||||
return join(
|
||||
pluginRoot,
|
||||
INSTALLS_DIRECTORY_NAME,
|
||||
@@ -330,6 +430,9 @@ function getInstallSourceKey(parsed: ParsedPluginSource, cwd: string): string {
|
||||
if (parsed.type === "git") {
|
||||
return `git:${parsed.repo}${parsed.ref ? `#${parsed.ref}` : ""}`;
|
||||
}
|
||||
if (parsed.type === "remote") {
|
||||
return `remote:${parsed.url}`;
|
||||
}
|
||||
return `local:${resolve(cwd, resolveHomePath(parsed.path))}`;
|
||||
}
|
||||
|
||||
@@ -626,6 +729,96 @@ async function installGitPackage(
|
||||
return packageRoot;
|
||||
}
|
||||
|
||||
function remotePluginSizeLimitError(url: string): Error {
|
||||
return new Error(
|
||||
`Remote plugin file from ${url} exceeds the ${REMOTE_PLUGIN_MAX_BYTES} byte limit`,
|
||||
);
|
||||
}
|
||||
|
||||
function getContentLength(response: Response): number | undefined {
|
||||
const raw = response.headers.get("content-length");
|
||||
if (!raw) {
|
||||
return undefined;
|
||||
}
|
||||
const value = Number(raw);
|
||||
if (!Number.isFinite(value) || value < 0) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
async function readRemotePluginBody(
|
||||
response: Response,
|
||||
url: string,
|
||||
): Promise<Buffer> {
|
||||
const contentLength = getContentLength(response);
|
||||
if (contentLength !== undefined && contentLength > REMOTE_PLUGIN_MAX_BYTES) {
|
||||
throw remotePluginSizeLimitError(url);
|
||||
}
|
||||
|
||||
if (!response.body) {
|
||||
const body = Buffer.from(await response.text(), "utf8");
|
||||
if (body.byteLength > REMOTE_PLUGIN_MAX_BYTES) {
|
||||
throw remotePluginSizeLimitError(url);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const chunks: Buffer[] = [];
|
||||
let received = 0;
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
const chunk = Buffer.from(value);
|
||||
received += chunk.byteLength;
|
||||
if (received > REMOTE_PLUGIN_MAX_BYTES) {
|
||||
await reader.cancel().catch(() => undefined);
|
||||
throw remotePluginSizeLimitError(url);
|
||||
}
|
||||
chunks.push(chunk);
|
||||
}
|
||||
return Buffer.concat(chunks, received);
|
||||
} finally {
|
||||
reader.releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
async function installRemoteFile(
|
||||
parsed: Extract<ParsedPluginSource, { type: "remote" }>,
|
||||
stagingRoot: string,
|
||||
): Promise<string> {
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => {
|
||||
controller.abort();
|
||||
}, REMOTE_PLUGIN_FETCH_TIMEOUT_MS);
|
||||
try {
|
||||
const response = await fetch(parsed.url, { signal: controller.signal });
|
||||
if (!response.ok) {
|
||||
const suffix = response.statusText ? ` ${response.statusText}` : "";
|
||||
throw new Error(
|
||||
`Failed to download plugin file from ${parsed.url}: ${response.status}${suffix}`,
|
||||
);
|
||||
}
|
||||
const body = await readRemotePluginBody(response, parsed.url);
|
||||
mkdirSync(stagingRoot, { recursive: true });
|
||||
await writeFile(join(stagingRoot, parsed.filename), body);
|
||||
return stagingRoot;
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.name === "AbortError") {
|
||||
throw new Error(
|
||||
`Timed out downloading plugin file from ${parsed.url} after ${REMOTE_PLUGIN_FETCH_TIMEOUT_MS}ms`,
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
async function installLocalPackage(
|
||||
parsed: Extract<ParsedPluginSource, { type: "local" }>,
|
||||
stagingRoot: string,
|
||||
@@ -737,6 +930,8 @@ export async function installPlugin(
|
||||
packageRoot = await installNpmPackage(parsed, stagingRoot, npmCommand);
|
||||
} else if (parsed.type === "git") {
|
||||
packageRoot = await installGitPackage(parsed, stagingRoot, npmCommand);
|
||||
} else if (parsed.type === "remote") {
|
||||
packageRoot = await installRemoteFile(parsed, stagingRoot);
|
||||
} else {
|
||||
packageRoot = await installLocalPackage(
|
||||
parsed,
|
||||
@@ -747,7 +942,8 @@ export async function installPlugin(
|
||||
}
|
||||
|
||||
const entryPaths =
|
||||
parsed.type === "local" && packageRoot === stagingRoot
|
||||
(parsed.type === "local" || parsed.type === "remote") &&
|
||||
packageRoot === stagingRoot
|
||||
? collectPluginEntries(stagingRoot).map(
|
||||
(entry) => `./${toPosixPath(relative(stagingRoot, entry))}`,
|
||||
)
|
||||
|
||||
@@ -232,7 +232,7 @@ export function commanderToParsedArgs(program: Command): ParsedArgs {
|
||||
if (opts.id !== undefined) result.id = opts.id;
|
||||
|
||||
// Positional args → prompt
|
||||
const positional = program.args.filter((a) => !a.startsWith("-"));
|
||||
const positional = program.args;
|
||||
if (positional.length > 0) {
|
||||
result.prompt = positional.join(" ");
|
||||
}
|
||||
|
||||
@@ -121,6 +121,74 @@ describe("runScheduleCommand list output", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("runScheduleCommand create delivery metadata", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("maps --delivery-bot to delivery.userName", async () => {
|
||||
mockEnsureCliHubServer.mockResolvedValue({
|
||||
url: "ws://127.0.0.1:25463/hub",
|
||||
authToken: "test-token",
|
||||
});
|
||||
mockSendHubCommand.mockResolvedValue({
|
||||
ok: true,
|
||||
payload: { schedule: { scheduleId: "sched_delivery" } },
|
||||
});
|
||||
|
||||
const output: string[] = [];
|
||||
const errors: string[] = [];
|
||||
const code = await runScheduleCommand(
|
||||
[
|
||||
"create",
|
||||
"Daily summary",
|
||||
"--cron",
|
||||
"0 9 * * *",
|
||||
"--prompt",
|
||||
"Summarize yesterday",
|
||||
"--workspace",
|
||||
"/tmp/workspace",
|
||||
"--delivery-adapter",
|
||||
"telegram",
|
||||
"--delivery-bot",
|
||||
"my_bot",
|
||||
"--delivery-thread",
|
||||
"telegram:123456789",
|
||||
"--address",
|
||||
"127.0.0.1:25463",
|
||||
],
|
||||
{
|
||||
writeln: (text?: string) => {
|
||||
output.push(text ?? "");
|
||||
},
|
||||
writeErr: (text: string) => {
|
||||
errors.push(text);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(code).toBe(0);
|
||||
expect(errors).toEqual([]);
|
||||
expect(output).toEqual(['{\n "scheduleId": "sched_delivery"\n}']);
|
||||
expect(mockSendHubCommand).toHaveBeenCalledWith(
|
||||
{ host: "127.0.0.1", port: 25463, pathname: "/hub" },
|
||||
{
|
||||
clientId: "cline-schedule",
|
||||
command: "schedule.create",
|
||||
payload: expect.objectContaining({
|
||||
metadata: {
|
||||
delivery: {
|
||||
adapter: "telegram",
|
||||
threadId: "telegram:123456789",
|
||||
userName: "my_bot",
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("runScheduleCommand import", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
@@ -2,7 +2,11 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join } from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { getInstallationInfo, PackageManager } from "./update";
|
||||
import {
|
||||
getInstallationInfo,
|
||||
PackageManager,
|
||||
withMinimumReleaseAgeBypass,
|
||||
} from "./update";
|
||||
|
||||
const originalArgv = [...process.argv];
|
||||
const originalWrapperPath = process.env.CLINE_WRAPPER_PATH;
|
||||
@@ -67,3 +71,37 @@ describe("getInstallationInfo", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("withMinimumReleaseAgeBypass", () => {
|
||||
it("adds the package-manager-specific cooldown bypass", () => {
|
||||
expect(
|
||||
withMinimumReleaseAgeBypass(
|
||||
"npm install -g cline@latest",
|
||||
PackageManager.NPM,
|
||||
).command,
|
||||
).toBe("npm install -g cline@latest --min-release-age=0");
|
||||
expect(
|
||||
withMinimumReleaseAgeBypass("bun add -g cline@latest", PackageManager.BUN)
|
||||
.command,
|
||||
).toBe("bun add -g cline@latest --minimum-release-age=0");
|
||||
expect(
|
||||
withMinimumReleaseAgeBypass(
|
||||
"yarn global add cline@latest",
|
||||
PackageManager.YARN,
|
||||
).command,
|
||||
).toBe("yarn global add cline@latest");
|
||||
expect(
|
||||
withMinimumReleaseAgeBypass(
|
||||
"yarn global add cline@latest",
|
||||
PackageManager.YARN,
|
||||
).env?.YARN_NPM_MINIMAL_AGE_GATE,
|
||||
).toBe("0");
|
||||
|
||||
expect(
|
||||
withMinimumReleaseAgeBypass(
|
||||
"pnpm add -g cline@latest",
|
||||
PackageManager.PNPM,
|
||||
).env?.pnpm_config_minimum_release_age,
|
||||
).toBe("0");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -36,6 +36,11 @@ interface InstallationInfo {
|
||||
updateCommand?: string;
|
||||
}
|
||||
|
||||
interface ManualUpdateCommand {
|
||||
command: string;
|
||||
env?: Readonly<Record<string, string>>;
|
||||
}
|
||||
|
||||
function isNightlyVersion(v: string): boolean {
|
||||
return v.includes("-nightly.");
|
||||
}
|
||||
@@ -133,6 +138,34 @@ export function getInstallationInfo(currentVersion: string): InstallationInfo {
|
||||
};
|
||||
}
|
||||
|
||||
export function withMinimumReleaseAgeBypass(
|
||||
updateCommand: string,
|
||||
packageManager: PackageManager,
|
||||
): ManualUpdateCommand {
|
||||
switch (packageManager) {
|
||||
case PackageManager.NPM:
|
||||
return { command: `${updateCommand} --min-release-age=0` };
|
||||
case PackageManager.PNPM:
|
||||
return {
|
||||
command: updateCommand,
|
||||
env: {
|
||||
PNPM_CONFIG_MINIMUM_RELEASE_AGE: "0",
|
||||
pnpm_config_minimum_release_age: "0",
|
||||
npm_config_minimum_release_age: "0",
|
||||
},
|
||||
};
|
||||
case PackageManager.YARN:
|
||||
return {
|
||||
command: updateCommand,
|
||||
env: { YARN_NPM_MINIMAL_AGE_GATE: "0" },
|
||||
};
|
||||
case PackageManager.BUN:
|
||||
return { command: `${updateCommand} --minimum-release-age=0` };
|
||||
default:
|
||||
return { command: updateCommand };
|
||||
}
|
||||
}
|
||||
|
||||
async function getLatestVersion(
|
||||
packageName: CliPackageName,
|
||||
currentVersion: string,
|
||||
@@ -168,11 +201,15 @@ function waitForProcessExit(child: ChildProcess): Promise<number> {
|
||||
});
|
||||
}
|
||||
|
||||
async function runCliUpdate(updateCommand: string): Promise<number> {
|
||||
const updateProcess = spawn(updateCommand, {
|
||||
async function runCliUpdate(
|
||||
updateCommand: ManualUpdateCommand,
|
||||
): Promise<number> {
|
||||
const updateProcess = spawn(updateCommand.command, {
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
env: process.env,
|
||||
env: updateCommand.env
|
||||
? { ...process.env, ...updateCommand.env }
|
||||
: process.env,
|
||||
windowsHide: true,
|
||||
});
|
||||
return waitForProcessExit(updateProcess);
|
||||
@@ -432,17 +469,21 @@ export async function checkForUpdates(
|
||||
);
|
||||
hadFailure = true;
|
||||
} else {
|
||||
const manualUpdateCommand = withMinimumReleaseAgeBypass(
|
||||
updateCommand,
|
||||
packageManager,
|
||||
);
|
||||
writeln(
|
||||
`${c.cyan}Installing ${packageName}@${latestVersion}…${c.reset}`,
|
||||
);
|
||||
try {
|
||||
const exitCode = await runCliUpdate(updateCommand);
|
||||
const exitCode = await runCliUpdate(manualUpdateCommand);
|
||||
if (exitCode === 0) {
|
||||
installedUpdates.push(`${packageName}@${latestVersion}`);
|
||||
await restartHubServerIfRunning();
|
||||
} else {
|
||||
writeErr(
|
||||
`Cline update failed (exit code ${exitCode}). Try running: ${updateCommand}`,
|
||||
`Cline update failed (exit code ${exitCode}). Try running: ${manualUpdateCommand.command}`,
|
||||
);
|
||||
hadFailure = true;
|
||||
}
|
||||
@@ -450,7 +491,7 @@ export async function checkForUpdates(
|
||||
const message =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
writeErr(
|
||||
`Failed to run Cline update command ${updateCommand}: ${message}`,
|
||||
`Failed to run Cline update command ${manualUpdateCommand.command}: ${message}`,
|
||||
);
|
||||
hadFailure = true;
|
||||
}
|
||||
|
||||
@@ -831,7 +831,10 @@ class DiscordConnector extends ConnectorBase<
|
||||
requestStop("rpc_server_shutting_down");
|
||||
return;
|
||||
}
|
||||
if (event.eventType !== "schedule.execution.completed") {
|
||||
if (
|
||||
event.eventType !== "schedule.execution.completed" &&
|
||||
event.eventType !== "schedule.execution.failed"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const scheduleId =
|
||||
|
||||
@@ -760,7 +760,10 @@ class GoogleChatConnector extends ConnectorBase<
|
||||
requestStop("rpc_server_shutting_down");
|
||||
return;
|
||||
}
|
||||
if (event.eventType !== "schedule.execution.completed") {
|
||||
if (
|
||||
event.eventType !== "schedule.execution.completed" &&
|
||||
event.eventType !== "schedule.execution.failed"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const scheduleId =
|
||||
|
||||
@@ -797,7 +797,10 @@ class LinearConnector extends ConnectorBase<
|
||||
requestStop("rpc_server_shutting_down");
|
||||
return;
|
||||
}
|
||||
if (event.eventType !== "schedule.execution.completed") {
|
||||
if (
|
||||
event.eventType !== "schedule.execution.completed" &&
|
||||
event.eventType !== "schedule.execution.failed"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const scheduleId =
|
||||
|
||||
@@ -996,7 +996,10 @@ class SlackConnector extends ConnectorBase<
|
||||
requestStop("rpc_server_shutting_down");
|
||||
return;
|
||||
}
|
||||
if (event.eventType !== "schedule.execution.completed") {
|
||||
if (
|
||||
event.eventType !== "schedule.execution.completed" &&
|
||||
event.eventType !== "schedule.execution.failed"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const scheduleId =
|
||||
|
||||
@@ -8,29 +8,31 @@ Create a bot with `@BotFather`:
|
||||
|
||||
1. Open Telegram and start a chat with `@BotFather`.
|
||||
2. Send `/newbot` and follow the prompts.
|
||||
3. Copy the bot username without the leading `@`.
|
||||
4. Copy the bot token. Treat it like a password.
|
||||
3. Copy the bot token. Treat it like a password.
|
||||
|
||||
Start the connector:
|
||||
|
||||
```bash
|
||||
cline connect telegram -m my_bot -k "$TELEGRAM_BOT_TOKEN"
|
||||
cline connect telegram -k "$TELEGRAM_BOT_TOKEN"
|
||||
```
|
||||
|
||||
The connector discovers the bot username from the token. Use `--bot-username`
|
||||
only if you need to override it.
|
||||
|
||||
Useful variants:
|
||||
|
||||
```bash
|
||||
# Keep logs in the active terminal while debugging.
|
||||
cline connect telegram -i -m my_bot -k "$TELEGRAM_BOT_TOKEN"
|
||||
cline connect telegram -i -k "$TELEGRAM_BOT_TOKEN"
|
||||
|
||||
# Read credentials from env vars.
|
||||
TELEGRAM_BOT_USERNAME=my_bot TELEGRAM_BOT_TOKEN=123456:ABCDEF... cline connect telegram
|
||||
TELEGRAM_BOT_TOKEN=123456:ABCDEF... cline connect telegram
|
||||
|
||||
# Override the workspace and model used for Telegram sessions.
|
||||
cline connect telegram -m my_bot -k "$TELEGRAM_BOT_TOKEN" --cwd /path/to/repo --provider cline --model openai/gpt-5.3-codex
|
||||
cline connect telegram -k "$TELEGRAM_BOT_TOKEN" --cwd /path/to/repo --provider cline --model openai/gpt-5.3-codex
|
||||
|
||||
# Disable tools for untrusted Telegram surfaces.
|
||||
cline connect telegram -m my_bot -k "$TELEGRAM_BOT_TOKEN" --no-tools
|
||||
cline connect telegram -k "$TELEGRAM_BOT_TOKEN" --no-tools
|
||||
|
||||
# Stop Telegram connector processes and sessions.
|
||||
cline connect --stop telegram
|
||||
@@ -69,7 +71,7 @@ Tools are enabled by default for Telegram sessions. That means anyone who can su
|
||||
Use `--no-tools` when the Telegram surface is not trusted:
|
||||
|
||||
```bash
|
||||
cline connect telegram -m my_bot -k "$TELEGRAM_BOT_TOKEN" --no-tools
|
||||
cline connect telegram -k "$TELEGRAM_BOT_TOKEN" --no-tools
|
||||
```
|
||||
|
||||
When the connector starts with `--no-tools`, chat commands such as `/tools on` and `/yolo on` cannot re-enable tools for that connector run.
|
||||
@@ -109,6 +111,11 @@ cline schedule create "Daily summary" \
|
||||
--delivery-thread telegram:123456789
|
||||
```
|
||||
|
||||
`--delivery-bot` is still supported after token-only connector setup. Use
|
||||
the Telegram bot username shown by `/whereami` as `deliveryUserName` when you
|
||||
need to target one specific Telegram connector, or omit the flag when the
|
||||
schedule does not need to be restricted to a specific bot.
|
||||
|
||||
The connector must be running when the scheduled result is delivered, and the target thread must have an existing thread binding.
|
||||
|
||||
## Limitations
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import type { ConnectTelegramOptions } from "@cline/shared";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { __test__, telegramConnector } from "./telegram";
|
||||
|
||||
const parseTelegramArgs = (rawArgs: string[]): ConnectTelegramOptions =>
|
||||
@@ -9,6 +12,28 @@ const parseTelegramArgs = (rawArgs: string[]): ConnectTelegramOptions =>
|
||||
}
|
||||
).parseArgs(rawArgs);
|
||||
|
||||
const originalClineDataDir = process.env.CLINE_DATA_DIR;
|
||||
const tempDataDirs: string[] = [];
|
||||
|
||||
function useTempClineDataDir(): string {
|
||||
const dataDir = mkdtempSync(join(tmpdir(), "cline-telegram-test-"));
|
||||
tempDataDirs.push(dataDir);
|
||||
process.env.CLINE_DATA_DIR = dataDir;
|
||||
return dataDir;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
if (originalClineDataDir === undefined) {
|
||||
delete process.env.CLINE_DATA_DIR;
|
||||
} else {
|
||||
process.env.CLINE_DATA_DIR = originalClineDataDir;
|
||||
}
|
||||
for (const dir of tempDataDirs.splice(0)) {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
describe("telegramConnector", () => {
|
||||
it("honors --no-tools", () => {
|
||||
const options = parseTelegramArgs([
|
||||
@@ -36,6 +61,129 @@ describe("telegramConnector", () => {
|
||||
|
||||
expect(options.enableTools).toBe(true);
|
||||
});
|
||||
|
||||
it("does not require the bot username", () => {
|
||||
const options = parseTelegramArgs([
|
||||
"--bot-token",
|
||||
"123:test",
|
||||
"--cwd",
|
||||
"/tmp/work",
|
||||
]);
|
||||
|
||||
expect(options.botUsername).toBeUndefined();
|
||||
expect(options.botToken).toBe("123:test");
|
||||
});
|
||||
|
||||
it("normalizes an explicit bot username", () => {
|
||||
const options = parseTelegramArgs([
|
||||
"--bot-username",
|
||||
" @test_bot ",
|
||||
"--bot-token",
|
||||
"123:test",
|
||||
"--cwd",
|
||||
"/tmp/work",
|
||||
]);
|
||||
|
||||
expect(options.botUsername).toBe("test_bot");
|
||||
});
|
||||
|
||||
it("does not call getMe when the token-only connector is already running", async () => {
|
||||
const dataDir = useTempClineDataDir();
|
||||
const connectorDir = join(dataDir, "connectors", "telegram");
|
||||
mkdirSync(connectorDir, { recursive: true });
|
||||
writeFileSync(
|
||||
join(connectorDir, "resolved_bot.json"),
|
||||
JSON.stringify({
|
||||
botUsername: "resolved_bot",
|
||||
botId: "123",
|
||||
pid: process.pid,
|
||||
rpcAddress: "127.0.0.1:54321",
|
||||
startedAt: new Date().toISOString(),
|
||||
}),
|
||||
);
|
||||
const fetchImpl = vi.fn(async () => {
|
||||
throw new Error("unexpected getMe call");
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchImpl);
|
||||
const output: string[] = [];
|
||||
const errors: string[] = [];
|
||||
|
||||
await expect(
|
||||
telegramConnector.run(["--bot-token", "123:test", "--cwd", "/tmp/work"], {
|
||||
writeln: (text = "") => output.push(text),
|
||||
writeErr: (text) => errors.push(text),
|
||||
}),
|
||||
).resolves.toBe(0);
|
||||
|
||||
expect(fetchImpl).not.toHaveBeenCalled();
|
||||
expect(errors).toEqual([]);
|
||||
expect(output).toEqual([
|
||||
`[telegram] connector already running pid=${process.pid} rpc=127.0.0.1:54321`,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("telegram bot username resolution", () => {
|
||||
it("reads the public Telegram bot id from a token", () => {
|
||||
expect(__test__.readTelegramBotId("123456:secret")).toBe("123456");
|
||||
expect(__test__.readTelegramBotId("not-a-token")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("uses the configured username without calling Telegram", async () => {
|
||||
const fetchImpl = vi.fn(async () => {
|
||||
throw new Error("unexpected fetch");
|
||||
});
|
||||
|
||||
await expect(
|
||||
__test__.resolveTelegramBotUsername(
|
||||
{
|
||||
botToken: "123:test",
|
||||
botUsername: "@configured_bot",
|
||||
cwd: "/tmp/work",
|
||||
mode: "act",
|
||||
interactive: true,
|
||||
enableTools: true,
|
||||
rpcAddress: "127.0.0.1:0",
|
||||
},
|
||||
fetchImpl,
|
||||
),
|
||||
).resolves.toBe("configured_bot");
|
||||
expect(fetchImpl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("fetches the username from Telegram getMe when omitted", async () => {
|
||||
const fetchImpl = vi.fn(async () => {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
ok: true,
|
||||
result: { username: "resolved_bot" },
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
await expect(
|
||||
__test__.fetchTelegramBotUsername("123:test", fetchImpl),
|
||||
).resolves.toBe("resolved_bot");
|
||||
expect(fetchImpl).toHaveBeenCalledWith(
|
||||
"https://api.telegram.org/bot123:test/getMe",
|
||||
);
|
||||
});
|
||||
|
||||
it("surfaces Telegram getMe failures", async () => {
|
||||
const fetchImpl = vi.fn(async () => {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
ok: false,
|
||||
description: "Unauthorized",
|
||||
}),
|
||||
{ status: 401, statusText: "Unauthorized" },
|
||||
);
|
||||
});
|
||||
|
||||
await expect(
|
||||
__test__.fetchTelegramBotUsername("bad-token", fetchImpl),
|
||||
).rejects.toThrow("Telegram getMe failed");
|
||||
});
|
||||
});
|
||||
|
||||
describe("telegram participant resolution", () => {
|
||||
|
||||
@@ -63,13 +63,86 @@ import { postTelegramFormattedReply } from "./telegram-format";
|
||||
const TELEGRAM_SYSTEM_RULES = getConnectorSystemRules("Telegram");
|
||||
|
||||
const TELEGRAM_FIRST_CONTACT_MESSAGE = getConnectorFirstContactMessage();
|
||||
const TELEGRAM_API_BASE = "https://api.telegram.org";
|
||||
|
||||
type TelegramThreadState = ConnectorThreadState;
|
||||
type ResolvedTelegramOptions = ConnectTelegramOptions & { botUsername: string };
|
||||
type TelegramGetMeResponse = {
|
||||
ok?: boolean;
|
||||
description?: string;
|
||||
result?: {
|
||||
username?: string;
|
||||
};
|
||||
};
|
||||
type FetchLike = (input: string | URL, init?: RequestInit) => Promise<Response>;
|
||||
|
||||
function truncateText(value: string, maxLength = 160): string {
|
||||
return truncateConnectorText(value, maxLength);
|
||||
}
|
||||
|
||||
function normalizeTelegramBotUsername(value: string): string {
|
||||
return value.trim().replace(/^@+/, "");
|
||||
}
|
||||
|
||||
function readTelegramBotId(botToken: string): string | undefined {
|
||||
const [botId] = botToken.trim().split(":", 1);
|
||||
return /^\d+$/.test(botId) ? botId : undefined;
|
||||
}
|
||||
|
||||
function describeTelegramGetMeFailure(
|
||||
response: Response,
|
||||
body: string,
|
||||
parsed: TelegramGetMeResponse | undefined,
|
||||
): string {
|
||||
const detail = parsed?.description || body.trim().slice(0, 240);
|
||||
return detail
|
||||
? `Telegram getMe failed (${response.status} ${response.statusText}): ${detail}`
|
||||
: `Telegram getMe failed (${response.status} ${response.statusText})`;
|
||||
}
|
||||
|
||||
async function readTelegramGetMeResponse(
|
||||
response: Response,
|
||||
): Promise<TelegramGetMeResponse> {
|
||||
const text = await response.text();
|
||||
let parsed: TelegramGetMeResponse;
|
||||
try {
|
||||
parsed = JSON.parse(text) as TelegramGetMeResponse;
|
||||
} catch {
|
||||
throw new Error(describeTelegramGetMeFailure(response, text, undefined));
|
||||
}
|
||||
if (!response.ok || parsed.ok !== true) {
|
||||
throw new Error(describeTelegramGetMeFailure(response, text, parsed));
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
async function fetchTelegramBotUsername(
|
||||
botToken: string,
|
||||
fetchImpl: FetchLike = fetch,
|
||||
apiBaseUrl = TELEGRAM_API_BASE,
|
||||
): Promise<string> {
|
||||
const response = await fetchImpl(`${apiBaseUrl}/bot${botToken}/getMe`);
|
||||
const payload = await readTelegramGetMeResponse(response);
|
||||
const username = normalizeTelegramBotUsername(payload.result?.username ?? "");
|
||||
if (!username) {
|
||||
throw new Error(
|
||||
"Telegram getMe did not return a bot username; pass --bot-username explicitly",
|
||||
);
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
async function resolveTelegramBotUsername(
|
||||
options: ConnectTelegramOptions,
|
||||
fetchImpl?: FetchLike,
|
||||
): Promise<string> {
|
||||
const configured = normalizeTelegramBotUsername(options.botUsername ?? "");
|
||||
if (configured) {
|
||||
return configured;
|
||||
}
|
||||
return fetchTelegramBotUsername(options.botToken, fetchImpl);
|
||||
}
|
||||
|
||||
async function stopSessionsForBot(
|
||||
state: TelegramConnectorState,
|
||||
): Promise<number> {
|
||||
@@ -331,8 +404,11 @@ class TelegramConnector extends ConnectorBase<
|
||||
protected override createCommand(): Command {
|
||||
return super
|
||||
.createCommand()
|
||||
.usage("-m <TELEGRAM_BOT_USERNAME> -k <TELEGRAM_BOT_TOKEN> [options]")
|
||||
.option("-m, --bot-username <name>", "Telegram bot username")
|
||||
.usage("-k <TELEGRAM_BOT_TOKEN> [options]")
|
||||
.option(
|
||||
"-m, --bot-username <name>",
|
||||
"Telegram bot username; fetched from token if omitted",
|
||||
)
|
||||
.option("-k, --bot-token <token>", "Telegram bot token")
|
||||
.option("--provider <id>", "Provider override")
|
||||
.option("--model <id>", "Model override")
|
||||
@@ -358,6 +434,7 @@ class TelegramConnector extends ConnectorBase<
|
||||
"Notes:",
|
||||
" - Without -i, the connector is launched in the background.",
|
||||
" - Tools are enabled by default for Telegram sessions.",
|
||||
" - Bot username is discovered from the Telegram bot token when omitted.",
|
||||
" - Provider/model default to the CLI's last-used provider settings.",
|
||||
].join("\n"),
|
||||
);
|
||||
@@ -379,18 +456,18 @@ class TelegramConnector extends ConnectorBase<
|
||||
hookCommand?: string;
|
||||
}>();
|
||||
const botUsername =
|
||||
opts.botUsername?.trim() || process.env.TELEGRAM_BOT_USERNAME?.trim();
|
||||
normalizeTelegramBotUsername(opts.botUsername ?? "") ||
|
||||
normalizeTelegramBotUsername(
|
||||
process.env.TELEGRAM_BOT_USERNAME?.trim() ?? "",
|
||||
);
|
||||
const botToken =
|
||||
opts.botToken?.trim() || process.env.TELEGRAM_BOT_TOKEN?.trim();
|
||||
if (!botUsername) {
|
||||
throw new Error("connect telegram requires -m/--bot-username <name>");
|
||||
}
|
||||
if (!botToken) {
|
||||
throw new Error("connect telegram requires -k/--bot-token <token>");
|
||||
}
|
||||
return {
|
||||
botToken,
|
||||
botUsername,
|
||||
...(botUsername ? { botUsername } : {}),
|
||||
cwd: opts.cwd || process.cwd(),
|
||||
model: opts.model,
|
||||
provider: opts.provider,
|
||||
@@ -445,6 +522,28 @@ class TelegramConnector extends ConnectorBase<
|
||||
this.writeStateFile(statePath, state);
|
||||
}
|
||||
|
||||
private findRunningConnectorStateByBotId(
|
||||
botId: string | undefined,
|
||||
): TelegramConnectorState | undefined {
|
||||
if (!botId) {
|
||||
return undefined;
|
||||
}
|
||||
for (const statePath of this.listConnectorStatePaths()) {
|
||||
const state = this.readConnectorState(statePath);
|
||||
if (!state) {
|
||||
continue;
|
||||
}
|
||||
if (!isProcessRunning(state.pid)) {
|
||||
this.removeStateFile(statePath);
|
||||
continue;
|
||||
}
|
||||
if (state.botId === botId) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async stopTelegramConnectorInstance(
|
||||
statePath: string,
|
||||
io: ConnectIo,
|
||||
@@ -475,10 +574,39 @@ class TelegramConnector extends ConnectorBase<
|
||||
}
|
||||
|
||||
protected override async runWithOptions(
|
||||
options: ConnectTelegramOptions,
|
||||
inputOptions: ConnectTelegramOptions,
|
||||
rawArgs: string[],
|
||||
io: ConnectIo,
|
||||
): Promise<number> {
|
||||
if (
|
||||
!inputOptions.botUsername &&
|
||||
!inputOptions.interactive &&
|
||||
process.env.CLINE_TELEGRAM_CONNECT_CHILD !== "1"
|
||||
) {
|
||||
const runningState = this.findRunningConnectorStateByBotId(
|
||||
readTelegramBotId(inputOptions.botToken),
|
||||
);
|
||||
if (runningState) {
|
||||
io.writeln(
|
||||
`[telegram] connector already running pid=${runningState.pid} rpc=${runningState.rpcAddress}`,
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
let resolvedBotUsername: string;
|
||||
try {
|
||||
resolvedBotUsername = await resolveTelegramBotUsername(inputOptions);
|
||||
} catch (error) {
|
||||
io.writeErr(error instanceof Error ? error.message : String(error));
|
||||
return 1;
|
||||
}
|
||||
const options: ResolvedTelegramOptions = {
|
||||
...inputOptions,
|
||||
botUsername: resolvedBotUsername,
|
||||
};
|
||||
const backgroundArgs = inputOptions.botUsername
|
||||
? rawArgs
|
||||
: [...rawArgs, "--bot-username", resolvedBotUsername];
|
||||
const statePath = this.resolveConnectorStatePath(options.botUsername);
|
||||
const bindingsPath = this.resolveBindingsPath(options.botUsername);
|
||||
this.removeStaleState(
|
||||
@@ -488,7 +616,7 @@ class TelegramConnector extends ConnectorBase<
|
||||
);
|
||||
if (
|
||||
await this.maybeRunInBackground({
|
||||
rawArgs,
|
||||
rawArgs: backgroundArgs,
|
||||
io,
|
||||
interactive: options.interactive,
|
||||
childEnvVar: "CLINE_TELEGRAM_CONNECT_CHILD",
|
||||
@@ -574,6 +702,7 @@ class TelegramConnector extends ConnectorBase<
|
||||
await client.connect();
|
||||
this.writeConnectorState(statePath, {
|
||||
botUsername: options.botUsername,
|
||||
botId: readTelegramBotId(options.botToken),
|
||||
pid: process.pid,
|
||||
rpcAddress,
|
||||
startedAt: new Date().toISOString(),
|
||||
@@ -847,7 +976,10 @@ class TelegramConnector extends ConnectorBase<
|
||||
requestStop("rpc_server_shutting_down");
|
||||
return;
|
||||
}
|
||||
if (event.eventType !== "schedule.execution.completed") {
|
||||
if (
|
||||
event.eventType !== "schedule.execution.completed" &&
|
||||
event.eventType !== "schedule.execution.failed"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const scheduleId =
|
||||
@@ -957,6 +1089,9 @@ export const telegramConnector: ConnectCommandDefinition =
|
||||
new TelegramConnector();
|
||||
|
||||
export const __test__ = {
|
||||
fetchTelegramBotUsername,
|
||||
readTelegramBotId,
|
||||
resolveTelegramBotUsername,
|
||||
resolveTelegramParticipant,
|
||||
findBindingForThread: (
|
||||
bindings: ConnectorBindingStore<TelegramThreadState>,
|
||||
|
||||
@@ -786,7 +786,10 @@ class WhatsAppConnector extends ConnectorBase<
|
||||
requestStop("rpc_server_shutting_down");
|
||||
return;
|
||||
}
|
||||
if (event.eventType !== "schedule.execution.completed") {
|
||||
if (
|
||||
event.eventType !== "schedule.execution.completed" &&
|
||||
event.eventType !== "schedule.execution.failed"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const scheduleId =
|
||||
|
||||
@@ -657,6 +657,27 @@ describe("runCli lightweight command dispatch", () => {
|
||||
expect(runtimeMocks.runInteractive).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("treats dash-prefixed positional text after -- as a prompt", async () => {
|
||||
forcePromptModeInput();
|
||||
process.argv = [
|
||||
"bun",
|
||||
"src/index.ts",
|
||||
"--",
|
||||
"- You are given a PyTorch state dictionary.",
|
||||
];
|
||||
|
||||
const { runCli } = await import("./main");
|
||||
|
||||
await expect(runCli()).resolves.toBeUndefined();
|
||||
expect(runtimeMocks.runAgent).toHaveBeenCalledTimes(1);
|
||||
expect(runtimeMocks.runAgent).toHaveBeenCalledWith(
|
||||
"- You are given a PyTorch state dictionary.",
|
||||
expect.any(Object),
|
||||
expect.anything(),
|
||||
);
|
||||
expect(runtimeMocks.runInteractive).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("applies --auto-approve as a runtime policy without changing the config default", async () => {
|
||||
process.argv = ["bun", "src/index.ts", "--auto-approve", "false"];
|
||||
|
||||
|
||||
@@ -245,8 +245,11 @@ export async function runCli(): Promise<void> {
|
||||
const pluginInstallCmd = pluginCmd
|
||||
.command("install")
|
||||
.alias("i")
|
||||
.description("Install a Cline Plugin from npm, git, or a local path")
|
||||
.argument("<source>", "npm package, git URL, or local plugin path")
|
||||
.description("Install a Cline Plugin from npm, git, URL, or a local path")
|
||||
.argument(
|
||||
"<source>",
|
||||
"npm package, git URL, plugin file URL, or local plugin path",
|
||||
)
|
||||
.option("--npm", "Treat source as an npm package")
|
||||
.option("--git", "Treat source as a git repository")
|
||||
.option("--force", "Replace an existing install for the same source")
|
||||
|
||||
@@ -42,6 +42,7 @@ function makeRuntime(): InteractiveChatCommandRuntime {
|
||||
return {
|
||||
forkCurrentSession: vi.fn(async () => undefined),
|
||||
getActiveSessionId: vi.fn(() => "session-1"),
|
||||
resetForNewSession: vi.fn(async () => {}),
|
||||
restartEmpty: vi.fn(async () => {}),
|
||||
};
|
||||
}
|
||||
@@ -101,6 +102,34 @@ describe("runInteractiveChatCommand", () => {
|
||||
expect(runtime.restartEmpty).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("resets slash new without eagerly restarting the runtime", async () => {
|
||||
const config = makeConfig();
|
||||
const runtime = makeRuntime();
|
||||
|
||||
const result = await runInteractiveChatCommand({
|
||||
prompt: "/new",
|
||||
enabled: true,
|
||||
config,
|
||||
host: chatCommandHost,
|
||||
chatCommandState: makeState(config),
|
||||
autoApproveAllRef: { current: false },
|
||||
setInteractiveAutoApprove: () => {},
|
||||
sessionRuntime: runtime,
|
||||
stop: () => {},
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
handled: true,
|
||||
turnResult: {
|
||||
usage: { inputTokens: 0, outputTokens: 0 },
|
||||
iterations: 0,
|
||||
commandOutput: "Started a fresh session.",
|
||||
},
|
||||
});
|
||||
expect(runtime.resetForNewSession).toHaveBeenCalledOnce();
|
||||
expect(runtime.restartEmpty).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("applies chat command state updates and returns command output", async () => {
|
||||
const config = makeConfig();
|
||||
const runtime = makeRuntime();
|
||||
|
||||
@@ -18,7 +18,10 @@ type AutoApproveRef = {
|
||||
|
||||
export type InteractiveChatCommandRuntime = Pick<
|
||||
ReturnType<typeof createInteractiveSessionRuntime>,
|
||||
"forkCurrentSession" | "getActiveSessionId" | "restartEmpty"
|
||||
| "forkCurrentSession"
|
||||
| "getActiveSessionId"
|
||||
| "resetForNewSession"
|
||||
| "restartEmpty"
|
||||
>;
|
||||
|
||||
export type InteractiveChatCommandResult =
|
||||
@@ -79,7 +82,7 @@ export async function runInteractiveChatCommand(input: {
|
||||
commandOutput = text;
|
||||
},
|
||||
reset: async () => {
|
||||
await input.sessionRuntime.restartEmpty();
|
||||
await input.sessionRuntime.resetForNewSession();
|
||||
},
|
||||
stop: async () => {
|
||||
input.stop();
|
||||
|
||||
@@ -3,6 +3,10 @@ import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import type { UserInstructionConfigService } from "@cline/core";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildSlashCommandRegistry,
|
||||
expandUserCommandPrompt,
|
||||
} from "../../tui/commands/slash-command-registry";
|
||||
import {
|
||||
applyPluginFailures,
|
||||
type InteractiveConfigItem,
|
||||
@@ -91,6 +95,19 @@ Use this skill.`,
|
||||
calls.push(`refreshType:${type}`);
|
||||
refreshed = true;
|
||||
},
|
||||
listRuntimeCommands() {
|
||||
calls.push("listRuntimeCommands");
|
||||
return refreshed
|
||||
? []
|
||||
: [
|
||||
{
|
||||
name: "skill-one",
|
||||
instructions: "Use this skill.",
|
||||
description: "Skill one",
|
||||
kind: "skill",
|
||||
},
|
||||
];
|
||||
},
|
||||
listRecords(type: string) {
|
||||
calls.push(`listRecords:${type}`);
|
||||
if (type !== "skill") {
|
||||
@@ -130,12 +147,97 @@ Use this skill.`,
|
||||
|
||||
expect(written).toContain("disabled: true");
|
||||
expect(data?.skills[0]?.enabled).toBe(false);
|
||||
expect(
|
||||
data?.workflowSlashCommands.map((command) => command.name),
|
||||
).not.toContain("skill-one");
|
||||
expect(calls).toContain("refreshType:skill");
|
||||
expect(calls.lastIndexOf("listRecords:skill")).toBeGreaterThan(
|
||||
calls.indexOf("refreshType:skill"),
|
||||
);
|
||||
});
|
||||
|
||||
it("returns refreshed slash commands so disabled skills stop expanding before submit", async () => {
|
||||
const tempRoot = await mkdtemp(join(tmpdir(), "cli-config-data-"));
|
||||
tempRoots.push(tempRoot);
|
||||
const skillPath = join(tempRoot, "SKILL.md");
|
||||
await writeFile(
|
||||
skillPath,
|
||||
`---
|
||||
name: find-skills
|
||||
---
|
||||
Find installable skills.`,
|
||||
);
|
||||
|
||||
let refreshed = false;
|
||||
const userInstructionService = {
|
||||
async refreshType() {
|
||||
refreshed = true;
|
||||
},
|
||||
listRuntimeCommands() {
|
||||
return refreshed
|
||||
? []
|
||||
: [
|
||||
{
|
||||
name: "find-skills",
|
||||
instructions: "Find installable skills.",
|
||||
description: "Find skills",
|
||||
kind: "skill",
|
||||
},
|
||||
];
|
||||
},
|
||||
listRecords(type: string) {
|
||||
if (type !== "skill") {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
{
|
||||
id: "find-skills",
|
||||
type: "skill",
|
||||
filePath: skillPath,
|
||||
item: {
|
||||
name: "find-skills",
|
||||
disabled: refreshed,
|
||||
description: "Find skills",
|
||||
instructions: "Find installable skills.",
|
||||
frontmatter: {},
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
} as unknown as UserInstructionConfigService;
|
||||
const loader = createInteractiveConfigDataLoader({
|
||||
config: createConfig(tempRoot),
|
||||
userInstructionService,
|
||||
});
|
||||
const initialData = await loader.loadConfigData();
|
||||
const initialRegistry = buildSlashCommandRegistry({
|
||||
workflowSlashCommands: initialData.workflowSlashCommands,
|
||||
});
|
||||
|
||||
expect(
|
||||
expandUserCommandPrompt("/find-skills what can u do?", initialRegistry),
|
||||
).toContain("<user_command");
|
||||
|
||||
const nextData = await loader.onToggleConfigItem({
|
||||
id: "find-skills",
|
||||
name: "find-skills",
|
||||
path: skillPath,
|
||||
enabled: true,
|
||||
source: "workspace",
|
||||
kind: "skill",
|
||||
});
|
||||
const refreshedRegistry = buildSlashCommandRegistry({
|
||||
workflowSlashCommands: nextData?.workflowSlashCommands,
|
||||
});
|
||||
|
||||
expect(
|
||||
nextData?.workflowSlashCommands.map((command) => command.name),
|
||||
).not.toContain("find-skills");
|
||||
expect(
|
||||
expandUserCommandPrompt("/find-skills what can u do?", refreshedRegistry),
|
||||
).toBe("/find-skills what can u do?");
|
||||
});
|
||||
|
||||
it("keeps plugin tool toggle behavior", async () => {
|
||||
const tempRoot = await mkdtemp(join(tmpdir(), "cli-config-data-"));
|
||||
tempRoots.push(tempRoot);
|
||||
@@ -163,7 +265,7 @@ Use this skill.`,
|
||||
) as { disabledTools?: string[] };
|
||||
|
||||
expect(settings.disabledTools).toEqual(["plugin-tool"]);
|
||||
expect(data).toBeDefined();
|
||||
expect(data).toBeUndefined();
|
||||
});
|
||||
|
||||
it("can skip plugin tool imports for fast settings open", async () => {
|
||||
@@ -341,13 +443,15 @@ Use this skill.`,
|
||||
}
|
||||
|
||||
const nextData = await loader.onToggleConfigItem(plugin);
|
||||
const refreshedData = await loader.loadConfigData();
|
||||
const settings = JSON.parse(
|
||||
await readFile(process.env.CLINE_GLOBAL_SETTINGS_PATH, "utf8"),
|
||||
) as { disabledPlugins?: string[] };
|
||||
|
||||
expect(settings.disabledPlugins).toBeUndefined();
|
||||
expect(nextData).toBeUndefined();
|
||||
expect(
|
||||
nextData?.plugins.find((item) => item.path === pluginPath)?.enabled,
|
||||
refreshedData.plugins.find((item) => item.path === pluginPath)?.enabled,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
createCoreSettingsService,
|
||||
setDisabledPlugin,
|
||||
setDisabledTools,
|
||||
type UserInstructionConfigService,
|
||||
} from "@cline/core";
|
||||
import {
|
||||
@@ -57,7 +58,7 @@ export function createInteractiveConfigDataLoader(input: {
|
||||
|
||||
if (item.kind === "plugin" && typeof item.enabled === "boolean") {
|
||||
setDisabledPlugin(item.path, item.enabled);
|
||||
return await loadConfigData(options);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (item.kind === "mcp" && typeof item.enabled === "boolean") {
|
||||
@@ -87,18 +88,22 @@ export function createInteractiveConfigDataLoader(input: {
|
||||
? item.toolNames
|
||||
: [item.name];
|
||||
const toolNames = [...new Set(rawToolNames.filter(Boolean))];
|
||||
if (typeof item.enabled === "boolean") {
|
||||
setDisabledTools(toolNames, item.enabled);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const name of toolNames) {
|
||||
await settings.toggle({
|
||||
type: "tools",
|
||||
name,
|
||||
enabled: typeof item.enabled === "boolean" ? !item.enabled : undefined,
|
||||
cwd: input.config.cwd,
|
||||
workspaceRoot: workspaceRoot(),
|
||||
userInstructionService: input.userInstructionService,
|
||||
availabilityContext: availabilityContext(),
|
||||
});
|
||||
}
|
||||
return await loadConfigData(options);
|
||||
return undefined;
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
import type {
|
||||
AgentEvent,
|
||||
ProviderSettingsManager,
|
||||
TeamEvent,
|
||||
ToolApprovalRequest,
|
||||
ToolApprovalResult,
|
||||
} from "@cline/core";
|
||||
import type { AgentTool } from "@cline/shared";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ChatCommandState } from "../../utils/chat-commands";
|
||||
import type { Config } from "../../utils/types";
|
||||
|
||||
const {
|
||||
mockCreateCliCore,
|
||||
mockCreateRuntimeHooks,
|
||||
mockLoadInteractiveResumeMessages,
|
||||
mockSetActiveCliSession,
|
||||
} = vi.hoisted(() => ({
|
||||
mockCreateCliCore: vi.fn(),
|
||||
mockCreateRuntimeHooks: vi.fn(),
|
||||
mockLoadInteractiveResumeMessages: vi.fn(),
|
||||
mockSetActiveCliSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../session/session", () => ({
|
||||
createCliCore: mockCreateCliCore,
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/hooks", () => ({
|
||||
createRuntimeHooks: mockCreateRuntimeHooks,
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/output", () => ({
|
||||
setActiveCliSession: mockSetActiveCliSession,
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/resume", () => ({
|
||||
loadInteractiveResumeMessages: mockLoadInteractiveResumeMessages,
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/approval", () => ({
|
||||
submitAndExitInTerminal: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../active-runtime", () => ({
|
||||
markAbortInProgress: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../session-events", () => ({
|
||||
subscribeToAgentEvents: vi.fn(() => vi.fn()),
|
||||
subscribeToPendingPromptEvents: vi.fn(() => vi.fn()),
|
||||
}));
|
||||
|
||||
import { createInteractiveSessionRuntime } from "./session-runtime";
|
||||
|
||||
function makeConfig(): Config {
|
||||
return {
|
||||
apiKey: "",
|
||||
providerId: "cline",
|
||||
modelId: "openai/gpt-5.3-codex",
|
||||
verbose: false,
|
||||
sandbox: false,
|
||||
thinking: false,
|
||||
outputMode: "text",
|
||||
mode: "act",
|
||||
systemPrompt: "",
|
||||
enableTools: true,
|
||||
enableSpawnAgent: true,
|
||||
enableAgentTeams: false,
|
||||
defaultToolAutoApprove: false,
|
||||
toolPolicies: {},
|
||||
cwd: "/tmp/work",
|
||||
workspaceRoot: "/tmp/work",
|
||||
};
|
||||
}
|
||||
|
||||
function makeChatCommandState(config: Config): ChatCommandState {
|
||||
return {
|
||||
enableTools: config.enableTools,
|
||||
autoApproveTools: config.defaultToolAutoApprove,
|
||||
cwd: config.cwd,
|
||||
workspaceRoot: config.workspaceRoot?.trim() || config.cwd,
|
||||
};
|
||||
}
|
||||
|
||||
function makeSwitchToActModeTool(): AgentTool {
|
||||
return {
|
||||
name: "switch_to_act_mode",
|
||||
description: "Switch to act mode",
|
||||
inputSchema: { type: "object", properties: {} },
|
||||
execute: () => ({ ok: true }),
|
||||
};
|
||||
}
|
||||
|
||||
function makeManager() {
|
||||
let startCount = 0;
|
||||
const start = vi.fn(async (_input?: unknown) => {
|
||||
startCount += 1;
|
||||
const sessionId = `session-${startCount}`;
|
||||
return {
|
||||
sessionId,
|
||||
manifest: {
|
||||
session_id: sessionId,
|
||||
},
|
||||
};
|
||||
});
|
||||
return {
|
||||
start,
|
||||
stop: vi.fn(async () => {}),
|
||||
send: vi.fn(),
|
||||
getAccumulatedUsage: vi.fn(),
|
||||
abort: vi.fn(),
|
||||
dispose: vi.fn(),
|
||||
get: vi.fn(),
|
||||
readMessages: vi.fn(async () => []),
|
||||
readTranscript: vi.fn(),
|
||||
ingestHookEvent: vi.fn(),
|
||||
subscribe: vi.fn(),
|
||||
updateSessionModel: vi.fn(),
|
||||
pendingPrompts: {
|
||||
update: vi.fn(),
|
||||
},
|
||||
restore: vi.fn(),
|
||||
};
|
||||
}
|
||||
|
||||
function makeRuntime(
|
||||
manager: ReturnType<typeof makeManager>,
|
||||
options: { resumeSessionId?: string } = {},
|
||||
) {
|
||||
mockCreateCliCore.mockResolvedValue(manager);
|
||||
const config = makeConfig();
|
||||
return createInteractiveSessionRuntime({
|
||||
config,
|
||||
providerSettingsManager: {} as ProviderSettingsManager,
|
||||
resumeSessionId: options.resumeSessionId,
|
||||
chatCommandState: makeChatCommandState(config),
|
||||
requestToolApproval: async (
|
||||
_request: ToolApprovalRequest,
|
||||
): Promise<ToolApprovalResult> => ({ approved: true }),
|
||||
askQuestionRef: { current: null },
|
||||
resolveMistakeLimitDecision: undefined,
|
||||
switchToActModeTool: makeSwitchToActModeTool(),
|
||||
onAgentEvent: (_event: AgentEvent) => {},
|
||||
onTeamEvent: (_event: TeamEvent) => {},
|
||||
onPendingPrompts: () => {},
|
||||
onPendingPromptSubmitted: () => {},
|
||||
});
|
||||
}
|
||||
|
||||
describe("createInteractiveSessionRuntime", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockCreateRuntimeHooks.mockReturnValue({
|
||||
hooks: undefined,
|
||||
shutdown: vi.fn(async () => {}),
|
||||
});
|
||||
mockLoadInteractiveResumeMessages.mockResolvedValue([]);
|
||||
});
|
||||
|
||||
it("defers creating the replacement session after a new-session reset", async () => {
|
||||
const manager = makeManager();
|
||||
const runtime = makeRuntime(manager);
|
||||
|
||||
await runtime.ensureReady();
|
||||
expect(manager.start).toHaveBeenCalledOnce();
|
||||
expect(runtime.getActiveSessionId()).toBe("session-1");
|
||||
|
||||
await runtime.resetForNewSession();
|
||||
|
||||
expect(manager.stop).toHaveBeenCalledWith("session-1");
|
||||
expect(manager.start).toHaveBeenCalledOnce();
|
||||
expect(runtime.getActiveSessionId()).toBe("");
|
||||
expect(mockSetActiveCliSession).toHaveBeenLastCalledWith(undefined);
|
||||
|
||||
await runtime.ensureReady();
|
||||
|
||||
expect(manager.start).toHaveBeenCalledTimes(2);
|
||||
expect(runtime.getActiveSessionId()).toBe("session-2");
|
||||
});
|
||||
|
||||
it("starts fresh after resetting an initially resumed session", async () => {
|
||||
const manager = makeManager();
|
||||
const runtime = makeRuntime(manager, {
|
||||
resumeSessionId: "resumed-session",
|
||||
});
|
||||
|
||||
await runtime.ensureReady();
|
||||
|
||||
expect(mockLoadInteractiveResumeMessages).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
manager,
|
||||
"resumed-session",
|
||||
);
|
||||
expect(manager.start).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
expect.objectContaining({
|
||||
config: expect.objectContaining({
|
||||
sessionId: "resumed-session",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
await runtime.resetForNewSession();
|
||||
await runtime.ensureReady();
|
||||
|
||||
expect(mockLoadInteractiveResumeMessages).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
manager,
|
||||
undefined,
|
||||
);
|
||||
expect(manager.start).toHaveBeenCalledTimes(2);
|
||||
expect(manager.start).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({
|
||||
config: expect.not.objectContaining({
|
||||
sessionId: "resumed-session",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps explicit empty restarts eager for config-driven restarts", async () => {
|
||||
const manager = makeManager();
|
||||
const runtime = makeRuntime(manager);
|
||||
|
||||
await runtime.ensureReady();
|
||||
await runtime.restartEmpty();
|
||||
|
||||
expect(manager.stop).toHaveBeenCalledWith("session-1");
|
||||
expect(manager.start).toHaveBeenCalledTimes(2);
|
||||
expect(runtime.getActiveSessionId()).toBe("session-2");
|
||||
});
|
||||
});
|
||||
@@ -74,8 +74,16 @@ export function createInteractiveSessionRuntime(input: {
|
||||
let shutdownRequested = false;
|
||||
let activeSessionId = "";
|
||||
let abortRequested = false;
|
||||
// A reset can happen while an earlier manager.start() is still in flight.
|
||||
// Bump this before resets and restarts so stale starts cannot become active.
|
||||
let sessionStartGeneration = 0;
|
||||
|
||||
const initialResumeSessionId = input.resumeSessionId?.trim() || undefined;
|
||||
let pendingResumeSessionId = input.resumeSessionId?.trim() || undefined;
|
||||
|
||||
const clearActiveSession = (): void => {
|
||||
activeSessionId = "";
|
||||
setActiveCliSession(undefined);
|
||||
};
|
||||
|
||||
const applyStartedSession = (started: StartedSession): void => {
|
||||
setActiveCliSession({
|
||||
@@ -155,6 +163,7 @@ export function createInteractiveSessionRuntime(input: {
|
||||
initial: Message[] = [],
|
||||
sessionMetadata?: Record<string, unknown>,
|
||||
): Promise<void> => {
|
||||
const generation = sessionStartGeneration;
|
||||
const manager = await ensureSessionManager();
|
||||
const started = await manager.start({
|
||||
source: SessionSource.CLI,
|
||||
@@ -168,6 +177,10 @@ export function createInteractiveSessionRuntime(input: {
|
||||
onTeamRestored: () => {},
|
||||
},
|
||||
});
|
||||
if (generation !== sessionStartGeneration) {
|
||||
await manager.stop(started.sessionId).catch(() => {});
|
||||
return;
|
||||
}
|
||||
applyStartedSession(started);
|
||||
};
|
||||
|
||||
@@ -175,6 +188,7 @@ export function createInteractiveSessionRuntime(input: {
|
||||
resumeId: string,
|
||||
initial: Message[] | undefined,
|
||||
): Promise<void> => {
|
||||
const generation = sessionStartGeneration;
|
||||
const manager = await ensureSessionManager();
|
||||
const started = await manager.start({
|
||||
source: SessionSource.CLI,
|
||||
@@ -190,24 +204,35 @@ export function createInteractiveSessionRuntime(input: {
|
||||
onTeamRestored: () => {},
|
||||
},
|
||||
});
|
||||
if (generation !== sessionStartGeneration) {
|
||||
await manager.stop(started.sessionId).catch(() => {});
|
||||
return;
|
||||
}
|
||||
applyStartedSession(started);
|
||||
};
|
||||
|
||||
const ensureReady = async (): Promise<void> => {
|
||||
if (activeSessionId) {
|
||||
return;
|
||||
}
|
||||
if (startupPromise) {
|
||||
return await startupPromise;
|
||||
}
|
||||
startupPromise = (async () => {
|
||||
const manager = await ensureSessionManager();
|
||||
const resumeSessionId = pendingResumeSessionId;
|
||||
const initialMessages = await loadInteractiveResumeMessages(
|
||||
manager,
|
||||
input.resumeSessionId,
|
||||
resumeSessionId,
|
||||
);
|
||||
if (shutdownRequested) {
|
||||
return;
|
||||
}
|
||||
if (initialResumeSessionId) {
|
||||
await startResumedSession(initialResumeSessionId, initialMessages);
|
||||
if (resumeSessionId) {
|
||||
await startResumedSession(resumeSessionId, initialMessages);
|
||||
if (pendingResumeSessionId === resumeSessionId) {
|
||||
pendingResumeSessionId = undefined;
|
||||
}
|
||||
} else {
|
||||
await startFreshSession(initialMessages);
|
||||
}
|
||||
@@ -226,8 +251,9 @@ export function createInteractiveSessionRuntime(input: {
|
||||
};
|
||||
|
||||
const stopCurrentSession = async (): Promise<void> => {
|
||||
if (sessionManager && activeSessionId) {
|
||||
await sessionManager.stop(activeSessionId);
|
||||
const sessionId = activeSessionId;
|
||||
if (sessionManager && sessionId) {
|
||||
await sessionManager.stop(sessionId);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -262,7 +288,12 @@ export function createInteractiveSessionRuntime(input: {
|
||||
messages: Message[],
|
||||
sessionMetadata?: Record<string, unknown>,
|
||||
): Promise<void> => {
|
||||
sessionStartGeneration += 1;
|
||||
pendingResumeSessionId = undefined;
|
||||
startupPromise = undefined;
|
||||
startupError = undefined;
|
||||
await stopCurrentSession();
|
||||
clearActiveSession();
|
||||
await startFreshSession(messages, sessionMetadata);
|
||||
};
|
||||
|
||||
@@ -275,6 +306,19 @@ export function createInteractiveSessionRuntime(input: {
|
||||
await restartWithMessages([]);
|
||||
};
|
||||
|
||||
const resetForNewSession = async (): Promise<void> => {
|
||||
sessionStartGeneration += 1;
|
||||
pendingResumeSessionId = undefined;
|
||||
startupPromise = undefined;
|
||||
startupError = undefined;
|
||||
const manager = sessionManager;
|
||||
const sessionId = activeSessionId;
|
||||
clearActiveSession();
|
||||
if (manager && sessionId) {
|
||||
await manager.stop(sessionId);
|
||||
}
|
||||
};
|
||||
|
||||
const applyMode = async (mode: "plan" | "act"): Promise<void> => {
|
||||
await applyInteractiveModeConfig({
|
||||
config: input.config,
|
||||
@@ -537,6 +581,7 @@ export function createInteractiveSessionRuntime(input: {
|
||||
getAccumulatedUsage,
|
||||
readCurrentMessages,
|
||||
restartEmpty,
|
||||
resetForNewSession,
|
||||
restartWithMessages,
|
||||
restartWithCurrentMessages,
|
||||
resumeSession,
|
||||
|
||||
@@ -585,6 +585,9 @@ export async function runInteractive(
|
||||
}
|
||||
await applyModeChange(mode);
|
||||
},
|
||||
onNewSession: async () => {
|
||||
await sessionRuntime.resetForNewSession();
|
||||
},
|
||||
onModelChange: async () => {
|
||||
await sessionRuntime.ensureReady();
|
||||
const existing = providerSettingsManager.getProviderSettings(
|
||||
|
||||
@@ -28,7 +28,7 @@ test.describe("cline --model (interactive mode, flag ignored)", () => {
|
||||
|
||||
test("starts interactive mode", async ({ terminal }) => {
|
||||
await waitForChatReady(terminal);
|
||||
await expectVisible(terminal, "GPT-5.3-Codex");
|
||||
await expectVisible(terminal, "GPT-5.3 Codex");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -166,6 +166,32 @@ describe("slash command registry", () => {
|
||||
expect(expandUserCommandPrompt("/settings", registry)).toBe("/settings");
|
||||
});
|
||||
|
||||
it("does not expand commands omitted from a refreshed user-command registry", () => {
|
||||
const staleRegistry = buildSlashCommandRegistry({
|
||||
workflowSlashCommands: [
|
||||
{
|
||||
name: "find-skills",
|
||||
instructions: "Find installable skills.",
|
||||
description: "Find skills",
|
||||
kind: "skill",
|
||||
},
|
||||
],
|
||||
});
|
||||
const refreshedRegistry = buildSlashCommandRegistry({
|
||||
workflowSlashCommands: [],
|
||||
});
|
||||
|
||||
expect(
|
||||
expandUserCommandPrompt("/find-skills what can u do?", staleRegistry),
|
||||
).toContain("<user_command");
|
||||
expect(
|
||||
resolveSlashCommand(refreshedRegistry, "find-skills"),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
expandUserCommandPrompt("/find-skills what can u do?", refreshedRegistry),
|
||||
).toBe("/find-skills what can u do?");
|
||||
});
|
||||
|
||||
it("hides fork from autocomplete until a session has messages", () => {
|
||||
const emptySessionRegistry = buildSlashCommandRegistry({ canFork: false });
|
||||
const activeSessionRegistry = buildSlashCommandRegistry({ canFork: true });
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from "../palette";
|
||||
import type { ChatEntry } from "../types";
|
||||
import { getSyntaxStyle } from "../utils/syntax-style";
|
||||
import { isWarningToolError } from "../utils/tool-errors";
|
||||
import {
|
||||
parseApplyPatchInput,
|
||||
parseAskQuestionInput,
|
||||
@@ -212,6 +213,7 @@ function ToolCallView(props: {
|
||||
defaultFg,
|
||||
} = props;
|
||||
const failed = result?.error != null;
|
||||
const warningFailure = isWarningToolError(result?.error);
|
||||
const params = formatToolParams(toolName, props.rawInput, inputSummary);
|
||||
|
||||
return (
|
||||
@@ -220,6 +222,8 @@ function ToolCallView(props: {
|
||||
<box width={2}>
|
||||
{streaming ? (
|
||||
<spinner name="dots" color="gray" />
|
||||
) : warningFailure ? (
|
||||
<text fg="yellow">!</text>
|
||||
) : failed ? (
|
||||
<text fg="red">x</text>
|
||||
) : (
|
||||
|
||||
@@ -33,25 +33,35 @@ export function ExtDetailContent(
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const previousItem = item;
|
||||
setToggleError(undefined);
|
||||
if (typeof item.enabled === "boolean") {
|
||||
setItem({ ...item, enabled: !item.enabled });
|
||||
}
|
||||
try {
|
||||
const nextData = await props.onToggleConfigItem(item, {
|
||||
includePluginTools: false,
|
||||
});
|
||||
const nextItem = [
|
||||
...(nextData?.workflows ?? []),
|
||||
...(nextData?.rules ?? []),
|
||||
...(nextData?.skills ?? []),
|
||||
...(nextData?.hooks ?? []),
|
||||
...(nextData?.agents ?? []),
|
||||
...(nextData?.plugins ?? []),
|
||||
...(nextData?.mcp ?? []),
|
||||
...(nextData?.tools ?? []),
|
||||
].find(
|
||||
(candidate) => candidate.id === item.id && candidate.path === item.path,
|
||||
);
|
||||
setItem(nextItem ?? { ...item, enabled: !item.enabled });
|
||||
if (nextData) {
|
||||
const nextItem = [
|
||||
...nextData.workflows,
|
||||
...nextData.rules,
|
||||
...nextData.skills,
|
||||
...nextData.hooks,
|
||||
...nextData.agents,
|
||||
...nextData.plugins,
|
||||
...nextData.mcp,
|
||||
...nextData.tools,
|
||||
].find(
|
||||
(candidate) =>
|
||||
candidate.id === item.id && candidate.path === item.path,
|
||||
);
|
||||
if (nextItem) {
|
||||
setItem(nextItem);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
setItem(previousItem);
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
setToggleError(`Failed to update ${item.name}: ${message}`);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { DialogActions, DialogId } from "@opentui-ui/dialog/react";
|
||||
|
||||
export type LoadingDialogActions = Pick<DialogActions, "show" | "close">;
|
||||
|
||||
export async function withShownDialog<T>(
|
||||
dialog: Pick<DialogActions, "close">,
|
||||
show: () => DialogId,
|
||||
run: () => Promise<T>,
|
||||
): Promise<T> {
|
||||
const loadingDialogId = show();
|
||||
// Give OpenTUI a microtask to mount the loading dialog before work starts.
|
||||
await Promise.resolve();
|
||||
try {
|
||||
return await run();
|
||||
} finally {
|
||||
dialog.close(loadingDialogId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import type { DialogActions, DialogId } from "@opentui-ui/dialog/react";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withShownDialog } from "./loading-dialog-lifecycle";
|
||||
|
||||
type LoadingDialogCall =
|
||||
| {
|
||||
name: "show";
|
||||
}
|
||||
| {
|
||||
name: "close";
|
||||
id: DialogId | undefined;
|
||||
};
|
||||
|
||||
function createDialog(calls: LoadingDialogCall[]) {
|
||||
return {
|
||||
close: (id?: DialogId): DialogId | undefined => {
|
||||
calls.push({ name: "close", id });
|
||||
return id;
|
||||
},
|
||||
} satisfies Pick<DialogActions, "close">;
|
||||
}
|
||||
|
||||
function showLoading(calls: LoadingDialogCall[]): DialogId {
|
||||
calls.push({ name: "show" });
|
||||
return "loading-dialog";
|
||||
}
|
||||
|
||||
describe("withShownDialog", () => {
|
||||
it("shows a loading dialog while work runs", async () => {
|
||||
const calls: LoadingDialogCall[] = [];
|
||||
const events: string[] = [];
|
||||
const dialog = createDialog(calls);
|
||||
|
||||
const result = await withShownDialog(
|
||||
dialog,
|
||||
() => showLoading(calls),
|
||||
async () => {
|
||||
events.push("run");
|
||||
return 42;
|
||||
},
|
||||
);
|
||||
|
||||
expect(result).toBe(42);
|
||||
expect(events).toEqual(["run"]);
|
||||
expect(calls.map((call) => call.name)).toEqual(["show", "close"]);
|
||||
expect(calls[1]).toEqual({ name: "close", id: "loading-dialog" });
|
||||
});
|
||||
|
||||
it("closes the loading dialog when work fails", async () => {
|
||||
const calls: LoadingDialogCall[] = [];
|
||||
const dialog = createDialog(calls);
|
||||
|
||||
await expect(
|
||||
withShownDialog(
|
||||
dialog,
|
||||
() => showLoading(calls),
|
||||
async () => {
|
||||
throw new Error("failed");
|
||||
},
|
||||
),
|
||||
).rejects.toThrow("failed");
|
||||
|
||||
expect(calls.map((call) => call.name)).toEqual(["show", "close"]);
|
||||
expect(calls[1]).toEqual({ name: "close", id: "loading-dialog" });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
// @jsxImportSource @opentui/react
|
||||
import type {
|
||||
DialogId,
|
||||
DialogSize,
|
||||
DialogStyle,
|
||||
} from "@opentui-ui/dialog/react";
|
||||
import "opentui-spinner/react";
|
||||
import {
|
||||
type LoadingDialogActions,
|
||||
withShownDialog,
|
||||
} from "./loading-dialog-lifecycle";
|
||||
|
||||
export interface LoadingDialogContentProps {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export function LoadingDialogContent(props: LoadingDialogContentProps) {
|
||||
return (
|
||||
<box flexDirection="row" gap={1} paddingX={1}>
|
||||
<spinner name="dots" color="gray" />
|
||||
<text fg="gray">{props.message}</text>
|
||||
</box>
|
||||
);
|
||||
}
|
||||
|
||||
export interface LoadingDialogOptions {
|
||||
size?: DialogSize;
|
||||
style?: DialogStyle;
|
||||
}
|
||||
|
||||
export function showLoadingDialog(
|
||||
dialog: LoadingDialogActions,
|
||||
message: string,
|
||||
options?: LoadingDialogOptions,
|
||||
): DialogId {
|
||||
return dialog.show({
|
||||
size: options?.size ?? "small",
|
||||
style: options?.style,
|
||||
closeOnEscape: false,
|
||||
closeOnClickOutside: false,
|
||||
content: () => <LoadingDialogContent message={message} />,
|
||||
});
|
||||
}
|
||||
|
||||
export async function withLoadingDialog<T>(
|
||||
dialog: LoadingDialogActions,
|
||||
message: string,
|
||||
run: () => Promise<T>,
|
||||
options?: LoadingDialogOptions,
|
||||
): Promise<T> {
|
||||
return await withShownDialog(
|
||||
dialog,
|
||||
() => showLoadingDialog(dialog, message, options),
|
||||
run,
|
||||
);
|
||||
}
|
||||
@@ -23,13 +23,13 @@ import {
|
||||
} from "../../../utils/codex-cli";
|
||||
import { isOAuthProvider } from "../../../utils/provider-auth";
|
||||
import { palette } from "../../palette";
|
||||
import { getProviderSection } from "../../utils/provider-sections";
|
||||
import {
|
||||
getDefaultAwsRegion,
|
||||
type ProviderConfigValues,
|
||||
resolveProviderConfigAwsRegion,
|
||||
updateProviderConfigValue,
|
||||
type ProviderConfigValues,
|
||||
} from "../../utils/provider-config-values";
|
||||
import { getProviderSection } from "../../utils/provider-sections";
|
||||
import {
|
||||
getSearchableListRowsWindow,
|
||||
type SearchableItem,
|
||||
@@ -456,6 +456,7 @@ export function ProviderConfigInputContent(
|
||||
return (
|
||||
<box key={key} flexDirection="column">
|
||||
<text fg="gray">{label}</text>
|
||||
{requirement.note && <text fg="gray">{requirement.note}</text>}
|
||||
<box
|
||||
border
|
||||
borderStyle="rounded"
|
||||
@@ -465,9 +466,7 @@ export function ProviderConfigInputContent(
|
||||
<input
|
||||
value={values[key] ?? ""}
|
||||
onInput={(v: string) =>
|
||||
setValues((prev) =>
|
||||
updateProviderConfigValue(prev, key, v),
|
||||
)
|
||||
setValues((prev) => updateProviderConfigValue(prev, key, v))
|
||||
}
|
||||
placeholder={placeholder}
|
||||
flexGrow={1}
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
shortenPath,
|
||||
} from "../../utils/tool-parsing";
|
||||
|
||||
function formatApprovalParams(
|
||||
export function formatApprovalParams(
|
||||
toolName: string,
|
||||
rawInput: unknown,
|
||||
): React.ReactNode {
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
import { useKeyboard, useTerminalDimensions } from "@opentui/react";
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { palette } from "../palette";
|
||||
import type { RuntimeToolInteraction } from "../types";
|
||||
import { formatApprovalParams } from "./dialogs/tool-approval";
|
||||
|
||||
export interface InlineToolResponseProps {
|
||||
interaction: RuntimeToolInteraction;
|
||||
accent: string;
|
||||
inputBackground: string;
|
||||
inputForeground: string;
|
||||
inputPlaceholder: string;
|
||||
onResolveToolApproval: (id: number, approved: boolean) => void;
|
||||
onResolveAskQuestion: (id: number, answer: string | null) => void;
|
||||
}
|
||||
|
||||
function isPrintableKey(name: string): boolean {
|
||||
return name.length === 1 || name === "space";
|
||||
}
|
||||
|
||||
function keyToText(name: string): string {
|
||||
return name === "space" ? " " : name;
|
||||
}
|
||||
|
||||
function Shell(
|
||||
props: Pick<
|
||||
InlineToolResponseProps,
|
||||
"accent" | "inputBackground" | "inputForeground"
|
||||
> & {
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
},
|
||||
) {
|
||||
const { height } = useTerminalDimensions();
|
||||
const maxHeight = Math.max(7, Math.min(14, Math.floor(height * 0.38)));
|
||||
|
||||
return (
|
||||
<box
|
||||
flexDirection="column"
|
||||
width="100%"
|
||||
maxHeight={maxHeight}
|
||||
backgroundColor={props.inputBackground}
|
||||
paddingX={1}
|
||||
paddingY={1}
|
||||
gap={1}
|
||||
>
|
||||
<box flexDirection="row" gap={1}>
|
||||
<text fg={palette.act}>{props.title}</text>
|
||||
</box>
|
||||
{props.children}
|
||||
</box>
|
||||
);
|
||||
}
|
||||
|
||||
function ChoiceButton(props: {
|
||||
label: string;
|
||||
selected: boolean;
|
||||
selectedFg?: string;
|
||||
onPress: () => void;
|
||||
}) {
|
||||
return (
|
||||
<box
|
||||
paddingX={1}
|
||||
backgroundColor={props.selected ? palette.selection : undefined}
|
||||
onMouseDown={props.onPress}
|
||||
>
|
||||
<text
|
||||
fg={
|
||||
props.selected
|
||||
? (props.selectedFg ?? palette.textOnSelection)
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{props.label}
|
||||
</text>
|
||||
</box>
|
||||
);
|
||||
}
|
||||
|
||||
function ToolApprovalResponse(
|
||||
props: InlineToolResponseProps & {
|
||||
interaction: Extract<RuntimeToolInteraction, { kind: "tool_approval" }>;
|
||||
},
|
||||
) {
|
||||
const [selected, setSelected] = useState<"approve" | "deny">("approve");
|
||||
const selectedRef = useRef(selected);
|
||||
selectedRef.current = selected;
|
||||
const request = props.interaction.request;
|
||||
const interactionId = props.interaction.id;
|
||||
const onResolveToolApproval = props.onResolveToolApproval;
|
||||
const params = formatApprovalParams(request.toolName, request.input);
|
||||
|
||||
const resolve = useCallback(
|
||||
(approved: boolean) => {
|
||||
onResolveToolApproval(interactionId, approved);
|
||||
},
|
||||
[interactionId, onResolveToolApproval],
|
||||
);
|
||||
|
||||
useKeyboard((key) => {
|
||||
if (key.name === "y") {
|
||||
resolve(true);
|
||||
return;
|
||||
}
|
||||
if (key.name === "n" || key.name === "escape") {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
if (key.name === "left" || key.name === "right" || key.name === "tab") {
|
||||
setSelected((current) => (current === "approve" ? "deny" : "approve"));
|
||||
return;
|
||||
}
|
||||
if (key.name === "return" || key.name === "enter") {
|
||||
resolve(selectedRef.current === "approve");
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Shell
|
||||
title="Cline needs permission"
|
||||
accent={props.accent}
|
||||
inputBackground={props.inputBackground}
|
||||
inputForeground={props.inputForeground}
|
||||
>
|
||||
<box flexDirection="column" gap={1}>
|
||||
<text fg="yellow">Approve tool call?</text>
|
||||
<text fg={props.accent} selectable>
|
||||
{request.toolName}
|
||||
</text>
|
||||
{params && (
|
||||
<box flexDirection="column" overflow="hidden">
|
||||
{params}
|
||||
</box>
|
||||
)}
|
||||
</box>
|
||||
<box flexDirection="row" gap={1}>
|
||||
<ChoiceButton
|
||||
label="[y] Approve"
|
||||
selected={selected === "approve"}
|
||||
onPress={() => resolve(true)}
|
||||
/>
|
||||
<ChoiceButton
|
||||
label="[n] Deny"
|
||||
selected={selected === "deny"}
|
||||
onPress={() => resolve(false)}
|
||||
/>
|
||||
</box>
|
||||
</Shell>
|
||||
);
|
||||
}
|
||||
|
||||
function AskQuestionResponse(
|
||||
props: InlineToolResponseProps & {
|
||||
interaction: Extract<RuntimeToolInteraction, { kind: "ask_question" }>;
|
||||
},
|
||||
) {
|
||||
const { interaction } = props;
|
||||
const [selected, setSelected] = useState(0);
|
||||
const [customValue, setCustomValue] = useState("");
|
||||
const [customEmptyAttempted, setCustomEmptyAttempted] = useState(false);
|
||||
const selectedRef = useRef(0);
|
||||
const customValueRef = useRef("");
|
||||
const interactionId = interaction.id;
|
||||
const onResolveAskQuestion = props.onResolveAskQuestion;
|
||||
const customIndex = interaction.options.length;
|
||||
const isTyping = selected === customIndex;
|
||||
const totalChoices = interaction.options.length + 1;
|
||||
|
||||
const selectIndex = useCallback(
|
||||
(index: number) => {
|
||||
selectedRef.current = index;
|
||||
setSelected(index);
|
||||
if (index !== customIndex) {
|
||||
setCustomEmptyAttempted(false);
|
||||
}
|
||||
},
|
||||
[customIndex],
|
||||
);
|
||||
|
||||
const setCustomText = useCallback((value: string) => {
|
||||
customValueRef.current = value;
|
||||
setCustomValue(value);
|
||||
if (value.trim()) {
|
||||
setCustomEmptyAttempted(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const resolveAnswer = useCallback(
|
||||
(answer: string | null) => {
|
||||
onResolveAskQuestion(interactionId, answer);
|
||||
},
|
||||
[interactionId, onResolveAskQuestion],
|
||||
);
|
||||
|
||||
useKeyboard((key) => {
|
||||
const typing = selectedRef.current === customIndex;
|
||||
if (key.name === "escape") {
|
||||
if (typing && customValueRef.current) {
|
||||
setCustomText("");
|
||||
return;
|
||||
}
|
||||
resolveAnswer(null);
|
||||
return;
|
||||
}
|
||||
if (typing && key.name === "backspace") {
|
||||
setCustomText(customValueRef.current.slice(0, -1));
|
||||
return;
|
||||
}
|
||||
if (typing && key.name === "delete") {
|
||||
setCustomText("");
|
||||
return;
|
||||
}
|
||||
if (key.name === "return" || key.name === "enter") {
|
||||
if (typing) {
|
||||
const answer = customValueRef.current.trim();
|
||||
if (answer) {
|
||||
resolveAnswer(answer);
|
||||
return;
|
||||
}
|
||||
setCustomEmptyAttempted(true);
|
||||
return;
|
||||
}
|
||||
resolveAnswer(interaction.options[selectedRef.current] ?? "");
|
||||
return;
|
||||
}
|
||||
if (key.name === "up" || (key.ctrl && key.name === "p")) {
|
||||
const next =
|
||||
selectedRef.current <= 0 ? totalChoices - 1 : selectedRef.current - 1;
|
||||
selectIndex(next);
|
||||
return;
|
||||
}
|
||||
if (key.name === "down" || (key.ctrl && key.name === "n")) {
|
||||
const next =
|
||||
selectedRef.current >= totalChoices - 1 ? 0 : selectedRef.current + 1;
|
||||
selectIndex(next);
|
||||
return;
|
||||
}
|
||||
if (!typing && key.name >= "1" && key.name <= "9") {
|
||||
const index = Number.parseInt(key.name, 10) - 1;
|
||||
const option = interaction.options[index];
|
||||
if (option) {
|
||||
resolveAnswer(option);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (typing && !key.ctrl && !key.meta && isPrintableKey(key.name)) {
|
||||
const value = keyToText(key.name);
|
||||
setCustomText(`${customValueRef.current}${value}`);
|
||||
return;
|
||||
}
|
||||
if (!key.ctrl && !key.meta && isPrintableKey(key.name)) {
|
||||
const value = keyToText(key.name);
|
||||
setCustomText(value);
|
||||
selectIndex(customIndex);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Shell
|
||||
title="Cline is asking a question"
|
||||
accent={props.accent}
|
||||
inputBackground={props.inputBackground}
|
||||
inputForeground={props.inputForeground}
|
||||
>
|
||||
<text fg={props.inputForeground} selectable>
|
||||
{interaction.question}
|
||||
</text>
|
||||
|
||||
<box flexDirection="column">
|
||||
{interaction.options.map((option, index) => {
|
||||
const optionSelected = !isTyping && selected === index;
|
||||
return (
|
||||
<box
|
||||
key={`${index.toString()}:${option}`}
|
||||
paddingX={1}
|
||||
flexDirection="row"
|
||||
gap={1}
|
||||
backgroundColor={optionSelected ? palette.selection : undefined}
|
||||
onMouseDown={() => resolveAnswer(option)}
|
||||
>
|
||||
<text
|
||||
fg={optionSelected ? palette.textOnSelection : "gray"}
|
||||
flexShrink={0}
|
||||
>
|
||||
{optionSelected ? ">" : " "}
|
||||
</text>
|
||||
<text
|
||||
fg={
|
||||
optionSelected
|
||||
? palette.textOnSelection
|
||||
: props.inputForeground
|
||||
}
|
||||
>
|
||||
{option}
|
||||
</text>
|
||||
</box>
|
||||
);
|
||||
})}
|
||||
<box
|
||||
paddingX={1}
|
||||
flexDirection="row"
|
||||
gap={1}
|
||||
backgroundColor={isTyping ? palette.selection : undefined}
|
||||
onMouseDown={() => selectIndex(customIndex)}
|
||||
>
|
||||
<text fg={isTyping ? palette.textOnSelection : "gray"} flexShrink={0}>
|
||||
{isTyping ? ">" : " "}
|
||||
</text>
|
||||
{isTyping ? (
|
||||
<text fg={palette.textOnSelection} flexGrow={1}>
|
||||
{customValue
|
||||
? `${customValue}|`
|
||||
: customEmptyAttempted
|
||||
? "Type a response first..."
|
||||
: "Type a response..."}
|
||||
</text>
|
||||
) : (
|
||||
<text fg={props.inputPlaceholder}>Type a response...</text>
|
||||
)}
|
||||
</box>
|
||||
</box>
|
||||
</Shell>
|
||||
);
|
||||
}
|
||||
|
||||
export function InlineToolResponse(props: InlineToolResponseProps) {
|
||||
if (props.interaction.kind === "tool_approval") {
|
||||
return <ToolApprovalResponse {...props} interaction={props.interaction} />;
|
||||
}
|
||||
|
||||
return <AskQuestionResponse {...props} interaction={props.interaction} />;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { useTerminalTheme } from "../hooks/use-terminal-background";
|
||||
import { diffPalettes, palette, type TerminalTheme } from "../palette";
|
||||
import { makeUnifiedDiff } from "../utils/diff";
|
||||
import { getSyntaxStyle } from "../utils/syntax-style";
|
||||
import { getToolErrorPresentation } from "../utils/tool-errors";
|
||||
import {
|
||||
detectLanguage,
|
||||
extractFullOutputText,
|
||||
@@ -292,13 +293,29 @@ function GenericOutput(props: { outputSummary: string; fullText?: string }) {
|
||||
export function ToolOutput(props: ToolOutputProps) {
|
||||
const { toolName, outputSummary, rawOutput, rawInput, error } = props;
|
||||
const terminalTheme = useTerminalTheme();
|
||||
const [errorExpanded, setErrorExpanded] = useState(false);
|
||||
|
||||
if (error) {
|
||||
const presentation = getToolErrorPresentation(error);
|
||||
const isWarning = presentation.severity === "warning";
|
||||
const showDetail =
|
||||
errorExpanded && presentation.detail !== presentation.summary.trim();
|
||||
return (
|
||||
<box paddingLeft={2}>
|
||||
<text fg="red" selectable>
|
||||
{" "} Error: {error}
|
||||
<box
|
||||
flexDirection="column"
|
||||
paddingLeft={2}
|
||||
onMouseDown={() => setErrorExpanded(!errorExpanded)}
|
||||
>
|
||||
<text fg={isWarning ? "yellow" : "red"} selectable>
|
||||
{" "} {isWarning ? "!" : "Error:"} {presentation.summary}
|
||||
</text>
|
||||
{showDetail && (
|
||||
<box paddingLeft={3}>
|
||||
<text fg="gray" selectable>
|
||||
{presentation.detail}
|
||||
</text>
|
||||
</box>
|
||||
)}
|
||||
</box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -218,23 +218,20 @@ export function SessionProvider(props: {
|
||||
setLastTotalCost(0);
|
||||
}, []);
|
||||
|
||||
const addUsageDelta = useCallback(
|
||||
(usage: UsageDelta) => {
|
||||
const nextTotalTokens = nextUsageTokenDisplay(0, usage);
|
||||
if (nextTotalTokens > 0) {
|
||||
setLastTotalTokens((prev) => nextUsageTokenDisplay(prev, usage));
|
||||
}
|
||||
const costDelta = usage.cost;
|
||||
if (
|
||||
typeof costDelta === "number" &&
|
||||
Number.isFinite(costDelta) &&
|
||||
costDelta > 0
|
||||
) {
|
||||
setLastTotalCost((prev) => prev + costDelta);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
const addUsageDelta = useCallback((usage: UsageDelta) => {
|
||||
const nextTotalTokens = nextUsageTokenDisplay(0, usage);
|
||||
if (nextTotalTokens > 0) {
|
||||
setLastTotalTokens((prev) => nextUsageTokenDisplay(prev, usage));
|
||||
}
|
||||
const costDelta = usage.cost;
|
||||
if (
|
||||
typeof costDelta === "number" &&
|
||||
Number.isFinite(costDelta) &&
|
||||
costDelta > 0
|
||||
) {
|
||||
setLastTotalCost((prev) => prev + costDelta);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const replaceEntries = useCallback((nextEntries: ChatEntry[]) => {
|
||||
setEntries(
|
||||
|
||||
@@ -198,13 +198,8 @@ export function useAutocomplete(opts: {
|
||||
);
|
||||
|
||||
const getFilteredMentionOptions = useCallback(
|
||||
(query: string): AutocompleteOption[] => {
|
||||
const q = query.toLowerCase();
|
||||
let filtered = mentionResults;
|
||||
if (q) {
|
||||
filtered = mentionResults.filter((f) => f.toLowerCase().includes(q));
|
||||
}
|
||||
return filtered.slice(0, MAX_COMPLETION_RESULTS).map((f) => ({
|
||||
(_query: string): AutocompleteOption[] => {
|
||||
return mentionResults.slice(0, MAX_COMPLETION_RESULTS).map((f) => ({
|
||||
display: f,
|
||||
value: formatMentionAutocompleteValue(f),
|
||||
}));
|
||||
@@ -233,6 +228,7 @@ export function useAutocomplete(opts: {
|
||||
if (searchTimerRef.current) {
|
||||
clearTimeout(searchTimerRef.current);
|
||||
}
|
||||
setMentionResults([]);
|
||||
const counter = ++searchCounterRef.current;
|
||||
searchTimerRef.current = setTimeout(() => {
|
||||
searchWorkspaceFilesForMention({
|
||||
|
||||
@@ -9,6 +9,7 @@ import type {
|
||||
} from "../../tui/interactive-config";
|
||||
import type { CliCompactionMode, Config } from "../../utils/types";
|
||||
import { ExtDetailContent } from "../components/dialogs/config-dialogs";
|
||||
import { withLoadingDialog } from "../components/dialogs/loading-dialog";
|
||||
import { ConfigPanelContent } from "../views/config-view";
|
||||
import type { ConfigAction } from "../views/config-view-helpers";
|
||||
import type { OpenModelSelectorOptions } from "./use-model-selector";
|
||||
@@ -43,6 +44,7 @@ export function useConfigPanel(opts: {
|
||||
plugins: [] as InteractiveConfigItem[],
|
||||
mcp: [] as InteractiveConfigItem[],
|
||||
tools: [] as InteractiveConfigItem[],
|
||||
workflowSlashCommands: [],
|
||||
}),
|
||||
[],
|
||||
);
|
||||
@@ -50,12 +52,17 @@ export function useConfigPanel(opts: {
|
||||
const openConfig = useCallback(async () => {
|
||||
let keepOpen = true;
|
||||
while (keepOpen) {
|
||||
const [data, providerInfo] = await Promise.all([
|
||||
opts
|
||||
.loadConfigData({ includePluginTools: false })
|
||||
.catch(() => emptyConfigData),
|
||||
Llms.getProvider(opts.config.providerId).catch(() => undefined),
|
||||
]);
|
||||
const [data, providerInfo] = await withLoadingDialog(
|
||||
opts.dialog,
|
||||
"Loading settings...",
|
||||
async () =>
|
||||
await Promise.all([
|
||||
opts
|
||||
.loadConfigData({ includePluginTools: false })
|
||||
.catch(() => emptyConfigData),
|
||||
Llms.getProvider(opts.config.providerId).catch(() => undefined),
|
||||
]),
|
||||
);
|
||||
const providerDisplayName = providerInfo?.name ?? opts.config.providerId;
|
||||
const action = await opts.dialog.choice<ConfigAction>({
|
||||
size: "large",
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { SlashCommandRegistry } from "../commands/slash-command-registry";
|
||||
import { resolveSlashCommand } from "../commands/slash-command-registry";
|
||||
import { ForkConfirmContent } from "../components/dialogs/fork-confirm";
|
||||
import { HelpDialogContent } from "../components/dialogs/help-dialog";
|
||||
import { withLoadingDialog } from "../components/dialogs/loading-dialog";
|
||||
import { useSession } from "../contexts/session-context";
|
||||
import type { AppView, TuiProps } from "../types";
|
||||
import { formatCompactionStatus } from "../utils/compaction-status";
|
||||
@@ -62,28 +63,30 @@ export function useLocalCommandActions(input: {
|
||||
});
|
||||
if (sessionId) {
|
||||
try {
|
||||
const result = await onResumeSession(sessionId);
|
||||
const { messages } = result;
|
||||
const entries = hydrateSessionMessages(messages);
|
||||
if (entries.length === 0) {
|
||||
session.appendEntry({
|
||||
kind: "error",
|
||||
text: `Session ${sessionId} has no messages to resume.`,
|
||||
});
|
||||
} else {
|
||||
session.clearEntries();
|
||||
for (const entry of entries) {
|
||||
session.appendEntry(entry);
|
||||
await withLoadingDialog(dialog, "Loading session...", async () => {
|
||||
const result = await onResumeSession(sessionId);
|
||||
const { messages } = result;
|
||||
const entries = hydrateSessionMessages(messages);
|
||||
if (entries.length === 0) {
|
||||
session.appendEntry({
|
||||
kind: "error",
|
||||
text: `Session ${sessionId} has no messages to resume.`,
|
||||
});
|
||||
} else {
|
||||
session.clearEntries();
|
||||
for (const entry of entries) {
|
||||
session.appendEntry(entry);
|
||||
}
|
||||
if (typeof result.currentContextSize === "number") {
|
||||
session.setLastTotalTokens(result.currentContextSize);
|
||||
}
|
||||
if (typeof result.totalCost === "number") {
|
||||
session.setLastTotalCost(result.totalCost);
|
||||
}
|
||||
session.setHasSubmitted(true);
|
||||
setAppView("chat");
|
||||
}
|
||||
if (typeof result.currentContextSize === "number") {
|
||||
session.setLastTotalTokens(result.currentContextSize);
|
||||
}
|
||||
if (typeof result.totalCost === "number") {
|
||||
session.setLastTotalCost(result.totalCost);
|
||||
}
|
||||
session.setHasSubmitted(true);
|
||||
setAppView("chat");
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
session.appendEntry({
|
||||
kind: "error",
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
isProviderConfigured,
|
||||
} from "../../utils/provider-auth";
|
||||
import type { Config } from "../../utils/types";
|
||||
import { withLoadingDialog } from "../components/dialogs/loading-dialog";
|
||||
import {
|
||||
CodexCliStatusContent,
|
||||
type ExistingProviderAction,
|
||||
@@ -91,8 +92,12 @@ async function runProviderChange(
|
||||
});
|
||||
if (!newProviderId) return false;
|
||||
|
||||
const displayName = await getProviderDisplayName(newProviderId);
|
||||
const manager = new ProviderSettingsManager();
|
||||
const displayName = await withLoadingDialog(
|
||||
dialog,
|
||||
"Loading provider...",
|
||||
async () => await getProviderDisplayName(newProviderId),
|
||||
);
|
||||
const existingSettings = manager.getProviderSettings(newProviderId);
|
||||
|
||||
let needsAuth = true;
|
||||
@@ -153,40 +158,48 @@ async function runProviderChange(
|
||||
}
|
||||
if (!saved) return false;
|
||||
}
|
||||
await refreshProviderModelsFromSource(manager, newProviderId).catch(() => {});
|
||||
const newSettings = manager.getProviderSettings(newProviderId);
|
||||
const newApiKey =
|
||||
getPersistedProviderApiKey(newProviderId, newSettings) ?? "";
|
||||
await withLoadingDialog(
|
||||
dialog,
|
||||
`Loading ${displayName} models...`,
|
||||
async () => {
|
||||
await refreshProviderModelsFromSource(manager, newProviderId).catch(
|
||||
() => {},
|
||||
);
|
||||
const newSettings = manager.getProviderSettings(newProviderId);
|
||||
const newApiKey =
|
||||
getPersistedProviderApiKey(newProviderId, newSettings) ?? "";
|
||||
|
||||
manager.saveProviderSettings(
|
||||
{
|
||||
...(newSettings ?? {}),
|
||||
provider: newProviderId,
|
||||
manager.saveProviderSettings(
|
||||
{
|
||||
...(newSettings ?? {}),
|
||||
provider: newProviderId,
|
||||
},
|
||||
{ setLastUsed: true },
|
||||
);
|
||||
|
||||
config.providerId = newProviderId;
|
||||
config.apiKey = newApiKey;
|
||||
|
||||
const resolved = await resolveProviderConfig(
|
||||
newProviderId,
|
||||
{
|
||||
loadLatestOnInit: true,
|
||||
loadPrivateOnAuth: true,
|
||||
failOnError: false,
|
||||
},
|
||||
manager.getProviderConfig(newProviderId, { includeKnownModels: false }),
|
||||
);
|
||||
config.knownModels = resolved?.knownModels;
|
||||
const modelIds = Object.keys(resolved?.knownModels ?? {});
|
||||
if (newSettings?.model) {
|
||||
config.modelId = newSettings.model;
|
||||
} else if (modelIds[0]) {
|
||||
config.modelId = modelIds[0];
|
||||
}
|
||||
|
||||
await onModelChange();
|
||||
},
|
||||
{ setLastUsed: true },
|
||||
);
|
||||
|
||||
config.providerId = newProviderId;
|
||||
config.apiKey = newApiKey;
|
||||
|
||||
const resolved = await resolveProviderConfig(
|
||||
newProviderId,
|
||||
{
|
||||
loadLatestOnInit: true,
|
||||
loadPrivateOnAuth: true,
|
||||
failOnError: false,
|
||||
},
|
||||
manager.getProviderConfig(newProviderId, { includeKnownModels: false }),
|
||||
);
|
||||
config.knownModels = resolved?.knownModels;
|
||||
const modelIds = Object.keys(resolved?.knownModels ?? {});
|
||||
if (newSettings?.model) {
|
||||
config.modelId = newSettings.model;
|
||||
} else if (modelIds[0]) {
|
||||
config.modelId = modelIds[0];
|
||||
}
|
||||
|
||||
await onModelChange();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -209,11 +222,10 @@ export function useModelSelector(opts: {
|
||||
refocusTextarea();
|
||||
};
|
||||
|
||||
await refreshCurrentProviderModels(config);
|
||||
let modelOptions = buildModelOptions(
|
||||
config.knownModels as Record<string, Llms.ModelInfo>,
|
||||
);
|
||||
let providerDisplayName = await getProviderDisplayName(config.providerId);
|
||||
let providerDisplayName = config.providerId;
|
||||
|
||||
const refreshProviderContext = async () => {
|
||||
modelOptions = buildModelOptions(
|
||||
@@ -222,6 +234,13 @@ export function useModelSelector(opts: {
|
||||
providerDisplayName = await getProviderDisplayName(config.providerId);
|
||||
};
|
||||
|
||||
if (!options?.startWithProviderChange) {
|
||||
await withLoadingDialog(dialog, "Loading models...", async () => {
|
||||
await refreshCurrentProviderModels(config);
|
||||
await refreshProviderContext();
|
||||
});
|
||||
}
|
||||
|
||||
const changeProvider = async (): Promise<boolean> => {
|
||||
const changed = await runProviderChange(
|
||||
dialog,
|
||||
@@ -229,7 +248,11 @@ export function useModelSelector(opts: {
|
||||
termHeight,
|
||||
onModelChange,
|
||||
);
|
||||
if (changed) await refreshProviderContext();
|
||||
if (changed) {
|
||||
await withLoadingDialog(dialog, "Loading models...", async () => {
|
||||
await refreshProviderContext();
|
||||
});
|
||||
}
|
||||
return changed;
|
||||
};
|
||||
|
||||
@@ -446,7 +469,9 @@ export function useModelSelector(opts: {
|
||||
pickingModel = false;
|
||||
}
|
||||
|
||||
await onModelChange();
|
||||
await withLoadingDialog(dialog, "Applying model...", async () => {
|
||||
await onModelChange();
|
||||
});
|
||||
refocusTextarea();
|
||||
},
|
||||
[dialog, config, termHeight, onModelChange, refocusTextarea],
|
||||
|
||||
@@ -1,11 +1,55 @@
|
||||
import type { AgentMode } from "@cline/core";
|
||||
import { useTerminalDimensions } from "@opentui/react";
|
||||
import type { ChoiceContext } from "@opentui-ui/dialog";
|
||||
import { useDialog } from "@opentui-ui/dialog/react";
|
||||
import { useEffect } from "react";
|
||||
import { AskQuestionContent } from "../components/dialogs/ask-question";
|
||||
import { ToolApprovalContent } from "../components/dialogs/tool-approval";
|
||||
import type { TuiProps } from "../types";
|
||||
import type { ToolApprovalRequest, ToolApprovalResult } from "@cline/shared";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import type { RuntimeToolInteraction, TuiProps } from "../types";
|
||||
|
||||
type PendingRuntimeToolInteraction =
|
||||
| {
|
||||
id: number;
|
||||
kind: "tool_approval";
|
||||
request: ToolApprovalRequest;
|
||||
resolve: (result: ToolApprovalResult) => void;
|
||||
}
|
||||
| {
|
||||
id: number;
|
||||
kind: "ask_question";
|
||||
question: string;
|
||||
options: string[];
|
||||
resolve: (answer: string) => void;
|
||||
};
|
||||
|
||||
function toRuntimeToolInteraction(
|
||||
pending: PendingRuntimeToolInteraction,
|
||||
): RuntimeToolInteraction {
|
||||
if (pending.kind === "tool_approval") {
|
||||
return {
|
||||
id: pending.id,
|
||||
kind: pending.kind,
|
||||
request: pending.request,
|
||||
};
|
||||
}
|
||||
return {
|
||||
id: pending.id,
|
||||
kind: pending.kind,
|
||||
question: pending.question,
|
||||
options: pending.options,
|
||||
};
|
||||
}
|
||||
|
||||
function deniedToolResult(request: ToolApprovalRequest): ToolApprovalResult {
|
||||
return {
|
||||
approved: false,
|
||||
reason: `Tool "${request.toolName}" was denied by user`,
|
||||
};
|
||||
}
|
||||
|
||||
function dismissPendingInteraction(pending: PendingRuntimeToolInteraction) {
|
||||
if (pending.kind === "tool_approval") {
|
||||
pending.resolve(deniedToolResult(pending.request));
|
||||
return;
|
||||
}
|
||||
pending.resolve("[User dismissed the question]");
|
||||
}
|
||||
|
||||
export function useRuntimeDialogBridge(input: {
|
||||
setToolApprover: TuiProps["setToolApprover"];
|
||||
@@ -14,8 +58,6 @@ export function useRuntimeDialogBridge(input: {
|
||||
setUiMode: (mode: AgentMode) => void;
|
||||
refocusTextarea: () => void;
|
||||
}) {
|
||||
const dialog = useDialog();
|
||||
const { height: termHeight } = useTerminalDimensions();
|
||||
const {
|
||||
setToolApprover,
|
||||
setAskQuestion,
|
||||
@@ -23,38 +65,118 @@ export function useRuntimeDialogBridge(input: {
|
||||
setUiMode,
|
||||
refocusTextarea,
|
||||
} = input;
|
||||
const [interaction, setInteraction] = useState<RuntimeToolInteraction | null>(
|
||||
null,
|
||||
);
|
||||
const activeRef = useRef<PendingRuntimeToolInteraction | null>(null);
|
||||
const queueRef = useRef<PendingRuntimeToolInteraction[]>([]);
|
||||
const nextIdRef = useRef(1);
|
||||
|
||||
const activate = useCallback((pending: PendingRuntimeToolInteraction) => {
|
||||
activeRef.current = pending;
|
||||
setInteraction(toRuntimeToolInteraction(pending));
|
||||
}, []);
|
||||
|
||||
const enqueue = useCallback(
|
||||
(pending: PendingRuntimeToolInteraction) => {
|
||||
if (activeRef.current) {
|
||||
queueRef.current.push(pending);
|
||||
return;
|
||||
}
|
||||
activate(pending);
|
||||
},
|
||||
[activate],
|
||||
);
|
||||
|
||||
const finishActive = useCallback(
|
||||
(id: number) => {
|
||||
if (activeRef.current?.id !== id) {
|
||||
return false;
|
||||
}
|
||||
const next = queueRef.current.shift() ?? null;
|
||||
if (next) {
|
||||
activate(next);
|
||||
return true;
|
||||
}
|
||||
activeRef.current = null;
|
||||
setInteraction(null);
|
||||
return false;
|
||||
},
|
||||
[activate],
|
||||
);
|
||||
|
||||
const resolveToolApproval = useCallback(
|
||||
(id: number, approved: boolean) => {
|
||||
const pending = activeRef.current;
|
||||
if (!pending || pending.id !== id || pending.kind !== "tool_approval") {
|
||||
return;
|
||||
}
|
||||
pending.resolve(
|
||||
approved ? { approved: true } : deniedToolResult(pending.request),
|
||||
);
|
||||
const hasNext = finishActive(id);
|
||||
if (!hasNext) {
|
||||
refocusTextarea();
|
||||
}
|
||||
},
|
||||
[finishActive, refocusTextarea],
|
||||
);
|
||||
|
||||
const resolveAskQuestion = useCallback(
|
||||
(id: number, answer: string | null) => {
|
||||
const pending = activeRef.current;
|
||||
if (!pending || pending.id !== id || pending.kind !== "ask_question") {
|
||||
return;
|
||||
}
|
||||
pending.resolve(
|
||||
answer === null ? "[User dismissed the question]" : answer,
|
||||
);
|
||||
const hasNext = finishActive(id);
|
||||
if (!hasNext) {
|
||||
refocusTextarea();
|
||||
}
|
||||
},
|
||||
[finishActive, refocusTextarea],
|
||||
);
|
||||
|
||||
const dismissAll = useCallback(() => {
|
||||
if (activeRef.current) {
|
||||
dismissPendingInteraction(activeRef.current);
|
||||
activeRef.current = null;
|
||||
}
|
||||
for (const pending of queueRef.current) {
|
||||
dismissPendingInteraction(pending);
|
||||
}
|
||||
queueRef.current = [];
|
||||
setInteraction(null);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setToolApprover(async (request) => {
|
||||
const approved = await dialog.choice<boolean>({
|
||||
style: { maxHeight: termHeight - 2 },
|
||||
closeOnEscape: false,
|
||||
content: (ctx: ChoiceContext<boolean>) => (
|
||||
<ToolApprovalContent {...ctx} request={request} />
|
||||
),
|
||||
});
|
||||
if (approved) {
|
||||
return { approved: true };
|
||||
}
|
||||
return {
|
||||
approved: false,
|
||||
reason: `Tool "${request.toolName}" was denied by user`,
|
||||
};
|
||||
});
|
||||
setAskQuestion(async (question, options) => {
|
||||
const answer = await dialog.choice<string | null>({
|
||||
style: { maxHeight: termHeight - 2 },
|
||||
closeOnEscape: false,
|
||||
content: (ctx: ChoiceContext<string | null>) => (
|
||||
<AskQuestionContent {...ctx} question={question} options={options} />
|
||||
),
|
||||
});
|
||||
refocusTextarea();
|
||||
if (answer === null) {
|
||||
return "[User dismissed the question]";
|
||||
}
|
||||
return answer ?? options[0] ?? "";
|
||||
});
|
||||
setToolApprover(
|
||||
(request) =>
|
||||
new Promise<ToolApprovalResult>((resolve) => {
|
||||
enqueue({
|
||||
id: nextIdRef.current,
|
||||
kind: "tool_approval",
|
||||
request,
|
||||
resolve,
|
||||
});
|
||||
nextIdRef.current += 1;
|
||||
}),
|
||||
);
|
||||
setAskQuestion(
|
||||
(question, options) =>
|
||||
new Promise<string>((resolve) => {
|
||||
enqueue({
|
||||
id: nextIdRef.current,
|
||||
kind: "ask_question",
|
||||
question,
|
||||
options,
|
||||
resolve,
|
||||
});
|
||||
nextIdRef.current += 1;
|
||||
}),
|
||||
);
|
||||
setModeChangeNotifier((mode) => {
|
||||
setUiMode(mode);
|
||||
});
|
||||
@@ -62,14 +184,20 @@ export function useRuntimeDialogBridge(input: {
|
||||
setToolApprover(null);
|
||||
setAskQuestion(null);
|
||||
setModeChangeNotifier(null);
|
||||
dismissAll();
|
||||
};
|
||||
}, [
|
||||
dialog,
|
||||
refocusTextarea,
|
||||
dismissAll,
|
||||
enqueue,
|
||||
setAskQuestion,
|
||||
setModeChangeNotifier,
|
||||
setToolApprover,
|
||||
setUiMode,
|
||||
termHeight,
|
||||
]);
|
||||
|
||||
return {
|
||||
interaction,
|
||||
resolveToolApproval,
|
||||
resolveAskQuestion,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ import {
|
||||
type WorkflowConfig,
|
||||
} from "@cline/core";
|
||||
import { getToolCatalog } from "../runtime/tools";
|
||||
import {
|
||||
type InteractiveSlashCommand,
|
||||
listInteractiveSlashCommands,
|
||||
} from "./interactive-welcome";
|
||||
|
||||
export type InteractiveConfigTab =
|
||||
| "general"
|
||||
@@ -70,6 +74,7 @@ export interface InteractiveConfigData {
|
||||
plugins: InteractiveConfigItem[];
|
||||
mcp: InteractiveConfigItem[];
|
||||
tools: InteractiveConfigItem[];
|
||||
workflowSlashCommands: InteractiveSlashCommand[];
|
||||
}
|
||||
|
||||
export interface LoadInteractiveConfigDataOptions {
|
||||
@@ -264,6 +269,9 @@ export async function loadInteractiveConfigData(input: {
|
||||
const plugins: InteractiveConfigItem[] = [];
|
||||
const mcp: InteractiveConfigItem[] = [];
|
||||
const tools: InteractiveConfigItem[] = [];
|
||||
const workflowSlashCommands = listInteractiveSlashCommands(
|
||||
input.userInstructionService,
|
||||
);
|
||||
|
||||
if (input.userInstructionService) {
|
||||
for (const record of input.userInstructionService.listRecords<WorkflowConfig>(
|
||||
@@ -425,5 +433,6 @@ export async function loadInteractiveConfigData(input: {
|
||||
plugins: toSorted(plugins.filter((item) => existsSync(item.path))),
|
||||
mcp: toSorted(mcp.filter((item) => existsSync(item.path))),
|
||||
tools: toSorted(tools),
|
||||
workflowSlashCommands,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { rankMentionPaths } from "./interactive-welcome";
|
||||
|
||||
describe("TUI file mention search ranking", () => {
|
||||
it("keeps initialism matches for compact and hyphenated input", () => {
|
||||
const paths = [
|
||||
"src/components/Button.tsx",
|
||||
"src/domain/MyAmazingClassDefinition.ts",
|
||||
"docs/MACD.md",
|
||||
"packages/core/src/runtime/manager.ts",
|
||||
];
|
||||
|
||||
expect(rankMentionPaths(paths, "MACD", 10)).toEqual([
|
||||
"docs/MACD.md",
|
||||
"src/domain/MyAmazingClassDefinition.ts",
|
||||
]);
|
||||
expect(rankMentionPaths(paths, "M-A-C-D", 10)).toEqual([
|
||||
"docs/MACD.md",
|
||||
"src/domain/MyAmazingClassDefinition.ts",
|
||||
]);
|
||||
});
|
||||
|
||||
it("normalizes common mention prefixes before matching workspace paths", () => {
|
||||
const paths = [
|
||||
"docs/architecture.md",
|
||||
"src/tui/interactive-welcome.ts",
|
||||
"src/tui/hooks/use-autocomplete.ts",
|
||||
];
|
||||
|
||||
expect(rankMentionPaths(paths, "./src/tui", 10)).toEqual([
|
||||
"src/tui/hooks/use-autocomplete.ts",
|
||||
"src/tui/interactive-welcome.ts",
|
||||
]);
|
||||
expect(rankMentionPaths(paths, "/docs", 10)).toEqual([
|
||||
"docs/architecture.md",
|
||||
]);
|
||||
});
|
||||
|
||||
it("ranks filename matches ahead of path-only fuzzy matches", () => {
|
||||
const paths = [
|
||||
"src/migrations/add-column.ts",
|
||||
"src/domain/MyAmazingClassDefinition.ts",
|
||||
"docs/classes.md",
|
||||
];
|
||||
|
||||
expect(rankMentionPaths(paths, "class", 10)[0]).toBe("docs/classes.md");
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
type ProviderSettings,
|
||||
type UserInstructionConfigService,
|
||||
} from "@cline/core";
|
||||
import { byLengthAsc, Fzf, type FzfResultItem } from "fzf";
|
||||
import type { Config } from "../utils/types";
|
||||
import { formatClineCredits, loadClineAccountSnapshot } from "./cline-account";
|
||||
|
||||
@@ -17,24 +18,95 @@ function normalizeLimit(limit: number | undefined): number {
|
||||
if (typeof limit !== "number" || Number.isNaN(limit)) {
|
||||
return 10;
|
||||
}
|
||||
return Math.min(50, Math.max(1, Math.trunc(limit)));
|
||||
return Math.min(200, Math.max(1, Math.trunc(limit)));
|
||||
}
|
||||
|
||||
function rankPath(path: string, query: string): number {
|
||||
if (query.length === 0) {
|
||||
return 3;
|
||||
function getPathLabel(filePath: string): string {
|
||||
const parts = filePath.split("/");
|
||||
return parts[parts.length - 1] ?? filePath;
|
||||
}
|
||||
|
||||
function normalizeMentionQuery(query: string): string {
|
||||
const trimmed = query.trim().replace(/^["']/, "");
|
||||
if (trimmed.startsWith("./")) {
|
||||
return trimmed.slice(2);
|
||||
}
|
||||
const lowerPath = path.toLowerCase();
|
||||
if (lowerPath.startsWith(query)) {
|
||||
return 0;
|
||||
if (trimmed.startsWith("/")) {
|
||||
return trimmed.slice(1);
|
||||
}
|
||||
if (lowerPath.includes(`/${query}`)) {
|
||||
return 1;
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
function compactSearchText(text: string): string {
|
||||
return text.toLowerCase().replace(/[^a-z0-9]/g, "");
|
||||
}
|
||||
|
||||
interface MentionPathItem {
|
||||
path: string;
|
||||
label: string;
|
||||
searchText: string;
|
||||
}
|
||||
|
||||
function countGaps(positions: Iterable<number>): number {
|
||||
const sortedPositions = Array.from(positions).sort((a, b) => a - b);
|
||||
let gaps = 0;
|
||||
let previous = Number.NEGATIVE_INFINITY;
|
||||
for (const position of sortedPositions) {
|
||||
if (previous !== Number.NEGATIVE_INFINITY && position - previous > 1) {
|
||||
gaps++;
|
||||
}
|
||||
previous = position;
|
||||
}
|
||||
if (lowerPath.includes(query)) {
|
||||
return 2;
|
||||
return gaps;
|
||||
}
|
||||
|
||||
function orderByMatchScore(
|
||||
left: FzfResultItem<MentionPathItem>,
|
||||
right: FzfResultItem<MentionPathItem>,
|
||||
): number {
|
||||
return countGaps(left.positions) - countGaps(right.positions);
|
||||
}
|
||||
|
||||
export function rankMentionPaths(
|
||||
paths: Iterable<string>,
|
||||
query: string,
|
||||
limit: number,
|
||||
): string[] {
|
||||
const items = Array.from(paths, (path): MentionPathItem => {
|
||||
const label = getPathLabel(path);
|
||||
return {
|
||||
path,
|
||||
label,
|
||||
searchText: [
|
||||
label,
|
||||
label,
|
||||
path,
|
||||
compactSearchText(label),
|
||||
compactSearchText(path),
|
||||
].join(" "),
|
||||
};
|
||||
});
|
||||
|
||||
const normalizedQuery = normalizeMentionQuery(query);
|
||||
if (!normalizedQuery) {
|
||||
return items
|
||||
.sort((left, right) => left.path.localeCompare(right.path))
|
||||
.slice(0, limit)
|
||||
.map((item) => item.path);
|
||||
}
|
||||
return Number.POSITIVE_INFINITY;
|
||||
|
||||
const fzf = new Fzf(items, {
|
||||
selector: (item) => item.searchText,
|
||||
tiebreakers: [orderByMatchScore, byLengthAsc],
|
||||
limit,
|
||||
});
|
||||
|
||||
const rawResults = fzf.find(normalizedQuery);
|
||||
const results =
|
||||
rawResults.length > 0
|
||||
? rawResults
|
||||
: fzf.find(compactSearchText(normalizedQuery));
|
||||
return results.map((result) => result.item.path);
|
||||
}
|
||||
|
||||
export function listInteractiveSlashCommands(
|
||||
@@ -90,21 +162,9 @@ export async function searchWorkspaceFilesForMention(input: {
|
||||
if (!workspaceRoot) {
|
||||
return [];
|
||||
}
|
||||
const query = input.query.trim().toLowerCase();
|
||||
const limit = normalizeLimit(input.limit);
|
||||
const index = await getFileIndex(workspaceRoot);
|
||||
const allPaths = Array.from(index).sort((a, b) => a.localeCompare(b));
|
||||
return allPaths
|
||||
.map((path) => ({ path, rank: rankPath(path, query) }))
|
||||
.filter((item) => Number.isFinite(item.rank))
|
||||
.sort((left, right) => {
|
||||
if (left.rank !== right.rank) {
|
||||
return left.rank - right.rank;
|
||||
}
|
||||
return left.path.localeCompare(right.path);
|
||||
})
|
||||
.slice(0, limit)
|
||||
.map((item) => item.path);
|
||||
return rankMentionPaths(index, input.query, limit);
|
||||
}
|
||||
|
||||
export async function resolveClineWelcomeLine(input: {
|
||||
|
||||
@@ -176,11 +176,11 @@ export function getModeInputPlaceholder(
|
||||
}
|
||||
|
||||
function srgbToLinear(c: number): number {
|
||||
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
||||
return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
||||
}
|
||||
|
||||
function linearToSrgb(c: number): number {
|
||||
const v = c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
||||
const v = c <= 0.0031308 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055;
|
||||
return Math.max(0, Math.min(1, v));
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,9 @@ function App(props: TuiProps) {
|
||||
: "home";
|
||||
});
|
||||
const [toast, setToast] = useState<ToastState | null>(null);
|
||||
const [workflowSlashCommands, setWorkflowSlashCommands] = useState(
|
||||
props.workflowSlashCommands,
|
||||
);
|
||||
const toastTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const checkpointRestoreInFlightRef = useRef(false);
|
||||
|
||||
@@ -102,13 +105,17 @@ function App(props: TuiProps) {
|
||||
[appView, props.initialPrompt, session.entries],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setWorkflowSlashCommands(props.workflowSlashCommands);
|
||||
}, [props.workflowSlashCommands]);
|
||||
|
||||
const {
|
||||
registry: slashCommandRegistry,
|
||||
systemCommands,
|
||||
skillCommands,
|
||||
invokableSkillCommands,
|
||||
} = useSlashCommands({
|
||||
workflowSlashCommands: props.workflowSlashCommands,
|
||||
workflowSlashCommands,
|
||||
loadAdditionalSlashCommands: props.loadAdditionalSlashCommands,
|
||||
canFork: canForkSession,
|
||||
});
|
||||
@@ -187,6 +194,19 @@ function App(props: TuiProps) {
|
||||
onSessionRestart: props.onSessionRestart,
|
||||
refocusTextarea: () => refocusTextareaRef.current(),
|
||||
});
|
||||
const propsOnToggleConfigItem = props.onToggleConfigItem;
|
||||
const onToggleConfigItem = useMemo<TuiProps["onToggleConfigItem"]>(() => {
|
||||
if (!propsOnToggleConfigItem) {
|
||||
return undefined;
|
||||
}
|
||||
return async (item, options) => {
|
||||
const data = await propsOnToggleConfigItem(item, options);
|
||||
if (data) {
|
||||
setWorkflowSlashCommands(data.workflowSlashCommands);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
}, [propsOnToggleConfigItem]);
|
||||
|
||||
const openConfig = useConfigPanel({
|
||||
dialog,
|
||||
@@ -198,7 +218,7 @@ function App(props: TuiProps) {
|
||||
setCompactionMode: session.setCompactionMode,
|
||||
termHeight,
|
||||
loadConfigData: props.loadConfigData,
|
||||
onToggleConfigItem: props.onToggleConfigItem,
|
||||
onToggleConfigItem,
|
||||
openModelSelector,
|
||||
openMcpManager,
|
||||
refocusTextarea: () => refocusTextareaRef.current(),
|
||||
@@ -215,10 +235,16 @@ function App(props: TuiProps) {
|
||||
});
|
||||
|
||||
const clearConversation = useCallback(async () => {
|
||||
const shouldRestartSession = session.hasSubmitted;
|
||||
session.clearEntries();
|
||||
session.setHasSubmitted(false);
|
||||
if (!shouldRestartSession) {
|
||||
setAppView("home");
|
||||
refocusTextareaRef.current();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await props.onSessionRestart();
|
||||
await props.onNewSession();
|
||||
setAppView("home");
|
||||
} catch (error) {
|
||||
setAppView("chat");
|
||||
@@ -708,6 +734,15 @@ function App(props: TuiProps) {
|
||||
removeLocalCommandInvocationRef.current = (invocation) => {
|
||||
promptInput.removeLocalCommandInvocation(invocation);
|
||||
};
|
||||
const runtimeBridge = useRuntimeDialogBridge({
|
||||
setToolApprover: props.setToolApprover,
|
||||
setAskQuestion: props.setAskQuestion,
|
||||
setModeChangeNotifier: props.setModeChangeNotifier,
|
||||
setUiMode: session.setUiMode,
|
||||
refocusTextarea: promptInput.refocusTextarea,
|
||||
});
|
||||
const runtimeInteraction = runtimeBridge.interaction;
|
||||
const isRuntimeInteractionOpen = runtimeInteraction !== null;
|
||||
const saveQueuedPromptEdit = useCallback(
|
||||
async (promptId: string, text: string) => {
|
||||
if (!promptId) return;
|
||||
@@ -757,9 +792,11 @@ function App(props: TuiProps) {
|
||||
const initialPromptSubmittedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDialogOpen || appView === "onboarding") return;
|
||||
if (isDialogOpen || isRuntimeInteractionOpen || appView === "onboarding") {
|
||||
return;
|
||||
}
|
||||
focusPromptTextarea();
|
||||
}, [isDialogOpen, appView, focusPromptTextarea]);
|
||||
}, [isDialogOpen, isRuntimeInteractionOpen, appView, focusPromptTextarea]);
|
||||
|
||||
useEffect(() => {
|
||||
if (initialPromptSubmittedRef.current) return;
|
||||
@@ -774,7 +811,7 @@ function App(props: TuiProps) {
|
||||
}, [appView, submitInitialPrompt, props.initialPrompt]);
|
||||
|
||||
useRootKeyboard({
|
||||
isDialogOpen,
|
||||
isDialogOpen: isDialogOpen || isRuntimeInteractionOpen,
|
||||
appView,
|
||||
autocomplete,
|
||||
inputHistory: promptInput.inputHistory,
|
||||
@@ -804,14 +841,6 @@ function App(props: TuiProps) {
|
||||
onCommandPaletteShortcut: runCommandPaletteShortcut,
|
||||
});
|
||||
|
||||
useRuntimeDialogBridge({
|
||||
setToolApprover: props.setToolApprover,
|
||||
setAskQuestion: props.setAskQuestion,
|
||||
setModeChangeNotifier: props.setModeChangeNotifier,
|
||||
setUiMode: session.setUiMode,
|
||||
refocusTextarea: promptInput.refocusTextarea,
|
||||
});
|
||||
|
||||
const acOptions = autocomplete.getFilteredOptions();
|
||||
|
||||
const eventBridgeHandlers = useMemo(
|
||||
@@ -843,6 +872,9 @@ function App(props: TuiProps) {
|
||||
void saveQueuedPromptEdit(id, prompt);
|
||||
},
|
||||
onToggleMode: toggleMode,
|
||||
runtimeInteraction,
|
||||
onResolveToolApproval: runtimeBridge.resolveToolApproval,
|
||||
onResolveAskQuestion: runtimeBridge.resolveAskQuestion,
|
||||
autocomplete: {
|
||||
mode: autocomplete.mode,
|
||||
options: acOptions,
|
||||
|
||||
@@ -103,6 +103,19 @@ export interface PendingPromptMutationResult {
|
||||
|
||||
export type AppView = "onboarding" | "home" | "chat";
|
||||
|
||||
export type RuntimeToolInteraction =
|
||||
| {
|
||||
id: number;
|
||||
kind: "tool_approval";
|
||||
request: ToolApprovalRequest;
|
||||
}
|
||||
| {
|
||||
id: number;
|
||||
kind: "ask_question";
|
||||
question: string;
|
||||
options: string[];
|
||||
};
|
||||
|
||||
export interface TuiProps {
|
||||
config: Config;
|
||||
initialView?: "chat" | "config";
|
||||
@@ -149,6 +162,7 @@ export interface TuiProps {
|
||||
onCompactionModeChange: (mode: CliCompactionMode) => Promise<void>;
|
||||
onModelChange: () => Promise<void>;
|
||||
onModeChange: (mode: AgentMode) => Promise<void>;
|
||||
onNewSession: () => Promise<void>;
|
||||
onSessionRestart: () => Promise<void>;
|
||||
onAccountChange: () => Promise<void>;
|
||||
onResumeSession: (sessionId: string) => Promise<ResumedSessionResult>;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
getToolErrorPresentation,
|
||||
isWarningToolError,
|
||||
unwrapToolError,
|
||||
} from "./tool-errors";
|
||||
|
||||
describe("tool error presentation", () => {
|
||||
it("unwraps JSON-encoded tool errors", () => {
|
||||
const raw = JSON.stringify({
|
||||
error: "Tool call run_commands was rejected before execution: nope",
|
||||
});
|
||||
|
||||
expect(unwrapToolError(raw)).toBe(
|
||||
"Tool call run_commands was rejected before execution: nope",
|
||||
);
|
||||
});
|
||||
|
||||
it("summarizes invalid tool input as a warning", () => {
|
||||
const raw = JSON.stringify({
|
||||
error:
|
||||
'Tool call run_commands was rejected before execution: Invalid input for tool run_commands: Type validation failed: Value: {"commands":[{"command":"cat file"}]}.\nError message: []',
|
||||
});
|
||||
|
||||
expect(getToolErrorPresentation(raw)).toMatchObject({
|
||||
severity: "warning",
|
||||
summary: "Invalid run_commands input; tool call skipped.",
|
||||
});
|
||||
expect(isWarningToolError(raw)).toBe(true);
|
||||
});
|
||||
|
||||
it("summarizes generic pre-execution rejections as warnings", () => {
|
||||
expect(
|
||||
getToolErrorPresentation(
|
||||
"Tool call editor was rejected before execution: approval request failed",
|
||||
),
|
||||
).toMatchObject({
|
||||
severity: "warning",
|
||||
summary: "editor call was skipped before execution.",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps non-rejection failures as errors", () => {
|
||||
const presentation = getToolErrorPresentation("command failed with exit 1");
|
||||
|
||||
expect(presentation).toEqual({
|
||||
severity: "error",
|
||||
summary: "command failed with exit 1",
|
||||
detail: "command failed with exit 1",
|
||||
});
|
||||
});
|
||||
|
||||
it("summarizes JSON-wrapped hard errors without dumping stacks", () => {
|
||||
const raw = JSON.stringify({
|
||||
error:
|
||||
"Error: command failed with exit 1\n at runTool (/tmp/tool.ts:10:1)\n at async main (/tmp/main.ts:5:1)",
|
||||
});
|
||||
|
||||
expect(getToolErrorPresentation(raw)).toEqual({
|
||||
severity: "error",
|
||||
summary: "command failed with exit 1",
|
||||
detail:
|
||||
"Error: command failed with exit 1\n at runTool (/tmp/tool.ts:10:1)\n at async main (/tmp/main.ts:5:1)",
|
||||
});
|
||||
});
|
||||
|
||||
it("collapses long one-line hard errors", () => {
|
||||
const detail = `Validation failed: ${"x".repeat(180)}`;
|
||||
const presentation = getToolErrorPresentation(detail);
|
||||
|
||||
expect(presentation.severity).toBe("error");
|
||||
expect(presentation.detail).toBe(detail);
|
||||
expect(presentation.summary.length).toBeLessThanOrEqual(140);
|
||||
expect(presentation.summary.endsWith("...")).toBe(true);
|
||||
});
|
||||
|
||||
it("uses a generic summary when no string error can be extracted", () => {
|
||||
const presentation = getToolErrorPresentation(
|
||||
JSON.stringify({ code: "E_TOOL", data: { value: 1 } }),
|
||||
);
|
||||
|
||||
expect(presentation).toEqual({
|
||||
severity: "error",
|
||||
summary: "Tool returned a structured error.",
|
||||
detail: JSON.stringify({ code: "E_TOOL", data: { value: 1 } }),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
export interface ToolErrorPresentation {
|
||||
severity: "warning" | "error";
|
||||
summary: string;
|
||||
detail: string;
|
||||
}
|
||||
|
||||
const MAX_ERROR_SUMMARY_LENGTH = 140;
|
||||
|
||||
function extractStringError(value: unknown): string | undefined {
|
||||
if (typeof value === "string") {
|
||||
return value.trim() || undefined;
|
||||
}
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return undefined;
|
||||
}
|
||||
const record = value as Record<string, unknown>;
|
||||
return (
|
||||
extractStringError(record.error) ??
|
||||
extractStringError(record.message) ??
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
export function unwrapToolError(error: string): string {
|
||||
let current = error.trim();
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
if (!current.startsWith("{") && !current.startsWith("[")) break;
|
||||
try {
|
||||
const parsed = JSON.parse(current) as unknown;
|
||||
const next = extractStringError(parsed);
|
||||
if (!next || next === current) break;
|
||||
current = next.trim();
|
||||
} catch {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
function summarizeInvalidInput(message: string): string | undefined {
|
||||
const rejected = message.match(
|
||||
/^Tool call\s+([A-Za-z0-9_-]+)\s+was rejected before execution:\s+Invalid input for tool\s+([A-Za-z0-9_-]+):\s*([^.\n]+)(?:\.|\n|$)/,
|
||||
);
|
||||
if (rejected) {
|
||||
return `Invalid ${rejected[2]} input; tool call skipped.`;
|
||||
}
|
||||
|
||||
const invalid = message.match(
|
||||
/^Invalid input for tool\s+([A-Za-z0-9_-]+):\s*([^.\n]+)(?:\.|\n|$)/,
|
||||
);
|
||||
if (invalid) {
|
||||
return `Invalid ${invalid[1]} input; tool call skipped.`;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function truncateSummary(text: string): string {
|
||||
const trimmed = text.trim();
|
||||
if (trimmed.length <= MAX_ERROR_SUMMARY_LENGTH) {
|
||||
return trimmed;
|
||||
}
|
||||
return `${trimmed.slice(0, MAX_ERROR_SUMMARY_LENGTH - 3).trimEnd()}...`;
|
||||
}
|
||||
|
||||
function summarizeErrorDetail(detail: string): string {
|
||||
const trimmed = detail.trim();
|
||||
if (!trimmed) {
|
||||
return "Tool failed.";
|
||||
}
|
||||
|
||||
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
||||
return "Tool returned a structured error.";
|
||||
}
|
||||
|
||||
const firstLine =
|
||||
trimmed
|
||||
.replace(/\r\n/g, "\n")
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.find(Boolean) ?? "Tool failed.";
|
||||
const withoutGenericPrefix = firstLine.replace(/^Error:\s+/i, "");
|
||||
|
||||
return truncateSummary(withoutGenericPrefix.replace(/\s+/g, " "));
|
||||
}
|
||||
|
||||
export function getToolErrorPresentation(error: string): ToolErrorPresentation {
|
||||
const detail = unwrapToolError(error);
|
||||
const inputSummary = summarizeInvalidInput(detail);
|
||||
if (inputSummary) {
|
||||
return {
|
||||
severity: "warning",
|
||||
summary: inputSummary,
|
||||
detail,
|
||||
};
|
||||
}
|
||||
|
||||
const rejected = detail.match(
|
||||
/^Tool call\s+([A-Za-z0-9_-]+)\s+was rejected before execution:/,
|
||||
);
|
||||
if (rejected) {
|
||||
return {
|
||||
severity: "warning",
|
||||
summary: `${rejected[1]} call was skipped before execution.`,
|
||||
detail,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
severity: "error",
|
||||
summary: summarizeErrorDetail(detail),
|
||||
detail,
|
||||
};
|
||||
}
|
||||
|
||||
export function isWarningToolError(error: string | undefined): boolean {
|
||||
return error ? getToolErrorPresentation(error).severity === "warning" : false;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ChatMessageList,
|
||||
type TranscriptScrollHandle,
|
||||
} from "../components/chat-message-list";
|
||||
import { InlineToolResponse } from "../components/inline-tool-response";
|
||||
import { InputBar, type TextareaHandle } from "../components/input-bar";
|
||||
import { QueuedPrompts } from "../components/queued-prompts";
|
||||
import {
|
||||
@@ -24,7 +25,11 @@ import {
|
||||
getModeInputForeground,
|
||||
getModeInputPlaceholder,
|
||||
} from "../palette";
|
||||
import type { QueuedPromptItem, TuiProps } from "../types";
|
||||
import type {
|
||||
QueuedPromptItem,
|
||||
RuntimeToolInteraction,
|
||||
TuiProps,
|
||||
} from "../types";
|
||||
|
||||
export function ChatView(props: {
|
||||
config: TuiProps["config"];
|
||||
@@ -51,6 +56,9 @@ export function ChatView(props: {
|
||||
editingQueuedPrompt?: QueuedPromptItem;
|
||||
onQueuedPromptEditConfirm: (id: string, prompt: string) => void;
|
||||
onToggleMode: () => void;
|
||||
runtimeInteraction?: RuntimeToolInteraction | null;
|
||||
onResolveToolApproval: (id: number, approved: boolean) => void;
|
||||
onResolveAskQuestion: (id: number, answer: string | null) => void;
|
||||
}) {
|
||||
const {
|
||||
config,
|
||||
@@ -73,6 +81,7 @@ export function ChatView(props: {
|
||||
session.uiMode === "plan" ? "Plan something..." : "Ask anything...";
|
||||
const modelDisplayName = resolveModelDisplayName(config);
|
||||
const maxInputTokens = resolveModelMaxInputTokens(config);
|
||||
const runtimeInteraction = props.runtimeInteraction ?? null;
|
||||
|
||||
return (
|
||||
<box flexDirection="column" width="100%" height="100%">
|
||||
@@ -84,36 +93,53 @@ export function ChatView(props: {
|
||||
/>
|
||||
|
||||
<box flexDirection="column" flexShrink={0}>
|
||||
{props.autocomplete && (
|
||||
<AutocompleteDropdown {...props.autocomplete} accent={accent} />
|
||||
)}
|
||||
{runtimeInteraction ? (
|
||||
<box marginBottom={1}>
|
||||
<InlineToolResponse
|
||||
key={runtimeInteraction.id}
|
||||
interaction={runtimeInteraction}
|
||||
accent={accent}
|
||||
inputBackground={inputBackground}
|
||||
inputForeground={inputForeground}
|
||||
inputPlaceholder={inputPlaceholder}
|
||||
onResolveToolApproval={props.onResolveToolApproval}
|
||||
onResolveAskQuestion={props.onResolveAskQuestion}
|
||||
/>
|
||||
</box>
|
||||
) : (
|
||||
<>
|
||||
{props.autocomplete && (
|
||||
<AutocompleteDropdown {...props.autocomplete} accent={accent} />
|
||||
)}
|
||||
|
||||
{props.queuedPrompts && props.queuedPrompts.length > 0 && (
|
||||
<QueuedPrompts
|
||||
items={props.queuedPrompts}
|
||||
selectedId={props.selectedQueuedPromptId ?? null}
|
||||
editingId={props.editingQueuedPrompt?.id ?? null}
|
||||
onEditConfirm={props.onQueuedPromptEditConfirm}
|
||||
/>
|
||||
)}
|
||||
{props.queuedPrompts && props.queuedPrompts.length > 0 && (
|
||||
<QueuedPrompts
|
||||
items={props.queuedPrompts}
|
||||
selectedId={props.selectedQueuedPromptId ?? null}
|
||||
editingId={props.editingQueuedPrompt?.id ?? null}
|
||||
onEditConfirm={props.onQueuedPromptEditConfirm}
|
||||
/>
|
||||
)}
|
||||
|
||||
<box marginBottom={1}>
|
||||
<InputBar
|
||||
accent={accent}
|
||||
inputBackground={inputBackground}
|
||||
inputForeground={inputForeground}
|
||||
inputPlaceholder={inputPlaceholder}
|
||||
placeholder={placeholder}
|
||||
initialValue={inputValue}
|
||||
inputKey={inputKey}
|
||||
onSubmit={onSubmit}
|
||||
onContentChange={onContentChange}
|
||||
onImagePaste={onImagePaste}
|
||||
onLargeTextPaste={onLargeTextPaste}
|
||||
onFocusRequest={props.onInputFocusRequest}
|
||||
textareaRef={props.textareaRef}
|
||||
/>
|
||||
</box>
|
||||
<box marginBottom={1}>
|
||||
<InputBar
|
||||
accent={accent}
|
||||
inputBackground={inputBackground}
|
||||
inputForeground={inputForeground}
|
||||
inputPlaceholder={inputPlaceholder}
|
||||
placeholder={placeholder}
|
||||
initialValue={inputValue}
|
||||
inputKey={inputKey}
|
||||
onSubmit={onSubmit}
|
||||
onContentChange={onContentChange}
|
||||
onImagePaste={onImagePaste}
|
||||
onLargeTextPaste={onLargeTextPaste}
|
||||
onFocusRequest={props.onInputFocusRequest}
|
||||
textareaRef={props.textareaRef}
|
||||
/>
|
||||
</box>
|
||||
</>
|
||||
)}
|
||||
|
||||
<StatusBar
|
||||
providerId={config.providerId}
|
||||
|
||||
@@ -162,8 +162,35 @@ export function isInlineConfigAction(
|
||||
return action?.kind === "toggle-item";
|
||||
}
|
||||
|
||||
export function getConfigFooterText(): string {
|
||||
return "←/→ switch tabs, ↑/↓ navigate, Tab/Enter select, Space toggle, Esc close";
|
||||
export function canToggleConfigFooterRow(
|
||||
row:
|
||||
| { kind: "toggle" }
|
||||
| { kind: "ext"; enabled?: boolean; item: InteractiveConfigItem }
|
||||
| { kind: string }
|
||||
| undefined,
|
||||
): boolean {
|
||||
if (!row) {
|
||||
return false;
|
||||
}
|
||||
if (row.kind === "toggle") {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
row.kind === "ext" &&
|
||||
"item" in row &&
|
||||
typeof row.enabled === "boolean" &&
|
||||
isToggleableConfigItem(row.item)
|
||||
);
|
||||
}
|
||||
|
||||
export function getConfigFooterText({
|
||||
canToggle = false,
|
||||
}: {
|
||||
canToggle?: boolean;
|
||||
} = {}): string {
|
||||
return canToggle
|
||||
? "←/→ switch tabs, ↑/↓ navigate, Tab/Enter select, Space toggle, Esc close"
|
||||
: "←/→ switch tabs, ↑/↓ navigate, Tab/Enter select, Esc close";
|
||||
}
|
||||
|
||||
export function getConfigItemDisplayName(name: string): string {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { InteractiveConfigItem } from "../../tui/interactive-config";
|
||||
import {
|
||||
canToggleConfigFooterRow,
|
||||
getAdjacentConfigTab,
|
||||
getConfigFooterText,
|
||||
getConfigItemDisplayName,
|
||||
@@ -36,6 +37,12 @@ describe("config view helpers", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("does not treat rule, agent, or hook rows as toggleable", () => {
|
||||
expect(isToggleableConfigItem(createItem({ kind: "rule" }))).toBe(false);
|
||||
expect(isToggleableConfigItem(createItem({ kind: "agent" }))).toBe(false);
|
||||
expect(isToggleableConfigItem(createItem({ kind: "hook" }))).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps plugin tool rows toggleable", () => {
|
||||
expect(
|
||||
isToggleableConfigItem(
|
||||
@@ -75,8 +82,38 @@ describe("config view helpers", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("mentions Space toggle in the footer", () => {
|
||||
expect(getConfigFooterText()).toContain("Space toggle");
|
||||
it("mentions Space toggle in the footer for toggleable rows", () => {
|
||||
expect(getConfigFooterText({ canToggle: true })).toContain("Space toggle");
|
||||
});
|
||||
|
||||
it("omits Space toggle in the footer for non-toggleable rows", () => {
|
||||
expect(getConfigFooterText({ canToggle: false })).not.toContain(
|
||||
"Space toggle",
|
||||
);
|
||||
expect(getConfigFooterText()).not.toContain("Space toggle");
|
||||
});
|
||||
|
||||
it("derives footer toggle affordance from selected row behavior", () => {
|
||||
const skill = createItem({ kind: "skill" });
|
||||
const hook = createItem({ kind: "hook" });
|
||||
|
||||
expect(canToggleConfigFooterRow({ kind: "provider" })).toBe(false);
|
||||
expect(canToggleConfigFooterRow({ kind: "toggle" })).toBe(true);
|
||||
expect(
|
||||
canToggleConfigFooterRow({
|
||||
kind: "ext",
|
||||
enabled: skill.enabled,
|
||||
item: skill,
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
canToggleConfigFooterRow({
|
||||
kind: "ext",
|
||||
enabled: hook.enabled,
|
||||
item: hook,
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(canToggleConfigFooterRow({ kind: "mcp-manager" })).toBe(false);
|
||||
});
|
||||
|
||||
it("supports restoring and advancing the active settings tab", () => {
|
||||
@@ -109,7 +146,7 @@ describe("config view helpers", () => {
|
||||
expect(
|
||||
isInlineConfigAction(resolveConfigItemSelectAction(builtinTool)),
|
||||
).toBe(true);
|
||||
expect(getConfigFooterText()).not.toContain("details");
|
||||
expect(getConfigFooterText({ canToggle: true })).not.toContain("details");
|
||||
});
|
||||
|
||||
it("returns item names without decoration", () => {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { resolveModelDisplayName } from "../components/status-bar";
|
||||
import { getModeAccent, palette } from "../palette";
|
||||
import {
|
||||
type ConfigAction,
|
||||
canToggleConfigFooterRow,
|
||||
getAdjacentConfigTab,
|
||||
getConfigFooterText,
|
||||
getConfigItemDisplayName,
|
||||
@@ -235,6 +236,63 @@ function appendToolRows(
|
||||
}
|
||||
}
|
||||
|
||||
function withOptimisticToggle(
|
||||
data: InteractiveConfigData,
|
||||
item: InteractiveConfigItem,
|
||||
): InteractiveConfigData {
|
||||
if (typeof item.enabled !== "boolean") {
|
||||
return data;
|
||||
}
|
||||
const nextEnabled = !item.enabled;
|
||||
const matchesItem = (candidate: InteractiveConfigItem) =>
|
||||
candidate.id === item.id &&
|
||||
candidate.path === item.path &&
|
||||
candidate.kind === item.kind;
|
||||
const toolNames = new Set(
|
||||
(item.toolNames && item.toolNames.length > 0
|
||||
? item.toolNames
|
||||
: [item.name]
|
||||
).filter(Boolean),
|
||||
);
|
||||
const updateItems = (items: InteractiveConfigItem[]) =>
|
||||
items.map((candidate) =>
|
||||
matchesItem(candidate)
|
||||
? { ...candidate, enabled: nextEnabled }
|
||||
: candidate,
|
||||
);
|
||||
const updateTools = (items: InteractiveConfigItem[]) =>
|
||||
items.map((candidate) => {
|
||||
if (matchesItem(candidate)) {
|
||||
return { ...candidate, enabled: nextEnabled };
|
||||
}
|
||||
if (
|
||||
item.kind === "tool" &&
|
||||
toolNames.has(candidate.name) &&
|
||||
(candidate.source === "builtin" ||
|
||||
candidate.source === "workspace-plugin" ||
|
||||
candidate.source === "global-plugin")
|
||||
) {
|
||||
return { ...candidate, enabled: nextEnabled };
|
||||
}
|
||||
if (item.kind === "plugin" && candidate.path === item.path) {
|
||||
return { ...candidate, enabled: nextEnabled };
|
||||
}
|
||||
return candidate;
|
||||
});
|
||||
|
||||
return {
|
||||
...data,
|
||||
workflows: updateItems(data.workflows),
|
||||
rules: updateItems(data.rules),
|
||||
skills: updateItems(data.skills),
|
||||
hooks: updateItems(data.hooks),
|
||||
agents: updateItems(data.agents),
|
||||
plugins: updateItems(data.plugins),
|
||||
mcp: updateItems(data.mcp),
|
||||
tools: updateTools(data.tools),
|
||||
};
|
||||
}
|
||||
|
||||
function getPluginLoadErrorLabel(
|
||||
item: InteractiveConfigItem,
|
||||
): string | undefined {
|
||||
@@ -394,6 +452,8 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
|
||||
const clampedNavPos = Math.min(navPos, Math.max(0, navIndices.length - 1));
|
||||
const selectedRowIdx = navIndices[clampedNavPos] ?? 0;
|
||||
const selectedRow = rows[selectedRowIdx];
|
||||
const canToggleSelectedRow = canToggleConfigFooterRow(selectedRow);
|
||||
|
||||
const setNavPosition = (nextNavPos: number) => {
|
||||
setNavPos(nextNavPos);
|
||||
@@ -401,8 +461,10 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
|
||||
const handleInlineToggle = async (item: InteractiveConfigItem) => {
|
||||
if (!props.onToggleConfigItem || togglingItemId) return;
|
||||
const previousData = configData;
|
||||
setTogglingItemId(item.id);
|
||||
setToggleError(undefined);
|
||||
setConfigData((current) => withOptimisticToggle(current, item));
|
||||
try {
|
||||
const nextData = await props.onToggleConfigItem(item, {
|
||||
includePluginTools: pluginToolsLoaded,
|
||||
@@ -410,8 +472,18 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
if (nextData) {
|
||||
setConfigData(nextData);
|
||||
setPluginToolsLoaded(nextData.tools.some((tool) => tool.pluginName));
|
||||
} else if (item.kind === "plugin" && loadConfigData) {
|
||||
const refreshedData = await loadConfigData({
|
||||
includePluginTools: true,
|
||||
});
|
||||
setConfigData(refreshedData);
|
||||
setPluginToolsLoaded(
|
||||
refreshedData.tools.some((tool) => tool.pluginName),
|
||||
);
|
||||
setPluginToolsError(undefined);
|
||||
}
|
||||
} catch (error) {
|
||||
setConfigData(previousData);
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
setToggleError(`Failed to update ${item.name}: ${message}`);
|
||||
} finally {
|
||||
@@ -705,7 +777,11 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
<text> </text>
|
||||
{toggleError && <text fg="red">{toggleError}</text>}
|
||||
<text fg="gray">
|
||||
<em>{togglingItemId ? "Applying settings" : getConfigFooterText()}</em>
|
||||
<em>
|
||||
{togglingItemId
|
||||
? "Applying settings"
|
||||
: getConfigFooterText({ canToggle: canToggleSelectedRow })}
|
||||
</em>
|
||||
</text>
|
||||
</box>
|
||||
);
|
||||
|
||||
@@ -11,10 +11,7 @@ import type { ChoiceContext } from "@opentui-ui/dialog";
|
||||
import { useDialogKeyboard } from "@opentui-ui/dialog/react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { listSessions } from "../../session/session";
|
||||
import {
|
||||
formatSessionStatusLabel,
|
||||
mergeHistoryStatusRows,
|
||||
} from "../../utils/history-format";
|
||||
import { mergeHistoryStatusRows } from "../../utils/history-format";
|
||||
import { formatUsd } from "../../utils/output";
|
||||
import { shouldShowCliUsageCost } from "../../utils/usage-cost-display";
|
||||
import { palette } from "../palette";
|
||||
@@ -77,25 +74,6 @@ type HistoryListContentProps = HistoryListActions & {
|
||||
) => void;
|
||||
};
|
||||
|
||||
function getStatusColor(
|
||||
status: SessionHistoryRecord["status"],
|
||||
selected: boolean,
|
||||
): string {
|
||||
if (selected) {
|
||||
return palette.textOnSelection;
|
||||
}
|
||||
switch (status) {
|
||||
case "running":
|
||||
return palette.success;
|
||||
case "failed":
|
||||
return "red";
|
||||
case "cancelled":
|
||||
return "yellow";
|
||||
case "completed":
|
||||
return "gray";
|
||||
}
|
||||
}
|
||||
|
||||
function HistoryListContent({
|
||||
initialRows,
|
||||
onResolve,
|
||||
@@ -353,7 +331,6 @@ function HistoryListContent({
|
||||
const showCost = shouldShowCliUsageCost(row.provider);
|
||||
const title = formatTitle(row, titleMaxLen);
|
||||
const date = formatRelativeDate(row.startedAt);
|
||||
const status = formatSessionStatusLabel(row.status);
|
||||
|
||||
return (
|
||||
<box
|
||||
@@ -377,11 +354,6 @@ function HistoryListContent({
|
||||
>
|
||||
{title}
|
||||
</text>
|
||||
<text fg={getStatusColor(row.status, isSel)} flexShrink={0}>
|
||||
{" ["}
|
||||
{status}
|
||||
{"]"}
|
||||
</text>
|
||||
{showCost && cost != null && cost > 0 && (
|
||||
<text
|
||||
fg={isSel ? palette.textOnSelection : "gray"}
|
||||
|
||||
@@ -28,13 +28,13 @@ import {
|
||||
useSearchableList,
|
||||
} from "../../components/searchable-list";
|
||||
import { palette } from "../../palette";
|
||||
import { getProviderSection } from "../../utils/provider-sections";
|
||||
import {
|
||||
getDefaultAwsRegion,
|
||||
type ProviderConfigValues,
|
||||
resolveProviderConfigAwsRegion,
|
||||
updateProviderConfigValue,
|
||||
type ProviderConfigValues,
|
||||
} from "../../utils/provider-config-values";
|
||||
import { getProviderSection } from "../../utils/provider-sections";
|
||||
import {
|
||||
isOnboardingOAuthProviderId,
|
||||
type OnboardingOAuthProviderId,
|
||||
|
||||
@@ -284,6 +284,7 @@ export function OnboardingProviderConfigScreen(props: {
|
||||
width={props.contentWidth}
|
||||
>
|
||||
<text fg="gray">{label}</text>
|
||||
{requirement.note && <text fg="gray">{requirement.note}</text>}
|
||||
<box
|
||||
border
|
||||
borderStyle="rounded"
|
||||
|
||||
@@ -2,6 +2,13 @@ import { describe, expect, it } from "vitest";
|
||||
import { PLATFORMS } from "./platforms";
|
||||
|
||||
describe("connect wizard platform security fields", () => {
|
||||
it("does not ask Telegram users to re-enter the bot username", () => {
|
||||
const telegram = PLATFORMS.find((platform) => platform.id === "telegram");
|
||||
|
||||
expect(telegram?.fields.map((field) => field.label)).toEqual(["Bot token"]);
|
||||
expect(telegram?.fields.map((field) => field.flag)).toEqual(["-k"]);
|
||||
});
|
||||
|
||||
it("rejects unsafe Telegram and Slack access restriction identifiers", () => {
|
||||
const telegram = PLATFORMS.find((platform) => platform.id === "telegram");
|
||||
const slack = PLATFORMS.find((platform) => platform.id === "slack");
|
||||
|
||||
@@ -55,23 +55,14 @@ export const PLATFORMS: PlatformDef[] = [
|
||||
type: "polling",
|
||||
hint: "Easiest to set up. No public URL needed.",
|
||||
fields: [
|
||||
{
|
||||
flag: "-m",
|
||||
label: "Bot username",
|
||||
placeholder: "my_cline_bot",
|
||||
required: true,
|
||||
help: [
|
||||
"Open Telegram and start a chat with @BotFather",
|
||||
"Send /newbot and follow the prompts",
|
||||
"The username must end in 'bot'",
|
||||
],
|
||||
},
|
||||
{
|
||||
flag: "-k",
|
||||
label: "Bot token",
|
||||
placeholder: "7123456789:AAH...",
|
||||
required: true,
|
||||
help: [
|
||||
"Open Telegram and start a chat with @BotFather",
|
||||
"Send /newbot and follow the prompts",
|
||||
"BotFather gives you this after creating the bot",
|
||||
"It looks like 7123456789:AAHxxx...",
|
||||
],
|
||||
|
||||
@@ -33,6 +33,7 @@ Requires Node.js 22+.
|
||||
|---------|-------------|----------|
|
||||
| [quickstart](./quickstart) | Send one prompt, stream the response. ~15 lines of code. | `Agent`, `subscribe`, `run()` |
|
||||
| [cli-agent](./cli-agent) | Interactive terminal chat with a shell tool. | `createTool`, multi-turn `run()`/`continue()`, streaming |
|
||||
| [cline-core-cli-agent](./cline-core-cli-agent) | Interactive terminal chat powered by ClineCore. | `ClineCore.create()`, `cline.start()`, `cline.send()`, built-in tools, streaming |
|
||||
|
||||
### Intermediate
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Cline Core CLI Agent
|
||||
|
||||
An interactive terminal chat agent powered by the `ClineCore` runtime. This example is similar in spirit to [`cli-agent`](../cli-agent), but uses stateful ClineCore sessions and built-in runtime tools instead of the stateless `Agent` class, to leverage Cline's internal agent harness.
|
||||
|
||||
## Getting started
|
||||
|
||||
Install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
bun run build:sdk
|
||||
```
|
||||
|
||||
Set an API key:
|
||||
|
||||
```bash
|
||||
export CLINE_API_KEY="sk_..."
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bun dev
|
||||
```
|
||||
|
||||
Type any message at the `you:` prompt to see a streaming response. Type `exit` to quit.
|
||||
|
||||
## Optional model configuration
|
||||
|
||||
The example defaults to Cline's gateway provider and Claude Sonnet:
|
||||
|
||||
```bash
|
||||
export CLINE_PROVIDER_ID="cline"
|
||||
export CLINE_MODEL_ID="anthropic/claude-sonnet-4.6"
|
||||
```
|
||||
|
||||
## What it does
|
||||
|
||||
- Creates a local `ClineCore` runtime with `ClineCore.create()`
|
||||
- Starts one interactive session with `cline.start()`
|
||||
- Sends each user turn with `cline.send({ sessionId, prompt })`
|
||||
- Streams `agent_event` text to stdout as the assistant responds
|
||||
- Logs tool calls and tool results inline
|
||||
- Uses ClineCore's built-in tools instead of defining custom tools
|
||||
- Calls `cline.stop()` and `cline.dispose()` during shutdown
|
||||
|
||||
## Concepts demonstrated
|
||||
|
||||
- Stateful sessions with `ClineCore`
|
||||
- Multi-turn conversation using a single `sessionId`
|
||||
- `CoreSessionEvent` subscription via `cline.subscribe()`
|
||||
- Built-in runtime tools (`read_files`, `search_codebase`, `run_commands`, etc.)
|
||||
- Basic tool policies: file reads/search are auto-approved, other tools request approval
|
||||
|
||||
## Notes
|
||||
|
||||
Use this example when you want the full ClineCore runtime with sessions, persistence, and built-in tools. For the smallest possible SDK example, see [quickstart](../quickstart). For the lightweight stateless runtime, see [cli-agent](../cli-agent).
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@cline/example-cline-core-cli-agent",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "bun run src/index.ts",
|
||||
"build:sdk": "bun run --cwd ../../.. build:sdk",
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cline/sdk": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
import * as readline from "node:readline";
|
||||
import {
|
||||
type AgentEvent,
|
||||
ClineCore,
|
||||
type ToolApprovalRequest,
|
||||
} from "@cline/sdk";
|
||||
|
||||
// ClineCore does not choose a model automatically; each session config must provide one.
|
||||
// These example defaults use the Cline gateway with Claude Sonnet, and can be overridden with env vars.
|
||||
const providerId = process.env.CLINE_PROVIDER_ID ?? "cline";
|
||||
const modelId = process.env.CLINE_MODEL_ID ?? "anthropic/claude-sonnet-4.6";
|
||||
const apiKey = process.env.CLINE_API_KEY;
|
||||
const cwd = process.cwd();
|
||||
|
||||
const systemPrompt = `You are a helpful assistant in an interactive terminal chat.
|
||||
Be concise. You can use built-in tools to inspect files, search the workspace, and run shell commands when helpful.`;
|
||||
|
||||
let cline: ClineCore | undefined;
|
||||
let unsubscribe: (() => void) | undefined;
|
||||
let activeSessionId: string | undefined;
|
||||
let hasPrintedAssistantPrefix = false;
|
||||
|
||||
function printAssistantPrefix(): void {
|
||||
if (!hasPrintedAssistantPrefix) {
|
||||
process.stdout.write("\nagent: ");
|
||||
hasPrintedAssistantPrefix = true;
|
||||
}
|
||||
}
|
||||
|
||||
function formatToolValue(value: unknown): string {
|
||||
const output =
|
||||
typeof value === "string" ? value : (JSON.stringify(value, null, 2) ?? "");
|
||||
return output.length > 200 ? `${output.slice(0, 200)}...` : output;
|
||||
}
|
||||
|
||||
function handleAgentEvent(event: AgentEvent): void {
|
||||
switch (event.type) {
|
||||
case "content_start":
|
||||
if (event.contentType === "text" && event.text) {
|
||||
printAssistantPrefix();
|
||||
process.stdout.write(event.text);
|
||||
}
|
||||
if (event.contentType === "tool" && event.toolName) {
|
||||
console.log(
|
||||
`\n[tool] ${event.toolName}(${JSON.stringify(event.input ?? {})})`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "content_update":
|
||||
if (event.contentType === "tool" && event.toolName) {
|
||||
console.log(
|
||||
`[update] ${event.toolName}: ${formatToolValue(event.update)}`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "content_end":
|
||||
if (event.contentType === "tool" && event.toolName) {
|
||||
if (event.error) {
|
||||
console.log(`[error] ${event.toolName}: ${event.error}`);
|
||||
} else {
|
||||
console.log(`[result] ${formatToolValue(event.output)}`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "notice":
|
||||
console.log(`\n[notice] ${event.message}`);
|
||||
break;
|
||||
case "error":
|
||||
console.error(`\n[error] ${event.error.message}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureCline(): Promise<ClineCore> {
|
||||
if (cline) {
|
||||
return cline;
|
||||
}
|
||||
|
||||
cline = await ClineCore.create({
|
||||
clientName: "cline-core-cli-agent",
|
||||
backendMode: "local",
|
||||
capabilities: {
|
||||
requestToolApproval,
|
||||
},
|
||||
});
|
||||
unsubscribe = cline.subscribe((event) => {
|
||||
if (event.type === "agent_event") {
|
||||
handleAgentEvent(event.payload.event);
|
||||
}
|
||||
});
|
||||
return cline;
|
||||
}
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
function ask(question: string): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
rl.question(question, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
async function requestToolApproval(request: ToolApprovalRequest) {
|
||||
console.log(`\n[approval] ${request.toolName} wants to run:`);
|
||||
console.log(formatToolValue(request.input));
|
||||
const answer = await ask("Approve? [y/N] ");
|
||||
const approved = answer.trim().toLowerCase() === "y";
|
||||
return {
|
||||
approved,
|
||||
...(approved ? {} : { reason: "User denied tool execution" }),
|
||||
};
|
||||
}
|
||||
|
||||
function prompt(): Promise<string> {
|
||||
return ask("\nyou: ");
|
||||
}
|
||||
|
||||
async function startSession(): Promise<string> {
|
||||
const runtime = await ensureCline();
|
||||
const result = await runtime.start({
|
||||
source: "cli",
|
||||
interactive: true,
|
||||
config: {
|
||||
providerId,
|
||||
modelId,
|
||||
apiKey,
|
||||
cwd,
|
||||
workspaceRoot: cwd,
|
||||
mode: "act",
|
||||
systemPrompt,
|
||||
maxIterations: 10,
|
||||
enableTools: true,
|
||||
enableSpawnAgent: false,
|
||||
enableAgentTeams: false,
|
||||
disableMcpSettingsTools: true,
|
||||
},
|
||||
toolPolicies: {
|
||||
"*": { autoApprove: false },
|
||||
read_files: { autoApprove: true },
|
||||
search_codebase: { autoApprove: true },
|
||||
},
|
||||
});
|
||||
return result.sessionId;
|
||||
}
|
||||
|
||||
async function runTurn(input: string): Promise<void> {
|
||||
activeSessionId ??= await startSession();
|
||||
hasPrintedAssistantPrefix = false;
|
||||
const runtime = await ensureCline();
|
||||
await runtime.send({
|
||||
sessionId: activeSessionId,
|
||||
prompt: input,
|
||||
});
|
||||
console.log();
|
||||
}
|
||||
|
||||
console.log("ClineCore CLI Agent (type 'exit' to quit)\n");
|
||||
console.log(`Provider: ${providerId}`);
|
||||
console.log(`Model: ${modelId}`);
|
||||
console.log(`CWD: ${cwd}`);
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const input = await prompt();
|
||||
const trimmed = input.trim();
|
||||
if (trimmed.toLowerCase() === "exit") {
|
||||
break;
|
||||
}
|
||||
if (!trimmed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await runTurn(trimmed);
|
||||
}
|
||||
} finally {
|
||||
rl.close();
|
||||
unsubscribe?.();
|
||||
if (activeSessionId && cline) {
|
||||
await cline.stop(activeSessionId).catch(() => undefined);
|
||||
}
|
||||
await cline?.dispose();
|
||||
console.log("Goodbye!");
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../../tsconfig.apps.json",
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"outDir": "dist",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
|
||||
import {
|
||||
createServer,
|
||||
type IncomingMessage,
|
||||
type ServerResponse,
|
||||
} from "node:http";
|
||||
import { Agent, createTool } from "@cline/sdk";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -1438,9 +1442,12 @@ async function loadPullRequest(prUrl: string): Promise<PullRequestBundle> {
|
||||
githubPaged<GitHubPullFile>(
|
||||
`https://api.github.com/repos/${ref.owner}/${ref.repo}/pulls/${ref.number}/files`,
|
||||
),
|
||||
githubText(`https://api.github.com/repos/${ref.owner}/${ref.repo}/pulls/${ref.number}`, {
|
||||
headers: { Accept: "application/vnd.github.v3.diff" },
|
||||
}),
|
||||
githubText(
|
||||
`https://api.github.com/repos/${ref.owner}/${ref.repo}/pulls/${ref.number}`,
|
||||
{
|
||||
headers: { Accept: "application/vnd.github.v3.diff" },
|
||||
},
|
||||
),
|
||||
loadChecks(ref, pr.head.sha),
|
||||
]);
|
||||
|
||||
@@ -1464,7 +1471,8 @@ async function loadChecks(ref: PullRequestRef, sha: string) {
|
||||
(run) => run.status !== "completed",
|
||||
);
|
||||
if (failedChecks.length > 0 || status.state === "failure") return "failing";
|
||||
if (pendingChecks.length > 0 || status.state === "pending") return "pending";
|
||||
if (pendingChecks.length > 0 || status.state === "pending")
|
||||
return "pending";
|
||||
if (checks.total_count > 0 || status.total_count > 0) return "passing";
|
||||
return "unknown";
|
||||
} catch {
|
||||
@@ -1566,7 +1574,8 @@ async function githubText(url: string, init: RequestInit = {}) {
|
||||
|
||||
async function githubFetch(url: string, init: RequestInit = {}) {
|
||||
const headers = new Headers(init.headers);
|
||||
if (!headers.has("Accept")) headers.set("Accept", "application/vnd.github+json");
|
||||
if (!headers.has("Accept"))
|
||||
headers.set("Accept", "application/vnd.github+json");
|
||||
headers.set("User-Agent", "cline-sdk-code-review-bot-example");
|
||||
headers.set("X-GitHub-Api-Version", "2022-11-28");
|
||||
if (GITHUB_TOKEN) headers.set("Authorization", `Bearer ${GITHUB_TOKEN}`);
|
||||
@@ -1614,7 +1623,12 @@ function formatReviewComment(
|
||||
const lines = ["## AI Review Bot", ""];
|
||||
if (summary) {
|
||||
lines.push(summary.summary, "");
|
||||
lines.push(summary.approve ? "**Status:** Looks safe to merge." : "**Status:** Changes requested.", "");
|
||||
lines.push(
|
||||
summary.approve
|
||||
? "**Status:** Looks safe to merge."
|
||||
: "**Status:** Changes requested.",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
if (findings.length === 0) {
|
||||
|
||||
@@ -152,7 +152,9 @@ function asString(value: unknown): string | undefined {
|
||||
}
|
||||
|
||||
function asNumber(value: unknown): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
||||
return typeof value === "number" && Number.isFinite(value)
|
||||
? value
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function basename(value: string | undefined): string {
|
||||
@@ -271,7 +273,9 @@ function summarizeClient(client: TrackedClient): {
|
||||
};
|
||||
}
|
||||
|
||||
function sessionTitle(session: SessionRecord | Record<string, unknown>): string {
|
||||
function sessionTitle(
|
||||
session: SessionRecord | Record<string, unknown>,
|
||||
): string {
|
||||
const raw = session as Record<string, unknown>;
|
||||
const metadata = metadataFor(session);
|
||||
const title = asString(metadata.title);
|
||||
@@ -827,7 +831,9 @@ async function main(): Promise<void> {
|
||||
const previousStatus = existing.status;
|
||||
existing.status = status;
|
||||
existing.updatedAt =
|
||||
asNumber(session.updatedAt) ?? asNumber(session.endedAt) ?? Date.now();
|
||||
asNumber(session.updatedAt) ??
|
||||
asNumber(session.endedAt) ??
|
||||
Date.now();
|
||||
existing.title = sessionTitle(session);
|
||||
existing.workspaceRoot =
|
||||
typeof session.workspaceRoot === "string"
|
||||
@@ -852,7 +858,11 @@ async function main(): Promise<void> {
|
||||
events,
|
||||
`Session ${status}`,
|
||||
`${existing.title ?? shortSessionId(sessionId)} changed from ${previousStatus}`,
|
||||
status === "running" ? "success" : status === "idle" ? "info" : "warn",
|
||||
status === "running"
|
||||
? "success"
|
||||
: status === "idle"
|
||||
? "info"
|
||||
: "warn",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -873,7 +883,7 @@ async function main(): Promise<void> {
|
||||
? session.sessionId
|
||||
: typeof payload.sessionId === "string"
|
||||
? payload.sessionId
|
||||
: undefined;
|
||||
: undefined;
|
||||
if (!sessionId) return;
|
||||
const participantCount = Array.isArray(session?.participants)
|
||||
? session.participants.length
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Agent } from "@cline/sdk";
|
||||
import { createServer } from "node:http";
|
||||
import { Agent } from "@cline/sdk";
|
||||
|
||||
const PORT = Number(process.env.PORT || 3456);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
readHubDiscovery,
|
||||
rememberRecoverableLocalHubUrl,
|
||||
resolveSharedHubOwnerContext,
|
||||
type SendSessionConnectionUpdate,
|
||||
type ToolPolicy,
|
||||
} from "@cline/core";
|
||||
import {
|
||||
@@ -1022,13 +1023,14 @@ class CoreChatWebviewController implements vscode.Disposable {
|
||||
|
||||
this.sending = true;
|
||||
try {
|
||||
await this.ensureSession(config);
|
||||
const startConfig = await this.ensureSession(config);
|
||||
const host = await this.getSessionHost();
|
||||
const activeSessionId = this.sessionId as string;
|
||||
await host.send({
|
||||
sessionId: activeSessionId,
|
||||
prompt: trimmedPrompt,
|
||||
userImages: attachments?.userImages,
|
||||
connection: buildConnectionUpdate(startConfig),
|
||||
});
|
||||
await this.refreshSessions();
|
||||
} catch (error) {
|
||||
@@ -1147,6 +1149,12 @@ class CoreChatWebviewController implements vscode.Disposable {
|
||||
|
||||
if (this.sessionId && this.startConfig) {
|
||||
if (areStartConfigsEqual(this.startConfig, startConfig)) {
|
||||
this.startConfig = {
|
||||
...this.startConfig,
|
||||
providerId: startConfig.providerId,
|
||||
modelId: startConfig.modelId,
|
||||
thinking: startConfig.thinking,
|
||||
};
|
||||
return this.startConfig;
|
||||
}
|
||||
await this.stopExistingSession();
|
||||
@@ -1537,13 +1545,10 @@ class CoreChatWebviewController implements vscode.Disposable {
|
||||
*/
|
||||
function areStartConfigsEqual(a: StartConfig, b: StartConfig): boolean {
|
||||
return (
|
||||
a.providerId === b.providerId &&
|
||||
a.modelId === b.modelId &&
|
||||
a.cwd === b.cwd &&
|
||||
a.workspaceRoot === b.workspaceRoot &&
|
||||
a.systemPrompt === b.systemPrompt &&
|
||||
a.maxIterations === b.maxIterations &&
|
||||
a.thinking === b.thinking &&
|
||||
a.enableTools === b.enableTools &&
|
||||
a.enableSpawnAgent === b.enableSpawnAgent &&
|
||||
a.enableAgentTeams === b.enableAgentTeams &&
|
||||
@@ -1559,6 +1564,16 @@ function areStartConfigsEqual(a: StartConfig, b: StartConfig): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function buildConnectionUpdate(
|
||||
config: StartConfig,
|
||||
): SendSessionConnectionUpdate {
|
||||
return {
|
||||
providerId: config.providerId,
|
||||
modelId: config.modelId,
|
||||
thinking: config.thinking === true,
|
||||
};
|
||||
}
|
||||
|
||||
function createToolPolicies(config: StartConfig): Record<string, ToolPolicy> {
|
||||
return {
|
||||
"*": { autoApprove: config.autoApproveTools !== false },
|
||||
|
||||
+202
-243
@@ -19,7 +19,7 @@
|
||||
},
|
||||
"apps/cli": {
|
||||
"name": "@cline/cli",
|
||||
"version": "3.0.3",
|
||||
"version": "3.0.11",
|
||||
"bin": {
|
||||
"cline": "src/index.ts",
|
||||
},
|
||||
@@ -38,6 +38,7 @@
|
||||
"@opentui/react": "0.1.102",
|
||||
"chat": "^4.23.0",
|
||||
"commander": "^14.0.3",
|
||||
"fzf": "^0.5.2",
|
||||
"marked": "^15.0.12",
|
||||
"open": "^10.2.0",
|
||||
"opentui-spinner": "^0.0.6",
|
||||
@@ -66,6 +67,16 @@
|
||||
"typescript": "^5.9.3",
|
||||
},
|
||||
},
|
||||
"apps/examples/cline-core-cli-agent": {
|
||||
"name": "@cline/example-cline-core-cli-agent",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@cline/sdk": "workspace:*",
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.9.3",
|
||||
},
|
||||
},
|
||||
"apps/examples/code-review-bot": {
|
||||
"name": "@cline/example-code-review-bot",
|
||||
"version": "0.0.0",
|
||||
@@ -287,7 +298,7 @@
|
||||
},
|
||||
"packages/agents": {
|
||||
"name": "@cline/agents",
|
||||
"version": "0.0.41",
|
||||
"version": "0.0.42",
|
||||
"dependencies": {
|
||||
"@cline/llms": "workspace:*",
|
||||
"@cline/shared": "workspace:*",
|
||||
@@ -296,7 +307,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@cline/core",
|
||||
"version": "0.0.41",
|
||||
"version": "0.0.42",
|
||||
"dependencies": {
|
||||
"@cline/agents": "workspace:*",
|
||||
"@cline/llms": "workspace:*",
|
||||
@@ -327,7 +338,7 @@
|
||||
},
|
||||
"packages/llms": {
|
||||
"name": "@cline/llms",
|
||||
"version": "0.0.41",
|
||||
"version": "0.0.42",
|
||||
"dependencies": {
|
||||
"@ai-sdk/amazon-bedrock": "^4.0.89",
|
||||
"@ai-sdk/anthropic": "^3.0.68",
|
||||
@@ -360,14 +371,14 @@
|
||||
},
|
||||
"packages/sdk": {
|
||||
"name": "@cline/sdk",
|
||||
"version": "0.0.41",
|
||||
"version": "0.0.42",
|
||||
"dependencies": {
|
||||
"@cline/core": "workspace:*",
|
||||
},
|
||||
},
|
||||
"packages/shared": {
|
||||
"name": "@cline/shared",
|
||||
"version": "0.0.41",
|
||||
"version": "0.0.42",
|
||||
"dependencies": {
|
||||
"aws4fetch": "^1.0.20",
|
||||
"jsonrepair": "^3.13.2",
|
||||
@@ -379,19 +390,19 @@
|
||||
"packages": {
|
||||
"@agentclientprotocol/sdk": ["@agentclientprotocol/sdk@0.16.1", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-1ad+Sc/0sCtZGHthxxvgEUo5Wsbw16I+aF+YwdiLnPwkZG8KAGUEAPK6LM6Pf69lCyJPt1Aomk1d+8oE3C4ZEw=="],
|
||||
|
||||
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.105", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.77", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-mNnJeRTIYRL2I2MS9ElRJTFMSeHqbx5EMCVsIlEKKTI4+2O+Zu0K7Rtp16HRXtxMepJF1Y756rAmUm/JvuXOGg=="],
|
||||
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.108", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.79", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cVAzseR9OoSSL7966TMj2uUbDOL2e1LaH2JXrWvyMXQvF5Me2rPfzdA06k/vhYjP0DQq1uvsZPRojmg4ghiI9g=="],
|
||||
|
||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.77", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ML8C2M1YvPA1ulEx4TiyF0k1xvC2ikEiPBIC1PPQ0a5xELUGrO2lAaEzsTEoJ+eCeDd8PSBuFJjs+r+9yIwQXA=="],
|
||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.79", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-saEX+h5JDOkT9P/+REKDyikbnJiToFuLipgNcsmu4Zr3GW5kW1m9HhvrPK+vj63itIOsoZU6tmVIjkrePOlIUA=="],
|
||||
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.114", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MqkZ5sd+qiq6RgIxELkoFQXg2/JwK+WCMaot7U+rtrZpWJl3fSyYvc28SC03b256o4F7OXjQtdjTqs81B2w+dA=="],
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.119", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-VAhfRWC+JexZakkVfmjaJKaTj00x7/UHdE8kMWL3NhuQAlf8oXtg9r4dfvFZrByXxchGRBvYE3biEUyibkg0xg=="],
|
||||
|
||||
"@ai-sdk/google": ["@ai-sdk/google@3.0.73", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-o2MuIeyvZrFIeIbnbA8Thrr63irdyUBh0uWBZ2lY6yFeXuE/tcwyXF74bDKS4KvTu84uFpQfpbS/LXHGKKXz+g=="],
|
||||
"@ai-sdk/google": ["@ai-sdk/google@3.0.79", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-QWVAvYeA7JzEX2wkSyXOWv/I9PD9kvTzdykkSTLi+Eu8RyJ6gA0tdPIGa8esEtOcHE//G5vy6FTB70qQw8l/uw=="],
|
||||
|
||||
"@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@4.0.128", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.77", "@ai-sdk/google": "3.0.73", "@ai-sdk/openai-compatible": "2.0.47", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-jK8fixb4km2yfgvb9DUFQRpV/jiDB0v9gyxHoHfPydaQvz+CpAz8DTt1quyaM+Wg9G2R8Zo68CYmHbIkUqW2AA=="],
|
||||
"@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@4.0.136", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.79", "@ai-sdk/google": "3.0.79", "@ai-sdk/openai-compatible": "2.0.47", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-h6y520LNDm61QSsa9phEfX1uSVHmLLGvfSu2JkFYqui+cu0SEui60WDe9R0vJ8bl9q54+qVzxctFN+7LuXX5lA=="],
|
||||
|
||||
"@ai-sdk/mistral": ["@ai-sdk/mistral@3.0.36", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-FLIb2QdLraOgQP3puUybuFYWbtsB02YWQBTOJOk8heiEsdFW3YE0dfuzwtsvoF4FXlBnbYYMWu5jgOesthcmWg=="],
|
||||
"@ai-sdk/mistral": ["@ai-sdk/mistral@3.0.37", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-KkdaMjs4C2y+vrZWJE990E3ZxBFiOTHQ94ZlquuIttpphcqJTMxNoIpnKT/4UzMVWXL0BUEE2vs+1UEVXkN8Kg=="],
|
||||
|
||||
"@ai-sdk/openai": ["@ai-sdk/openai@3.0.63", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4yY/m8a57MNNVoJCsXuNblKf6BO4yuAuLKRX4tzSNffBEBSp1FlcWdPE0Z4FkqUeS0AJhYSSqp0GIiA/cIcDNA=="],
|
||||
"@ai-sdk/openai": ["@ai-sdk/openai@3.0.65", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZlVoWH+zrdiYDiUt6n/xvfCsk33mzsB81TUQkBRVx79rxU1FKZqVH9J/QCtEpSLqx0cUzjvtIw9l9p7EbUv+dw=="],
|
||||
|
||||
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Enm5UlL0zUCrW3792opk5h7hRWxZOZzDe6eQYVFqX9LUOGGCe1h8MZWAGim765nwzgnjlpeYOsuzZmLtRsTPlg=="],
|
||||
|
||||
@@ -399,31 +410,31 @@
|
||||
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
|
||||
|
||||
"@ai-sdk/react": ["@ai-sdk/react@3.0.182", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.27", "ai": "6.0.180", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-cnfF5N6XRsQ29VsSSoFqFpYQJx1y4sSCL3lGMIwgE0034aqn8i3+joRe52O9xV+EaJ7fziI7xn6ql7qjrf+Blw=="],
|
||||
"@ai-sdk/react": ["@ai-sdk/react@3.0.192", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.27", "ai": "6.0.190", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-QB7ViYcM1o2zN6Zo1nVD1FqAkiivCPOi1vmT/OmWAxctmXUGTdWOL7MBs9q3zuzPbZpkty4xDERwemWYoZx6Kw=="],
|
||||
|
||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||
|
||||
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.2.140", "", { "dependencies": { "@anthropic-ai/sdk": "^0.81.0", "@modelcontextprotocol/sdk": "^1.29.0" }, "optionalDependencies": { "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.2.140", "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.2.140", "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.2.140", "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.2.140", "@anthropic-ai/claude-agent-sdk-linux-x64": "0.2.140", "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.2.140", "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.2.140", "@anthropic-ai/claude-agent-sdk-win32-x64": "0.2.140" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-Zq2L7YCoTdbxTUi3/soN1axrTqbG7GoKuc6Im8EpkBRdwaY0D1W9+Ux3vAbV/cX8Qk31Vck7DQLZz1lGEArdoQ=="],
|
||||
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.2.141", "", { "dependencies": { "@anthropic-ai/sdk": "^0.93.0", "@modelcontextprotocol/sdk": "^1.29.0" }, "optionalDependencies": { "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.2.141", "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.2.141", "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.2.141", "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.2.141", "@anthropic-ai/claude-agent-sdk-linux-x64": "0.2.141", "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.2.141", "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.2.141", "@anthropic-ai/claude-agent-sdk-win32-x64": "0.2.141" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-AIBacMWGcZIUcXlUoObqjwJ6pmJI3BayAqPAFXuvSq3DHJXdiuZVs7l/zTB5l3nRhRv5cqSrI2XbiDeHgZWizw=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": ["@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.140", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zEbDsDKeoDO4DzbyX6wBVlcPhLy/gYiCrKzKnxmkOhyNtJBeshgiOTdr+M7WX1xcuI/M/UhEY+B9U6oo884lAQ=="],
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": ["@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.141", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9HZ0ot6+FwOfQ1aeMqQLH4IJGMm/DcP08SysDxscVjBm6l2JjqleHohxi3zid0DurfGweqT+4x9GScJffwg55g=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": ["@anthropic-ai/claude-agent-sdk-darwin-x64@0.2.140", "", { "os": "darwin", "cpu": "x64" }, "sha512-BFJGeZEksvERy7mMJ0mkNAWoMrZOgl6XN/mKPaunGnaC/i+1ykx7xih7e58bRhsrzKzo2mnUrwtjiFyF3MFNRQ=="],
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": ["@anthropic-ai/claude-agent-sdk-darwin-x64@0.2.141", "", { "os": "darwin", "cpu": "x64" }, "sha512-4iAdarJaQ+2R58s6QJswZCzUdz2WQmL5lYG7Y+FLzWbRSROFfcH0QYpmOqSaPXd2KRQhIJwEacqecDZd/Q1XKQ=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": ["@anthropic-ai/claude-agent-sdk-linux-arm64@0.2.140", "", { "os": "linux", "cpu": "arm64" }, "sha512-FauGGg3zikxrjAUnu+Pso6zD9Qv4Z2+QBiTiZqc12U+x4uoikNsplymUnsJ7MYD9VaTGmLJuZ9pCch0IiKrseQ=="],
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": ["@anthropic-ai/claude-agent-sdk-linux-arm64@0.2.141", "", { "os": "linux", "cpu": "arm64" }, "sha512-Jdf0ZEwJzOP8sE6rPqdJN+SxMb0/L8sxJg4twCv/7S+Qzk0hJtls+wxSi+0Tjh6EEMaNxJqEGc7S3fx99Wi99Q=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": ["@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.2.140", "", { "os": "linux", "cpu": "arm64" }, "sha512-nG7xLL0nKb4ymFVnX0QhSGLoyhh9fuuDpBR+TYz5O4ZQc2RVUMSMqGusqcCNEIGxAKQSVKWCf0WgpCG/edAO9Q=="],
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": ["@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.2.141", "", { "os": "linux", "cpu": "arm64" }, "sha512-6H1AJ/AVaWNnV22kubUPkOTRzZFH0+qP9k7WlhriHMN9gtgZcVAsITMddDeGjQsQJMCAdhXFd6sgi7TM1LdeOQ=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64": ["@anthropic-ai/claude-agent-sdk-linux-x64@0.2.140", "", { "os": "linux", "cpu": "x64" }, "sha512-7f627Tq2mIiwFoBYfCKTdEeZSP90r8UOWu/I5DezudTtwtoVl2zRaRCnJ8c4rW+Tzw+xWSfP/pHvR9bTQGXaOw=="],
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64": ["@anthropic-ai/claude-agent-sdk-linux-x64@0.2.141", "", { "os": "linux", "cpu": "x64" }, "sha512-DVjp72f3HmrRYpbneWZZWIqkUht5kTZXS7wXGFiwzLz6eNYEgjjh+GcsnhIi8UOwZUtNiKUrjZnoP38ovFqV8A=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": ["@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.2.140", "", { "os": "linux", "cpu": "x64" }, "sha512-EZ7VzOGmvft/1ymh2rwts5v3yPnsGGlGrTJlY2Dqnr1ABF43JIhEm1NFYrLnXQWSN74s5Pj8tgkPbYS9x4BhFA=="],
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": ["@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.2.141", "", { "os": "linux", "cpu": "x64" }, "sha512-fTI1YuM4cxOa4nSgsyMAdB5ELizkWp+w5Ispo4JnnYtcczMAL4D9GBNjWPW0sUzKvjsJOUVim68SmWLWhUOpXQ=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": ["@anthropic-ai/claude-agent-sdk-win32-arm64@0.2.140", "", { "os": "win32", "cpu": "arm64" }, "sha512-9EOozRF+LTt3UedeJtjJXC8pj9VTAFtPBuB+/YUmcpmDAEH9qcWWknWhf7NDKTapKtBWkNP/387x+18L15MLqg=="],
|
||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": ["@anthropic-ai/claude-agent-sdk-win32-arm64@0.2.141", "", { "os": "win32", "cpu": "arm64" }, "sha512-Wm10J6kfbufbPGFELokiJ/7Y5Oqug4Uag3HXFsV8g7TWCpaItx/oqVaJoiGptuAtXQB7xGLQVTuk082wER+Y5w=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-win32-x64": ["@anthropic-ai/claude-agent-sdk-win32-x64@0.2.140", "", { "os": "win32", "cpu": "x64" }, "sha512-puQyWoYiqosjDEYULWAS/lBJse1vzib0NmQj/bYTirWCbtiUcu6ixKMd4NmLbE+Si/DKTB8XNz6hVZ/KckqeoQ=="],
|
||||
"@anthropic-ai/claude-agent-sdk-win32-x64": ["@anthropic-ai/claude-agent-sdk-win32-x64@0.2.141", "", { "os": "win32", "cpu": "x64" }, "sha512-IXuP29YJuWbR5Q6xOHrjFVGG54V2s1FC61UVNwEN5fpxL09MwPnbwtQL6fqgzt/U1MP7vWAwpXZriYAklkH/mg=="],
|
||||
|
||||
"@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.81.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw=="],
|
||||
"@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.93.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-q9vaSZQVFx6B/gPxetGYfLXSJD5v0sOmh0OpZDq7yCrTSA+Rscvrtyol7JJTW40wEpQB4U1B4JXzxQitbQ3CAA=="],
|
||||
|
||||
"@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="],
|
||||
|
||||
@@ -435,61 +446,41 @@
|
||||
|
||||
"@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="],
|
||||
|
||||
"@aws-sdk/client-cognito-identity": ["@aws-sdk/client-cognito-identity@3.1045.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.8", "@aws-sdk/credential-provider-node": "^3.972.39", "@aws-sdk/middleware-host-header": "^3.972.10", "@aws-sdk/middleware-logger": "^3.972.10", "@aws-sdk/middleware-recursion-detection": "^3.972.11", "@aws-sdk/middleware-user-agent": "^3.972.38", "@aws-sdk/region-config-resolver": "^3.972.13", "@aws-sdk/types": "^3.973.8", "@aws-sdk/util-endpoints": "^3.996.8", "@aws-sdk/util-user-agent-browser": "^3.972.10", "@aws-sdk/util-user-agent-node": "^3.973.24", "@smithy/config-resolver": "^4.4.17", "@smithy/core": "^3.23.17", "@smithy/fetch-http-handler": "^5.3.17", "@smithy/hash-node": "^4.2.14", "@smithy/invalid-dependency": "^4.2.14", "@smithy/middleware-content-length": "^4.2.14", "@smithy/middleware-endpoint": "^4.4.32", "@smithy/middleware-retry": "^4.5.7", "@smithy/middleware-serde": "^4.2.20", "@smithy/middleware-stack": "^4.2.14", "@smithy/node-config-provider": "^4.3.14", "@smithy/node-http-handler": "^4.6.1", "@smithy/protocol-http": "^5.3.14", "@smithy/smithy-client": "^4.12.13", "@smithy/types": "^4.14.1", "@smithy/url-parser": "^4.2.14", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", "@smithy/util-defaults-mode-browser": "^4.3.49", "@smithy/util-defaults-mode-node": "^4.2.54", "@smithy/util-endpoints": "^3.4.2", "@smithy/util-middleware": "^4.2.14", "@smithy/util-retry": "^4.3.6", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-3OEn8zvtfJoN0jFfjVJ9jF2GVRDL3IjDfk6CAgVTAqjfCVjajiUD0iFAGQ4cOzdcv1LGsZ0b/snJDWalY3OePQ=="],
|
||||
"@aws-sdk/client-cognito-identity": ["@aws-sdk/client-cognito-identity@3.1053.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.13", "@aws-sdk/credential-provider-node": "^3.972.44", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/fetch-http-handler": "^5.4.3", "@smithy/node-http-handler": "^4.7.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-fMwSPTOWcYrKsB1NG1z9uRSLE/GDJR/375tjiAyO6z2UTlpLSuWkfoYx98oMwHaJpqb1fEhtZZQ7o8czblShJQ=="],
|
||||
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.974.8", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@aws-sdk/xml-builder": "^3.972.22", "@smithy/core": "^3.23.17", "@smithy/node-config-provider": "^4.3.14", "@smithy/property-provider": "^4.2.14", "@smithy/protocol-http": "^5.3.14", "@smithy/signature-v4": "^5.3.14", "@smithy/smithy-client": "^4.12.13", "@smithy/types": "^4.14.1", "@smithy/util-base64": "^4.3.2", "@smithy/util-middleware": "^4.2.14", "@smithy/util-retry": "^4.3.6", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-njR2qoG6ZuB0kvAS2FyICsFZJ6gmCcf2X/7JcD14sUvGDm26wiZ5BrA6LOiUxKFEF+IVe7kdroxyE00YlkiYsw=="],
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.974.13", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.25", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.3", "@smithy/signature-v4": "^5.4.2", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-+Y5/4tHki0uYgyx8eun146DegRVQBpdKGK5RbV0FTKJPpaKTchvqVxrrRFK6Wk0JksO4iAZKw3eqxGEIwtO98w=="],
|
||||
|
||||
"@aws-sdk/credential-provider-cognito-identity": ["@aws-sdk/credential-provider-cognito-identity@3.972.31", "", { "dependencies": { "@aws-sdk/nested-clients": "^3.997.6", "@aws-sdk/types": "^3.973.8", "@smithy/property-provider": "^4.2.14", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-W5JtzDp3ejzhOOknXlnt+vJsNN2GZdAcBK+hR7HQ1DCacXqS0UpmnIyihIU7CK0IB+XYWeBaN3bBv4pXavp7Vg=="],
|
||||
"@aws-sdk/credential-provider-cognito-identity": ["@aws-sdk/credential-provider-cognito-identity@3.972.36", "", { "dependencies": { "@aws-sdk/nested-clients": "^3.997.11", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-DkibmGSpgUKUwqvbooEnwoU/18pbrneuOcysCwHolC85Q6UXGesZ73Sk00oK/SpWOe+lfjDxq2nMDypJvi2OmQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.34", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/types": "^3.973.8", "@smithy/property-provider": "^4.2.14", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-XT0jtf8Fw9JE6ppsQeoNnZRiG+jqRixMT1v1ZR17G60UvVdsQmTG8nbEyHuEPfMxDXEhfdARaM/XiEhca4lGHQ=="],
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.39", "", { "dependencies": { "@aws-sdk/core": "^3.974.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-29wX9zpAvEt1vcj0psha+y6ygBHy2V/S72mp6e7q0KARLWXq+pwE/lR6qGkwknQvruh52lXvlqZIga8Hdxkucw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.36", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/types": "^3.973.8", "@smithy/fetch-http-handler": "^5.3.17", "@smithy/node-http-handler": "^4.6.1", "@smithy/property-provider": "^4.2.14", "@smithy/protocol-http": "^5.3.14", "@smithy/smithy-client": "^4.12.13", "@smithy/types": "^4.14.1", "@smithy/util-stream": "^4.5.25", "tslib": "^2.6.2" } }, "sha512-DPoGWfy7J7RKxvbf5kOKIGQkD2ek3dbKgzKIGrnLuvZBz5myU+Im/H6pmc14QcnFbqHMqxvtWSgRDSJW3qXLQg=="],
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.41", "", { "dependencies": { "@aws-sdk/core": "^3.974.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/fetch-http-handler": "^5.4.3", "@smithy/node-http-handler": "^4.7.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-IA3CQTjtJkb6u1H4mE4936c8OPBMa9Jggtwe8U2Mqw/vvb/tZ5Ebd0mcZcX0uKWQhOyYo/+qNIwkV5Xh+FeJJA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.38", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/credential-provider-env": "^3.972.34", "@aws-sdk/credential-provider-http": "^3.972.36", "@aws-sdk/credential-provider-login": "^3.972.38", "@aws-sdk/credential-provider-process": "^3.972.34", "@aws-sdk/credential-provider-sso": "^3.972.38", "@aws-sdk/credential-provider-web-identity": "^3.972.38", "@aws-sdk/nested-clients": "^3.997.6", "@aws-sdk/types": "^3.973.8", "@smithy/credential-provider-imds": "^4.2.14", "@smithy/property-provider": "^4.2.14", "@smithy/shared-ini-file-loader": "^4.4.9", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-oDzUBu2MGJFgoar05sPMCwSrhw44ASyccrHzj66vO69OZqi7I6hZZxXfuPLC8OCzW7C+sU+bI73XHij41yekgQ=="],
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.43", "", { "dependencies": { "@aws-sdk/core": "^3.974.13", "@aws-sdk/credential-provider-env": "^3.972.39", "@aws-sdk/credential-provider-http": "^3.972.41", "@aws-sdk/credential-provider-login": "^3.972.43", "@aws-sdk/credential-provider-process": "^3.972.39", "@aws-sdk/credential-provider-sso": "^3.972.43", "@aws-sdk/credential-provider-web-identity": "^3.972.43", "@aws-sdk/nested-clients": "^3.997.11", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/credential-provider-imds": "^4.3.2", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-4mzII+3mZEVXXE1xzrLQrCJL7/r62A63bA6SVzZoNL5rqCJghpf+xgGltVrIBBs0n+mOZBKrQl2tRREtvZ5l6A=="],
|
||||
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.38", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/nested-clients": "^3.997.6", "@aws-sdk/types": "^3.973.8", "@smithy/property-provider": "^4.2.14", "@smithy/protocol-http": "^5.3.14", "@smithy/shared-ini-file-loader": "^4.4.9", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-g1NosS8qe4OF++G2UFCM5ovSkgipC7YYor5KCWatG0UoMSO5YFj9C8muePlyVmOBV/WTI16Jo3/s1NUo/o1Bww=="],
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.43", "", { "dependencies": { "@aws-sdk/core": "^3.974.13", "@aws-sdk/nested-clients": "^3.997.11", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-HG7kQCwXtbv3oBV61Ins0oNX8KKyvrMqqRkb6ZiAfQHbMuHaiNaEb2KnpKLPkNpqImSBK82UkVE/kaY6IfWikA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.39", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.34", "@aws-sdk/credential-provider-http": "^3.972.36", "@aws-sdk/credential-provider-ini": "^3.972.38", "@aws-sdk/credential-provider-process": "^3.972.34", "@aws-sdk/credential-provider-sso": "^3.972.38", "@aws-sdk/credential-provider-web-identity": "^3.972.38", "@aws-sdk/types": "^3.973.8", "@smithy/credential-provider-imds": "^4.2.14", "@smithy/property-provider": "^4.2.14", "@smithy/shared-ini-file-loader": "^4.4.9", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-HEswDQyxUtadoZ/bJsPPENHg7R0Lzym5LuMksJeHvqhCOpP+rtkDLKI4/ZChH4w3cf5kG8n6bZuI8PzajoiqMg=="],
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.44", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.39", "@aws-sdk/credential-provider-http": "^3.972.41", "@aws-sdk/credential-provider-ini": "^3.972.43", "@aws-sdk/credential-provider-process": "^3.972.39", "@aws-sdk/credential-provider-sso": "^3.972.43", "@aws-sdk/credential-provider-web-identity": "^3.972.43", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/credential-provider-imds": "^4.3.2", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-sDaBIT0yrNNIPfvlsiTCmANm07zKju+ipWODjEXgZlsjMeIJR3LVp7RDyAOzUoAsTbDfYKDWp+i5WrFiQP6rmQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.34", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/types": "^3.973.8", "@smithy/property-provider": "^4.2.14", "@smithy/shared-ini-file-loader": "^4.4.9", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-T3IFs4EVmVi1dVN5RciFnklCANSzvrQd/VuHY9ThHSQmYkTogjcGkoJEr+oNUPQZnso52183088NqysMPji1/Q=="],
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.39", "", { "dependencies": { "@aws-sdk/core": "^3.974.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-2k/amBifLd75eXNwgvPw/2lKYSQ3NhvHQgkVKVjfUq13/eJ3JRtHmznuFenn74OK3sSfp4SMy1YB2w+UVXoKqA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.38", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/nested-clients": "^3.997.6", "@aws-sdk/token-providers": "3.1041.0", "@aws-sdk/types": "^3.973.8", "@smithy/property-provider": "^4.2.14", "@smithy/shared-ini-file-loader": "^4.4.9", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-5ZxG+t0+3Q3QPh8KEjX6syskhgNf7I0MN7oGioTf6Lm1NTjfP7sIcYGNsthXC2qR8vcD3edNZwCr2ovfSSWuRA=="],
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.43", "", { "dependencies": { "@aws-sdk/core": "^3.974.13", "@aws-sdk/nested-clients": "^3.997.11", "@aws-sdk/token-providers": "3.1052.0", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-LPc3+Y4vhH1T4x6CMqwCM6hk5+SRf/Lwmgm8INm95wxTtIRHcMwQUVkDzWu4Iw/RSncxYM2BC01OrYbxOPZvyg=="],
|
||||
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.38", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/nested-clients": "^3.997.6", "@aws-sdk/types": "^3.973.8", "@smithy/property-provider": "^4.2.14", "@smithy/shared-ini-file-loader": "^4.4.9", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-lYHFF30DGI20jZcYX8cm6Ns0V7f1dDN6g/MBDLTyD/5iw+bXs3yBr2iAiHDkx4RFU5JgsnZvCHYKiRVPRdmOgw=="],
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.43", "", { "dependencies": { "@aws-sdk/core": "^3.974.13", "@aws-sdk/nested-clients": "^3.997.11", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-wQtL34lUD/09VXjwAUo2T+I3aEXRDxMB3DKmTJL/Zj0Gi6sLDTrVhae1XVt01yzkquOWajI/sZW72JGDZ1ciTw=="],
|
||||
|
||||
"@aws-sdk/credential-providers": ["@aws-sdk/credential-providers@3.1045.0", "", { "dependencies": { "@aws-sdk/client-cognito-identity": "3.1045.0", "@aws-sdk/core": "^3.974.8", "@aws-sdk/credential-provider-cognito-identity": "^3.972.31", "@aws-sdk/credential-provider-env": "^3.972.34", "@aws-sdk/credential-provider-http": "^3.972.36", "@aws-sdk/credential-provider-ini": "^3.972.38", "@aws-sdk/credential-provider-login": "^3.972.38", "@aws-sdk/credential-provider-node": "^3.972.39", "@aws-sdk/credential-provider-process": "^3.972.34", "@aws-sdk/credential-provider-sso": "^3.972.38", "@aws-sdk/credential-provider-web-identity": "^3.972.38", "@aws-sdk/nested-clients": "^3.997.6", "@aws-sdk/types": "^3.973.8", "@smithy/config-resolver": "^4.4.17", "@smithy/core": "^3.23.17", "@smithy/credential-provider-imds": "^4.2.14", "@smithy/node-config-provider": "^4.3.14", "@smithy/property-provider": "^4.2.14", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-J+it58HUGyMIAquB6pWtvmO4m0E/gQ/Tz9Xcoogk3Rety13likU5U8HioeIgE+aN1DDOAB//MARoIdLZS1Mpfw=="],
|
||||
"@aws-sdk/credential-providers": ["@aws-sdk/credential-providers@3.1053.0", "", { "dependencies": { "@aws-sdk/client-cognito-identity": "3.1053.0", "@aws-sdk/core": "^3.974.13", "@aws-sdk/credential-provider-cognito-identity": "^3.972.36", "@aws-sdk/credential-provider-env": "^3.972.39", "@aws-sdk/credential-provider-http": "^3.972.41", "@aws-sdk/credential-provider-ini": "^3.972.43", "@aws-sdk/credential-provider-login": "^3.972.43", "@aws-sdk/credential-provider-node": "^3.972.44", "@aws-sdk/credential-provider-process": "^3.972.39", "@aws-sdk/credential-provider-sso": "^3.972.43", "@aws-sdk/credential-provider-web-identity": "^3.972.43", "@aws-sdk/nested-clients": "^3.997.11", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/credential-provider-imds": "^4.3.2", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-jMzNBhYIIzaKiVOFndhyWSvEIosiU/zSxgcOaGXrHGcwlRXcFgTgZEcOFL504hxg4BdrrAIVdGw55Zk9zMhs7g=="],
|
||||
|
||||
"@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.972.10", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@smithy/protocol-http": "^5.3.14", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-IJSsIMeVQ8MMCPbuh1AbltkFhLBLXn7aejzfX5YKT/VLDHn++Dcz8886tXckE+wQssyPUhaXrJhdakO2VilRhg=="],
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.11", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.13", "@aws-sdk/signature-v4-multi-region": "^3.996.28", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/fetch-http-handler": "^5.4.3", "@smithy/node-http-handler": "^4.7.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-nWXXJ1r/r8N2Gw1pWolRgED38/A9A8DHR2ETWIv220zh4PZHcybbR4hUVWWktmNXTRHzDJwRluapHn0rZxuoqA=="],
|
||||
|
||||
"@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.972.10", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-OOuGvvz1Dm20SjZo5oEBePFqxt5nf8AwkNDSyUHvD9/bfNASmstcYxFAHUowy4n6Io7mWUZ04JURZwSBvyQanQ=="],
|
||||
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.28", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/signature-v4": "^5.4.2", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-qs9z5LqXO/CZC2Lg9SGKpoLU8Rhi+m2pFKZqfO9pytX1clc0katqtsDNupJxFy0xT9wsZSPzM2v1y+/H/zfp5Q=="],
|
||||
|
||||
"@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.972.11", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.14", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-+zz6f79Kj9V5qFK2P+D8Ehjnw4AhphAlCAsPjUqEcInA9umtSSKMrHbSagEeOIsDNuvVrH98bjRHcyQukTrhaQ=="],
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1052.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.13", "@aws-sdk/nested-clients": "^3.997.11", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-QqZNB3so7UIDxZtroc85TQaLVxdZRFm0eWM1CSR2N+b06as9TOrilvrlTZuj3guYlxMs6yLOgGxnklJ5qMYtTw=="],
|
||||
|
||||
"@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.972.37", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/types": "^3.973.8", "@aws-sdk/util-arn-parser": "^3.972.3", "@smithy/core": "^3.23.17", "@smithy/node-config-provider": "^4.3.14", "@smithy/protocol-http": "^5.3.14", "@smithy/signature-v4": "^5.3.14", "@smithy/smithy-client": "^4.12.13", "@smithy/types": "^4.14.1", "@smithy/util-config-provider": "^4.2.2", "@smithy/util-middleware": "^4.2.14", "@smithy/util-stream": "^4.5.25", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-Km7M+i8DrLArVzrid1gfxeGhYHBd3uxvE77g0s5a52zPSVosxzQBnJ0gwWb6NIp/DOk8gsBMhi7V+cpJG0ndTA=="],
|
||||
|
||||
"@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.972.38", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/types": "^3.973.8", "@aws-sdk/util-endpoints": "^3.996.8", "@smithy/core": "^3.23.17", "@smithy/protocol-http": "^5.3.14", "@smithy/types": "^4.14.1", "@smithy/util-retry": "^4.3.6", "tslib": "^2.6.2" } }, "sha512-iz+B29TXcAZsJpwB+AwG/TTGA5l/VnmMZ2UxtiySOZjI6gCdmviXPwdgzcmuazMy16rXoPY4mYCGe7zdNKfx5A=="],
|
||||
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.6", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.8", "@aws-sdk/middleware-host-header": "^3.972.10", "@aws-sdk/middleware-logger": "^3.972.10", "@aws-sdk/middleware-recursion-detection": "^3.972.11", "@aws-sdk/middleware-user-agent": "^3.972.38", "@aws-sdk/region-config-resolver": "^3.972.13", "@aws-sdk/signature-v4-multi-region": "^3.996.25", "@aws-sdk/types": "^3.973.8", "@aws-sdk/util-endpoints": "^3.996.8", "@aws-sdk/util-user-agent-browser": "^3.972.10", "@aws-sdk/util-user-agent-node": "^3.973.24", "@smithy/config-resolver": "^4.4.17", "@smithy/core": "^3.23.17", "@smithy/fetch-http-handler": "^5.3.17", "@smithy/hash-node": "^4.2.14", "@smithy/invalid-dependency": "^4.2.14", "@smithy/middleware-content-length": "^4.2.14", "@smithy/middleware-endpoint": "^4.4.32", "@smithy/middleware-retry": "^4.5.7", "@smithy/middleware-serde": "^4.2.20", "@smithy/middleware-stack": "^4.2.14", "@smithy/node-config-provider": "^4.3.14", "@smithy/node-http-handler": "^4.6.1", "@smithy/protocol-http": "^5.3.14", "@smithy/smithy-client": "^4.12.13", "@smithy/types": "^4.14.1", "@smithy/url-parser": "^4.2.14", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", "@smithy/util-defaults-mode-browser": "^4.3.49", "@smithy/util-defaults-mode-node": "^4.2.54", "@smithy/util-endpoints": "^3.4.2", "@smithy/util-middleware": "^4.2.14", "@smithy/util-retry": "^4.3.6", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-WBDnqatJl+kGObpfmfSxqnXeYTu3Me8wx8WCtvoxX3pfWrrTv8I4WTMSSs7PZqcRcVh8WeUKMgGFjMG+52SR1w=="],
|
||||
|
||||
"@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.972.13", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@smithy/config-resolver": "^4.4.17", "@smithy/node-config-provider": "^4.3.14", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-CvJ2ZIjK/jVD/lbOpowBVElJyC1YxLTIJ13yM0AEo0t2v7swOzGjSA6lJGH+DwZXQhcjUjoYwc8bVYCX5MDr1A=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.25", "", { "dependencies": { "@aws-sdk/middleware-sdk-s3": "^3.972.37", "@aws-sdk/types": "^3.973.8", "@smithy/protocol-http": "^5.3.14", "@smithy/signature-v4": "^5.3.14", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-+CMIt3e1VzlklAECmG+DtP1sV8iKq25FuA0OKpnJ4KA0kxUtd7CgClY7/RU6VzJBQwbN4EJ9Ue6plvqx1qGadw=="],
|
||||
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1041.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.8", "@aws-sdk/nested-clients": "^3.997.6", "@aws-sdk/types": "^3.973.8", "@smithy/property-provider": "^4.2.14", "@smithy/shared-ini-file-loader": "^4.4.9", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-Th7kPI6YPtvJUcdznooXJMy+9rQWjmEF81LxaJssngBzuysK4a/x+l8kjm1zb7nYsUPbndnBdUnwng/3PLvtGw=="],
|
||||
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.973.8", "", { "dependencies": { "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw=="],
|
||||
|
||||
"@aws-sdk/util-arn-parser": ["@aws-sdk/util-arn-parser@3.972.3", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA=="],
|
||||
|
||||
"@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.996.8", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@smithy/types": "^4.14.1", "@smithy/url-parser": "^4.2.14", "@smithy/util-endpoints": "^3.4.2", "tslib": "^2.6.2" } }, "sha512-oOZHcRDihk5iEe5V25NVWg45b3qEA8OpHWVdU/XQh8Zj4heVPAJqWvMphQnU7LkufmUo10EpvFPZuQMiFLJK3g=="],
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="],
|
||||
|
||||
"@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.5", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ=="],
|
||||
|
||||
"@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.972.10", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@smithy/types": "^4.14.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-FAzqXvfEssGdSIz8ejatan0bOdx1qefBWKF/gWmVBXIP1HkS7v/wjjaqrAGGKvyihrXTXW00/2/1nTJtxpXz7g=="],
|
||||
|
||||
"@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.973.24", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "^3.972.38", "@aws-sdk/types": "^3.973.8", "@smithy/node-config-provider": "^4.3.14", "@smithy/types": "^4.14.1", "@smithy/util-config-provider": "^4.2.2", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-ZWwlkjcIp7cEL8ZfTpTAPNkwx25p7xol0xlKoWVVf22+nsjwmLcHYtTPjIV1cSpmB/b6DaK4cb1fSkvCXHgRdw=="],
|
||||
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.22", "", { "dependencies": { "@nodable/entities": "2.1.0", "@smithy/types": "^4.14.1", "fast-xml-parser": "5.7.2", "tslib": "^2.6.2" } }, "sha512-PMYKKtJd70IsSG0yHrdAbxBr+ZWBKLvzFZfD3/urxgf6hXVMzuU5M+3MJ5G67RpOmLBu1fAUN65SbWuKUCOlAA=="],
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.25", "", { "dependencies": { "@nodable/entities": "2.1.0", "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-GH+Kjz4nPKWKHnsiQpnhP1MJdTGIcK4rAka6tzakgjjUkVgNsmPeEbbRAf09SzS1hjGu6duGHCBsxYke0BhHjQ=="],
|
||||
|
||||
"@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.4", "", {}, "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ=="],
|
||||
|
||||
@@ -551,9 +542,9 @@
|
||||
|
||||
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
||||
|
||||
"@base-ui/react": ["@base-ui/react@1.4.1", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@base-ui/utils": "0.2.8", "@floating-ui/react-dom": "^2.1.8", "@floating-ui/utils": "^0.2.11", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@date-fns/tz": "^1.2.0", "@types/react": "^17 || ^18 || ^19", "date-fns": "^4.0.0", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@date-fns/tz", "@types/react", "date-fns"] }, "sha512-Ab5/LIhcmL8BQcsBUYiOfkSDRdLpvgUBzMK30cu684JPcLclYlztharvCZyNNgzJtbAiREzI9q0pI5erHCMgCw=="],
|
||||
"@base-ui/react": ["@base-ui/react@1.5.0", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@base-ui/utils": "0.2.9", "@floating-ui/react-dom": "^2.1.8", "@floating-ui/utils": "^0.2.11", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@date-fns/tz": "^1.2.0", "@types/react": "^17 || ^18 || ^19", "date-fns": "^4.0.0", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@date-fns/tz", "@types/react", "date-fns"] }, "sha512-z1gSAlced1yY+iM+mHDEtIkD8UI3Ebs52MuBPxvV6f5hRutk+xvCH/wuB7hDqDzK9JG5FoMz5nhrqtSs1wjt1A=="],
|
||||
|
||||
"@base-ui/utils": ["@base-ui/utils@0.2.8", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@floating-ui/utils": "^0.2.11", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-jvOi+c+ftGlGotNcKnzPVg2IhCaDTB6/6R3JeqdjdXktuAJi3wKH9T7+svuaKh1mmfVU11UWzUZVH74JDfi/wQ=="],
|
||||
"@base-ui/utils": ["@base-ui/utils@0.2.9", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@floating-ui/utils": "^0.2.11", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-x/PDDCYzoqPpjrdyb3VcyylTI2IjUXEtYDGi5foh7KsnmNJIIaVwA2GLgDH1dps1GgXiJbA60hM+AyuTfQzIvw=="],
|
||||
|
||||
"@biomejs/biome": ["@biomejs/biome@2.4.5", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.5", "@biomejs/cli-darwin-x64": "2.4.5", "@biomejs/cli-linux-arm64": "2.4.5", "@biomejs/cli-linux-arm64-musl": "2.4.5", "@biomejs/cli-linux-x64": "2.4.5", "@biomejs/cli-linux-x64-musl": "2.4.5", "@biomejs/cli-win32-arm64": "2.4.5", "@biomejs/cli-win32-x64": "2.4.5" }, "bin": { "biome": "bin/biome" } }, "sha512-OWNCyMS0Q011R6YifXNOg6qsOg64IVc7XX6SqGsrGszPbkVCoaO7Sr/lISFnXZ9hjQhDewwZ40789QmrG0GYgQ=="],
|
||||
|
||||
@@ -575,19 +566,19 @@
|
||||
|
||||
"@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="],
|
||||
|
||||
"@chat-adapter/discord": ["@chat-adapter/discord@4.28.1", "", { "dependencies": { "@chat-adapter/shared": "4.28.1", "chat": "4.28.1", "discord-api-types": "^0.37.119", "discord-interactions": "^4.4.0", "discord.js": "^14.25.1" } }, "sha512-j9/mym6upfS0aIpc9TQSxHKZDBlIUz6kq8v9jduq1YuErV+a3bVqxLXBzHRtCQMmVBj89Zy8mH7jXkBavlth5A=="],
|
||||
"@chat-adapter/discord": ["@chat-adapter/discord@4.29.0", "", { "dependencies": { "@chat-adapter/shared": "4.29.0", "chat": "4.29.0", "discord-api-types": "^0.37.119", "discord-interactions": "^4.4.0", "discord.js": "^14.25.1" } }, "sha512-C6pDVKn7s0PhvgeqldYxoShWXJzthwtlo+sCesqenh56M03eHsioinqxeJttmtK8y1ZD8/qiP2lAZufDwuEQhA=="],
|
||||
|
||||
"@chat-adapter/gchat": ["@chat-adapter/gchat@4.28.1", "", { "dependencies": { "@chat-adapter/shared": "4.28.1", "@googleapis/chat": "^44.6.0", "@googleapis/workspaceevents": "^9.1.0", "chat": "4.28.1" } }, "sha512-+S1JsooTc3cQJi8Es4bqC+a4segz0KiIIlYPlr6m4EZYB9mX+eT27Dxz3Ce5V6oAM6cFGLfRpR8gz4dwSkLq2w=="],
|
||||
"@chat-adapter/gchat": ["@chat-adapter/gchat@4.29.0", "", { "dependencies": { "@chat-adapter/shared": "4.29.0", "@googleapis/chat": "^44.6.0", "@googleapis/workspaceevents": "^9.1.0", "chat": "4.29.0" } }, "sha512-SZ5ZgzFmZ4oRj0AAISbjPztPiICTpw+RdPiPywNwqGWt2LItUOL+8+dl8zZMk+F86E/r0sqRjdbc8+9GqUe2pA=="],
|
||||
|
||||
"@chat-adapter/linear": ["@chat-adapter/linear@4.28.1", "", { "dependencies": { "@chat-adapter/shared": "4.28.1", "@linear/sdk": "^76.0.0", "chat": "4.28.1" } }, "sha512-ZLcmb6lU26ZSJEwo6g8IyXUsTInBVPbqV72CQ0zGy9SyKs/xBUv8xftj6Q1UMIncaLLPbAa4vpjW6+zvCruZ4A=="],
|
||||
"@chat-adapter/linear": ["@chat-adapter/linear@4.29.0", "", { "dependencies": { "@chat-adapter/shared": "4.29.0", "@linear/sdk": "^76.0.0", "chat": "4.29.0" } }, "sha512-4cq7pBv0CICka8V0uuae7bNfb1rTdmYjsNjOs7Gkr4vChlhDxRUEGUoiBqvOEYKqxFtFOkRk9Wod0tIQmbPySw=="],
|
||||
|
||||
"@chat-adapter/shared": ["@chat-adapter/shared@4.28.1", "", { "dependencies": { "chat": "4.28.1" } }, "sha512-v7AcZMrvS2gxFlRiUO1o9Nta2iipnnmV54Gie8e3nQTQvnghENfSf7j7nimA5DOUWCgj+e4DV7LE0x1pakNtkA=="],
|
||||
"@chat-adapter/shared": ["@chat-adapter/shared@4.29.0", "", { "dependencies": { "chat": "4.29.0" } }, "sha512-ARqTDoHJHKN9rpytbFPJbNmqqx3fOg5xwsTZdlingQPAssOSeHDBdqrFJkgDhyCRGbmDtG09cuS0FkVzeoh2qg=="],
|
||||
|
||||
"@chat-adapter/slack": ["@chat-adapter/slack@4.28.1", "", { "dependencies": { "@chat-adapter/shared": "4.28.1", "@slack/socket-mode": "^2.0.5", "@slack/web-api": "^7.14.0", "chat": "4.28.1" } }, "sha512-JxgV7+cRXXeKpj0MzS7nzG3JvpnfhIgnPo9r/sdEIzeWhIb8tUcT2PbLl/fpSu/cb+WkICS0bCENn1I0PS39Hg=="],
|
||||
"@chat-adapter/slack": ["@chat-adapter/slack@4.29.0", "", { "dependencies": { "@chat-adapter/shared": "4.29.0", "@slack/socket-mode": "^2.0.5", "@slack/web-api": "^7.14.0", "chat": "4.29.0" } }, "sha512-s2DXAwkTpmiIKSATXgrO879s1pqFwS70Y0JPd+TRGRzDeh6nfqt5dnKt5Bug0P1zwkB6DoPurhnYS9nqhSmD/w=="],
|
||||
|
||||
"@chat-adapter/telegram": ["@chat-adapter/telegram@4.28.1", "", { "dependencies": { "@chat-adapter/shared": "4.28.1", "chat": "4.28.1" } }, "sha512-ZBw6zx36enxXGlbOoigzCsWH6slbTCOWyTGatCz7jq4DFTDpvjRgBBH760n9peFkZpXJWOAXZKJm/IW8saT5aw=="],
|
||||
"@chat-adapter/telegram": ["@chat-adapter/telegram@4.29.0", "", { "dependencies": { "@chat-adapter/shared": "4.29.0", "chat": "4.29.0" } }, "sha512-015tU3HEjFQWw7DgebXWkDeQA6lTdTVEO4btAV3f6U1kEnOfjLVJq98latcsM1WkEvv+3LIFKpsz9pG53aamBw=="],
|
||||
|
||||
"@chat-adapter/whatsapp": ["@chat-adapter/whatsapp@4.28.1", "", { "dependencies": { "@chat-adapter/shared": "4.28.1", "chat": "4.28.1" } }, "sha512-NSU4Yda/uhbZXQNBnIgDHFWN+3ZBJ7L7mrFHUIctwZBX1XHlGkweWucfFbDynWgxb4IDm6NYZxA34+HVe8ugBA=="],
|
||||
"@chat-adapter/whatsapp": ["@chat-adapter/whatsapp@4.29.0", "", { "dependencies": { "@chat-adapter/shared": "4.29.0", "chat": "4.29.0" } }, "sha512-CDKmlDHmiiJ2xtca0wZ2DIYnySUFuiKn6f3ZQvschFVa6pSaDmaldmJc3iul+ELi10+RE7x5+immfc//+TTzFg=="],
|
||||
|
||||
"@chevrotain/types": ["@chevrotain/types@11.1.2", "", {}, "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw=="],
|
||||
|
||||
@@ -605,6 +596,8 @@
|
||||
|
||||
"@cline/example-cli-agent": ["@cline/example-cli-agent@workspace:apps/examples/cli-agent"],
|
||||
|
||||
"@cline/example-cline-core-cli-agent": ["@cline/example-cline-core-cli-agent@workspace:apps/examples/cline-core-cli-agent"],
|
||||
|
||||
"@cline/example-code-review-bot": ["@cline/example-code-review-bot@workspace:apps/examples/code-review-bot"],
|
||||
|
||||
"@cline/example-multi-agent": ["@cline/example-multi-agent@workspace:apps/examples/multi-agent"],
|
||||
@@ -621,7 +614,7 @@
|
||||
|
||||
"@cline/vscode": ["@cline/vscode@workspace:apps/examples/vscode"],
|
||||
|
||||
"@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
|
||||
"@date-fns/tz": ["@date-fns/tz@1.5.0", "", {}, "sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg=="],
|
||||
|
||||
"@dimforge/rapier2d-simd-compat": ["@dimforge/rapier2d-simd-compat@0.17.3", "", {}, "sha512-bijvwWz6NHsNj5e5i1vtd3dU2pDhthSaTUZSh14DUGGKJfw8eMnlWZsxwHBxB/a3AXVNDjL9abuHw1k9FGR+jg=="],
|
||||
|
||||
@@ -637,7 +630,7 @@
|
||||
|
||||
"@discordjs/ws": ["@discordjs/ws@1.2.3", "", { "dependencies": { "@discordjs/collection": "^2.1.0", "@discordjs/rest": "^2.5.1", "@discordjs/util": "^1.1.0", "@sapphire/async-queue": "^1.5.2", "@types/ws": "^8.5.10", "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "^0.38.1", "tslib": "^2.6.2", "ws": "^8.17.0" } }, "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw=="],
|
||||
|
||||
"@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.65.0", "", { "dependencies": { "commander": "^11.1.0", "dotenv": "^17.2.1", "eciesjs": "^0.4.10", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "picomatch": "^4.0.4", "which": "^4.0.0", "yocto-spinner": "^1.1.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-v4FA/Lw3pTEloLxBqTOaYDX6MNo0Jo7lGBsPZhwnJBqRJp0AzQg1ZZNxrFsh6HVC6QWeWrfIKLn0y2eyIXaVDg=="],
|
||||
"@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.67.0", "", { "dependencies": { "commander": "^11.1.0", "dotenv": "^17.2.1", "eciesjs": "^0.4.10", "enquirer": "^2.4.1", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "picomatch": "^4.0.4", "which": "^4.0.0", "yocto-spinner": "^1.1.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-KBfIx5OrAG6giqSkHCkQWynZmT47XkSTuuYIcvjHxlKoVRlYbxNrJmyIPaefnszU8MCvMwrrB+viJQzPqzgpcg=="],
|
||||
|
||||
"@ecies/ciphers": ["@ecies/ciphers@0.2.6", "", { "peerDependencies": { "@noble/ciphers": "^1.0.0" } }, "sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g=="],
|
||||
|
||||
@@ -725,11 +718,11 @@
|
||||
|
||||
"@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],
|
||||
|
||||
"@fontsource-variable/geist": ["@fontsource-variable/geist@5.2.8", "", {}, "sha512-cJ6m9e+8MQ5dCYJsLylfZrgBh6KkG4bOLckB35Tr9J/EqdkEM6QllH5PxqP1dhTvFup+HtMRPuz9xOjxXJggxw=="],
|
||||
"@fontsource-variable/geist": ["@fontsource-variable/geist@5.2.9", "", {}, "sha512-TP+QSBG3wxKGPE33CbMy/L0Nu3qvJ6Fy81Yc4LnQ95xH+i+cfEp8fyU8/kfV14YwszxIFPhnoMTbjL71waVpyQ=="],
|
||||
|
||||
"@googleapis/chat": ["@googleapis/chat@44.6.0", "", { "dependencies": { "googleapis-common": "^8.0.0" } }, "sha512-Bnqzev/bSTXSbE0/N2WS4Stnleo8j9bJJ1LkCBk1fXQnehcArVMv7q543rzPYU6MJql4D34On6diNGAuYtI9xQ=="],
|
||||
"@googleapis/chat": ["@googleapis/chat@44.7.0", "", { "dependencies": { "googleapis-common": "^8.0.0" } }, "sha512-1TTvtQ/nRD4Yb5PcMWl1J6vN3QjOyDr3t9XtM1iRJlAO8wux5dOChJSOyAlm2IOcRrrqmL4d0DVUkgMqovHjNA=="],
|
||||
|
||||
"@googleapis/workspaceevents": ["@googleapis/workspaceevents@9.1.0", "", { "dependencies": { "googleapis-common": "^8.0.0" } }, "sha512-aJiMrTi/YyUUaaTO0tnhTHDYU+N9CTD3l3FSfe0yzEHQl7DEc+1LISgdK1o2nurvCtguBEumify5kTkr6Cg5eA=="],
|
||||
"@googleapis/workspaceevents": ["@googleapis/workspaceevents@9.2.0", "", { "dependencies": { "googleapis-common": "^8.0.0" } }, "sha512-9tU0h6O/Ao9k53TQSgLs6D/mN++wKTHPIpT8tbPaayhOL3e4OhtJ3t+OD42avMe2pBmFcdRUVOSpZvqytxvWEg=="],
|
||||
|
||||
"@gramio/format": ["@gramio/format@0.7.0", "", { "dependencies": { "@gramio/types": "^9.6.0" }, "peerDependencies": { "marked": "^15.0.11", "node-html-parser": ">=6.0.0" }, "optionalPeers": ["marked", "node-html-parser"] }, "sha512-+qLKopeQHU3dfnwtVd7smKqyJTEYbveAj0l3hfuVwzdCfTQFdBcJvM3hhhTIcchlhUpPx7znKzw1+Vrq0GCNyg=="],
|
||||
|
||||
@@ -947,21 +940,21 @@
|
||||
|
||||
"@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="],
|
||||
|
||||
"@openai/codex": ["@openai/codex@0.105.0", "", { "optionalDependencies": { "@openai/codex-darwin-arm64": "npm:@openai/codex@0.105.0-darwin-arm64", "@openai/codex-darwin-x64": "npm:@openai/codex@0.105.0-darwin-x64", "@openai/codex-linux-arm64": "npm:@openai/codex@0.105.0-linux-arm64", "@openai/codex-linux-x64": "npm:@openai/codex@0.105.0-linux-x64", "@openai/codex-win32-arm64": "npm:@openai/codex@0.105.0-win32-arm64", "@openai/codex-win32-x64": "npm:@openai/codex@0.105.0-win32-x64" }, "bin": { "codex": "bin/codex.js" } }, "sha512-enoNmQs3aOgUhsKYC6kfuKEG0AogS4q01pqcySPwf9zl2r8OcKuMUoLw1v5n4Y7sd3B6qGS7UtTABqbcT5FaMA=="],
|
||||
"@openai/codex": ["@openai/codex@0.130.0", "", { "optionalDependencies": { "@openai/codex-darwin-arm64": "npm:@openai/codex@0.130.0-darwin-arm64", "@openai/codex-darwin-x64": "npm:@openai/codex@0.130.0-darwin-x64", "@openai/codex-linux-arm64": "npm:@openai/codex@0.130.0-linux-arm64", "@openai/codex-linux-x64": "npm:@openai/codex@0.130.0-linux-x64", "@openai/codex-win32-arm64": "npm:@openai/codex@0.130.0-win32-arm64", "@openai/codex-win32-x64": "npm:@openai/codex@0.130.0-win32-x64" }, "bin": { "codex": "bin/codex.js" } }, "sha512-WGDj+RZ3TXWC/7MlwprgLWOqzpwatPIINPhP3IRzHA0ni+o3QZ4i4xrS2uWwGmHUJ395J5JHwoZAAZYyfJyz6w=="],
|
||||
|
||||
"@openai/codex-darwin-arm64": ["@openai/codex@0.105.0-darwin-arm64", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9TD7pDIg8o7itmOhyEPcC2HeVnVIOxxrrbwTvnTibMj2rHPLnY8E0JaK8QOBRNiIUlqI4WKspTMUZQg5Fegndw=="],
|
||||
"@openai/codex-darwin-arm64": ["@openai/codex@0.130.0-darwin-arm64", "", { "os": "darwin", "cpu": "arm64" }, "sha512-R9pkGC7kwC8yQ8el5hvBlmugQlcsG/pHMEFgZluu03X9fD2TezGxdq3KqRDRCZuMYl07ILamVEoqknuJ0cq7MA=="],
|
||||
|
||||
"@openai/codex-darwin-x64": ["@openai/codex@0.105.0-darwin-x64", "", { "os": "darwin", "cpu": "x64" }, "sha512-00xRV2X7RwKFRY8LB99/WmVSWqhHnMV6BB4gc5x4MMuDPDslaNrGTYWdp6KBukok1ayrg0JfwazUeAawNWU5Zw=="],
|
||||
"@openai/codex-darwin-x64": ["@openai/codex@0.130.0-darwin-x64", "", { "os": "darwin", "cpu": "x64" }, "sha512-gJ+7J8djevgtdra+NgDAiQQPW+O3KTsgGfE3E5dpDfww3zS5OCeV0V2dhxqnJdlOjOSDw99o0P2LqBv19mhpRw=="],
|
||||
|
||||
"@openai/codex-linux-arm64": ["@openai/codex@0.105.0-linux-arm64", "", { "os": "linux", "cpu": "arm64" }, "sha512-UFGyZhRB0Gtr31wFf0WDd//W3XGbZZ7mxYwf528i6rhlwabb3FIJKWrgv4DVXKQZCGiBujqAk0pr32PziElouA=="],
|
||||
"@openai/codex-linux-arm64": ["@openai/codex@0.130.0-linux-arm64", "", { "os": "linux", "cpu": "arm64" }, "sha512-tFtH0V9/hEI3d9y7zP92BXI9FM4Z3+STNQaOR52Czv18TRtCFUp7CbIUYaToopuq6UBfnE1VKr8RLhwT5FcbmA=="],
|
||||
|
||||
"@openai/codex-linux-x64": ["@openai/codex@0.105.0-linux-x64", "", { "os": "linux", "cpu": "x64" }, "sha512-cZgNzNjspqHmXNf/CraqqQrfotw5cXO7wvkSSYs2NZjZR7Ud10u5hFeumUW1sEvb5/F9tEKsjO+WCj+bVxdrYQ=="],
|
||||
"@openai/codex-linux-x64": ["@openai/codex@0.130.0-linux-x64", "", { "os": "linux", "cpu": "x64" }, "sha512-3VcNlez99xdnEf+kB1IOpWv9fICYV9PiGj4sLCO4TCcShLnyxe+YBGa3poknkvXLnMG0qiN9SMnYS2FGrMxQcA=="],
|
||||
|
||||
"@openai/codex-win32-arm64": ["@openai/codex@0.105.0-win32-arm64", "", { "os": "win32", "cpu": "arm64" }, "sha512-OGvHTn/XAyY8889n0ZEcvUgiaPeT/rLFEFUEOzWgt5yhKiODV+zEzfruYmcvZUpzgFJ1kRQlDgKPMbW7u2r01Q=="],
|
||||
"@openai/codex-win32-arm64": ["@openai/codex@0.130.0-win32-arm64", "", { "os": "win32", "cpu": "arm64" }, "sha512-vdpmiNp57L/arZabltLXn8TyEtNa7W1meOEkr+3R6W/8ZyBt++wuqz1Orv134OT2grrcFJsIVCAIPiqUxCvBkA=="],
|
||||
|
||||
"@openai/codex-win32-x64": ["@openai/codex@0.105.0-win32-x64", "", { "os": "win32", "cpu": "x64" }, "sha512-8V26RjFeg06i4mrrhQTKLY6lcRXsm0s1cxT3lamApLccvBBAhhAOE0je6jHb5nkrncvf9x/lee+WmY0louvvGQ=="],
|
||||
"@openai/codex-win32-x64": ["@openai/codex@0.130.0-win32-x64", "", { "os": "win32", "cpu": "x64" }, "sha512-FzMznm7fr5/nbjZgOujZ9Y9AbdGm7ji1FOoWiY3U+srqauvZaTgn6o6aCheSL7kuymu7nTLOO/cAyWV6NuesqQ=="],
|
||||
|
||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@1.14.48", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-wKM86jCzV/ZApyWrdm3uP8XdWcS0LMbu3FV+OWz1ChiGGg1wiIWNGMJs5CY8/QX2/rUuZrd1Q1DqvdamZ0zLeg=="],
|
||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@1.15.8", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-e6O78KooMK3o5kZeUO1MQbzRt3W0fmQkE2ZdVRE50s10kBHrOavEeAEwUhFMaH8z2TZV/59az98nUlBLAE+wzA=="],
|
||||
|
||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="],
|
||||
|
||||
@@ -1011,7 +1004,7 @@
|
||||
|
||||
"@opentui/react": ["@opentui/react@0.1.102", "", { "dependencies": { "@opentui/core": "0.1.102", "react-reconciler": "^0.32.0" }, "peerDependencies": { "react": ">=19.0.0", "react-devtools-core": "^7.0.1", "ws": "^8.18.0" } }, "sha512-c7EiK30xlvaHc6WBOLAH7TJ8xC4QbiD5ZA6tb4zZ74XM4SH5Tb+uBee8b4TztTLseq+hGtW85qrIUJM3OrdtNw=="],
|
||||
|
||||
"@oxc-project/types": ["@oxc-project/types@0.129.0", "", {}, "sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg=="],
|
||||
"@oxc-project/types": ["@oxc-project/types@0.132.0", "", {}, "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ=="],
|
||||
|
||||
"@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="],
|
||||
|
||||
@@ -1023,13 +1016,13 @@
|
||||
|
||||
"@protobufjs/codegen": ["@protobufjs/codegen@2.0.5", "", {}, "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g=="],
|
||||
|
||||
"@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="],
|
||||
"@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.1", "", {}, "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg=="],
|
||||
|
||||
"@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="],
|
||||
"@protobufjs/fetch": ["@protobufjs/fetch@1.1.1", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1" } }, "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw=="],
|
||||
|
||||
"@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
|
||||
|
||||
"@protobufjs/inquire": ["@protobufjs/inquire@1.1.1", "", {}, "sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew=="],
|
||||
"@protobufjs/inquire": ["@protobufjs/inquire@1.1.2", "", {}, "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw=="],
|
||||
|
||||
"@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
|
||||
|
||||
@@ -1157,41 +1150,41 @@
|
||||
|
||||
"@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
|
||||
|
||||
"@rive-app/react-webgl2": ["@rive-app/react-webgl2@4.28.4", "", { "dependencies": { "@rive-app/webgl2": "2.37.6" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0" } }, "sha512-OeUAmHQjhqYza2zcpd7wctF3JxBNLCPQORYRIlZkGN1Tzcy7XF4ctyy7d0SAObW2vfS7+NWcTf9owoCzx5uehQ=="],
|
||||
"@rive-app/react-webgl2": ["@rive-app/react-webgl2@4.28.6", "", { "dependencies": { "@rive-app/webgl2": "2.37.8" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0" } }, "sha512-QqtlD7bm01SxMLuEHE/BfhiPoX3RZ2/B32nF0IR0IRPe2ykxMeebWPtsX50AL9EKLbOh3Fgk3PJ7smkkvQwD2w=="],
|
||||
|
||||
"@rive-app/webgl2": ["@rive-app/webgl2@2.37.6", "", {}, "sha512-ZvUgD8yleilzqu0DuQF2r9bFOk+id1cmgSE/4QayyNGlqUTgANcKs2Ft78F27qeGLO06SE589ugrdgZLtL4kbw=="],
|
||||
"@rive-app/webgl2": ["@rive-app/webgl2@2.37.8", "", {}, "sha512-Y2nXPwAeQtZrADNIzY7v3Lk7XZRMy4Gd+bpGFyzkaQ/EQ91Hp/6sCdd8yTCyjH4b71N/T6kU0MHIYA0IDmpjyQ=="],
|
||||
|
||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0", "", { "os": "android", "cpu": "arm64" }, "sha512-TWMZnRLMe63C2Lhyicviu7ZHaU4kxa6PS3rofvc9GmcvptzNN11BcfQ4Sl7MwTOsisQoa2keB/EBdNCAnUo8vA=="],
|
||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.2", "", { "os": "android", "cpu": "arm64" }, "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ=="],
|
||||
|
||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-6XcD+8k0gPVItNagEw78/qqcBDwKcwDYS8V2hRmVsfUSIrd8cWe/CBvRDI5toqFyPfj+FJr6t8U6Xj2P2prEew=="],
|
||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w=="],
|
||||
|
||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-iN/tWVXRQDWvmZlKdceP1Dwug9GDpEymhb9p4xnEe6zvCg5lFmzVljl+1qR1NVx3yfGpr2Na+CuLmv5IU8uzfQ=="],
|
||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA=="],
|
||||
|
||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jjQMDvvwSOuhOwMszD/klSOjyWMM3zI64hWTj9KT5x4MxRbZAf+7vLQ6qouRhtsLVFHr3f0ILaJAfgENPiQdAQ=="],
|
||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA=="],
|
||||
|
||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0", "", { "os": "linux", "cpu": "arm" }, "sha512-d//Dtg2x6/m3mbV64yUGNnDGNZaDGRpDLLNGerHQUVObuNaIQaaDp25yUiqGXtHEXX+NP2d0wAlmKgpYgIAJ2A=="],
|
||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w=="],
|
||||
|
||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-n7Ofp0mx+aB2cC+Sdy5YtMnXtY9lchnHbY+3Yt0uq9JsWQExf4f5Whu0tK0R8Jdc9S6RchTHjIFY7uc92puOVQ=="],
|
||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig=="],
|
||||
|
||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-EIVjy2cgd7uuMMo94FVkBp7F6DhcZAUwNURkSG3RwUmvAXR6s0ISxM81U+IydcZByPG0pZIHsf1b6kTxoFDgJA=="],
|
||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw=="],
|
||||
|
||||
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-JEwwOPcwTLAcpDQlqSmjEmfs63xJnSiUNIGvLcDLUHCWK4XowpS/7c7tUsUH6uT/ct6bMUTdXKfI8967FYj6mg=="],
|
||||
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA=="],
|
||||
|
||||
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-0wjCFhLrihtAubnT9iA0N++0pSV0z5Hg7tNGdNJ4RFaINceHadoF+kiFGyY1qSSNVIAZtLotG8Ju1bgDPkjnFA=="],
|
||||
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ=="],
|
||||
|
||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Dfn7iak9BcMMePxcoJfpSbWqnEyrp/dRF63/8qW/eHBdOZov6x5aShLLEYGYdIeSJ6vMLK/XCVB+lGIxm41bQA=="],
|
||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ=="],
|
||||
|
||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-5/utzzDmD/pD/bmuaUcbTf/sZYy0aztwIVlfpoW1fTjCZ0BaPOMVWGZL1zvgxyi7ZIVYWlxKONHmSbHuiOh8Jw=="],
|
||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw=="],
|
||||
|
||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0", "", { "os": "none", "cpu": "arm64" }, "sha512-ouJs8VcUomfLfpbUECqFMRqdV4x6aeAK3MA4m6vTrJJjKyWTV5KnxZx7Jd9G+GlDaQQxubcba00x16OyJ1meig=="],
|
||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w=="],
|
||||
|
||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-E+oHKGiDA+lsKMmFtffDDw91EryDT7uJocrIuCHqhm6bCTM6xFK+3gaCkYOHfPwQr0cCNarSM2xaELoQDz9jJg=="],
|
||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.2", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ=="],
|
||||
|
||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-yYK02n8Rngo+gbm1y6G0+7jk1sJ/2Wt7K0me0Y7k/ErBpyf+LJ2gFpqWVTcRV1rUepBlQRmpgWkTQCiiwrK0Ow=="],
|
||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A=="],
|
||||
|
||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0", "", { "os": "win32", "cpu": "x64" }, "sha512-14bpChMahXRRXiTwahSl+zzHPW6qQTXtkMuJBFlbo+pqSAews2d4BdCSHfrJ/MBsCZtpmTafsY+1QhBzitcmdg=="],
|
||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ=="],
|
||||
|
||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.7", "", {}, "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA=="],
|
||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="],
|
||||
|
||||
"@sapphire/async-queue": ["@sapphire/async-queue@1.5.5", "", {}, "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="],
|
||||
|
||||
@@ -1201,19 +1194,19 @@
|
||||
|
||||
"@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
|
||||
|
||||
"@shikijs/core": ["@shikijs/core@4.0.2", "", { "dependencies": { "@shikijs/primitive": "4.0.2", "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw=="],
|
||||
"@shikijs/core": ["@shikijs/core@4.1.0", "", { "dependencies": { "@shikijs/primitive": "4.1.0", "@shikijs/types": "4.1.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-jLJtSJeuFffqX6/inRE1zqU5aFv2hrszvYgq3OjbAgFRZiWv7abKMDdQzYxuSDfmUPQozZvI/kuy6VMTvnvqTQ=="],
|
||||
|
||||
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag=="],
|
||||
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.1.0", "", { "dependencies": { "@shikijs/types": "4.1.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" } }, "sha512-YquhawCUgaBfhsS72e2Y/dI59gCBNPHu3fEO/tvLaXrTssxZrY5ddjtNLTwndrMgPo8b3IscE+xoICDzpTmlFQ=="],
|
||||
|
||||
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-UpCB9Y2sUKlS9z8juFSKz7ZtysmeXCgnRF0dlhXBkmQnek7lAToPte8DkxmEYGNTMii72zU/lyXiCB6StuZeJg=="],
|
||||
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@4.1.0", "", { "dependencies": { "@shikijs/types": "4.1.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-axLpjVs45YBvvINa+dJF+NPW+KtFkNXsFr4SDw2BMj9GdeMnGxVB9PQb2xXlJYovslt/nz6giedAyOANkfc7hg=="],
|
||||
|
||||
"@shikijs/langs": ["@shikijs/langs@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2" } }, "sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg=="],
|
||||
"@shikijs/langs": ["@shikijs/langs@4.1.0", "", { "dependencies": { "@shikijs/types": "4.1.0" } }, "sha512-nwOMruEkbgdZfQ/b8CgpNBVOpvG1k0N5tbmgiFeqsan401+x3ILqlzZJowSla4Agmq4hG2Uf2wh5jLTEhR8VSg=="],
|
||||
|
||||
"@shikijs/primitive": ["@shikijs/primitive@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw=="],
|
||||
"@shikijs/primitive": ["@shikijs/primitive@4.1.0", "", { "dependencies": { "@shikijs/types": "4.1.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zx2/2Uwj2q9X3KSyYREEhXO23xBw5WUhP4orK2lE4r+t9JGITmEe0JH+wPmJhqHpOT2bRRs6lAL945+LDvOAGw=="],
|
||||
|
||||
"@shikijs/themes": ["@shikijs/themes@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2" } }, "sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA=="],
|
||||
"@shikijs/themes": ["@shikijs/themes@4.1.0", "", { "dependencies": { "@shikijs/types": "4.1.0" } }, "sha512-emCcTnUM7yO2wltYbaxm+yLvcCI4+h8XBKc4KmJ7EZUXoSGjcCHifkI//R4OFit9ewpg7H2/9tjOuXrT2v/Knw=="],
|
||||
|
||||
"@shikijs/types": ["@shikijs/types@4.0.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg=="],
|
||||
"@shikijs/types": ["@shikijs/types@4.1.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3EQWX54fMpniOrDblzAhiwiJwpiTMW6+B9DWyUd9ska483tbayFYuw47UxwuPknI31bKnySfVQ/QW+jFL4rFdA=="],
|
||||
|
||||
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
|
||||
|
||||
@@ -1231,75 +1224,27 @@
|
||||
|
||||
"@slack/types": ["@slack/types@2.21.1", "", {}, "sha512-I8vmSjNYWsaxuWPx6dz4yeh0h7vRBWbgAMK14LEmblbZ404BtrPbXs6jDPx4cYgGf8msDGF4A9opLZBu21FViQ=="],
|
||||
|
||||
"@slack/web-api": ["@slack/web-api@7.15.2", "", { "dependencies": { "@slack/logger": "^4.0.1", "@slack/types": "^2.21.0", "@types/node": ">=18", "@types/retry": "0.12.0", "axios": "^1.15.0", "eventemitter3": "^5.0.1", "form-data": "^4.0.4", "is-electron": "2.2.2", "is-stream": "^2", "p-queue": "^6", "p-retry": "^4", "retry": "^0.13.1" } }, "sha512-/m9qVFkiq85Oa/FSQwYIRDa/AO4qNYkDh4sRBK1WqEc2+RyG7w4tbU6rBIwUOcc/TmWOIr24Nraquxg7um5mYw=="],
|
||||
"@slack/web-api": ["@slack/web-api@7.16.0", "", { "dependencies": { "@slack/logger": "^4.0.1", "@slack/types": "^2.21.0", "@types/node": ">=18", "@types/retry": "0.12.0", "axios": "^1.16.0", "eventemitter3": "^5.0.1", "form-data": "^4.0.4", "is-electron": "2.2.2", "is-stream": "^2", "p-queue": "^6", "p-retry": "^4", "retry": "^0.13.1" } }, "sha512-68SAV77uuGKuhyyaRytX8UijVnqSLsTSKslGXw17cjQYXn+jtNl7gbaEjHgC5x2rhCuFdahBrEC2VCLppbzReg=="],
|
||||
|
||||
"@smithy/config-resolver": ["@smithy/config-resolver@4.5.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-abXk3LhODsvRHsk0ZS9ztrg/fZatTa9Z/z4pgx65YSLR+rY6kvUG/1IgcDKEUciR8MfdnkT5oPeHJTy/HhzDIQ=="],
|
||||
"@smithy/core": ["@smithy/core@3.24.4", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-3UNRKEyQyAgVgM0LGlerCLm+ChZWZ1GPfde+jBEW6bm6bSBGU1p0EbblaUV3unbhwvidjLA5Zs3sOs7mnZwvAw=="],
|
||||
|
||||
"@smithy/core": ["@smithy/core@3.24.1", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-3mT7o4qQyUWttYnVK3A0Z/u3Xha3E81tXn32Tz6vjZiUXhBrkEivpw1hBYfh84iFF9CSzkBU9Y1DJ3Q6RQ231g=="],
|
||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.3.4", "", { "dependencies": { "@smithy/core": "^3.24.4", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-vKW0MEFRU4Y3MkVZUkpJm+g9qyPGLCXhc0YLggUdSdBB4g7IaSSsCE75P9rBXyWHrXY1UYSQUl8/DwsTR7QciA=="],
|
||||
|
||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-0S/acwHnqX4WrjXzhdiDRxsG2s9SC0cpPIK9nZ1R6UOHd+j7uL28+4bHu22urbLk2TVw3fkp6na/+fkUt/pLNQ=="],
|
||||
"@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.3.4", "", { "dependencies": { "@smithy/core": "^3.24.4", "tslib": "^2.6.2" } }, "sha512-uI00gSvwvBEiVuqpHFcMPGXnVh1XQYuqlQREIX/GUmuwNNTdGRliUI8R71tbfwNLYP7t8E/HVqdohvjoWU13iA=="],
|
||||
|
||||
"@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-yS8AiJM3Kf7LR+lZyUilUyjdJGksAqxfSC3C9k3d1OCrAvWjpMlsJ+rW9cIslZJM4AtWh2UAqgZUWTtMeMdtDQ=="],
|
||||
|
||||
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.4.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-r7bN6spQ+caZC8AnyvSxkRUb57zt2jhhRw3Z+2Ez8hjq6coIikDBFUUI/+CQ1xx9K6eX1Gx6wUKo4ylU66TIqw=="],
|
||||
|
||||
"@smithy/hash-node": ["@smithy/hash-node@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-u0/zo11mg7yNneoYgTkH4sXwSmcBpbl49o4UNCtQ7hYsXxynsN25KYHmXzqi7TPk5HQL5klGnpU5koOY0O+9hw=="],
|
||||
|
||||
"@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-cLmwtDoulyZvRepAfyV+3rx5oMvuh51dbE+6En3vGC09j3uVSRt1U4oguNu32ub3soGX0oYtBs8E7S2Q4SxTqg=="],
|
||||
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.4.4", "", { "dependencies": { "@smithy/core": "^3.24.4", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-qM7AUKI4G6d7lNgaZD3lA1tWSolh5r6gcixfTZAPstVURfjIbvreVTPz+994M0yC3HbX4YYhDRgr31Xy3XwWOQ=="],
|
||||
|
||||
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-l4BUIP+wljW/Ar+0/QcGdmElI9lalrywfzNijXMBG34Z510FRzPyrDLx/blNTZOAm0C4Mvx5t/bf760CZo1ajg=="],
|
||||
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.4", "", { "dependencies": { "@smithy/core": "^3.24.4", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-HIeF+1vrDGzPkkv39Hj2vlHSXHY3p958jd/8ZnePIY6+ZOsQX8coyEUKO5yQu4r0bQIVsbpotVIrXXwyycMStQ=="],
|
||||
|
||||
"@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.5.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-qtqu5TS+8Y18ZDkJoiXN5AMW1G4JAg1+xytzpsUvIR5a4EUsgd5HQg12lekEHWpm2TDUmOgg+hBaHK7dvyWdkA=="],
|
||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.4.4", "", { "dependencies": { "@smithy/core": "^3.24.4", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-e5UtkMvsatzBfbeBZjEOt0k0Z3BEsjTFL/n6fdO5vtBLe67tdy0dX7xw2DU7uZ3acwoHyeCqpU2Fzb7pxwHb6Q=="],
|
||||
|
||||
"@smithy/middleware-retry": ["@smithy/middleware-retry@4.6.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-eTaQhxs0rfUuAkL2MSKrH8DTO7YCeAgrdN0B2/RAeuHmXQ+x52dk5qUBsi/jtcqe5LxItgq5AG5tI6Cp8c0sow=="],
|
||||
|
||||
"@smithy/middleware-serde": ["@smithy/middleware-serde@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-t7YtUe076zWVypVmy1rX91oKi2TFJCkpfFpfMhJFpEIRPP0iL9JxjeSyFQ+1bF45JUfDzOzslUJa150WcSrBug=="],
|
||||
|
||||
"@smithy/middleware-stack": ["@smithy/middleware-stack@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-1jKwiKZxCMQNqmp4uVPYA6r+MLGjEtH07gnOUdPgbnjuOIrl/0JY/ICdpQtFgeBsQ/Up01gnSv8GYEL0fb8yvg=="],
|
||||
|
||||
"@smithy/node-config-provider": ["@smithy/node-config-provider@4.4.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-q7tDJEJXcaSG/8TVpu2f2l9bzxTzDM9geWmltbzsY6Hfh3yiuXXTpLIO8+zwYASPPVFaTJpdKwjSSjdoDoccgw=="],
|
||||
|
||||
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-BdEYko85f/ldp68uH8XEyIvo810xFk6eyPH81SRggTOApYHWA+Xu7B2EzLuHbe37WVLaUA7F1fWR3/zBeme2WA=="],
|
||||
|
||||
"@smithy/property-provider": ["@smithy/property-provider@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-3NHoqVBhzpY2b4YBx9AqyKC4C8nnEjl5FyKuxrCjvnjinG0ODj+yg1xX360nNahT6wghYjSw1SooCt3kIdnqIA=="],
|
||||
|
||||
"@smithy/protocol-http": ["@smithy/protocol-http@5.4.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-8irPNCQgYxcSFp1aGcnDNFkTwSA+xPUaFq9V/v1+JXWu8sKr5b3cFmg2kBTkjkvypDmGeNffuNu0x5iqw1NoAw=="],
|
||||
|
||||
"@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.5.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-FKoKxVzdFPhyynFI+SPTWrgOP60fZ4l1UwukWYj4eyhpSmEI7MJ6p58hawIIt9bwp+aek9NEm8Zika7E+GEoeg=="],
|
||||
|
||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.4.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-728lZZEWYWubBESrfntNslZQYDKRlJDY4dcDnYbL50+gu35pGPLblu4S0/RH/RDLF6me1M87ECHsHELGL7dA/Q=="],
|
||||
|
||||
"@smithy/smithy-client": ["@smithy/smithy-client@4.13.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-IcznNM8Qd9u1X3oflp12tkzyOB4HbT+sfYWlWiyEysgNzSHoWcHUUsTT4y1jjDjtVuuVVQbYks+g1kVd7u1eGQ=="],
|
||||
|
||||
"@smithy/types": ["@smithy/types@4.14.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg=="],
|
||||
|
||||
"@smithy/url-parser": ["@smithy/url-parser@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-tuelFlF2PZR/wogFC58NIrPOv+Zna4N1+3kA161/33D1Gbwvl6Nh4WsAsW05ZyPp0O6CMGsdbb0S2b/qVjRMCw=="],
|
||||
|
||||
"@smithy/util-base64": ["@smithy/util-base64@4.4.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-fTHiwW2xbiRiWzfSk4IGAr3gNZCH4fuRYqt8+IuarsP/YON35576iVdePraZ6yJlFxlCL0eMec3/F7xYqoKzlg=="],
|
||||
|
||||
"@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-1scg5t4nV3hV7CZs996/XHb80aDZ5YotH4NcvkW/w/rHj+cSz0aCIzwz8aUNKB4nCDPSHRCbrKoj+TvycYefmw=="],
|
||||
|
||||
"@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-VRC8MKVPKrgUYThTA7ughcKMfjW6/X92H0wXGJoda0Apw4O5xbXL0GMLz40DTWlsb5hh2iItk6+XL72uJdxYcw=="],
|
||||
"@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="],
|
||||
|
||||
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@smithy/util-config-provider": ["@smithy/util-config-provider@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-lw6L5GF5+W19vO6o3fZwRT2cXEG+8b2LH0b9ppjDT6nIxjUgmljEQGninx5XorylwKZZ4XLVABeroJ8oaF9RmQ=="],
|
||||
|
||||
"@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.4.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-1rA7w+LjK1WJClsffC81Z/ZtjFt22QsKhBjUYEnZsGVS2nOTfOENKBzdg4SxhdwFvBCjcbpjscUfXOPwE3UHWQ=="],
|
||||
|
||||
"@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-1fk1wfQHBenQD5NitVKOFgW0wsISYAFPIXGyStJWAeCtMyRhgHYvtJxBk2rwGWA0L5QX6oM6yeHSLKPFMk59ww=="],
|
||||
|
||||
"@smithy/util-endpoints": ["@smithy/util-endpoints@3.5.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-yORYzJD5zoGbSDkAACr0dIjDiSEA3X8h8lggDENl1dkKpCG0TQIoItPBqtvuJHzFFjRXumcoH+/09xIuixGyCw=="],
|
||||
|
||||
"@smithy/util-middleware": ["@smithy/util-middleware@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-SRRMDcIgVXVhVbxviBaSZbuWuVW3jD08wv4ESV0V2oiw0Mki8TPVQ5IxwD3MvSTPg52QYsRP+JoMw5WdUdeWAg=="],
|
||||
|
||||
"@smithy/util-retry": ["@smithy/util-retry@4.4.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-qkgWgwn1xw0GoY9Ea/B6FrYSPfHA0zyOtJkokwxZuvucRf2+2lfTut6adi4e4Y7LEAaxsFG7r6i05mtDCxbHKA=="],
|
||||
|
||||
"@smithy/util-stream": ["@smithy/util-stream@4.6.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-GjZfEft0M0V3n2YM/LGkr5LeLd8gxHUIzW0rUz6VtTtlAq245GxHlJghvoPEjJHKTj255iHFAiA4IsIdK40Ueg=="],
|
||||
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.3.1", "", { "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" } }, "sha512-FtRrSnriXtOs4+J8/y9SbQ1xmN71hrOsN/YJr5PQQj5nR1l7YNkGS/TEk4gr0WN7gyrUqw8/RFaYVjI18732ZA=="],
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.3.4", "", { "dependencies": { "@smithy/core": "^3.24.4", "tslib": "^2.6.2" } }, "sha512-s8lfXcv+5C2GjBwGUBqFLgNmhyp9/n4TSKbOzKlIqJ/x0L/zwIxjNBC6DN4xUy59NvOrsiZI1t3tWi4ADUDyNw=="],
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
@@ -1379,29 +1324,29 @@
|
||||
|
||||
"@tauri-apps/api": ["@tauri-apps/api@2.11.0", "", {}, "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA=="],
|
||||
|
||||
"@tauri-apps/cli": ["@tauri-apps/cli@2.11.1", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.11.1", "@tauri-apps/cli-darwin-x64": "2.11.1", "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.1", "@tauri-apps/cli-linux-arm64-gnu": "2.11.1", "@tauri-apps/cli-linux-arm64-musl": "2.11.1", "@tauri-apps/cli-linux-riscv64-gnu": "2.11.1", "@tauri-apps/cli-linux-x64-gnu": "2.11.1", "@tauri-apps/cli-linux-x64-musl": "2.11.1", "@tauri-apps/cli-win32-arm64-msvc": "2.11.1", "@tauri-apps/cli-win32-ia32-msvc": "2.11.1", "@tauri-apps/cli-win32-x64-msvc": "2.11.1" }, "bin": { "tauri": "tauri.js" } }, "sha512-rpEbaJ/HzNb6fwsquwoAbq29/Vt4gADhS423A8fdkwL4edJ0wZmoB8ar7O6JPDL834MUKOCm/rrJ7c9oAaEaYQ=="],
|
||||
"@tauri-apps/cli": ["@tauri-apps/cli@2.11.2", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.11.2", "@tauri-apps/cli-darwin-x64": "2.11.2", "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.2", "@tauri-apps/cli-linux-arm64-gnu": "2.11.2", "@tauri-apps/cli-linux-arm64-musl": "2.11.2", "@tauri-apps/cli-linux-riscv64-gnu": "2.11.2", "@tauri-apps/cli-linux-x64-gnu": "2.11.2", "@tauri-apps/cli-linux-x64-musl": "2.11.2", "@tauri-apps/cli-win32-arm64-msvc": "2.11.2", "@tauri-apps/cli-win32-ia32-msvc": "2.11.2", "@tauri-apps/cli-win32-x64-msvc": "2.11.2" }, "bin": { "tauri": "tauri.js" } }, "sha512-bk3HemqvGRoy+5D/dVMUQHKMYLglD0jVnMm/0iGMH6ufZ+p8r14m6BpIixwij3PBvZdvORUp1YifTD8QxVZ1Nw=="],
|
||||
|
||||
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-6eEKMBXsQPCuM1EmvrjT2+aBuxWQuFdKdW8pzNuNQtpq45nEEpBlD5gr8pUeAyOU1DQKlkFaEc/MPBxb/Pfjtg=="],
|
||||
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.11.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+4UZzLt+eOAEQCwgd+TqKgyUJMrvx+BgdXLLaqJYmPqzP+nE6YZr/hY6CWLYGQb8jFn99jEkmC6uA3tNvamA1w=="],
|
||||
|
||||
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-LQUO7exfRWjWALNhetph5guWpMeHphRpokOLk0OIbTTExaNwJNFu3I4vb+CCM/4G/QGoZe/5XikZOJdNEFP1ig=="],
|
||||
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.11.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-VjYYtZUPqDMLutSfJEyxFE3Bz+DPi7c8wC3imckgvciLDZLq4qwKJxBicg0BXGhXjJsl8vKWgWRFNMPELQ+Xyg=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-5i/awiBCRRhOUG8yjn0fMHXIWD5Ez8eEk5LtvOxyQrKuJkRaZDvnbIjZbE183blAwkoA4xN3aO/prJiqscl02Q=="],
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.11.2", "", { "os": "linux", "cpu": "arm" }, "sha512-yMemD6f4i95AQriS8EazyOFzbE34yjnP16i3IOzpHGQvBoy2DjypFMFBq0NtPuITURv/cOGguRtHR5d79/9CSA=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-9LrwDw3S9Fygtw/Q6WDhOP+3svJRGAsejeE+GKrc0eO1ThMVhwi2LL6hw4dlKw93IfS7VY1G19sWGxJ/NcU4nA=="],
|
||||
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.11.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-cgI91D2wL8GSgoWwZXDqt+DwnuZCP2/bz03QAE4TrhgAKIsrB4hX26W/H1EONPUUNkqrsgeCD0wU6pcNjV/5kw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mNA5dbbqPqDUdTIwdUYYuhO2GvIe9UnB2r0VU2njxBOS3Opbx4gKNC5yP0Iu4rYmEmqdlwry9VzGZQ3wq9dyFg=="],
|
||||
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.11.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-X1rm0BERqAAggtYTESSgXrS3sz4Sb/OiPiz54UqISlXW+GkR3vNIGnsy/lejNmoXGVqri3Q53BCfQiclOIyRPw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-fZj3Gwq+6fUs305T5WQiD5iSGJw+j/4w/HGmk4sHDAcy+rp9zU5eaxB7nOyz5/I/nkNAuKPqfp6uIbiUBXkBCw=="],
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.11.2", "", { "os": "linux", "cpu": "none" }, "sha512-usbMLJbT3KtkOrBMDVeGYNM35aTHXx38SJSzTMSqqjeUIOQ+iVPjb2yAGNAE+KqmBbAx4FOFIyMeKXx2M/JKGQ=="],
|
||||
|
||||
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-XFxGxOvHM7jjeD6ozCKdGfhzJ7lERYDGZl1/Kb4fsvchaJsfLJ981TlyTG8Qy/gFq+f5GitH3bfrX9JAkjPEyw=="],
|
||||
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.11.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Ru4gwJKPG0ctVGchRGpRup4Y4lW2SSfFnrbQcyHhCliKy4g8Qz97TrUgCur4CbWyAgKxvGh3SjrkA0LDYzDGiw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-d5C2/Zm+68v7R9wTuTCjRQEVrWjcdMkJBZ1+rXse+QdMMlTB9+u9PDNDLw9PQflWxYLaYZ7tjxxL9Nb9II6PbA=="],
|
||||
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.11.2", "", { "os": "linux", "cpu": "x64" }, "sha512-eUm7T6clN1MMmNSRQ9gaWsQdyehQx2Gmn5hht/QUlqZQI/qcP2OJK5dnaxqwFzCr2HdsEo9ydxaqcS1oJzMvUw=="],
|
||||
|
||||
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YdeVWFAR1pTXzUU6NLstPq4G6OLxuDrXCXEBdmBH+5EZIDXUx0D2kJlz3+YjpazkKvAzYpgziTsyRagls0OfRQ=="],
|
||||
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.11.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-HeeZW80jU+gVTOEX4X/hC6NVSAdDVXajwP5fxIZ/3z9WvUC7qrudX2GMTilYq6Dg0e0sk0XgsAJD1hZ5wPBXUA=="],
|
||||
|
||||
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-VBGkuH0eB9K9LLSMv361Gzr5Ou72sCS4+ztpmkWEQ+wd/amhcYOsf3X6qn1RJZDzIhiOYHJEOysZUC3baD01rA=="],
|
||||
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.11.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YhjQNZcXfbkCLyazSv1nPnJ9iRFE1wm6kc51FDbU10/Dk09io+6PAGMLjkxnX2GdM0qMnDmTjstY8mTDVvtKeA=="],
|
||||
|
||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-b3ORhIAKgp9ZYY+zBt7b7r0kLU2kjvyGF0+MS2SBym3emsweGPybEqocJcmtMuxyBhkOKHP4CiuEJEDuAlTx6A=="],
|
||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.11.2", "", { "os": "win32", "cpu": "x64" }, "sha512-d2JchlFIpZevZVReyqhQOekJmb1UH3rhZ5VX6sH3ty9ETE0TKQavpihvoScUXfKKpW6HZC0MrFGRU0ZtD+w3gA=="],
|
||||
|
||||
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
||||
|
||||
@@ -1509,7 +1454,7 @@
|
||||
|
||||
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
||||
|
||||
"@types/node": ["@types/node@25.7.0", "", { "dependencies": { "undici-types": "~7.21.0" } }, "sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg=="],
|
||||
"@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="],
|
||||
|
||||
"@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="],
|
||||
|
||||
@@ -1531,7 +1476,7 @@
|
||||
|
||||
"@types/validate-npm-package-name": ["@types/validate-npm-package-name@4.0.2", "", {}, "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw=="],
|
||||
|
||||
"@types/vscode": ["@types/vscode@1.118.0", "", {}, "sha512-Ah6eTlqDcwIMELEVwQMO++rJAFBRz/oLluLD/vWdYrH1KuI9kfpaM+7pg0OvvascgcJy+ghLCERAYouM4QbzGw=="],
|
||||
"@types/vscode": ["@types/vscode@1.120.0", "", {}, "sha512-feaT4Rst+FkTch5zz/ZbNCxoIvo55YU80Be2kiL7OJcod4+CUYf2lUBPdIJzozNnSEMq1VRTGrWEcCGFB3fBmA=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
||||
|
||||
@@ -1539,25 +1484,25 @@
|
||||
|
||||
"@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.59.3", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.59.3", "@typescript-eslint/type-utils": "8.59.3", "@typescript-eslint/utils": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.59.3", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw=="],
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.59.4", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.59.4", "@typescript-eslint/type-utils": "8.59.4", "@typescript-eslint/utils": "8.59.4", "@typescript-eslint/visitor-keys": "8.59.4", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.59.4", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.59.3", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/typescript-estree": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg=="],
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.59.4", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.59.4", "@typescript-eslint/types": "8.59.4", "@typescript-eslint/typescript-estree": "8.59.4", "@typescript-eslint/visitor-keys": "8.59.4", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ=="],
|
||||
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.59.3", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.59.3", "@typescript-eslint/types": "^8.59.3", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng=="],
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.59.4", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.59.4", "@typescript-eslint/types": "^8.59.4", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3" } }, "sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA=="],
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.59.4", "", { "dependencies": { "@typescript-eslint/types": "8.59.4", "@typescript-eslint/visitor-keys": "8.59.4" } }, "sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q=="],
|
||||
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.59.3", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw=="],
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.59.4", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "@typescript-eslint/typescript-estree": "8.59.3", "@typescript-eslint/utils": "8.59.3", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ=="],
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.59.4", "", { "dependencies": { "@typescript-eslint/types": "8.59.4", "@typescript-eslint/typescript-estree": "8.59.4", "@typescript-eslint/utils": "8.59.4", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.59.3", "", {}, "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg=="],
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.59.4", "", {}, "sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.3", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.3", "@typescript-eslint/tsconfig-utils": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg=="],
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.4", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.4", "@typescript-eslint/tsconfig-utils": "8.59.4", "@typescript-eslint/types": "8.59.4", "@typescript-eslint/visitor-keys": "8.59.4", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.59.3", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/typescript-estree": "8.59.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg=="],
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.59.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.59.4", "@typescript-eslint/types": "8.59.4", "@typescript-eslint/typescript-estree": "8.59.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "eslint-visitor-keys": "^5.0.0" } }, "sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg=="],
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.59.4", "", { "dependencies": { "@typescript-eslint/types": "8.59.4", "eslint-visitor-keys": "^5.0.0" } }, "sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ=="],
|
||||
|
||||
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.1", "", {}, "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ=="],
|
||||
|
||||
@@ -1567,21 +1512,21 @@
|
||||
|
||||
"@vercel/oidc": ["@vercel/oidc@3.2.0", "", {}, "sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug=="],
|
||||
|
||||
"@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@4.3.0", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.7", "@swc/core": "^1.15.11" }, "peerDependencies": { "vite": "^4 || ^5 || ^6 || ^7 || ^8" } }, "sha512-mOkXCII839dHyAt/gpoSlm28JIVDwhZ6tnG6wJxUy2bmOx7UaPjvOyIDf3SFv5s7Eo7HVaq6kRcu6YMEzt5Z7w=="],
|
||||
"@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@4.3.1", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.0", "@swc/core": "^1.15.11" }, "peerDependencies": { "vite": "^4 || ^5 || ^6 || ^7 || ^8" } }, "sha512-PaeokKjAGraNN+s5SIApgsktnJprIyt3zgEIu7awnEdfn29QiB2crTcCzyi2XGpX9rUnTc0cKU07Wm0N0g7H2w=="],
|
||||
|
||||
"@vitest/expect": ["@vitest/expect@4.1.6", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.6", "@vitest/utils": "4.1.6", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-7EHDquPthALSV0jhhjgEW8FXaviMx7rSqu8W6oqCoAuOhKov814P99QDV1pxMA3QPv21YudvJngIhjrNI4opLg=="],
|
||||
"@vitest/expect": ["@vitest/expect@4.1.7", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.7", "@vitest/utils": "4.1.7", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w=="],
|
||||
|
||||
"@vitest/mocker": ["@vitest/mocker@4.1.6", "", { "dependencies": { "@vitest/spy": "4.1.6", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-MCFc63czMjEInOlcY2cpQCvCN+KgbAn+60xu9cMgP4sKaLC5JNAKw7JH8QdAnoAC88hW1IiSNZ+GgVXlN1UcMQ=="],
|
||||
"@vitest/mocker": ["@vitest/mocker@4.1.7", "", { "dependencies": { "@vitest/spy": "4.1.7", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA=="],
|
||||
|
||||
"@vitest/pretty-format": ["@vitest/pretty-format@4.1.6", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-h5SxD/IzNhZYnrSZRsUZQIC+vD0GY8cUvq0iwsmkFKixRCKLLWqCXa/FIQ4S1R+sI+PGoojkHsdNrbZiM9Qpgw=="],
|
||||
"@vitest/pretty-format": ["@vitest/pretty-format@4.1.7", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw=="],
|
||||
|
||||
"@vitest/runner": ["@vitest/runner@4.1.6", "", { "dependencies": { "@vitest/utils": "4.1.6", "pathe": "^2.0.3" } }, "sha512-nOPCmn2+yD0ZNmKdsXGv/UxMMWbMuKeD6GyYncNwdkYDxpQvrPSKYj2rWuDjC2Y4b6w6hjip5dBKFzEUuZe3vA=="],
|
||||
"@vitest/runner": ["@vitest/runner@4.1.7", "", { "dependencies": { "@vitest/utils": "4.1.7", "pathe": "^2.0.3" } }, "sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw=="],
|
||||
|
||||
"@vitest/snapshot": ["@vitest/snapshot@4.1.6", "", { "dependencies": { "@vitest/pretty-format": "4.1.6", "@vitest/utils": "4.1.6", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-YhsdE6xAVfTDmzjxL2ZDUvjj+ZsgyOKe+TdQzqkD72wIOmHka8NuGQ6NpTNZv9D2Z63fbwWKJPeVpEw4EQgYxw=="],
|
||||
"@vitest/snapshot": ["@vitest/snapshot@4.1.7", "", { "dependencies": { "@vitest/pretty-format": "4.1.7", "@vitest/utils": "4.1.7", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw=="],
|
||||
|
||||
"@vitest/spy": ["@vitest/spy@4.1.6", "", {}, "sha512-JFKxMx6udhwKh/Ldo270e17QX710vgunMkuPAvXjHSvC6oqLWAHhVhjg/I71q0u0CBSErIODV1Kjv0FQNSWjdg=="],
|
||||
"@vitest/spy": ["@vitest/spy@4.1.7", "", {}, "sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q=="],
|
||||
|
||||
"@vitest/utils": ["@vitest/utils@4.1.6", "", { "dependencies": { "@vitest/pretty-format": "4.1.6", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-FxIY+U81R3LGKCxaHHFRQ5+g6/iRgGLmeHWdp2Amj4ljQRrEIWHmZyDfDYBRZlpyqA7qKxtS9DD1dhk8RnRIVQ=="],
|
||||
"@vitest/utils": ["@vitest/utils@4.1.7", "", { "dependencies": { "@vitest/pretty-format": "4.1.7", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw=="],
|
||||
|
||||
"@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.7", "", {}, "sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g=="],
|
||||
|
||||
@@ -1605,11 +1550,11 @@
|
||||
|
||||
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||
|
||||
"ai": ["ai@6.0.180", "", { "dependencies": { "@ai-sdk/gateway": "3.0.114", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@opentelemetry/api": "^1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tOyRbwD0PEjMZKGvYQcTsv95K2zktwwNhQ49QOUAh0g8MNprO7ELIO1SgANMuPc0BFtkP6Ny6OAdjq3TtxLCbQ=="],
|
||||
"ai": ["ai@6.0.190", "", { "dependencies": { "@ai-sdk/gateway": "3.0.119", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@opentelemetry/api": "^1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-T+ixHbWZ6jmHRREpVVJTkFyWJeCekCdzLPan7lp1F32jG5OUw4+odlVYjtMRXVzogU+pWzpMmXdRiHUmdL/q0w=="],
|
||||
|
||||
"ai-sdk-provider-claude-code": ["ai-sdk-provider-claude-code@3.4.4", "", { "dependencies": { "@ai-sdk/provider": "^3.0.0", "@ai-sdk/provider-utils": "^4.0.1", "@anthropic-ai/claude-agent-sdk": "^0.2.63" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-iHcup5SHh4Tul1RIi9J+bnpngen8WX66yC3lsz1YlbtwAmRhUEzZUuGKzmFGIN8Pmx9uQrerGfLJdbFxIxKkyw=="],
|
||||
|
||||
"ai-sdk-provider-codex-cli": ["ai-sdk-provider-codex-cli@1.1.0", "", { "dependencies": { "@ai-sdk/provider": "^3.0.0", "@ai-sdk/provider-utils": "^4.0.1", "jsonc-parser": "^3.3.1" }, "optionalDependencies": { "@openai/codex": "^0.105.0" }, "peerDependencies": { "zod": "^3.0.0 || ^4.0.0" } }, "sha512-l1ap+RAwCpdwEaLmB2cpQ4br+h2ut2IR0IvI88QvUMAAk5c3h2dSnx+vYZhwsOt1th3CS7FUQmvCTcnxqYshWg=="],
|
||||
"ai-sdk-provider-codex-cli": ["ai-sdk-provider-codex-cli@1.2.0", "", { "dependencies": { "@ai-sdk/provider": "^3.0.0", "@ai-sdk/provider-utils": "^4.0.1", "jsonc-parser": "^3.3.1" }, "optionalDependencies": { "@openai/codex": "^0.130.0" }, "peerDependencies": { "zod": "^3.0.0 || ^4.0.0" } }, "sha512-UZrJNoPVTUJV3NPobRe8LtDx/1P7y+HMTlkKjKkhWej5DAx1gcV/ZrXqMak+uh0wT7oFrTvnfyU+kuBRsnUGgg=="],
|
||||
|
||||
"ai-sdk-provider-opencode-sdk": ["ai-sdk-provider-opencode-sdk@3.0.2", "", { "dependencies": { "@ai-sdk/provider": "^3.0.8", "@ai-sdk/provider-utils": "^4.0.15", "@opencode-ai/sdk": "^1.2.15" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-X2UDG+gRR7/V8YClSRWKXwCGNIUld8NnkIRXMzPB7MYKiZ0mYm4XJqo1HW9C6UsgNvsuQJBf/LTsFHSnEQF/fw=="],
|
||||
|
||||
@@ -1619,6 +1564,8 @@
|
||||
|
||||
"anser": ["anser@2.3.5", "", {}, "sha512-vcZjxvvVoxTeR5XBNJB38oTu/7eDCZlwdz32N1eNgpyPF7j/Z7Idf+CUwQOkKKpJ7RJyjxgLHCM7vdIK0iCNMQ=="],
|
||||
|
||||
"ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
|
||||
|
||||
"ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
@@ -1647,7 +1594,7 @@
|
||||
|
||||
"aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="],
|
||||
|
||||
"axios": ["axios@1.16.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w=="],
|
||||
"axios": ["axios@1.16.1", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A=="],
|
||||
|
||||
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
|
||||
|
||||
@@ -1655,7 +1602,7 @@
|
||||
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.29", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ=="],
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.32", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg=="],
|
||||
|
||||
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
|
||||
|
||||
@@ -1699,7 +1646,7 @@
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001792", "", {}, "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw=="],
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001793", "", {}, "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA=="],
|
||||
|
||||
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
||||
|
||||
@@ -1717,7 +1664,7 @@
|
||||
|
||||
"character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
|
||||
|
||||
"chat": ["chat@4.28.1", "", { "dependencies": { "@workflow/serde": "4.1.0-beta.2", "mdast-util-to-string": "^4.0.0", "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "remend": "^1.2.1", "unified": "^11.0.5" } }, "sha512-oKBeLQ746rSmHWGoXmPgDOqMVdIe9cWFQBQ1G2pw0l2vV4sAsZgfEJmc1UYqSJR4kYy4PxKgRFy31pe4RJ644Q=="],
|
||||
"chat": ["chat@4.29.0", "", { "dependencies": { "@workflow/serde": "4.1.0-beta.2", "mdast-util-to-string": "^4.0.0", "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "remend": "^1.2.1", "unified": "^11.0.5" }, "peerDependencies": { "ai": "^6.0.182", "zod": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["ai", "zod"] }, "sha512-KdPfzaie5ivYytyRICTERg5xT+LeCbYefokvNAqTHe92eqkFaoTMXXkSitikxJVWhZIb2YoXF1b9UZHyzSzKzw=="],
|
||||
|
||||
"ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="],
|
||||
|
||||
@@ -1781,7 +1728,7 @@
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
||||
"cytoscape": ["cytoscape@3.33.3", "", {}, "sha512-Gej7U+OKR+LZ8kvX7rb2HhCYJ0IhvEFsnkud4SB1PR+BUY/TsSO0dmOW59WEVLu51b1Rm+gQRKoz4bLYxGSZ2g=="],
|
||||
"cytoscape": ["cytoscape@3.33.4", "", {}, "sha512-HIN5Pmd9MrX9BkV7tDwnOcEJCSFvCpc8X97h3f508J6I5FsqAY65wKOCvgH2CuP42CaahWaz4tuh32SOOIH7ww=="],
|
||||
|
||||
"cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="],
|
||||
|
||||
@@ -1907,7 +1854,7 @@
|
||||
|
||||
"dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="],
|
||||
|
||||
"dompurify": ["dompurify@3.4.3", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-VVwJidIJcp1hpg2OMXML3ZVRPYSZiq4aX7qBh83BSIpOaRDqI+qxhXjjIWnpzkOXhmp0L81lnoME1mnCc9H48A=="],
|
||||
"dompurify": ["dompurify@3.4.5", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-OrwIBKsdNSVEeubdJ1HBv/wNENRM9ytAVCv7YXt//A3vPdVMNuACRqK9mXCGCBW2ln7BT/A4X0jXHo2Gu89miA=="],
|
||||
|
||||
"dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="],
|
||||
|
||||
@@ -1921,7 +1868,7 @@
|
||||
|
||||
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.354", "", {}, "sha512-JaBHwWcfIdmSAfWM5l3uwjGd431j8YEMikZ+K/2nXVuBqJKyZ0f+2h4n4JY5AyNiZmnY9qQr2RU3v9DxDmHMNg=="],
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.361", "", {}, "sha512-Q6Hts7N9FnJc5LeGRINFvLhCI9xZmNtTDe5ZbcVezQz7cU4a8Aua3GH1b8J2XY8Al9PF+OCwYqhgsOOheMdvkA=="],
|
||||
|
||||
"embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
|
||||
|
||||
@@ -1933,7 +1880,9 @@
|
||||
|
||||
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
||||
|
||||
"enhanced-resolve": ["enhanced-resolve@5.21.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q=="],
|
||||
"enhanced-resolve": ["enhanced-resolve@5.22.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A=="],
|
||||
|
||||
"enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="],
|
||||
|
||||
"entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
|
||||
|
||||
@@ -1949,7 +1898,7 @@
|
||||
|
||||
"es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="],
|
||||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||
"es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
|
||||
|
||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
@@ -2015,7 +1964,7 @@
|
||||
|
||||
"express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
|
||||
|
||||
"express-rate-limit": ["express-rate-limit@8.5.1", "", { "dependencies": { "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-5O6KYmyJEpuPJV5hNTXKbAHWRqrzyu+OI3vUnSd2kXFubIVpG7ezpgxQy76Zo5GQZtrQBg86hF+CM/NX+cioiQ=="],
|
||||
"express-rate-limit": ["express-rate-limit@8.5.2", "", { "dependencies": { "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A=="],
|
||||
|
||||
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
||||
|
||||
@@ -2035,11 +1984,11 @@
|
||||
|
||||
"fast-uri": ["fast-uri@3.1.2", "", {}, "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ=="],
|
||||
|
||||
"fast-wrap-ansi": ["fast-wrap-ansi@0.2.0", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w=="],
|
||||
"fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="],
|
||||
|
||||
"fast-xml-builder": ["fast-xml-builder@1.2.0", "", { "dependencies": { "path-expression-matcher": "^1.5.0", "xml-naming": "^0.1.0" } }, "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q=="],
|
||||
|
||||
"fast-xml-parser": ["fast-xml-parser@5.7.2", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.5", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w=="],
|
||||
"fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="],
|
||||
|
||||
"fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
|
||||
|
||||
@@ -2075,7 +2024,7 @@
|
||||
|
||||
"fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="],
|
||||
|
||||
"framer-motion": ["framer-motion@12.38.0", "", { "dependencies": { "motion-dom": "^12.38.0", "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g=="],
|
||||
"framer-motion": ["framer-motion@12.40.0", "", { "dependencies": { "motion-dom": "^12.40.0", "motion-utils": "^12.39.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-uaBd3qC1v3KQqBEjwTUd183K6PbS+j0yR9w9VmEOLWA/tnUcSn8Xa3uck7t4dgpDoUss8xQTcj8W2L07lrnLFg=="],
|
||||
|
||||
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
|
||||
|
||||
@@ -2087,6 +2036,8 @@
|
||||
|
||||
"fuzzysort": ["fuzzysort@3.1.0", "", {}, "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ=="],
|
||||
|
||||
"fzf": ["fzf@0.5.2", "", {}, "sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q=="],
|
||||
|
||||
"gaxios": ["gaxios@7.1.4", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA=="],
|
||||
|
||||
"gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="],
|
||||
@@ -2171,7 +2122,7 @@
|
||||
|
||||
"hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
||||
|
||||
"hono": ["hono@4.12.18", "", {}, "sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ=="],
|
||||
"hono": ["hono@4.12.22", "", {}, "sha512-7fvVPbB92zNRsQke+uiRGwtTuef0tB2Dg4hWxYfFNvkQhIltWoyi0ONReM5LWA+jJWS3nfT5lTq+qbsIpX0IQw=="],
|
||||
|
||||
"html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
|
||||
|
||||
@@ -2311,7 +2262,7 @@
|
||||
|
||||
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
||||
|
||||
"katex": ["katex@0.16.45", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA=="],
|
||||
"katex": ["katex@0.16.47", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg=="],
|
||||
|
||||
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
||||
|
||||
@@ -2515,11 +2466,11 @@
|
||||
|
||||
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"motion": ["motion@12.38.0", "", { "dependencies": { "framer-motion": "^12.38.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w=="],
|
||||
"motion": ["motion@12.40.0", "", { "dependencies": { "framer-motion": "^12.40.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-yjrHUrBFW6kQvjJwRsoiPSAhC5tRwRqNGJWmiJ4CrGnbKp0V88AdzkhBmDoqIsIPfarOe0Uddd37Xq43/gIocA=="],
|
||||
|
||||
"motion-dom": ["motion-dom@12.38.0", "", { "dependencies": { "motion-utils": "^12.36.0" } }, "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA=="],
|
||||
"motion-dom": ["motion-dom@12.40.0", "", { "dependencies": { "motion-utils": "^12.39.0" } }, "sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg=="],
|
||||
|
||||
"motion-utils": ["motion-utils@12.36.0", "", {}, "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg=="],
|
||||
"motion-utils": ["motion-utils@12.39.0", "", {}, "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
@@ -2547,7 +2498,7 @@
|
||||
|
||||
"node-pty": ["node-pty@1.2.0-beta.11", "", { "dependencies": { "node-addon-api": "^7.1.0" } }, "sha512-THcUyu1WwdgoIyUvgXOZ70EOMXzheGa0q3tbEb5kUIfKgcpBJ+AJ9Q1kq0bKtYmQzr77usXiTORZTLmAUQlnoQ=="],
|
||||
|
||||
"node-releases": ["node-releases@2.0.44", "", {}, "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ=="],
|
||||
"node-releases": ["node-releases@2.0.46", "", {}, "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ=="],
|
||||
|
||||
"npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="],
|
||||
|
||||
@@ -2659,7 +2610,7 @@
|
||||
|
||||
"points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
|
||||
|
||||
"postcss": ["postcss@8.5.14", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg=="],
|
||||
"postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
|
||||
|
||||
"postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="],
|
||||
|
||||
@@ -2685,7 +2636,7 @@
|
||||
|
||||
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
||||
|
||||
"protobufjs": ["protobufjs@7.5.8", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.1", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-dvpCIeLPbXZS/Ete7yLaO7RenOdken2NHKykBXbsaGxZT0UTltcarBciw+A78SRQs9iMAAVpsYA+l8b1hTePIA=="],
|
||||
"protobufjs": ["protobufjs@7.6.1", "", { "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/inquire": "^1.1.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-4K0myLaWL5EteuSAro91EGFgcfVgxb64Jx+7oDAY6GOkXD4M69yuSEljNcInGVCA5sOPxmZ/EqDLj2x0Q0+Ygg=="],
|
||||
|
||||
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
||||
|
||||
@@ -2693,7 +2644,7 @@
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"qs": ["qs@6.15.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg=="],
|
||||
"qs": ["qs@6.15.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw=="],
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
@@ -2713,7 +2664,7 @@
|
||||
|
||||
"react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
|
||||
|
||||
"react-hook-form": ["react-hook-form@7.75.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-Ovv94H+0p3sJ7B9B5QxPuCP1u8V/cHuVGyH55cSwodYDtoJwK+fqk3vjfIgSX59I2U/bU4z0nRJ9HMLpNiWEmw=="],
|
||||
"react-hook-form": ["react-hook-form@7.76.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-eKtLGgFeSgkHqQD8J59AMZ9a4uD1D83iSIzt4YlTGD7liDen5rrjcUO1rVIGd9yC1gofryjtHbv+4ny4hkLWlw=="],
|
||||
|
||||
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
|
||||
@@ -2781,7 +2732,7 @@
|
||||
|
||||
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
|
||||
|
||||
"reselect": ["reselect@5.1.1", "", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="],
|
||||
"reselect": ["reselect@5.2.0", "", {}, "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw=="],
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
@@ -2797,7 +2748,7 @@
|
||||
|
||||
"robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="],
|
||||
|
||||
"rolldown": ["rolldown@1.0.0", "", { "dependencies": { "@oxc-project/types": "=0.129.0", "@rolldown/pluginutils": "1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0", "@rolldown/binding-darwin-arm64": "1.0.0", "@rolldown/binding-darwin-x64": "1.0.0", "@rolldown/binding-freebsd-x64": "1.0.0", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0", "@rolldown/binding-linux-arm64-gnu": "1.0.0", "@rolldown/binding-linux-arm64-musl": "1.0.0", "@rolldown/binding-linux-ppc64-gnu": "1.0.0", "@rolldown/binding-linux-s390x-gnu": "1.0.0", "@rolldown/binding-linux-x64-gnu": "1.0.0", "@rolldown/binding-linux-x64-musl": "1.0.0", "@rolldown/binding-openharmony-arm64": "1.0.0", "@rolldown/binding-wasm32-wasi": "1.0.0", "@rolldown/binding-win32-arm64-msvc": "1.0.0", "@rolldown/binding-win32-x64-msvc": "1.0.0" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-yD986aXDESFGS95spT1LAv0jssywP4npMEjmMHyN2/5+eE8qQJUype2AaKkRiLgBgyD0LFlubwAht7VmY8rGoA=="],
|
||||
"rolldown": ["rolldown@1.0.2", "", { "dependencies": { "@oxc-project/types": "=0.132.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.2", "@rolldown/binding-darwin-arm64": "1.0.2", "@rolldown/binding-darwin-x64": "1.0.2", "@rolldown/binding-freebsd-x64": "1.0.2", "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", "@rolldown/binding-linux-arm64-gnu": "1.0.2", "@rolldown/binding-linux-arm64-musl": "1.0.2", "@rolldown/binding-linux-ppc64-gnu": "1.0.2", "@rolldown/binding-linux-s390x-gnu": "1.0.2", "@rolldown/binding-linux-x64-gnu": "1.0.2", "@rolldown/binding-linux-x64-musl": "1.0.2", "@rolldown/binding-openharmony-arm64": "1.0.2", "@rolldown/binding-wasm32-wasi": "1.0.2", "@rolldown/binding-win32-arm64-msvc": "1.0.2", "@rolldown/binding-win32-x64-msvc": "1.0.2" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g=="],
|
||||
|
||||
"roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
|
||||
|
||||
@@ -2819,7 +2770,7 @@
|
||||
|
||||
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
||||
|
||||
"semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="],
|
||||
"semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="],
|
||||
|
||||
"send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
|
||||
|
||||
@@ -2829,7 +2780,7 @@
|
||||
|
||||
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||
|
||||
"shadcn": ["shadcn@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "https-proxy-agent": "^7.0.6", "kleur": "^4.1.5", "msw": "^2.10.4", "node-fetch": "^3.3.2", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-70fwnesNrY1GgeD7Kdzn+3SsYeyfibm8immsA5L68+OusoPTvYF01oWExl8/latKpMpvVXcbgdbbE6VFBJQ38w=="],
|
||||
"shadcn": ["shadcn@4.8.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "https-proxy-agent": "^7.0.6", "kleur": "^4.1.5", "msw": "^2.10.4", "node-fetch": "^3.3.2", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-LAm3I/1FdoU/zu5GVG8Hbna4X9zlzEG5TeeCPXqsopkjvGk8QUF9OFhqeRN8oM6Oh/ynUI/yQHZxQAO3Ymcqsg=="],
|
||||
|
||||
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
|
||||
|
||||
@@ -2837,9 +2788,9 @@
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
|
||||
"shell-quote": ["shell-quote@1.8.4", "", {}, "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ=="],
|
||||
|
||||
"shiki": ["shiki@4.0.2", "", { "dependencies": { "@shikijs/core": "4.0.2", "@shikijs/engine-javascript": "4.0.2", "@shikijs/engine-oniguruma": "4.0.2", "@shikijs/langs": "4.0.2", "@shikijs/themes": "4.0.2", "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ=="],
|
||||
"shiki": ["shiki@4.1.0", "", { "dependencies": { "@shikijs/core": "4.1.0", "@shikijs/engine-javascript": "4.1.0", "@shikijs/engine-oniguruma": "4.1.0", "@shikijs/langs": "4.1.0", "@shikijs/themes": "4.1.0", "@shikijs/types": "4.1.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-l/ABZPUR5v70jI10EzqfMS/I96vjSGv2y0ihUV+WYFzv0EfvW4s54m0Lg8wCrrL+2IkwBzFTuxkZjPf8b2NX9Q=="],
|
||||
|
||||
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
||||
|
||||
@@ -2937,7 +2888,7 @@
|
||||
|
||||
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
|
||||
|
||||
"thread-stream": ["thread-stream@4.1.0", "", { "dependencies": { "real-require": "^1.0.0" } }, "sha512-Bw6h2iBDt16v6iHLChBIoVYU8CBo9GPsW8TG7h1hRVhqKhIkH6N8qkxNSmiOZTKsCLPbtWG4ViWLkU6KeKXpig=="],
|
||||
"thread-stream": ["thread-stream@4.2.0", "", { "dependencies": { "real-require": "^1.0.0" } }, "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ=="],
|
||||
|
||||
"three": ["three@0.177.0", "", {}, "sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg=="],
|
||||
|
||||
@@ -2993,17 +2944,17 @@
|
||||
|
||||
"type-fest": ["type-fest@5.6.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA=="],
|
||||
|
||||
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
||||
"type-is": ["type-is@2.1.0", "", { "dependencies": { "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.59.3", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.59.3", "@typescript-eslint/parser": "8.59.3", "@typescript-eslint/typescript-estree": "8.59.3", "@typescript-eslint/utils": "8.59.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-KgusgyDgG4LI8Ih/sWaCtZ06tckLAS5CvT5A4D1Q7bYVoAAyzwiZvE4BmwDHkhRVkvhRBepKeASoFzQetha7Fg=="],
|
||||
"typescript-eslint": ["typescript-eslint@8.59.4", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.59.4", "@typescript-eslint/parser": "8.59.4", "@typescript-eslint/typescript-estree": "8.59.4", "@typescript-eslint/utils": "8.59.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Rw6+44QNFaXtgHSjPy+Kw8hrJniMYzR85E9yLmOLcfZ91/rz+JXQbDTCmc6ccxMPY6K6PgAq26f0JCBfR7LIPQ=="],
|
||||
|
||||
"uc.micro": ["uc.micro@1.0.6", "", {}, "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="],
|
||||
|
||||
"undici": ["undici@6.24.1", "", {}, "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA=="],
|
||||
|
||||
"undici-types": ["undici-types@7.21.0", "", {}, "sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ=="],
|
||||
"undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="],
|
||||
|
||||
"unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
|
||||
|
||||
@@ -3063,9 +3014,9 @@
|
||||
|
||||
"victory-vendor": ["victory-vendor@36.9.2", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ=="],
|
||||
|
||||
"vite": ["vite@8.0.12", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.14", "rolldown": "1.0.0", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w2dDofOWv2QB09ZITZBsvKTVAlYvPR4IAmrY/v0ir9KvLs0xybR7i48wxhM1/oyBWO34wPns+bPGw5ZrZqDpZg=="],
|
||||
"vite": ["vite@8.0.14", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.15", "rolldown": "1.0.2", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw=="],
|
||||
|
||||
"vitest": ["vitest@4.1.6", "", { "dependencies": { "@vitest/expect": "4.1.6", "@vitest/mocker": "4.1.6", "@vitest/pretty-format": "4.1.6", "@vitest/runner": "4.1.6", "@vitest/snapshot": "4.1.6", "@vitest/spy": "4.1.6", "@vitest/utils": "4.1.6", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.6", "@vitest/browser-preview": "4.1.6", "@vitest/browser-webdriverio": "4.1.6", "@vitest/coverage-istanbul": "4.1.6", "@vitest/coverage-v8": "4.1.6", "@vitest/ui": "4.1.6", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-6lvjbS3p9b4CrdCmguzbh2/4uoXhGE2q71R4OX5sqF9R1bo9Xd6fGrMAfvp5wnCzlBnFVdCOp6onuTQVbo8iUQ=="],
|
||||
"vitest": ["vitest@4.1.7", "", { "dependencies": { "@vitest/expect": "4.1.7", "@vitest/mocker": "4.1.7", "@vitest/pretty-format": "4.1.7", "@vitest/runner": "4.1.7", "@vitest/snapshot": "4.1.7", "@vitest/spy": "4.1.7", "@vitest/utils": "4.1.7", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.7", "@vitest/browser-preview": "4.1.7", "@vitest/browser-webdriverio": "4.1.7", "@vitest/coverage-istanbul": "4.1.7", "@vitest/coverage-v8": "4.1.7", "@vitest/ui": "4.1.7", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA=="],
|
||||
|
||||
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
|
||||
|
||||
@@ -3089,7 +3040,7 @@
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="],
|
||||
"ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
|
||||
|
||||
"wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
|
||||
|
||||
@@ -3305,6 +3256,8 @@
|
||||
|
||||
"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
||||
|
||||
"axios/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
||||
|
||||
"cli-truncate/string-width": ["string-width@8.2.1", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA=="],
|
||||
|
||||
"cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
@@ -3335,6 +3288,8 @@
|
||||
|
||||
"discord.js/discord-api-types": ["discord-api-types@0.38.47", "", {}, "sha512-XgXQodHQBAE6kfD7kMvVo30863iHX1LHSqNq6MGUTDwIFCCvHva13+rwxyxVXDqudyApMNAd32PGjgVETi5rjA=="],
|
||||
|
||||
"enquirer/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"eslint/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
|
||||
|
||||
"eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
@@ -3415,11 +3370,11 @@
|
||||
|
||||
"radix-ui/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||
|
||||
"react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
||||
"react-devtools-core/ws": ["ws@7.5.11", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA=="],
|
||||
|
||||
"react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||
|
||||
"react-jsx-parser/@types/react": ["@types/react@18.3.28", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" } }, "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw=="],
|
||||
"react-jsx-parser/@types/react": ["@types/react@18.3.29", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" } }, "sha512-ch0qJdr2JY0r04NXSprbK6TXOgnaJ1Tz23fm5W+z0/CBah6BSBc3n96h7K9GOtwh0HrilNWHIBzE1Ko4Dcw/Wg=="],
|
||||
|
||||
"react-jsx-parser/@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="],
|
||||
|
||||
@@ -3427,8 +3382,6 @@
|
||||
|
||||
"restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
|
||||
"rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0", "", {}, "sha512-aKs/3GSWyV0mrhNmt/96/Z3yczC3yvrzYATCiCXQebBsGyYzjNdUphRVLeJQ67ySKVXRfMxt2lm12pmXvbPFQQ=="],
|
||||
|
||||
"router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
|
||||
|
||||
"shadcn/open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="],
|
||||
@@ -3451,6 +3404,8 @@
|
||||
|
||||
"thread-stream/real-require": ["real-require@1.0.0", "", {}, "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g=="],
|
||||
|
||||
"type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
||||
|
||||
"webview/@types/node": ["@types/node@24.12.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA=="],
|
||||
|
||||
"webview/lucide-react": ["lucide-react@0.577.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A=="],
|
||||
@@ -3499,6 +3454,8 @@
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
||||
|
||||
"axios/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||
|
||||
"cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"cliui/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
@@ -3513,6 +3470,8 @@
|
||||
|
||||
"d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="],
|
||||
|
||||
"enquirer/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||
|
||||
"execa/pretty-ms/parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="],
|
||||
|
||||
@@ -4,7 +4,7 @@ Learn how to build with the Cline SDK through practical, runnable examples.
|
||||
|
||||
## 📁 Plugin, Hook, and Automation Examples
|
||||
|
||||
Plugins extend the CLI and SDK with custom capabilities. Install them in `~/.cline/plugins/`:
|
||||
Plugins extend the CLI and SDK with custom capabilities. Install local files, GitHub file URLs, package directories, git repos, and npm packages with `cline plugin install`:
|
||||
|
||||
### [`./plugins/`](./plugins/)
|
||||
|
||||
@@ -22,8 +22,7 @@ Examples include:
|
||||
- `background-terminal.ts` - Background shell jobs with logging
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.cline/plugins
|
||||
cp examples/plugins/weather-metrics.ts ~/.cline/plugins/weather-metrics.ts
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/weather-metrics.ts
|
||||
cline -i "What's the weather like in Tokyo and Paris?"
|
||||
```
|
||||
|
||||
@@ -37,7 +36,7 @@ TypeScript LSP plugin that gives the agent a `goto_definition` tool powered by t
|
||||
- Zero extra dependencies -- resolves `typescript` from the target project
|
||||
|
||||
```bash
|
||||
cp examples/plugins/typescript-lsp/index.ts ~/.cline/plugins/typescript-lsp.ts
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/typescript-lsp/index.ts
|
||||
cline -i "Find where createTool is defined"
|
||||
```
|
||||
|
||||
@@ -59,8 +58,7 @@ Skills available:
|
||||
- API design, code review, debugging, documentation, migration, refactoring, test generation
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.cline/plugins
|
||||
cp examples/plugins/agents-squad/index.ts ~/.cline/plugins/portable-subagents.ts
|
||||
cline plugin install ./examples/plugins/agents-squad
|
||||
cline -i "Use subagents to inspect this repository and report back."
|
||||
```
|
||||
|
||||
|
||||
@@ -223,8 +223,7 @@ mkdir -p ~/.cline/cron/events
|
||||
cp examples/cron/events/local-plugin-event.event.md ~/.cline/cron/events/
|
||||
|
||||
# Load the plugin that emits these events
|
||||
mkdir -p ~/.cline/plugins
|
||||
cp examples/plugins/automation-events.ts ~/.cline/plugins/
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/automation-events.ts
|
||||
|
||||
# Run CLI with automation enabled; the plugin emits events
|
||||
cline --enable-automation -i "Test automation events"
|
||||
|
||||
@@ -409,8 +409,7 @@ echo '{"tool_call": {"name": "read_files", "input": {"filePath": "test.ts"}}}' |
|
||||
File hooks observe lifecycle events. For more advanced use cases like message compaction, use a TypeScript **runtime hook** plugin:
|
||||
|
||||
```bash
|
||||
mkdir -p .cline/plugins
|
||||
cp examples/hooks/custom-compaction-hook.example.ts .cline/plugins/custom-compaction-hook.ts
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/hooks/custom-compaction-hook.example.ts --cwd .
|
||||
|
||||
cline -i "Search the codebase for dispatcher usage, then summarize it"
|
||||
```
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
* summary message before the provider request.
|
||||
*
|
||||
* Installation:
|
||||
* mkdir -p .cline/plugins
|
||||
* cp examples/hooks/custom-compaction-hook.example.ts .cline/plugins/custom-compaction-hook.ts
|
||||
* cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/hooks/custom-compaction-hook.example.ts --cwd .
|
||||
*
|
||||
* Usage:
|
||||
* cline -i "Search the codebase for dispatcher usage, then summarize it"
|
||||
|
||||
@@ -27,22 +27,19 @@ The runtime-hook variant of compaction lives in [../hooks/custom-compaction-hook
|
||||
|
||||
## Try it with the CLI
|
||||
|
||||
The CLI auto-discovers plugins from `.cline/plugins` in the workspace, `~/.cline/plugins`, and the system Plugins folder. Drop a file in, run `cline`:
|
||||
The CLI auto-discovers plugins from `.cline/plugins` in the workspace, `~/.cline/plugins`, and the system Plugins folder. Use `cline plugin install` for local files, GitHub file URLs, package directories, git repos, and npm packages:
|
||||
|
||||
```bash
|
||||
mkdir -p .cline/plugins
|
||||
cp examples/plugins/weather-metrics.ts .cline/plugins/
|
||||
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/weather-metrics.ts --cwd .
|
||||
cline -i "What's the weather like in Tokyo and Paris?"
|
||||
```
|
||||
|
||||
Swap `weather-metrics.ts` for any other example. Each one ships ready to copy.
|
||||
Swap the GitHub URL for any other single-file example.
|
||||
|
||||
To block file access for paths ignored by workspace `.gitignore` files:
|
||||
|
||||
```bash
|
||||
cp examples/plugins/gitignore-read-files-guard.ts .cline/plugins/
|
||||
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/gitignore-read-files-guard.ts --cwd .
|
||||
cline -i "Read the ignored .env file"
|
||||
```
|
||||
|
||||
@@ -57,8 +54,7 @@ cline plugin install ./examples/plugins/agents-squad
|
||||
To add web search through a normal plugin tool:
|
||||
|
||||
```bash
|
||||
mkdir -p .cline/plugins
|
||||
cp examples/plugins/web-search.ts .cline/plugins/web-search.ts
|
||||
cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/web-search.ts --cwd .
|
||||
|
||||
export EXA_API_KEY=...
|
||||
export OPENROUTER_API_KEY=...
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
* ClineCore automation without importing cron internals.
|
||||
*
|
||||
* Local demo:
|
||||
* mkdir -p .cline/plugins .cline/cron/events
|
||||
* cp examples/plugins/automation-events.ts .cline/plugins/automation-events.ts
|
||||
* cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/automation-events.ts --cwd .
|
||||
* mkdir -p .cline/cron/events
|
||||
* cp examples/cron/events/local-plugin-event.event.md .cline/cron/events/local-plugin-event.event.md
|
||||
* perl -0pi -e "s#/absolute/path/to/repo#$PWD#g" .cline/cron/events/local-plugin-event.event.md
|
||||
* CLINE_LOCAL_EVENT_INTERVAL_MS=2000 cline -i "wait for the plugin event"
|
||||
|
||||
@@ -24,8 +24,7 @@ import {
|
||||
* into the current session when the command exits.
|
||||
*
|
||||
* CLI usage:
|
||||
* mkdir -p .cline/plugins
|
||||
* cp examples/plugins/background-terminal.ts .cline/plugins/background-terminal.ts
|
||||
* cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/background-terminal.ts --cwd .
|
||||
* cline -i "Start the dev server in the background and keep working"
|
||||
*/
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
* so provider-safe normalization and hard truncation remain the final pass.
|
||||
*
|
||||
* CLI usage:
|
||||
* mkdir -p .cline/plugins
|
||||
* cp examples/plugins/custom-compaction.ts .cline/plugins/custom-compaction.ts
|
||||
* cline plugin install https://github.com/cline/cline/blob/main/sdk/examples/plugins/custom-compaction.ts --cwd .
|
||||
* cline -i "Search the codebase for dispatcher usage, then summarize it"
|
||||
*/
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user