diff --git a/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/.openspec.yaml b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/.openspec.yaml new file mode 100644 index 00000000..3a038210 --- /dev/null +++ b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-07-25 diff --git a/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/design.md b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/design.md new file mode 100644 index 00000000..1be68db8 --- /dev/null +++ b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/design.md @@ -0,0 +1,66 @@ +## Context + +The frontend receives provider and tool catalogs dynamically, but it keeps static TypeScript contracts and field lists for persisted user settings, tool purposes, category grouping, translations, and provider icons. The backend now returns provider ID `twelve-data`, settings fields `twelve_data_api_key` and `tool_choice_api_stock_quote`, tool type `api_stock_quote`, and additional asset/stock errors. Without matching static entries, the provider can appear but its credential and tool choice cannot be saved, and the stock tool is intentionally hidden when translations are absent. + +The frontend also maps numeric API errors locally. Backend code `6002` historically represented insufficient credits and remains supported by the frontend, while stock quote rate limiting has been assigned the new unique backend code `6003`. + +## Goals / Non-Goals + +**Goals:** + +- Make Twelve Data credentials fully editable, mask-aware, clearable, and persistable through the existing access-settings flow. +- Make the stock-quote tool visible and configurable through presets and custom intelligence settings. +- Keep every API error code mapped once with matching semantics and complete localization. +- Provide a temporary deterministic Twelve Data icon without blocking implementation on the final brand asset. + +**Non-Goals:** + +- Add a stock-price lookup page, price-alert page, or new HTTP client endpoint. +- Reimplement stock lookup, alert logic, or provider validation in the frontend. +- Change provider metadata that is already supplied by the backend, including the API-key URL. +- Add a new test framework or runtime dependency. + +## Decisions + +### 1. Extend the existing settings contract symmetrically + +Add `twelve_data_api_key` and `tool_choice_api_stock_quote` everywhere their CoinMarketCap and cryptocurrency-tool counterparts participate: response and payload types, provider-to-setting mapping, masked-field diffing, string-field diffing, API-key detection, and bulk clearing. + +This preserves the existing sparse PATCH behavior. A provider-specific form or separate stock settings service would duplicate the access-settings flow and is unnecessary. + +### 2. Continue consuming provider metadata dynamically + +Use backend provider ID `twelve-data`; continue displaying its backend-supplied name, token format, `Stocks` label, and `https://twelvedata.com/account/api-keys` management URL. Only the field mapping and icon remain frontend-owned. + +Hard-coding the URL or provider display metadata again in the frontend would create an avoidable second source of truth. + +### 3. Integrate stock quotes into the existing tool taxonomy + +Add `api_stock_quote` to `ToolType`, place it in the integrations category and changed-state map, assign a stock-market icon, and add its title and description to all locales. The user-facing title uses the natural local equivalent of “Stocks and stock market,” including exact Serbian title `Akcije i berza`, rather than a literal translation of the provider operation “stock quote.” Preset comparison and application continue using the existing dynamic `tool_choice_${toolType}` convention once the typed settings field exists. + +### 4. Use a clearly named temporary provider asset + +Copy `coinmarketcap-white.svg` to a distinct Twelve Data asset path and map `twelve-data` to that copy. The duplicate is intentional and temporary: callers reference the correct provider-specific filename now, so replacing the artwork later changes only the asset contents. + +The last implementation task is a manual TODO for the user to provide and review the real Twelve Data icon. The temporary asset remains until that separate input is available. + +### 5. Preserve the existing error mapping shape while auditing it mechanically + +Keep `getErrorTranslationKey` as the central numeric mapping and add missing current backend codes exactly once. Rename the semantic key for `4003` to `invalid_resource_token`; add the previously omitted `1039`; add asset/stock codes `1040`, `1041`, `1042`, `2014`, `5014`, and `6003`; and retain `6002` solely as a documented legacy insufficient-credit mapping. + +All mapped keys are added to every locale, and the normal i18n lint regenerates the typed translation-key union. A deterministic comparison against the backend constants verifies completeness, uniqueness, and the single documented legacy exception. + +## Risks / Trade-offs + +- [The copied CoinMarketCap artwork can misrepresent Twelve Data] → Use a distinct filename, call it temporary in the task record, and stop at a final manual replacement TODO. +- [Static frontend settings lists can drift again] → Update every symmetric list in one task and verify key save, clear, and preset paths during review. +- [Legacy `6002` makes a strict set comparison report one frontend-only code] → Treat it as the only documented legacy exception; current stock rate limiting uses unique code `6003`. +- [Missing locale entries cause the stock tool to disappear] → Update all locales before running i18n lint and verify the rendered tool group exists. + +## Migration Plan + +Deploy the backend containing stock code `6003` before or with this frontend. The frontend remains compatible with older insufficient-credit responses through `6002`. Rollback requires only reverting the frontend; unknown Twelve Data fields returned by the backend are otherwise ignored. + +## Open Questions + +- The final Twelve Data icon asset is pending from the user and will replace the temporary copied artwork after the implementation review. diff --git a/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/proposal.md b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/proposal.md new file mode 100644 index 00000000..e1dce810 --- /dev/null +++ b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/proposal.md @@ -0,0 +1,31 @@ +## Why + +The backend now exposes Twelve Data credentials, stock-quote tool selection, and stock-specific structured errors, but the frontend cannot persist those settings or display that tool. The frontend error-code catalog has also drifted from the backend, including a historical collision at code `6002`, so the contracts need to be aligned before the feature is exposed. + +## What Changes + +- Add Twelve Data API-key and stock-quote tool-choice fields to the frontend settings contracts and changed-payload handling. +- Display Twelve Data in access settings using the provider metadata supplied by the backend. +- Add stock quotes to the advanced tool selector, preset comparison, changed-state tracking, icons, and every supported locale. +- Temporarily copy the existing CoinMarketCap icon for Twelve Data so the provider has a deterministic visual until the real asset is supplied. +- Align frontend API error mappings with the backend, retain `6002` only for legacy insufficient-credit responses, and map stock quote rate limiting to the new unique code `6003`. +- Add every new or renamed error translation to all supported locales and regenerate the typed translation-key catalog. +- End implementation with a manual TODO for the user to supply and review the real Twelve Data icon before the placeholder is replaced. + +## Capabilities + +### New Capabilities + +- `stock-quote-settings`: Frontend support for configuring a Twelve Data key and selecting the stock-quote tool through the existing access and intelligence settings flows. +- `api-error-code-alignment`: Complete, duplicate-free frontend mapping of backend API error codes, including localized stock-price errors and explicit legacy-code handling. + +### Modified Capabilities + +None. + +## Impact + +- Affects user-settings and external-tools service types, changed-payload construction, access-key clearing, advanced tool grouping, provider/tool icons, error parsing, and all locale files. +- Consumes the backend fields `twelve_data_api_key` and `tool_choice_api_stock_quote`, provider ID `twelve-data`, tool type `api_stock_quote`, and stock error codes. +- Adds no runtime dependency and no new user-facing HTTP endpoint. +- Requires frontend lint and production build validation. diff --git a/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/specs/api-error-code-alignment/spec.md b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/specs/api-error-code-alignment/spec.md new file mode 100644 index 00000000..22318d01 --- /dev/null +++ b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/specs/api-error-code-alignment/spec.md @@ -0,0 +1,56 @@ +## ADDED Requirements + +### Requirement: Complete API error mapping +The frontend SHALL map every current backend API error code to exactly one semantic translation key and SHALL contain no duplicate numeric cases. + +#### Scenario: Current backend error is received +- **WHEN** an API response contains a numeric code defined by the backend error-code catalog +- **THEN** `getErrorTranslationKey` SHALL return the corresponding semantic translation key + +#### Scenario: Error catalog is audited +- **WHEN** frontend validation compares the mapping with the backend catalog +- **THEN** it SHALL report no missing current codes, no duplicate numeric mappings, and no undocumented frontend-only codes + +### Requirement: Corrected existing error mappings +The frontend SHALL map code `1039` to `unsupported_media_type` and code `4003` to `invalid_resource_token`. + +#### Scenario: Unsupported media is returned +- **WHEN** the backend returns error code `1039` +- **THEN** the frontend SHALL display the localized unsupported-media message + +#### Scenario: Resource token is invalid +- **WHEN** the backend returns error code `4003` +- **THEN** the frontend SHALL display the localized invalid-resource-token message + +### Requirement: Asset and stock error mappings +The frontend SHALL map `1040` to `invalid_asset_type`, `1041` to `invalid_asset_amount`, `1042` to `invalid_stock_symbol`, `2014` to `stock_quote_not_found`, `5014` to `stock_quote_failed`, and `6003` to `stock_quote_rate_limited`. + +#### Scenario: Asset validation fails +- **WHEN** the backend returns code `1040`, `1041`, or `1042` +- **THEN** the frontend SHALL display the corresponding localized validation message + +#### Scenario: Stock provider operation fails +- **WHEN** the backend returns code `2014`, `5014`, or `6003` +- **THEN** the frontend SHALL display the corresponding localized not-found, provider-failure, or rate-limit message + +### Requirement: Explicit legacy code compatibility +The frontend SHALL retain code `6002` as the sole documented frontend-only legacy mapping and SHALL interpret it only as `insufficient_credits`; current stock rate limiting SHALL use `6003`. + +#### Scenario: Legacy insufficient-credit response is received +- **WHEN** an older backend returns code `6002` +- **THEN** the frontend SHALL display the insufficient-credits message + +#### Scenario: Current stock rate limit is received +- **WHEN** the current backend returns code `6003` +- **THEN** the frontend SHALL display the stock-quote-rate-limited message without colliding with legacy code `6002` + +### Requirement: Localized API errors +Every API error translation key used by the mapping SHALL exist in every supported locale and in the generated typed translation-key catalog. + +#### Scenario: New error is displayed in any locale +- **WHEN** a user receives an asset, stock, media, or resource-token error in any supported language +- **THEN** the frontend SHALL render localized text rather than a missing key + +#### Scenario: Unknown error code is received +- **WHEN** an API response contains an unmapped code +- **THEN** the existing unknown-error fallback SHALL remain in effect diff --git a/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/specs/stock-quote-settings/spec.md b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/specs/stock-quote-settings/spec.md new file mode 100644 index 00000000..defcd34c --- /dev/null +++ b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/specs/stock-quote-settings/spec.md @@ -0,0 +1,56 @@ +## ADDED Requirements + +### Requirement: Twelve Data credential settings +The frontend SHALL represent `twelve_data_api_key` in user settings and sparse update payloads and SHALL associate backend provider ID `twelve-data` with that field. + +#### Scenario: Existing credential is loaded +- **WHEN** the user-settings API returns a masked Twelve Data credential +- **THEN** the access page SHALL display the masked value for the Twelve Data provider without treating it as a local change + +#### Scenario: Credential is saved +- **WHEN** a user enters or replaces a Twelve Data credential +- **THEN** the frontend SHALL send `twelve_data_api_key` in the sparse settings PATCH payload + +#### Scenario: Credential is cleared +- **WHEN** a user clears Twelve Data individually or uses the remove-all-keys action +- **THEN** the frontend SHALL send an empty `twelve_data_api_key` and SHALL include that removal in changed-state detection + +### Requirement: Backend-owned Twelve Data metadata +The frontend SHALL display the Twelve Data name, key-management URL, token format, and tool labels from the external-provider response rather than duplicating those values locally. + +#### Scenario: Provider catalog is displayed +- **WHEN** the external-tools API returns provider ID `twelve-data` +- **THEN** the access page SHALL render the provider using the returned metadata, including `https://twelvedata.com/account/api-keys` + +### Requirement: Stock quote tool choice +The frontend SHALL support `api_stock_quote` as an integrations tool type and SHALL persist its selection through `tool_choice_api_stock_quote`. + +#### Scenario: Stock quote tool is returned +- **WHEN** the external-tools API returns a tool with type `api_stock_quote` +- **THEN** the advanced tool panel SHALL render a localized stock-quote section in the integrations category + +#### Scenario: Custom stock quote choice is saved +- **WHEN** a user changes the stock-quote tool selection +- **THEN** changed-state detection SHALL activate and the sparse settings PATCH SHALL contain `tool_choice_api_stock_quote` + +#### Scenario: Preset includes stock quotes +- **WHEN** the selected intelligence preset contains an `api_stock_quote` choice +- **THEN** preset application and preset detection SHALL include the stock-quote setting + +### Requirement: Stock quote localization +Every supported locale SHALL provide a natural local equivalent of “Stocks and stock market” as the title and a localized description for `tools.types.api_stock_quote`, and the generated translation-key type SHALL contain both keys. The Serbian title SHALL be exactly `Akcije i berza`. + +#### Scenario: Any supported locale is active +- **WHEN** the intelligence page renders the stock-quote tool +- **THEN** it SHALL show the natural localized “Stocks and stock market” title and description rather than a literal provider-operation label, hiding the type, or displaying a raw key + +### Requirement: Temporary Twelve Data icon +The frontend SHALL map provider ID `twelve-data` to a provider-specific asset path that temporarily contains a copy of the existing CoinMarketCap icon. + +#### Scenario: Temporary icon is rendered +- **WHEN** Twelve Data appears in access or intelligence settings before the real icon is supplied +- **THEN** the frontend SHALL render the temporary provider asset instead of the generic unknown-provider icon + +#### Scenario: Real icon becomes available +- **WHEN** the user supplies and approves the real Twelve Data artwork +- **THEN** the temporary asset contents SHALL be replaced without changing provider IDs or component logic diff --git a/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/tasks.md b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/tasks.md new file mode 100644 index 00000000..976cf79d --- /dev/null +++ b/openspec/changes/archive/2026-07-25-add-stock-quote-frontend-support/tasks.md @@ -0,0 +1,23 @@ +## 1. Twelve Data access settings + +- [x] 1.1 Add `twelve_data_api_key` to the user settings response/payload contracts, map provider ID `twelve-data`, and include the field in masked diffing, API-key detection, and sparse PATCH construction. +- [x] 1.2 Add `twelve_data_api_key` to the remove-all-keys flow and verify individual save, masked reload, individual clear, and bulk clear produce the intended sparse payloads. +- [x] 1.3 Copy `coinmarketcap-white.svg` to a provider-specific temporary Twelve Data asset path and map `twelve-data` to that asset without hard-coding provider metadata or the key-management URL. + +## 2. Stock quote tool settings + +- [x] 2.1 Add `api_stock_quote` to `ToolType` and `tool_choice_api_stock_quote` to user settings response/payload contracts and string-field changed-payload handling. +- [x] 2.2 Add `api_stock_quote` to the integrations category, changed-category detection, and tool icon mapping so custom selections and preset comparison/application include stock quotes. +- [x] 2.3 Add the natural local equivalent of “Stocks and stock market” and a description under `tools.types.api_stock_quote` in every supported locale, using exact Serbian title `Akcije i berza`, preserving locale key ordering, and allowing the normal lint task to regenerate typed translation keys. + +## 3. API error-code alignment + +- [x] 3.1 Update `getErrorTranslationKey` for `1039`, `1040`, `1041`, `1042`, `2014`, `4003`, `5014`, and `6003`; retain `6002` only as the documented legacy insufficient-credit mapping. +- [x] 3.2 Add or rename the corresponding semantic error keys in every supported locale, including `invalid_resource_token`, and regenerate the typed translation-key catalog through the normal lint workflow. +- [x] 3.3 Mechanically compare the frontend mapping with the backend error-code catalog and confirm every current backend code is mapped exactly once, numeric cases contain no duplicates, all translation keys exist in every locale, and `6002` is the only documented legacy frontend-only exception. + +## 4. Validation and icon handoff + +- [x] 4.1 Run `bun run lint` and `bun run build` from the frontend repository, run `git diff --check`, and resolve all regressions without adding a new test framework. +- [x] 4.2 Manually review the Twelve Data access card, masked-key save/clear behavior, stock-quote custom choice and presets, localized tool visibility, provider navigation, and representative new API error mappings. +- [x] 4.3 **TODO — STOP for the user to supply and approve the real Twelve Data icon. Keep the copied CoinMarketCap artwork explicitly temporary; once the real asset is supplied, replace only the provider-specific asset contents and rerun lint, build, and visual review before completing the change.** diff --git a/openspec/specs/translation-key-ordering/spec.md b/openspec/specs/translation-key-ordering/spec.md deleted file mode 100644 index ce073e42..00000000 --- a/openspec/specs/translation-key-ordering/spec.md +++ /dev/null @@ -1,46 +0,0 @@ -## Requirements - -### Requirement: Key ordering matches English source - -The system SHALL ensure that all non-English i18n JSON files have their keys ordered to match `en.json` at every nesting level. `en.json` itself SHALL NOT be modified. - -#### Scenario: Keys are already in correct order -- **WHEN** a non-English file has all keys in the same order as `en.json` at every nesting level -- **THEN** the file is not rewritten - -#### Scenario: Keys are out of order at top level -- **WHEN** a non-English file has the same keys as `en.json` but in a different top-level order -- **THEN** the file is rewritten with keys reordered to match `en.json` -- **AND** the file's values are preserved exactly - -#### Scenario: Keys are out of order in nested objects -- **WHEN** a non-English file has nested object keys in a different order than the corresponding nested object in `en.json` -- **THEN** the nested keys are reordered to match `en.json` recursively at every depth - -#### Scenario: Plural form key ordering -- **WHEN** a plural form object (containing keys like `zero`, `one`, `two`, `few`, `many`, `other`) has keys in a different order than `en.json` -- **THEN** the plural form keys are reordered to match `en.json` - -### Requirement: Reorder logging - -The system SHALL log which files were reordered during the validation run. - -#### Scenario: Files were reordered -- **WHEN** one or more non-English files are rewritten due to key ordering mismatch -- **THEN** the script logs a message identifying each reordered file - -#### Scenario: No files need reordering -- **WHEN** all non-English files already match `en.json` key order -- **THEN** the script logs a success message indicating all files are correctly ordered - -### Requirement: Validation ordering - -The key ordering check SHALL run after all correctness validations (JSON syntax, duplicate keys, key matching, placeholder validation) and before TypeScript type generation. - -#### Scenario: File has correctness errors -- **WHEN** a file fails syntax, duplicate, key matching, or placeholder validation -- **THEN** the script fails with the correctness error before reaching the ordering step - -#### Scenario: File passes all validations -- **WHEN** a file passes all correctness validations but has misordered keys -- **THEN** the file is auto-fixed and type generation proceeds with correctly ordered data diff --git a/package-lock.json b/package-lock.json index 375570f4..b274fa59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "agent-web", - "version": "5.19.12", + "version": "5.27.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agent-web", - "version": "5.19.12", + "version": "5.27.1", "dependencies": { "@radix-ui/react-accordion": "^1.2.16", "@radix-ui/react-dialog": "^1.1.19", @@ -18,13 +18,13 @@ "@radix-ui/react-switch": "^1.3.3", "@radix-ui/react-tabs": "^1.1.17", "@radix-ui/react-tooltip": "^1.2.12", - "@tailwindcss/vite": "^4.3.2", + "@tailwindcss/vite": "^4.3.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "embla-carousel-react": "^8.6.0", "input-otp": "^1.4.2", "jwt-decode": "^4.0.0", - "lucide-react": "^1.24.0", + "lucide-react": "^1.25.0", "make-plural": "^8.1.0", "next-themes": "^0.4.6", "radix-ui": "^1.6.2", @@ -33,18 +33,18 @@ "react-router-dom": "^7.18.1", "sonner": "^2.0.7", "tailwind-merge": "^3.6.0", - "tailwindcss": "^4.3.2", + "tailwindcss": "^4.3.3", "vaul": "^1.1.2" }, "devDependencies": { "@eslint/js": "^9.39.5", - "@tailwindcss/postcss": "^4.3.2", + "@tailwindcss/postcss": "^4.3.3", "@types/node": "^26.1.1", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@types/react-router-dom": "^5.3.3", "@vitejs/plugin-react": "^6.0.2", - "autoprefixer": "^10.5.0", + "autoprefixer": "^10.5.4", "eslint": "^9.39.5", "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.3", @@ -55,14 +55,14 @@ "postcss-import": "^16.1.1", "postcss-nesting": "^14.0.0", "postcss-theme-ui": "^0.10.0", - "shadcn": "^4.13.0", + "shadcn": "^4.13.1", "stylelint": "17.14.0", "stylelint-config-standard": "^40.0.0", "stylelint-config-tailwindcss": "^1.0.1", "tw-animate-css": "^1.4.0", "typescript": "~5.8.3", - "typescript-eslint": "^8.63.0", - "vite": "^8.1.4" + "typescript-eslint": "^8.64.0", + "vite": "^8.1.5" } }, "node_modules/@alloc/quick-lru": { @@ -3253,47 +3253,47 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.2.tgz", - "integrity": "sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "5.21.6", + "enhanced-resolve": "^5.24.1", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.3.2" + "tailwindcss": "4.3.3" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.2.tgz", - "integrity": "sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", "license": "MIT", "engines": { "node": ">= 20" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.2", - "@tailwindcss/oxide-darwin-arm64": "4.3.2", - "@tailwindcss/oxide-darwin-x64": "4.3.2", - "@tailwindcss/oxide-freebsd-x64": "4.3.2", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.2", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.2", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.2", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.2", - "@tailwindcss/oxide-linux-x64-musl": "4.3.2", - "@tailwindcss/oxide-wasm32-wasi": "4.3.2", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.2", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.2" + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.2.tgz", - "integrity": "sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", "cpu": [ "arm64" ], @@ -3307,9 +3307,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.2.tgz", - "integrity": "sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", "cpu": [ "arm64" ], @@ -3323,9 +3323,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.2.tgz", - "integrity": "sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", "cpu": [ "x64" ], @@ -3339,9 +3339,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.2.tgz", - "integrity": "sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", "cpu": [ "x64" ], @@ -3355,9 +3355,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.2.tgz", - "integrity": "sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", "cpu": [ "arm" ], @@ -3371,9 +3371,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.2.tgz", - "integrity": "sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", "cpu": [ "arm64" ], @@ -3387,9 +3387,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.2.tgz", - "integrity": "sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", "cpu": [ "arm64" ], @@ -3403,9 +3403,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.2.tgz", - "integrity": "sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", "cpu": [ "x64" ], @@ -3419,9 +3419,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.2.tgz", - "integrity": "sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", "cpu": [ "x64" ], @@ -3435,9 +3435,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.2.tgz", - "integrity": "sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -3524,9 +3524,9 @@ "optional": true }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.2.tgz", - "integrity": "sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", "cpu": [ "arm64" ], @@ -3540,9 +3540,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.2.tgz", - "integrity": "sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", "cpu": [ "x64" ], @@ -3556,28 +3556,28 @@ } }, "node_modules/@tailwindcss/postcss": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.2.tgz", - "integrity": "sha512-rjVWYCa7Ngbi5AarT6k8TkxUG3Wl1QKzHdIZVsjZSzf36Jmo2IKZt/NHRAwly8oDkbBOH0YTu+CHuf9jPxMc+g==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz", + "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==", "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.3.2", - "@tailwindcss/oxide": "4.3.2", - "postcss": "^8.5.15", - "tailwindcss": "4.3.2" + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" } }, "node_modules/@tailwindcss/vite": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.2.tgz", - "integrity": "sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", + "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.3.2", - "@tailwindcss/oxide": "4.3.2", - "tailwindcss": "4.3.2" + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "tailwindcss": "4.3.3" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" @@ -3726,17 +3726,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.63.0.tgz", - "integrity": "sha512-rvwSgqT+DHpWdzfSzPatRLm02a0GlESt++9iy3hLCDY4BgkaLcl8LBi9Yh7XGFBpwcBE/K3024QuXWTpbz4FfQ==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.64.0.tgz", + "integrity": "sha512-CGvQPBxN3wZLu6Rz2kFUpZeoCm78xUic92ck39KPePkO1NPOwjCqdQnm5Q87tpWw9vcBvW8XLrDXjH9PWYtJ3Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.63.0", - "@typescript-eslint/type-utils": "8.63.0", - "@typescript-eslint/utils": "8.63.0", - "@typescript-eslint/visitor-keys": "8.63.0", + "@typescript-eslint/scope-manager": "8.64.0", + "@typescript-eslint/type-utils": "8.64.0", + "@typescript-eslint/utils": "8.64.0", + "@typescript-eslint/visitor-keys": "8.64.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -3749,7 +3749,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.63.0", + "@typescript-eslint/parser": "^8.64.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -3765,16 +3765,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.63.0.tgz", - "integrity": "sha512-gwh4gvvlaVDKKxyfxMG+Gnu1u9X0OQBwyGLkbwB65dIzBKnxeRiJlNFqlI3zwVhNXJIs6qV7mlFCn/BIajlVig==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.64.0.tgz", + "integrity": "sha512-KA0OshtlcCCXmbfqyZkM5pV3/WNraJf7DkJRLpyrmwPtud57H5BDX7C3k0LPSPxpprfRL+cJDGabF10mvNCoCw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.63.0", - "@typescript-eslint/types": "8.63.0", - "@typescript-eslint/typescript-estree": "8.63.0", - "@typescript-eslint/visitor-keys": "8.63.0", + "@typescript-eslint/scope-manager": "8.64.0", + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/typescript-estree": "8.64.0", + "@typescript-eslint/visitor-keys": "8.64.0", "debug": "^4.4.3" }, "engines": { @@ -3790,14 +3790,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.63.0.tgz", - "integrity": "sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.64.0.tgz", + "integrity": "sha512-tk4WpOJ6IEbGrVHaNmM0YRrwAD3exZlIK3iadQNAxh4YKk6jvUQ4ecq18n+v7+meh+cJ3j+D8nbk8sRKhlwLQg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.63.0", - "@typescript-eslint/types": "^8.63.0", + "@typescript-eslint/tsconfig-utils": "^8.64.0", + "@typescript-eslint/types": "^8.64.0", "debug": "^4.4.3" }, "engines": { @@ -3812,14 +3812,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.63.0.tgz", - "integrity": "sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.64.0.tgz", + "integrity": "sha512-CXEaFdYXjSTgKhisNkwCcJwTP8Pl+fmRrEQrri4nm3vU743bALrxzLmq7fHG/7e6a5xO0lDYeURpZmBuhHk54w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.63.0", - "@typescript-eslint/visitor-keys": "8.63.0" + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/visitor-keys": "8.64.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3830,9 +3830,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.63.0.tgz", - "integrity": "sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.64.0.tgz", + "integrity": "sha512-2yo8rRNKuzbVWQp5kslhANqZ2uDAeROQHBRZNPu8JDsHmeFNj/XJJhX/FhNUWmkHHvoNsKa6+tHJiig87EzsQw==", "dev": true, "license": "MIT", "engines": { @@ -3847,15 +3847,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.63.0.tgz", - "integrity": "sha512-Nzzh/OGxVCOjObjaj1CQF2RUasyYy2Jfuh+zZ3PjLzG2fYRriAiZLib9UKtO+CpQAS3YHiAS+ckZDclwqI1TPA==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.64.0.tgz", + "integrity": "sha512-XWG4Fmmv/6SvyS9nH8jWrKs6terwJvE8cyRt1CzYYqzp9OrPhCT4cMc/f7C6RZCwG+qMmiffJS1/qJP8G1URtg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.63.0", - "@typescript-eslint/typescript-estree": "8.63.0", - "@typescript-eslint/utils": "8.63.0", + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/typescript-estree": "8.64.0", + "@typescript-eslint/utils": "8.64.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -3872,9 +3872,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.63.0.tgz", - "integrity": "sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.64.0.tgz", + "integrity": "sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==", "dev": true, "license": "MIT", "engines": { @@ -3886,16 +3886,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.63.0.tgz", - "integrity": "sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.64.0.tgz", + "integrity": "sha512-Pztpsn1aCE1oWDvDEfUk31nngvvF7vUB5SwHFEaZIFpvw7WJtqUHHL4plBZDA9HfWJJjL13BdG0YrJInTUvoVA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.63.0", - "@typescript-eslint/tsconfig-utils": "8.63.0", - "@typescript-eslint/types": "8.63.0", - "@typescript-eslint/visitor-keys": "8.63.0", + "@typescript-eslint/project-service": "8.64.0", + "@typescript-eslint/tsconfig-utils": "8.64.0", + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/visitor-keys": "8.64.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3924,16 +3924,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", - "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { @@ -3966,16 +3966,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.63.0.tgz", - "integrity": "sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.64.0.tgz", + "integrity": "sha512-aJUGVB3+U0htrrCjoA8qukw8cm8fNCGAxK/tVoS70k8aeb7DETKeFozRiVFIwEeN9WJLsjaP3ph8I60tY2XZoQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.63.0", - "@typescript-eslint/types": "8.63.0", - "@typescript-eslint/typescript-estree": "8.63.0" + "@typescript-eslint/scope-manager": "8.64.0", + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/typescript-estree": "8.64.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3990,13 +3990,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.63.0.tgz", - "integrity": "sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.64.0.tgz", + "integrity": "sha512-mrtuL8Nsn6gi2H4mo5KMTp823M+3Q19Ew/i+Zlikq20tIMm99C3Ez0dCmkWWnxut20esQvTg8aUSEhMcAOXhEw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.63.0", + "@typescript-eslint/types": "8.64.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -4231,9 +4231,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.5.2", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.2.tgz", - "integrity": "sha512-rD5t5DwOjJdmSORcTq64j8MawTC+tbQ+HHqjR4NDumamy/ambn1UJrlKL+KdwujWxMkFjPM3pPHOEA9tl4767Q==", + "version": "10.5.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz", + "integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==", "dev": true, "funding": [ { @@ -4251,8 +4251,8 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.28.4", - "caniuse-lite": "^1.0.30001799", + "browserslist": "^4.28.6", + "caniuse-lite": "^1.0.30001806", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -4275,9 +4275,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.40", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz", - "integrity": "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==", + "version": "2.10.43", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.43.tgz", + "integrity": "sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4351,9 +4351,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", - "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", + "version": "4.28.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz", + "integrity": "sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==", "dev": true, "funding": [ { @@ -4371,10 +4371,10 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.38", - "caniuse-lite": "^1.0.30001799", - "electron-to-chromium": "^1.5.376", - "node-releases": "^2.0.48", + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001803", + "electron-to-chromium": "^1.5.389", + "node-releases": "^2.0.51", "update-browserslist-db": "^1.2.3" }, "bin": { @@ -4476,9 +4476,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001799", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", - "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "version": "1.0.30001806", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", "dev": true, "funding": [ { @@ -5055,9 +5055,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.380", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.380.tgz", - "integrity": "sha512-W6d5AbuEoRayO447cqrg6lKJIlscgRnnxOZl/08kfV71BQDoEBC7Wwis68z87LjyK6f4kWyTaubuDbhHKrZkbA==", + "version": "1.5.393", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.393.tgz", + "integrity": "sha512-kiDJdIUawuEIcp9XoICKp1iTYDEbgguIPq526N1Q7jIQDeQ3CqoMx71025PI/7E48Ddtw2HuWsVjY7afEgNxmg==", "dev": true, "license": "ISC" }, @@ -5107,9 +5107,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.21.6", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", - "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", + "version": "5.24.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.2.tgz", + "integrity": "sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -7063,9 +7063,9 @@ } }, "node_modules/lucide-react": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.24.0.tgz", - "integrity": "sha512-YT6mBD8lGKkg4nM39enlm94/sfJIiW0YKUT60fBy4YK8tai31ylg1VhGNWxkpSKHo9UagfnZqwIff3HTDQwXeA==", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.25.0.tgz", + "integrity": "sha512-/mdJTRbiwcLOQ1NZZK1amZF9rIZyvO18D6r9TngE6TG1NmqHgFuT4eE7Xrkm9UsXMbBJD1NlfwHVltCDWHrOTw==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -7320,9 +7320,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.50", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", - "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", "dev": true, "license": "MIT", "engines": { @@ -7816,9 +7816,9 @@ } }, "node_modules/postcss": { - "version": "8.5.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", - "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", + "version": "8.5.19", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.19.tgz", + "integrity": "sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==", "funding": [ { "type": "opencollective", @@ -8729,9 +8729,9 @@ "license": "ISC" }, "node_modules/shadcn": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/shadcn/-/shadcn-4.13.0.tgz", - "integrity": "sha512-5fuJ4jI/GcPeA/iTL4cJivCZuYQGXz/N3bIzyd+Gd/FM6xUCy2MxGG+LaDQuw2cjNy9zGPSFPTEmI048UwPTZA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/shadcn/-/shadcn-4.13.1.tgz", + "integrity": "sha512-pSNPND8mVWGBytdd8l4Cksg7MyRZOsv28HpvNCtFtLwZoxLSGM6v3NMUpmpbOaIoreopS/UOpQvnCyttOHVLAQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9488,9 +9488,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.2.tgz", - "integrity": "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", "license": "MIT" }, "node_modules/tapable": { @@ -9668,16 +9668,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.63.0.tgz", - "integrity": "sha512-xgwXyzG4sK9ALkBxbyGkTMMOS+imnW65iPhxCQMK83KhxyoDNW7l+IDqEf9vMdoUidHpOoS967RCq4eMiTexwQ==", + "version": "8.64.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.64.0.tgz", + "integrity": "sha512-0qg+pDNMnqYzqH9AnNK+39tejHvsShUOUUoRUgtnTGE7QuMZhiFDnozq8nHJVq+Wae6NMLKNWLg5WmkcC/ndyQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.63.0", - "@typescript-eslint/parser": "8.63.0", - "@typescript-eslint/typescript-estree": "8.63.0", - "@typescript-eslint/utils": "8.63.0" + "@typescript-eslint/eslint-plugin": "8.64.0", + "@typescript-eslint/parser": "8.64.0", + "@typescript-eslint/typescript-estree": "8.64.0", + "@typescript-eslint/utils": "8.64.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -9866,15 +9866,15 @@ } }, "node_modules/vite": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz", - "integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", + "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", - "postcss": "^8.5.16", - "rolldown": "~1.1.4", + "postcss": "^8.5.17", + "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "bin": { diff --git a/package.json b/package.json index 2e3d69f1..d2fa5e20 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "agent-web", "private": true, - "version": "5.19.12", + "version": "5.27.1", "type": "module", "scripts": { "clean": "rm -rf dist .vite node_modules/.vite", @@ -28,13 +28,13 @@ "@radix-ui/react-switch": "^1.3.3", "@radix-ui/react-tabs": "^1.1.17", "@radix-ui/react-tooltip": "^1.2.12", - "@tailwindcss/vite": "^4.3.2", + "@tailwindcss/vite": "^4.3.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "embla-carousel-react": "^8.6.0", "input-otp": "^1.4.2", "jwt-decode": "^4.0.0", - "lucide-react": "^1.24.0", + "lucide-react": "^1.25.0", "make-plural": "^8.1.0", "next-themes": "^0.4.6", "radix-ui": "^1.6.2", @@ -43,18 +43,18 @@ "react-router-dom": "^7.18.1", "sonner": "^2.0.7", "tailwind-merge": "^3.6.0", - "tailwindcss": "^4.3.2", + "tailwindcss": "^4.3.3", "vaul": "^1.1.2" }, "devDependencies": { "@eslint/js": "^9.39.5", - "@tailwindcss/postcss": "^4.3.2", + "@tailwindcss/postcss": "^4.3.3", "@types/node": "^26.1.1", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@types/react-router-dom": "^5.3.3", "@vitejs/plugin-react": "^6.0.2", - "autoprefixer": "^10.5.0", + "autoprefixer": "^10.5.4", "eslint": "^9.39.5", "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.3", @@ -65,13 +65,13 @@ "postcss-import": "^16.1.1", "postcss-nesting": "^14.0.0", "postcss-theme-ui": "^0.10.0", - "shadcn": "^4.13.0", + "shadcn": "^4.13.1", "stylelint": "17.14.0", "stylelint-config-standard": "^40.0.0", "stylelint-config-tailwindcss": "^1.0.1", "tw-animate-css": "^1.4.0", "typescript": "~5.8.3", - "typescript-eslint": "^8.63.0", - "vite": "^8.1.4" + "typescript-eslint": "^8.64.0", + "vite": "^8.1.5" } } diff --git a/src/assets/i18n/ar.json b/src/assets/i18n/ar.json index 75d9b0f1..b938d2fa 100644 --- a/src/assets/i18n/ar.json +++ b/src/assets/i18n/ar.json @@ -367,6 +367,10 @@ "title": "صرف العملات المشفرة", "description": "الوصول إلى أسعار الصرف في الوقت الفعلي للعملات المشفرة." }, + "api_stock_quote": { + "title": "الأسهم والبورصة", + "description": "الوصول إلى أسعار الأسهم في الوقت الفعلي." + }, "api_twitter": { "title": "X / تويتر", "description": "الوصول لقراءة وتحليل محتوى تويتر." @@ -457,7 +461,7 @@ "unauthorized_seller": "بائع غير مصرح له", "empty_token": "رمز فارغ", "no_user_id_in_token": "لا يوجد معرّف مستخدم في الرمز", - "invalid_attachment_token": "المرفق غير موجود", + "invalid_resource_token": "رمز المورد غير صالح", "image_generation_failed": "فشل في توليد الصورة", "web_fetch_failed": "فشل في جلب محتوى الويب", "llm_unexpected_response": "تم استلام استجابة غير متوقعة من نموذج الذكاء الاصطناعي", @@ -500,7 +504,13 @@ "too_many_input_images": "تم تقديم عدد كبير جدًا من الصور المدخلة", "not_chat_member": "أنت لست عضواً في هذه المحادثة.", "empty_chat_settings_payload": "لم يتم تغيير أي شيء — قم بإجراء تعديل أولاً.", - "unsupported_media_type": "نوع الوسائط غير مدعوم" + "unsupported_media_type": "نوع الوسائط غير مدعوم", + "invalid_asset_type": "نوع الأصل غير صالح", + "invalid_asset_amount": "كمية الأصل غير صالحة", + "invalid_stock_symbol": "رمز السهم غير صالح", + "stock_quote_not_found": "لم يتم العثور على سعر السهم", + "stock_quote_failed": "فشل جلب سعر السهم", + "stock_quote_rate_limited": "تم تجاوز حد طلبات أسعار الأسهم" }, "features": { "header": "الميزات", diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index ca8df1e7..82781a93 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -367,6 +367,10 @@ "title": "Krypto-Wechselkurs", "description": "Zugang zu Echtzeit-Wechselkursen für Kryptowährungen." }, + "api_stock_quote": { + "title": "Aktien und Börse", + "description": "Zugriff auf Aktienkurse in Echtzeit." + }, "api_twitter": { "title": "X / Twitter", "description": "Zugang zum Lesen und Analysieren von Twitter-Inhalten." @@ -457,7 +461,7 @@ "unauthorized_seller": "Nicht autorisierter Verkäufer", "empty_token": "Leeres Token", "no_user_id_in_token": "Keine Benutzer-ID im Token vorhanden", - "invalid_attachment_token": "Anhang nicht gefunden", + "invalid_resource_token": "Ungültiges Ressourcen-Token", "image_generation_failed": "Bilderstellung fehlgeschlagen", "web_fetch_failed": "Abrufen von Webinhalten fehlgeschlagen", "llm_unexpected_response": "Unerwartete Antwort vom KI-Modell erhalten", @@ -500,7 +504,13 @@ "too_many_input_images": "Zu viele Eingabebilder angegeben", "not_chat_member": "Du bist kein Mitglied dieses Chats.", "empty_chat_settings_payload": "Die Einstellungen waren leer — bitte zuerst etwas ändern.", - "unsupported_media_type": "Nicht unterstützter Medientyp" + "unsupported_media_type": "Nicht unterstützter Medientyp", + "invalid_asset_type": "Ungültiger Anlagetyp", + "invalid_asset_amount": "Ungültiger Anlagebetrag", + "invalid_stock_symbol": "Ungültiges Aktiensymbol", + "stock_quote_not_found": "Aktienkurs nicht gefunden", + "stock_quote_failed": "Aktienkurs konnte nicht abgerufen werden", + "stock_quote_rate_limited": "Anfragelimit für Aktienkurse erreicht" }, "features": { "header": "Funktionen", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 84ccfdc8..64e37887 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -367,6 +367,10 @@ "title": "Crypto Exchange", "description": "Access to real-time exchange rates for cryptocurrencies." }, + "api_stock_quote": { + "title": "Stocks and Stock Market", + "description": "Access to real-time stock market quotes." + }, "api_twitter": { "title": "X / Twitter", "description": "Access to read and analyze Twitter content." @@ -457,7 +461,7 @@ "unauthorized_seller": "Unauthorized seller", "empty_token": "Empty token", "no_user_id_in_token": "No user ID present in token", - "invalid_attachment_token": "Attachment not found", + "invalid_resource_token": "Invalid resource token", "image_generation_failed": "Failed to generate the image", "web_fetch_failed": "Web content fetch failed", "llm_unexpected_response": "Received an unexpected response from the AI model", @@ -500,7 +504,13 @@ "too_many_input_images": "Too many input images provided", "not_chat_member": "You are not a member of this chat.", "empty_chat_settings_payload": "Settings save was empty — change something first.", - "unsupported_media_type": "Unsupported media type" + "unsupported_media_type": "Unsupported media type", + "invalid_asset_type": "Invalid asset type", + "invalid_asset_amount": "Invalid asset amount", + "invalid_stock_symbol": "Invalid stock symbol", + "stock_quote_not_found": "Stock quote not found", + "stock_quote_failed": "Failed to retrieve stock quote", + "stock_quote_rate_limited": "Stock quote request limit reached" }, "features": { "header": "Features", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index 74712362..bde79194 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -367,6 +367,10 @@ "title": "Cambio de criptomoneda", "description": "Acceso a tipos de cambio en tiempo real para criptomonedas." }, + "api_stock_quote": { + "title": "Acciones y bolsa", + "description": "Acceso a cotizaciones bursátiles en tiempo real." + }, "api_twitter": { "title": "X / Twitter", "description": "Acceso para leer y analizar contenido de Twitter." @@ -457,7 +461,7 @@ "unauthorized_seller": "Vendedor no autorizado", "empty_token": "Token vacío", "no_user_id_in_token": "No hay ID de usuario presente en el token", - "invalid_attachment_token": "Archivo adjunto no encontrado", + "invalid_resource_token": "Token de recurso no válido", "image_generation_failed": "Error al generar la imagen", "web_fetch_failed": "Error al obtener contenido web", "llm_unexpected_response": "Se recibió una respuesta inesperada del modelo de IA", @@ -500,7 +504,13 @@ "too_many_input_images": "Se proporcionaron demasiadas imágenes de entrada", "not_chat_member": "No eres miembro de este chat.", "empty_chat_settings_payload": "El guardado de configuración estaba vacío — cambia algo primero.", - "unsupported_media_type": "Tipo de medio no compatible" + "unsupported_media_type": "Tipo de medio no compatible", + "invalid_asset_type": "Tipo de activo no válido", + "invalid_asset_amount": "Cantidad de activo no válida", + "invalid_stock_symbol": "Símbolo bursátil no válido", + "stock_quote_not_found": "Cotización bursátil no encontrada", + "stock_quote_failed": "No se pudo obtener la cotización bursátil", + "stock_quote_rate_limited": "Se alcanzó el límite de solicitudes de cotizaciones bursátiles" }, "features": { "header": "Funciones", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 54b900f5..7af60972 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -367,6 +367,10 @@ "title": "Change de cryptomonnaies", "description": "Accès aux taux de change en temps réel pour les cryptomonnaies." }, + "api_stock_quote": { + "title": "Actions et bourse", + "description": "Accès aux cours des actions en temps réel." + }, "api_twitter": { "title": "X / Twitter", "description": "Accès pour lire et analyser le contenu Twitter." @@ -457,7 +461,7 @@ "unauthorized_seller": "Vendeur non autorisé", "empty_token": "Jeton vide", "no_user_id_in_token": "Aucun ID utilisateur présent dans le jeton", - "invalid_attachment_token": "Pièce jointe introuvable", + "invalid_resource_token": "Jeton de ressource invalide", "image_generation_failed": "Échec de la génération de l'image", "web_fetch_failed": "Échec de la récupération du contenu web", "llm_unexpected_response": "Réponse inattendue reçue du modèle d'IA", @@ -500,7 +504,13 @@ "too_many_input_images": "Trop d'images d'entrée fournies", "not_chat_member": "Vous n'êtes pas membre de cette discussion.", "empty_chat_settings_payload": "Aucune modification détectée — effectuez un changement d'abord.", - "unsupported_media_type": "Type de média non pris en charge" + "unsupported_media_type": "Type de média non pris en charge", + "invalid_asset_type": "Type d'actif invalide", + "invalid_asset_amount": "Montant d'actif invalide", + "invalid_stock_symbol": "Symbole boursier invalide", + "stock_quote_not_found": "Cours de l'action introuvable", + "stock_quote_failed": "Impossible de récupérer le cours de l'action", + "stock_quote_rate_limited": "Limite de demandes de cours d'actions atteinte" }, "features": { "header": "Fonctionnalités", diff --git a/src/assets/i18n/hi.json b/src/assets/i18n/hi.json index 4476e327..9e327c2c 100644 --- a/src/assets/i18n/hi.json +++ b/src/assets/i18n/hi.json @@ -367,6 +367,10 @@ "title": "क्रिप्टो एक्सचेंज", "description": "क्रिप्टोकरेंसी के लिए वास्तविक समय विनिमय दरों तक पहुंच।" }, + "api_stock_quote": { + "title": "शेयर और शेयर बाज़ार", + "description": "रीयल-टाइम शेयर बाज़ार भावों तक पहुंच।" + }, "api_twitter": { "title": "X / Twitter", "description": "Twitter सामग्री पढ़ने और विश्लेषण करने के लिए पहुंच।" @@ -457,7 +461,7 @@ "unauthorized_seller": "अनधिकृत विक्रेता", "empty_token": "खाली टोकन", "no_user_id_in_token": "टोकन में कोई उपयोगकर्ता ID मौजूद नहीं है", - "invalid_attachment_token": "अटैचमेंट नहीं मिला", + "invalid_resource_token": "अमान्य संसाधन टोकन", "image_generation_failed": "छवि उत्पन्न करने में विफल", "web_fetch_failed": "वेब सामग्री प्राप्त करने में विफल", "llm_unexpected_response": "AI मॉडल से एक अप्रत्याशित प्रतिक्रिया प्राप्त हुई", @@ -500,7 +504,13 @@ "too_many_input_images": "बहुत अधिक इनपुट छवियाँ प्रदान की गईं", "not_chat_member": "आप इस चैट के सदस्य नहीं हैं.", "empty_chat_settings_payload": "सेटिंग्स सेव खाली था — पहले कुछ बदलें.", - "unsupported_media_type": "असमर्थित मीडिया प्रकार" + "unsupported_media_type": "असमर्थित मीडिया प्रकार", + "invalid_asset_type": "अमान्य संपत्ति प्रकार", + "invalid_asset_amount": "अमान्य संपत्ति राशि", + "invalid_stock_symbol": "अमान्य शेयर प्रतीक", + "stock_quote_not_found": "शेयर भाव नहीं मिला", + "stock_quote_failed": "शेयर भाव प्राप्त करने में विफल", + "stock_quote_rate_limited": "शेयर भाव अनुरोध सीमा पूरी हो गई" }, "features": { "header": "विशेषताएं", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index df6101bd..9cc3e0de 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -367,6 +367,10 @@ "title": "Cambio criptovalute", "description": "Accesso ai tassi di cambio in tempo reale per le criptovalute." }, + "api_stock_quote": { + "title": "Azioni e borsa", + "description": "Accesso alle quotazioni azionarie in tempo reale." + }, "api_twitter": { "title": "X / Twitter", "description": "Accesso per leggere e analizzare i contenuti di Twitter." @@ -457,7 +461,7 @@ "unauthorized_seller": "Venditore non autorizzato", "empty_token": "Token vuoto", "no_user_id_in_token": "Nessun ID utente presente nel token", - "invalid_attachment_token": "Allegato non trovato", + "invalid_resource_token": "Token della risorsa non valido", "image_generation_failed": "Impossibile generare l'immagine", "web_fetch_failed": "Recupero del contenuto web non riuscito", "llm_unexpected_response": "Ricevuta una risposta inaspettata dal modello IA", @@ -500,7 +504,13 @@ "too_many_input_images": "Troppe immagini di input fornite", "not_chat_member": "Non sei membro di questa chat.", "empty_chat_settings_payload": "Il salvataggio delle impostazioni era vuoto — modifica prima qualcosa.", - "unsupported_media_type": "Tipo di media non supportato" + "unsupported_media_type": "Tipo di media non supportato", + "invalid_asset_type": "Tipo di asset non valido", + "invalid_asset_amount": "Importo dell'asset non valido", + "invalid_stock_symbol": "Simbolo azionario non valido", + "stock_quote_not_found": "Quotazione azionaria non trovata", + "stock_quote_failed": "Impossibile recuperare la quotazione azionaria", + "stock_quote_rate_limited": "Limite di richieste di quotazioni azionarie raggiunto" }, "features": { "header": "Funzionalità", diff --git a/src/assets/i18n/ru.json b/src/assets/i18n/ru.json index 7eb7b1fa..77bfdfd0 100644 --- a/src/assets/i18n/ru.json +++ b/src/assets/i18n/ru.json @@ -367,6 +367,10 @@ "title": "Обмен криптовалют", "description": "Доступ к курсам обмена криптовалют в реальном времени." }, + "api_stock_quote": { + "title": "Акции и биржа", + "description": "Доступ к котировкам акций в реальном времени." + }, "api_twitter": { "title": "X / Twitter", "description": "Доступ для чтения и анализа контента Twitter." @@ -457,7 +461,7 @@ "unauthorized_seller": "Неавторизованный продавец", "empty_token": "Пустой токен", "no_user_id_in_token": "ID пользователя отсутствует в токене", - "invalid_attachment_token": "Вложение не найдено", + "invalid_resource_token": "Недопустимый токен ресурса", "image_generation_failed": "Не удалось сгенерировать изображение", "web_fetch_failed": "Не удалось загрузить веб-контент", "llm_unexpected_response": "Получен неожиданный ответ от модели ИИ", @@ -500,7 +504,13 @@ "too_many_input_images": "Предоставлено слишком много входных изображений", "not_chat_member": "Вы не являетесь участником этого чата.", "empty_chat_settings_payload": "Сохранение настроек было пустым — сначала измените что-нибудь.", - "unsupported_media_type": "Неподдерживаемый тип медиафайла" + "unsupported_media_type": "Неподдерживаемый тип медиафайла", + "invalid_asset_type": "Недопустимый тип актива", + "invalid_asset_amount": "Недопустимое количество актива", + "invalid_stock_symbol": "Недопустимый биржевой символ", + "stock_quote_not_found": "Котировка акции не найдена", + "stock_quote_failed": "Не удалось получить котировку акции", + "stock_quote_rate_limited": "Достигнут лимит запросов котировок акций" }, "features": { "header": "Возможности", diff --git a/src/assets/i18n/sr.json b/src/assets/i18n/sr.json index 9e84e3d3..7f5b993b 100644 --- a/src/assets/i18n/sr.json +++ b/src/assets/i18n/sr.json @@ -367,6 +367,10 @@ "title": "Kripto menjačnica", "description": "Pristup kursevima kripto valuta u realnom vremenu." }, + "api_stock_quote": { + "title": "Akcije i berza", + "description": "Pristup informacijama s berzi u realnom vremenu." + }, "api_twitter": { "title": "X / Twitter", "description": "Pristup za čitanje i analizu Twitter sadržaja." @@ -457,7 +461,7 @@ "unauthorized_seller": "Neautorizovan prodavac", "empty_token": "Prazan token", "no_user_id_in_token": "Korisnički ID nije prisutan u tokenu", - "invalid_attachment_token": "Prilog nije pronađen", + "invalid_resource_token": "Nevažeći token resursa", "image_generation_failed": "Generisanje slike nije uspelo", "web_fetch_failed": "Preuzimanje web sadržaja nije uspelo", "llm_unexpected_response": "Primljen je neočekivan odgovor od AI modela", @@ -500,7 +504,13 @@ "too_many_input_images": "Previše ulaznih slika je dostavljeno", "not_chat_member": "Nisi član ovog četa.", "empty_chat_settings_payload": "Čuvanje podešavanja je bilo prazno — prvo promenite nešto.", - "unsupported_media_type": "Nepodržan tip medija" + "unsupported_media_type": "Nepodržan tip medija", + "invalid_asset_type": "Nevažeći tip imovine", + "invalid_asset_amount": "Nevažeća količina imovine", + "invalid_stock_symbol": "Nevažeći simbol akcije", + "stock_quote_not_found": "Berzanska kotacija nije pronađena", + "stock_quote_failed": "Preuzimanje berzanske kotacije nije uspelo", + "stock_quote_rate_limited": "Dostignuto je ograničenje zahteva za berzanske kotacije" }, "features": { "header": "Mogućnosti", diff --git a/src/assets/i18n/tr.json b/src/assets/i18n/tr.json index 10dd6c3d..62eedf42 100644 --- a/src/assets/i18n/tr.json +++ b/src/assets/i18n/tr.json @@ -367,6 +367,10 @@ "title": "Kripto Döviz Kuru", "description": "Kripto para birimleri için gerçek zamanlı döviz kurlarına erişim." }, + "api_stock_quote": { + "title": "Hisseler ve borsa", + "description": "Gerçek zamanlı hisse senedi fiyatlarına erişim." + }, "api_twitter": { "title": "X / Twitter", "description": "Twitter içeriğini okumak ve analiz etmek için erişim." @@ -457,7 +461,7 @@ "unauthorized_seller": "Yetkisiz satıcı", "empty_token": "Boş belirteç", "no_user_id_in_token": "Belirteçte kullanıcı kimliği bulunmuyor", - "invalid_attachment_token": "Ek bulunamadı", + "invalid_resource_token": "Geçersiz kaynak belirteci", "image_generation_failed": "Görüntü oluşturulamadı", "web_fetch_failed": "Web içeriği getirilemedi", "llm_unexpected_response": "AI modelinden beklenmeyen yanıt alındı", @@ -500,7 +504,13 @@ "too_many_input_images": "Çok fazla giriş görüntüsü sağlandı", "not_chat_member": "Bu sohbetin üyesi değilsiniz.", "empty_chat_settings_payload": "Kaydedilecek ayar yok — önce bir şeyi değiştirin.", - "unsupported_media_type": "Desteklenmeyen medya türü" + "unsupported_media_type": "Desteklenmeyen medya türü", + "invalid_asset_type": "Geçersiz varlık türü", + "invalid_asset_amount": "Geçersiz varlık miktarı", + "invalid_stock_symbol": "Geçersiz hisse senedi sembolü", + "stock_quote_not_found": "Hisse senedi fiyatı bulunamadı", + "stock_quote_failed": "Hisse senedi fiyatı alınamadı", + "stock_quote_rate_limited": "Hisse senedi fiyatı istek sınırına ulaşıldı" }, "features": { "header": "Özellikler", diff --git a/src/assets/i18n/zh.json b/src/assets/i18n/zh.json index c5c4a579..5f23e506 100644 --- a/src/assets/i18n/zh.json +++ b/src/assets/i18n/zh.json @@ -367,6 +367,10 @@ "title": "加密货币汇率", "description": "访问加密货币的实时汇率。" }, + "api_stock_quote": { + "title": "股票与股市", + "description": "访问实时股票市场报价。" + }, "api_twitter": { "title": "X / Twitter", "description": "访问以读取和分析Twitter内容。" @@ -457,7 +461,7 @@ "unauthorized_seller": "未授权的卖家", "empty_token": "令牌为空", "no_user_id_in_token": "令牌中不存在用户ID", - "invalid_attachment_token": "未找到附件", + "invalid_resource_token": "无效的资源令牌", "image_generation_failed": "生成图像失败", "web_fetch_failed": "网页内容获取失败", "llm_unexpected_response": "收到AI模型的意外响应", @@ -500,7 +504,13 @@ "too_many_input_images": "提供了过多的输入图片", "not_chat_member": "您不是此聊天的成员。", "empty_chat_settings_payload": "未检测到任何更改 — 请先修改设置。", - "unsupported_media_type": "不支持的媒体类型" + "unsupported_media_type": "不支持的媒体类型", + "invalid_asset_type": "无效的资产类型", + "invalid_asset_amount": "无效的资产数量", + "invalid_stock_symbol": "无效的股票代码", + "stock_quote_not_found": "未找到股票报价", + "stock_quote_failed": "获取股票报价失败", + "stock_quote_rate_limited": "已达到股票报价请求限制" }, "features": { "header": "功能", diff --git a/src/assets/svg/twelve-data-white.svg b/src/assets/svg/twelve-data-white.svg new file mode 100644 index 00000000..5e143ac0 --- /dev/null +++ b/src/assets/svg/twelve-data-white.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/components/AdvancedToolsPanel.tsx b/src/components/AdvancedToolsPanel.tsx index 2e06fe4c..dbe3214d 100644 --- a/src/components/AdvancedToolsPanel.tsx +++ b/src/components/AdvancedToolsPanel.tsx @@ -11,6 +11,7 @@ import { DatabaseZap, Euro, Bitcoin, + ChartCandlestick, Bird, ArrowLeftRight, BookOpenText, @@ -89,6 +90,7 @@ const getToolGroupCategory = (toolType: ToolType): ToolGroupCategory => { search: "integrations", api_fiat_exchange: "integrations", api_crypto_exchange: "integrations", + api_stock_quote: "integrations", api_twitter: "integrations", credit_transfer: "integrations", deprecated: "integrations", @@ -182,6 +184,7 @@ const AdvancedToolsPanel: React.FC = ({ search: "integrations", api_fiat_exchange: "integrations", api_crypto_exchange: "integrations", + api_stock_quote: "integrations", api_twitter: "integrations", credit_transfer: "integrations", } as Record) @@ -209,6 +212,7 @@ const AdvancedToolsPanel: React.FC = ({ embedding: DatabaseZap, api_fiat_exchange: Euro, api_crypto_exchange: Bitcoin, + api_stock_quote: ChartCandlestick, api_twitter: Bird, credit_transfer: ArrowLeftRight, }; @@ -468,6 +472,7 @@ const AdvancedToolsPanel: React.FC = ({ onProviderNavigate={onProviderNavigate} hasCredits={hasCredits} labelClassName="text-base" + showLabel={!isSingleOption} hideCostEstimateButton={isSingleOption} /> ) : ( diff --git a/src/components/ProviderIcon.tsx b/src/components/ProviderIcon.tsx index f1d48b71..4ee3b864 100644 --- a/src/components/ProviderIcon.tsx +++ b/src/components/ProviderIcon.tsx @@ -5,6 +5,7 @@ import GoogleAILogo from "@/assets/svg/googleai-white.svg"; import PerplexityLogo from "@/assets/svg/perplexity-white.svg"; import RapidAPILogo from "@/assets/svg/rapidapi-white.svg"; import CoinMarketCapLogo from "@/assets/svg/coinmarketcap-white.svg"; +import TwelveDataLogo from "@/assets/svg/twelve-data-white.svg"; import ReplicateLogo from "@/assets/svg/replicate-white.svg"; import XLogo from "@/assets/svg/x-logo-white.svg"; import XAILogo from "@/assets/svg/x-ai-logo-white.svg"; @@ -31,6 +32,7 @@ const ProviderIcon: React.FC = ({ perplexity: PerplexityLogo, "rapid-api": RapidAPILogo, "coinmarketcap-api": CoinMarketCapLogo, + "twelve-data": TwelveDataLogo, replicate: ReplicateLogo, x: XLogo, x_ai: XAILogo, diff --git a/src/components/SectionedSelector.tsx b/src/components/SectionedSelector.tsx index 20ed2ca7..b5263660 100644 --- a/src/components/SectionedSelector.tsx +++ b/src/components/SectionedSelector.tsx @@ -51,6 +51,7 @@ interface SectionedSelectorProps { hasCredits?: boolean; className?: string; labelClassName?: string; + showLabel?: boolean; triggerClassName?: string; contentClassName?: string; hideCostEstimateButton?: boolean; @@ -69,6 +70,7 @@ const SectionedSelector: React.FC = ({ hasCredits = false, className = "", labelClassName = "", + showLabel = true, triggerClassName = "", contentClassName = "", hideCostEstimateButton = false, @@ -90,32 +92,36 @@ const SectionedSelector: React.FC = ({ return (
-
- - {onUndo !== undefined && ( - - - - - {t("restore")} - - )} -
+ {onUndo !== undefined && ( + + + + + {t("restore")} + + )} +
+ )}