diff --git a/.agents/skills/add-block/SKILL.md b/.agents/skills/add-block/SKILL.md index cf4f36e6b7f..d65cc549ee0 100644 --- a/.agents/skills/add-block/SKILL.md +++ b/.agents/skills/add-block/SKILL.md @@ -627,19 +627,78 @@ export const ServiceV2Block: BlockConfig = { } ``` +## Block Metadata (BlockMeta) + +Every integration block **must** export a `{Service}BlockMeta` object at the bottom of the block file. This metadata drives the integration catalog, tag filters, and workflow template suggestions shown to users. + +### Structure + +```typescript +import type { BlockConfig, BlockMeta } from '@/blocks/types' + +// ... block definition above ... + +export const {Service}BlockMeta = { + tags: ['messaging', 'automation'], // Same tags as the block's tags field + templates: [ // Optional but strongly encouraged + { + icon: {Service}Icon, + title: '{Service} use-case title', + prompt: 'Build a workflow that ...', + modules: ['agent', 'workflows'], // Modules the template uses + category: 'productivity', // Template category + tags: ['automation'], // Template-level tags + alsoIntegrations: ['slack'], // Other blocks referenced in the prompt (optional) + }, + ], +} as const satisfies BlockMeta +``` + +### Rules + +- **Import `BlockMeta`** from `@/blocks/types` alongside `BlockConfig` +- **`tags`** must match the `tags` array on the block config exactly +- **Templates are optional** but should be added for any integration that has a recognizable use case — aim for 2–4 templates per block +- **Template `prompt`** should start with "Build a workflow that..." or "Create a workflow that..." and be concrete enough to generate a real workflow in Mothership +- **Template `modules`** lists the Sim modules the template relies on: `'knowledge-base' | 'tables' | 'files' | 'workflows' | 'scheduled' | 'agent'` +- **Template `category`** is one of: `'popular' | 'sales' | 'support' | 'engineering' | 'marketing' | 'productivity' | 'operations'` +- **`alsoIntegrations`** names other block types (e.g. `'slack'`, `'linear'`) referenced in the template prompt — helps the catalog surface this template when those blocks are selected +- Place the export **after** the main `{Service}Block` export, at the very bottom of the file + +### Register in the blocksMeta object + +After adding `{Service}BlockMeta` to the block file, register it in `apps/sim/blocks/registry.ts`: + +```typescript +// Add import (alongside the block import, alphabetically) +import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service' + +// Add to blocksMeta object (alphabetically) +export const blocksMeta = { + // ... existing entries ... + service: ServiceBlockMeta, +} +``` + ## Registering Blocks After creating the block, remind the user to: -1. Import in `apps/sim/blocks/registry.ts` +1. Import `{Service}Block` and `{Service}BlockMeta` in `apps/sim/blocks/registry.ts` 2. Add to the `registry` object (alphabetically): +3. Add to the `blocksMeta` object (alphabetically): ```typescript -import { ServiceBlock } from '@/blocks/blocks/service' +import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service' export const registry: Record = { // ... existing blocks ... service: ServiceBlock, } + +export const blocksMeta = { + // ... existing entries ... + service: ServiceBlockMeta, +} ``` ## Complete Example @@ -827,7 +886,10 @@ All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MU - [ ] Tools.access lists all tool IDs (snake_case) - [ ] Tools.config.tool returns correct tool ID (snake_case) - [ ] Outputs match tool outputs -- [ ] Block registered in registry.ts +- [ ] Block registered in `registry.ts` blocks object (alphabetically) +- [ ] `{Service}BlockMeta` exported at bottom of block file with `tags` and `templates` +- [ ] `BlockMeta` imported from `@/blocks/types` alongside `BlockConfig` +- [ ] Block meta registered in `registry.ts` blocksMeta object (alphabetically) - [ ] If icon missing: asked user to provide SVG - [ ] If triggers exist: `triggers` config set, trigger subBlocks spread - [ ] Optional/rarely-used fields set to `mode: 'advanced'` diff --git a/.agents/skills/add-enrichment/SKILL.md b/.agents/skills/add-enrichment/SKILL.md new file mode 100644 index 00000000000..f963ce14517 --- /dev/null +++ b/.agents/skills/add-enrichment/SKILL.md @@ -0,0 +1,142 @@ +--- +name: add-enrichment +description: Add a code-defined table enrichment (registry entry) under `apps/sim/enrichments/` backed by an ordered provider cascade, ensuring every provider tool it calls has hosted-key support. Use when adding a per-row table enrichment that fills cells via existing Sim tools. +--- + +# Adding a Table Enrichment + +Enrichments are code-defined entries in `apps/sim/enrichments/` that run **directly per table row** (no workflow). Each enrichment declares inputs, outputs, and an ordered list of **providers**; the cascade runner tries providers in order and the first non-empty result fills the cell. Each provider calls one existing Sim tool via `executeTool`, which injects the workspace's BYOK key or a **hosted key** and bills usage automatically. + +Because enrichments run on Sim's hosted keys by default, **every provider tool you reference must have hosted-key support** — otherwise it can only run when the workspace brings its own key. This command makes that check a required step. + +## Overview + +| Step | What | Where | +|------|------|-------| +| 1 | Pick the data-source tool(s) for each output | `tools/{service}/` + `tools/registry.ts` | +| 2 | **Verify each tool has `hosting`; if not, run `/add-hosted-key`** | `tools/{service}/{action}.ts` | +| 3 | Write the enrichment definition | `enrichments/{name}/{name}.ts` + `index.ts` | +| 4 | Register it | `enrichments/registry.ts` | +| 5 | Verify | tsc / biome / manual run | + +## Architecture (what you're plugging into) + +- **`enrichments/types.ts`** — `EnrichmentConfig { id, name, description, icon, inputs, outputs, providers }` and `EnrichmentProvider { id, label, toolId, buildParams, mapOutput }`. Providers are **plain data** (no `@/tools` import) so the catalog stays client-safe. +- **`enrichments/providers.ts`** — `toolProvider(...)` (typed passthrough) plus shared input helpers: `str(v)`, `normalizeDomain(v)`, `firstNonEmpty(arr)`, `splitName(fullName)`. +- **`enrichments/run.ts`** — the server-only cascade runner. Calls `executeTool(provider.toolId, { ...params, _context: { workspaceId } })`, accumulates hosted-key cost, returns the first non-empty mapped result. **You do not edit this** — it works for any registry entry. +- **`enrichments/registry.ts`** — `ENRICHMENT_REGISTRY` / `ALL_ENRICHMENTS` / `getEnrichment`. Register new entries here. + +Outputs automatically become table columns; billing, the catalog/sidebar UI, the column meta-header icon, and per-row execution all work with no extra wiring. + +## Step 1: Pick the data-source tool(s) + +For each output the enrichment produces, decide which existing tool provides it. Look up the service's API and the tool in `apps/sim/tools/{service}/` (e.g. `hunter_email_finder`, `pdl_person_enrich`, `pdl_company_enrich`). Confirm: + +- The tool id is registered in `apps/sim/tools/registry.ts`. +- Its `params` accept what you can derive from table columns (read the tool's `params`). +- Its `outputs` / `transformResponse` actually expose the field you need (read the real output shape — don't assume). + +Order providers **cheapest / most-likely-to-hit first**; the cascade stops at the first non-empty result. Apollo / LinkedIn are not hosted-safe (ToS) — don't use them. + +## Step 2: Verify hosted-key support — chain to `/add-hosted-key` if missing + +**This is the required gate.** For every tool a provider calls, open `apps/sim/tools/{service}/{action}.ts` and check for a `hosting` block: + +```typescript +hosting: { + envKeyPrefix: 'SERVICE_API_KEY', + apiKeyParam: 'apiKey', + byokProviderId: 'service', + pricing: { /* ... */ }, + rateLimit: { /* ... */ }, +} +``` + +- **If `hosting` is present** — good. Note the `envKeyPrefix`; the deployment needs `{PREFIX}_COUNT` + `{PREFIX}_1..N` env vars set for the hosted key to actually resolve at runtime (ops concern, not code). If those env vars aren't set in the target environment, the provider will only run with a workspace BYOK key. +- **If `hosting` is absent** — the tool can't use a Sim-provided key, so the enrichment would silently produce blank cells on hosted Sim. **Stop and run `/add-hosted-key `** to add hosted-key support to that tool first, then come back. Do this for every provider tool that lacks it. + +Why it matters: the cascade runner only bills (and only reads `output.cost.total`) when `executeTool` injected a hosted key, which requires the tool's `hosting` config. No `hosting` → no hosted key → the enrichment depends entirely on per-workspace BYOK. + +## Step 3: Write the enrichment definition + +Create `apps/sim/enrichments/{name}/{name}.ts` and a barrel `index.ts`. Mirror the existing entries (`work-email`, `phone-number`, `company-domain`, `company-info`). + +```typescript +import { SomeIcon } from 'lucide-react' +import { filterUndefined } from '@sim/utils/object' +import { normalizeDomain, splitName, str, toolProvider } from '@/enrichments/providers' +import type { EnrichmentConfig } from '@/enrichments/types' + +export const myEnrichment: EnrichmentConfig = { + id: 'my-enrichment', + name: 'My Enrichment', + description: 'One concise sentence describing what it finds.', + icon: SomeIcon, + inputs: [ + // Person enrichments take a single canonical `fullName` (Clay-style); + // split it with splitName() for tools that need first/last. + { id: 'fullName', name: 'Full name', type: 'string', required: true }, + { id: 'companyDomain', name: 'Company domain', type: 'string' }, + ], + outputs: [{ id: 'value', name: 'value', type: 'string' }], + providers: [ + toolProvider({ + id: 'provider-a', + label: 'Provider A', + toolId: 'service_action', // must have `hosting` (Step 2) + buildParams: (inputs) => { + // Return null when there aren't enough inputs → cascade skips this provider. + const name = splitName(inputs.fullName) + const domain = normalizeDomain(inputs.companyDomain) + if (!name || !domain) return null + return { domain, first_name: name.firstName, last_name: name.lastName } + }, + mapOutput: (output) => { + // Return { [outputId]: value } on a hit, or null to fall through. + const value = str(output.value) + return value ? { value } : null + }, + }), + // ...additional fallback providers, in priority order. + ], +} +``` + +```typescript +// apps/sim/enrichments/{name}/index.ts +export { myEnrichment } from './my-enrichment' +``` + +Rules: +- Keep the file **client-safe**: import only `lucide-react`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call. +- `buildParams` returns `null` when inputs are insufficient (provider skipped). `mapOutput` returns `null`/empty for a miss (falls through). Use `filterUndefined` when assembling optional tool params; coerce numbers explicitly (don't pass `''` to number outputs). +- Output `id`s are the keys `mapOutput` returns; output `name`s are the default column names (the user can rename them in the config). + +## Step 4: Register it + +In `apps/sim/enrichments/registry.ts`, import and add the entry (catalog order is registration order): + +```typescript +import { myEnrichment } from '@/enrichments/my-enrichment' + +export const ENRICHMENT_REGISTRY: EnrichmentRegistry = { + // ...existing + [myEnrichment.id]: myEnrichment, +} +``` + +## Step 5: Verify + +1. `bunx tsc --noEmit` (from `apps/sim`, `NODE_OPTIONS=--max-old-space-size=8192`) and `bunx biome check` on the changed files. +2. In a table → **+ New column → Enrichments** → pick the new enrichment, map its inputs to columns, name the output column(s), Save. Confirm it appears in the catalog with its icon/description. +3. With hosted keys (or a workspace BYOK key) configured for each provider's service, run a row and confirm the cell fills; the dev-server log shows `Enrichment hit { provider }`. A row whose providers all miss completes blank; a row where every provider errored shows an error cell. + +## Checklist + +- [ ] Each output mapped to a real tool field (verified against the tool's `params`/`outputs`) +- [ ] **Every provider tool has a `hosting` block — ran `/add-hosted-key` for any that didn't** +- [ ] Providers ordered cheapest / most-likely-first; Apollo/LinkedIn not used +- [ ] Enrichment file is client-safe (no `@/tools` import); uses `toolProvider` + shared helpers +- [ ] `buildParams` returns `null` on insufficient inputs; `mapOutput` returns `null` on a miss +- [ ] Registered in `enrichments/registry.ts` +- [ ] tsc + biome clean; created and ran the column end-to-end diff --git a/.agents/skills/add-enrichment/agents/openai.yaml b/.agents/skills/add-enrichment/agents/openai.yaml new file mode 100644 index 00000000000..f19413c0a44 --- /dev/null +++ b/.agents/skills/add-enrichment/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Add Enrichment" + short_description: "Build a table enrichment cascade" + brand_color: "#16A34A" + default_prompt: "Use $add-enrichment to add a code-defined Sim table enrichment backed by a provider cascade." diff --git a/.agents/skills/add-hosted-key/SKILL.md b/.agents/skills/add-hosted-key/SKILL.md new file mode 100644 index 00000000000..2cb257c2060 --- /dev/null +++ b/.agents/skills/add-hosted-key/SKILL.md @@ -0,0 +1,296 @@ +--- +name: add-hosted-key +description: Add hosted API key support to a tool so Sim provides the key (metered and billed to the workspace) when a user has not brought their own. Use when adding a `hosting` config to a tool under `apps/sim/tools/{service}/`. +--- + +# Adding Hosted Key Support to a Tool + +When a tool has hosted key support, Sim provides its own API key if the user hasn't configured one (via BYOK or env var). Usage is metered and billed to the workspace. + +## Overview + +| Step | What | Where | +|------|------|-------| +| 1 | Register BYOK provider ID | `tools/types.ts`, `app/api/workspaces/[id]/byok-keys/route.ts` | +| 2 | Research the API's pricing and rate limits | API docs / pricing page (before writing any code) | +| 3 | Add `hosting` config to the tool | `tools/{service}/{action}.ts` | +| 4 | Hide API key field when hosted | `blocks/blocks/{service}.ts` | +| 5 | Add to BYOK settings UI | BYOK settings component (`byok.tsx`) | +| 6 | Summarize pricing and throttling comparison | Output to user (after all code changes) | + +## Step 1: Register the BYOK Provider ID + +Add the new provider to the `BYOKProviderId` union in `tools/types.ts`: + +```typescript +export type BYOKProviderId = + | 'openai' + | 'anthropic' + // ...existing providers + | 'your_service' +``` + +Then add it to `VALID_PROVIDERS` in `app/api/workspaces/[id]/byok-keys/route.ts`: + +```typescript +const VALID_PROVIDERS = ['openai', 'anthropic', 'google', 'mistral', 'your_service'] as const +``` + +## Step 2: Research the API's Pricing Model and Rate Limits + +**Before writing any `getCost` or `rateLimit` code**, look up the service's official documentation for both pricing and rate limits. You need to understand: + +### Pricing + +1. **How the API charges** — per request, per credit, per token, per step, per minute, etc. +2. **Whether the API reports cost in its response** — look for fields like `creditsUsed`, `costDollars`, `tokensUsed`, or similar in the response body or headers +3. **Whether cost varies by endpoint/options** — some APIs charge more for certain features (e.g., Firecrawl charges 1 credit/page base but +4 for JSON format, +4 for enhanced mode) +4. **The dollar-per-unit rate** — what each credit/token/unit costs in dollars on our plan + +### Rate Limits + +1. **What rate limits the API enforces** — requests per minute/second, tokens per minute, concurrent requests, etc. +2. **Whether limits vary by plan tier** — free vs paid vs enterprise often have different ceilings +3. **Whether limits are per-key or per-account** — determines whether adding more hosted keys actually increases total throughput +4. **What the API returns when rate limited** — HTTP 429, `Retry-After` header, error body format, etc. +5. **Whether there are multiple dimensions** — some APIs limit both requests/min AND tokens/min independently + +Search the API's docs/pricing page (use WebSearch/WebFetch). Capture the pricing model as a comment in `getCost` so future maintainers know the source of truth. + +### Setting Our Rate Limits + +Our rate limiter (`lib/core/rate-limiter/hosted-key/`) uses a token-bucket algorithm applied **per billing actor** (workspace). It supports two modes: + +- **`per_request`** — simple; just `requestsPerMinute`. Good when the API charges flat per-request or cost doesn't vary much. +- **`custom`** — `requestsPerMinute` plus additional `dimensions` (e.g., `tokens`, `search_units`). Each dimension has its own `limitPerMinute` and an `extractUsage` function that reads actual usage from the response. Use when the API charges on a variable metric (tokens, credits) and you want to cap that metric too. + +When choosing values for `requestsPerMinute` and any dimension limits: + +- **Stay well below the API's per-key limit** — our keys are shared across all workspaces. If the API allows 60 RPM per key and we have 3 keys, the global ceiling is ~180 RPM. Set the per-workspace limit low enough (e.g., 20-60 RPM) that many workspaces can coexist without collectively hitting the API's ceiling. +- **Account for key pooling** — our round-robin distributes requests across `N` hosted keys, so the effective API-side rate per key is `(total requests) / N`. But per-workspace limits are enforced *before* key selection, so they apply regardless of key count. +- **Prefer conservative defaults** — it's easy to raise limits later but hard to claw back after users depend on high throughput. + +## Step 3: Add `hosting` Config to the Tool + +Add a `hosting` object to the tool's `ToolConfig`. This tells the execution layer how to acquire hosted keys, calculate cost, and rate-limit. + +```typescript +hosting: { + envKeyPrefix: 'YOUR_SERVICE_API_KEY', + apiKeyParam: 'apiKey', + byokProviderId: 'your_service', + pricing: { + type: 'custom', + getCost: (_params, output) => { + if (output.creditsUsed == null) { + throw new Error('Response missing creditsUsed field') + } + const creditsUsed = output.creditsUsed as number + const cost = creditsUsed * 0.001 // dollars per credit + return { cost, metadata: { creditsUsed } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 100, + }, +}, +``` + +### Hosted Key Env Var Convention + +Keys use a numbered naming pattern driven by a count env var: + +``` +YOUR_SERVICE_API_KEY_COUNT=3 +YOUR_SERVICE_API_KEY_1=sk-... +YOUR_SERVICE_API_KEY_2=sk-... +YOUR_SERVICE_API_KEY_3=sk-... +``` + +The `envKeyPrefix` value (`YOUR_SERVICE_API_KEY`) determines which env vars are read at runtime. Adding more keys only requires bumping the count and adding the new env var. + +### Pricing: Prefer API-Reported Cost + +Always prefer using cost data returned by the API (e.g., `creditsUsed`, `costDollars`). This is the most accurate because it accounts for variable pricing tiers, feature modifiers, and plan-level discounts. + +**When the API reports cost** — use it directly and throw if missing: + +```typescript +pricing: { + type: 'custom', + getCost: (params, output) => { + if (output.creditsUsed == null) { + throw new Error('Response missing creditsUsed field') + } + // $0.001 per credit — from https://example.com/pricing + const cost = (output.creditsUsed as number) * 0.001 + return { cost, metadata: { creditsUsed: output.creditsUsed } } + }, +}, +``` + +**When the API does NOT report cost** — compute it from params/output based on the pricing docs, but still validate the data you depend on: + +```typescript +pricing: { + type: 'custom', + getCost: (params, output) => { + if (!Array.isArray(output.searchResults)) { + throw new Error('Response missing searchResults, cannot determine cost') + } + // Serper: 1 credit for <=10 results, 2 credits for >10 — from https://serper.dev/pricing + const credits = Number(params.num) > 10 ? 2 : 1 + return { cost: credits * 0.001, metadata: { credits } } + }, +}, +``` + +**`getCost` must always throw** if it cannot determine cost. Never silently fall back to a default — this would hide billing inaccuracies. + +### Capturing Cost Data from the API + +If the API returns cost info, capture it in `transformResponse` so `getCost` can read it from the output: + +```typescript +transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + results: data.results, + creditsUsed: data.creditsUsed, // pass through for getCost + }, + } +}, +``` + +For async/polling tools, capture it in `postProcess` when the job completes: + +```typescript +if (jobData.status === 'completed') { + result.output = { + data: jobData.data, + creditsUsed: jobData.creditsUsed, + } +} +``` + +## Step 4: Hide the API Key Field When Hosted + +In the block config (`blocks/blocks/{service}.ts`), add `hideWhenHosted: true` to the API key subblock. This hides the field on hosted Sim since the platform provides the key: + +```typescript +{ + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your API key', + password: true, + required: true, + hideWhenHosted: true, +}, +``` + +The visibility is controlled by `isSubBlockHidden()` in `lib/workflows/subblocks/visibility.ts`, which checks both the `isHosted` feature flag (`hideWhenHosted`) and optional env var conditions (`hideWhenEnvSet`). + +### Excluding Specific Operations from Hosted Key Support + +When a block has multiple operations but some operations should **not** use a hosted key (e.g., the underlying API is deprecated, unsupported, or too expensive), use the **duplicate apiKey subblock** pattern. This is the same pattern Exa uses for its `research` operation: + +1. **Remove the `hosting` config** from the tool definition for that operation — it must not have a `hosting` object at all. +2. **Duplicate the `apiKey` subblock** in the block config with opposing conditions: + +```typescript +// API Key — hidden when hosted for operations with hosted key support +{ + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your API key', + password: true, + required: true, + hideWhenHosted: true, + condition: { field: 'operation', value: 'unsupported_op', not: true }, +}, +// API Key — always visible for unsupported_op (no hosted key support) +{ + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your API key', + password: true, + required: true, + condition: { field: 'operation', value: 'unsupported_op' }, +}, +``` + +Both subblocks share the same `id: 'apiKey'`, so the same value flows to the tool. The conditions ensure only one is visible at a time. The first has `hideWhenHosted: true` and shows for all hosted operations; the second has no `hideWhenHosted` and shows only for the excluded operation — meaning users must always provide their own key for that operation. + +To exclude multiple operations, use an array: `{ field: 'operation', value: ['op_a', 'op_b'] }`. + +**Reference implementations:** +- **Exa** (`blocks/blocks/exa.ts`): `research` operation excluded from hosting — lines 309-329 +- **Google Maps** (`blocks/blocks/google_maps.ts`): `speed_limits` operation excluded from hosting (deprecated Roads API) + +## Step 5: Add to the BYOK Settings UI + +Add an entry to the `PROVIDERS` array in the BYOK settings component so users can bring their own key. You need the service icon from `components/icons.tsx`: + +```typescript +{ + id: 'your_service', + name: 'Your Service', + icon: YourServiceIcon, + description: 'What this service does', + placeholder: 'Enter your API key', +}, +``` + +## Step 6: Summarize Pricing and Throttling Comparison + +After all code changes are complete, output a detailed summary to the user covering: + +### What to include + +1. **API's pricing model** — how the service charges (per token, per credit, per request, etc.), the specific rates found in docs, and whether the API reports cost in responses. +2. **Our `getCost` approach** — how we calculate cost, what fields we depend on, and any assumptions or estimates (especially when the API doesn't report exact dollar cost). +3. **API's rate limits** — the documented limits (RPM, TPM, concurrent, etc.), which plan tier they apply to, and whether they're per-key or per-account. +4. **Our `rateLimit` config** — what we set for `requestsPerMinute` (and dimensions if custom mode), why we chose those values, and how they compare to the API's limits. +5. **Key pooling impact** — how many hosted keys we expect, and how round-robin distribution affects the effective per-key rate at the API. +6. **Gaps or risks** — anything the API charges for that we don't meter, rate limit dimensions we chose not to enforce, or pricing that may be inaccurate due to variable model/tier costs. + +### Format + +Present this as a structured summary with clear headings. Example: + +``` +### Pricing +- **API charges**: $X per 1M tokens (input), $Y per 1M tokens (output) — varies by model +- **Response reports cost?**: No — only token counts in `usage` field +- **Our getCost**: Estimates cost at $Z per 1M total tokens based on median model pricing +- **Risk**: Actual cost varies by model; our estimate may over/undercharge for cheap/expensive models + +### Throttling +- **API limits**: 300 RPM per key (paid tier), 60 RPM (free tier) +- **Per-key or per-account**: Per key — more keys = more throughput +- **Our config**: 60 RPM per workspace (per_request mode) +- **With N keys**: Effective per-key rate is (total RPM across workspaces) / N +- **Headroom**: Comfortable — even 10 active workspaces at full rate = 600 RPM / 3 keys = 200 RPM per key, under the 300 RPM API limit +``` + +This summary helps reviewers verify that the pricing and rate limiting are well-calibrated and surfaces any risks that need monitoring. + +## Checklist + +- [ ] Provider added to `BYOKProviderId` in `tools/types.ts` +- [ ] Provider added to `VALID_PROVIDERS` in the BYOK keys API route +- [ ] API pricing docs researched — understand per-unit cost and whether the API reports cost in responses +- [ ] API rate limits researched — understand RPM/TPM limits, per-key vs per-account, and plan tiers +- [ ] `hosting` config added to the tool with `envKeyPrefix`, `apiKeyParam`, `byokProviderId`, `pricing`, and `rateLimit` +- [ ] `getCost` throws if required cost data is missing from the response +- [ ] Cost data captured in `transformResponse` or `postProcess` if API provides it +- [ ] `hideWhenHosted: true` added to the API key subblock in the block config +- [ ] Provider entry added to the BYOK settings UI with icon and description +- [ ] Env vars documented: `{PREFIX}_COUNT` and `{PREFIX}_1..N` +- [ ] Pricing and throttling summary provided to reviewer diff --git a/.agents/skills/add-hosted-key/agents/openai.yaml b/.agents/skills/add-hosted-key/agents/openai.yaml new file mode 100644 index 00000000000..97dfcf458cf --- /dev/null +++ b/.agents/skills/add-hosted-key/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Add Hosted Key" + short_description: "Add hosted API key to a tool" + brand_color: "#CA8A04" + default_prompt: "Use $add-hosted-key to add hosted API key support (metered and billed) to a Sim tool." diff --git a/.agents/skills/add-integration/SKILL.md b/.agents/skills/add-integration/SKILL.md index 25983f357fd..6c9b3bed627 100644 --- a/.agents/skills/add-integration/SKILL.md +++ b/.agents/skills/add-integration/SKILL.md @@ -128,7 +128,7 @@ export const {service}{Action}Tool: ToolConfig = { ### Block Structure ```typescript import { {Service}Icon } from '@/components/icons' -import type { BlockConfig } from '@/blocks/types' +import type { BlockConfig, BlockMeta } from '@/blocks/types' import { AuthMode } from '@/blocks/types' import { getScopesForService } from '@/lib/oauth/utils' @@ -177,8 +177,32 @@ export const {Service}Block: BlockConfig = { outputs: { /* ... */ }, } + +export const {Service}BlockMeta = { + tags: ['tag1', 'tag2'], // IntegrationTag values matching the service's capabilities + templates: [ + { + icon: {Service}Icon, + title: '{Service} use-case title', + prompt: 'Build a workflow that ...', + modules: ['agent', 'workflows'], + category: 'productivity', + tags: ['automation'], + alsoIntegrations: ['slack'], // Optional: other blocks referenced in the prompt + }, + ], +} as const satisfies BlockMeta ``` +### BlockMeta rules + +- **Tags**: Use `IntegrationTag` values from `@/blocks/types`. Do NOT add a `tags` field to the `BlockConfig` object — tags belong only in `BlockMeta`. +- **`integrationType`**: Must be a valid `IntegrationType` enum value (AI, Analytics, Commerce, Communication, Databases, DevOps, Documents, Email, HR, Marketing, Observability, Productivity, Sales, Search, Security, Support). Never invent a value that doesn't exist in the enum. +- **Templates**: Aim for 2–4 templates per integration. Prompts should be concrete enough to generate a real workflow in Mothership. Start with "Build a workflow that..." or "Create a workflow that...". +- **`alsoIntegrations`**: List other block type IDs referenced in the template prompt (e.g. `'slack'`, `'linear'`). +- Place `{Service}BlockMeta` at the very bottom of the file, after the main block export. +- Register it in both the import and the `blocksMeta` object in `registry.ts`. + ### Key SubBlock Patterns **Condition-based visibility:** @@ -359,14 +383,20 @@ export const tools: Record = { ### Block Registry (`apps/sim/blocks/registry.ts`) ```typescript -// Add import (alphabetically) -import { {Service}Block } from '@/blocks/blocks/{service}' +// Add import (alphabetically) — include BlockMeta +import { {Service}Block, {Service}BlockMeta } from '@/blocks/blocks/{service}' -// Add to registry (alphabetically) +// Add to blocks registry (alphabetically) export const registry: Record = { // ... existing blocks ... {service}: {Service}Block, } + +// Add to blocksMeta registry (alphabetically) +export const blocksMeta = { + // ... existing entries ... + {service}: {Service}BlockMeta, +} ``` ### Trigger Registry (`apps/sim/triggers/registry.ts`) - If triggers exist @@ -433,7 +463,12 @@ If creating V2 versions (API-aligned outputs): - [ ] Configured tools.access with all tool IDs - [ ] Configured tools.config.tool selector - [ ] Defined outputs matching tool outputs -- [ ] Registered block in `blocks/registry.ts` +- [ ] `integrationType` uses a valid `IntegrationType` enum value (no invented values) +- [ ] No `tags` field on the `BlockConfig` object (tags live only in `BlockMeta`) +- [ ] `{Service}BlockMeta` exported at bottom of file with `tags` and `templates` +- [ ] `BlockMeta` type imported from `@/blocks/types` alongside `BlockConfig` +- [ ] Block registered in `blocks/registry.ts` blocks object (alphabetically) +- [ ] Block meta registered in `blocks/registry.ts` blocksMeta object (alphabetically) - [ ] If triggers: set `triggers.enabled` and `triggers.available` - [ ] If triggers: spread trigger subBlocks with `getTrigger()` diff --git a/.agents/skills/add-model/SKILL.md b/.agents/skills/add-model/SKILL.md new file mode 100644 index 00000000000..f97c966e1f3 --- /dev/null +++ b/.agents/skills/add-model/SKILL.md @@ -0,0 +1,209 @@ +--- +name: add-model +description: Add a new LLM model to `apps/sim/providers/models.ts` with every pricing and capability value verified against the provider's live API docs (no hallucination), plus the repo-side touchpoints that are not data-driven — hosted-key billing, tests, and provider-code handling. Use when adding a model to an existing provider in `apps/sim/providers/models.ts`. +--- + +# Add Model Skill + +You add a new model entry to `apps/sim/providers/models.ts`. **Every numeric and capability claim MUST be derived from a live web fetch of the provider's official docs in this session.** Marketing emails, training data, and your prior knowledge are not sources of truth — they routinely hallucinate pricing, context windows, and capability lists. + +## Hard rules (do not skip) + +1. **Live-fetch or refuse.** Before writing the entry, you must successfully WebFetch the provider's official models/pricing page in this session. If you cannot reach an authoritative source for any field, **mark the field as UNVERIFIED in your report and ask the user before guessing**. Never fill in pricing or capabilities from memory. +2. **Two-source rule for pricing.** Cross-check input/output/cached pricing against at least one secondary source (OpenRouter, Artificial Analysis, CloudPrice, mem0, intuitionlabs). If sources disagree, the provider's own docs win — but flag the disagreement. +3. **Read the code before setting capability flags.** Capability flags are dead unless the provider's implementation under `apps/sim/providers/{provider}/` actually consumes them (see Consumption Matrix below). Setting a flag the provider ignores is a silent bug. +4. **Cite every fact.** Your final report must list the URL each value came from. No URL → not verified. + +## Your Task + +1. Identify provider and model id from user args +2. Live-fetch official docs + pricing page + capability/parameter pages + at least one secondary source +3. Apply the Consumption Matrix to know which capability flags are real +4. Read 2-3 sibling entries in `models.ts` and match their pattern exactly +5. Check the repo-side touchpoints that are NOT data-driven (hosted-key billing, tests, provider code) +6. Insert the entry, run `bun run lint`, print the verification report + +## Step 1: Live source-of-truth lookup + +In priority order — fetch all that exist for the provider: + +| Provider | Models index | Pricing | Reasoning/parameter caveats | +|---|---|---|---| +| OpenAI | platform.openai.com/docs/models | openai.com/api/pricing | platform.openai.com/docs/guides/reasoning | +| Anthropic | docs.anthropic.com/en/docs/about-claude/models | anthropic.com/pricing | docs.anthropic.com/en/docs/build-with-claude/extended-thinking | +| Google (Gemini) | ai.google.dev/gemini-api/docs/models | ai.google.dev/pricing | ai.google.dev/gemini-api/docs/thinking | +| xAI | docs.x.ai/developers/models | docs.x.ai/developers/models (per-model detail page) | docs.x.ai/developers/model-capabilities/text/reasoning | +| Mistral | docs.mistral.ai/getting-started/models/models_overview | mistral.ai/pricing | n/a | +| DeepSeek | api-docs.deepseek.com/quick_start/pricing | same | api-docs.deepseek.com/guides/reasoning_model | +| Groq | console.groq.com/docs/models | groq.com/pricing | n/a | +| Cerebras | inference-docs.cerebras.ai/models | cerebras.ai/pricing | n/a | + +Secondary verification (use at least one): `openrouter.ai//`, `artificialanalysis.ai/models/`, `cloudprice.net/models/-`. + +Use a precise WebFetch prompt: *"Extract for {model_id}: exact model id string, context window in tokens, input price per 1M, cached input price per 1M, output price per 1M, max output tokens, supported reasoning effort levels, accepted parameters (temperature, top_p), release date. Do not fill in fields you cannot find."* + +## Step 2: Consumption Matrix (which provider honors which capability) + +| Capability | Honored by | Effect if set elsewhere | +|---|---|---| +| `temperature` | All providers (passed through if set) | Safe but inert on always-reasoning models that reject it | +| `toolUsageControl` | All providers (provider-level, not per-model) | n/a — set on `ProviderDefinition`, not models | +| `reasoningEffort` | `openai/core.ts`, `azure-openai`, `anthropic/core.ts` (mapped to thinking), `gemini/core.ts` | **Dead on xai, deepseek, mistral, groq, cerebras, openrouter, fireworks, bedrock, vertex** unless their core consumes it — re-grep before assuming | +| `verbosity` | `openai/core.ts`, `azure-openai/index.ts` only | Dead elsewhere | +| `thinking` | `anthropic/core.ts`, `gemini/core.ts` | Dead elsewhere | +| `nativeStructuredOutputs` | `anthropic/core.ts`, `fireworks/index.ts`, `openrouter/index.ts` | Dead on openai, xai, google, vertex, bedrock, azure-openai, deepseek, mistral, groq, cerebras | +| `maxOutputTokens` | Read by UI + executor for token estimation | Always meaningful — set if provider documents a cap | +| `computerUse` | `anthropic/core.ts` | Dead elsewhere | +| `deepResearch` | UI flag for routing to deep-research SKUs | Set only on actual deep-research model IDs | +| `memory: false` | Conversation persistence opt-out | Set only when model genuinely cannot maintain history (e.g., deep-research) | + +**Always re-grep before relying on this table** — the codebase moves: + +```bash +rg "reasoningEffort|reasoning_effort" apps/sim/providers// +rg "verbosity" apps/sim/providers// +rg "request\.thinking|thinking:" apps/sim/providers// +rg "supportsNativeStructuredOutputs|nativeStructuredOutputs" apps/sim/providers// +``` + +## Step 3: Match the provider's existing entry pattern + +Open `apps/sim/providers/models.ts`, find `PROVIDER_DEFINITIONS[].models`, read 2-3 sibling entries. Match field order exactly: + +```ts +{ + id: '', + pricing: { + input: , + cachedInput: , // omit if provider doesn't offer caching + output: , + updatedAt: '', + }, + capabilities: { + // only flags the provider actually consumes — see matrix + }, + contextWindow: , + releaseDate: '', + recommended: true, // only if new flagship; ask user before swapping + speedOptimized: true, // only on smallest/fastest tier + deprecated: true, // only on retired models +} +``` + +### Reseller providers (azure-openai, azure-anthropic, vertex, bedrock, openrouter) + +Model id MUST be prefixed: `azure/`, `azure-anthropic/`, `vertex/`, `bedrock/`, `openrouter/`. Pricing usually mirrors the upstream provider but verify on the reseller's own pricing page. + +### Insertion order + +Within a family, newest first (matches existing convention: GPT-5.5 above GPT-5.4 above GPT-5.2). Across families, biggest/flagship at top of list. + +### `recommended` / `speedOptimized` + +- At most one or two `recommended: true` per provider — the current flagship(s). +- If you're adding a new flagship, ask the user before removing `recommended` from the previous flagship. Never silently flip it. +- `speedOptimized: true` only on the smallest/fastest tier (nano, flash-lite, haiku class). + +## Step 4: Repo-side touchpoints beyond the entry + +Adding the `models.ts` entry is most of the job because nearly every consumer is **data-driven** and picks the model up automatically: the ~40 query helpers in `models.ts` / `providers/utils.ts`, the public `/models` catalog (`app/(landing)/models/utils.ts` iterates `PROVIDER_DEFINITIONS`), the agent-block model dropdown, and copilot's `isKnownModelId` / `suggestModelIdsForUnknownModel` validation. The touchpoints below are the exceptions — they are **not** data-driven, so check each one. + +### Hosted = auto-billed, by provider + +`getHostedModels()` in `apps/sim/providers/models.ts` returns **every** model under `openai`, `anthropic`, and `google`: + +```ts +export function getHostedModels(): string[] { + return [ + ...getProviderModels('openai'), + ...getProviderModels('anthropic'), + ...getProviderModels('google'), + ] +} +``` + +So a model added to any of those three providers is **automatically served with Sim's rotating hosted key and billed** to the workspace via `shouldBillModelUsage()` (`providers/utils.ts`). Before you insert: + +- **If the model should be BYOK-only / never-billed**, do NOT drop it under `openai`/`anthropic`/`google` as-is — that silently enrolls it in hosted billing. Confirm hosting/billing intent with the user. (Precedent: Ollama Cloud is a deliberately separate `isReseller` provider specifically to stay BYOK-only/never-billed.) +- **If the model should be hosted**, the deployment must actually have a key for it — the provider's `{PREFIX}_COUNT` / `{PREFIX}_1..N` env vars must be set, or hosted runs fail at execution time. +- State the hosted/billing status explicitly in the verification report. + +### Tests with hardcoded model IDs + +`bun run lint` does **not** run tests. A few tests assert specific model IDs and can break or need updating when you touch a hosted or flagship model: + +- `apps/sim/providers/utils.test.ts` — asserts membership of `getHostedModels()` / `shouldBillModelUsage()` +- `apps/sim/providers/index.test.ts` and serializer tests — reference concrete model IDs + +```bash +rg "|getHostedModels|shouldBillModelUsage" apps/sim/providers/*.test.ts +``` + +If anything matches, run the affected provider tests and update assertions as needed. + +### New API behavior is NOT data-driven + +The Consumption Matrix (Step 2) tells you which capability *flags* are honored by existing provider code. But if the new model needs **net-new** request handling that the provider doesn't implement yet — a new beta header (e.g. Anthropic's `anthropic-beta` structured-outputs header in `anthropic/index.ts`), a new thinking/reasoning encoding, a Responses-API quirk — you must edit `apps/sim/providers//core.ts` / `index.ts`. Setting a flag whose behavior isn't implemented is a silent no-op. + +### Wrong family entirely? + +- **Embedding or rerank model** → it does NOT go in the `models[]` array. Use `EMBEDDING_MODEL_PRICING` / `RERANK_MODEL_PRICING` in `models.ts` instead. +- **Brand-new provider** (not just a new model under an existing one) → much larger surface: add the id to `ProviderId` in `providers/types.ts`, a registry entry in `providers/registry.ts`, a provider implementation under `providers//`, an icon in `components/icons.tsx`, and the `PROVIDER_DEFINITIONS` block. That is beyond this skill — tell the user. + +## Step 5: Write, lint + +```bash +bun run lint +``` + +Lint must pass before reporting done. **If lint fails:** read the error, fix the syntax/typing issue in the entry you just wrote (do not delete the entry — it's the work product), re-run lint, and note the fix in a "Lint adjustments" line in the verification report. Never report done with lint failing. + +## Step 6: Verification report (mandatory format) + +End with this exact structure: + +```markdown +### Verification — + +| Field | Value | Source URL | Status | +|---|---|---|---| +| `id` | `grok-4.3` | https://docs.x.ai/... | ✓ verified | +| `contextWindow` | 1,000,000 | https://docs.x.ai/... + https://openrouter.ai/... | ✓ verified (2 sources agree) | +| `input` | $1.25/M | https://docs.x.ai/... | ✓ verified | +| `cachedInput` | $0.20/M | https://cloudprice.net/... | ⚠️ single source | +| `output` | $2.50/M | https://docs.x.ai/... + https://openrouter.ai/... | ✓ verified | +| `capabilities.temperature` | `{ min: 0, max: 1 }` | matches sibling entries | — pattern-match only | +| `capabilities.reasoningEffort` | NOT SET | provider docs say API rejects it for this model | ✓ correctly omitted | +| `releaseDate` | 2026-04-30 | https://docs.x.ai/... announcement | ✓ verified | +| hosted/billing | BYOK-only (xai not in `getHostedModels`) | `providers/models.ts` | — confirmed intent | + +**Disagreements** +- _none_ OR _OpenRouter says X, provider docs say Y — used Y per provider rule_ + +**Unverified fields** +- _none_ OR _: could not find authoritative source — left as based on sibling pattern; please confirm_ +``` + +If any row is ⚠️ single-source or "unverified," **state it plainly to the user and ask whether to proceed**. Do not silently merge. + +## What to do if you cannot find a source + +Omitting a field is **not the same as verifying it**. Any field you cannot confirm from a live fetch must be **both** omitted from the entry **and** listed as ❓ UNVERIFIED in the report's "Unverified fields" section, with the URLs you attempted. Then ask the user to confirm before merging. + +- Pricing missing → do NOT guess. Omit `cachedInput`. Mark ❓ UNVERIFIED. Ask the user for the price or the docs URL. +- Context window missing → do NOT guess. Ask the user; mark ❓ UNVERIFIED. +- Release date missing → omit the field; mark ❓ UNVERIFIED in the report. +- Capability uncertain → omit the flag (safer than setting a dead/wrong one); mark ❓ UNVERIFIED so the user knows you didn't confirm it either way. + +## Anti-patterns this skill exists to prevent + +- ❌ Trusting a marketing email (xAI's grok-4.3 email claimed "3 reasoning efforts" but the API rejects `reasoning_effort` — verified by official docs only) +- ❌ Setting `nativeStructuredOutputs: true` on xai/openai/google (dead — only anthropic/fireworks/openrouter consume it) +- ❌ Setting `thinking` on non-Anthropic/non-Gemini providers +- ❌ Setting `verbosity` on anything other than OpenAI gpt-5.x +- ❌ Copying `pricing.updatedAt` from a sibling instead of using today's date +- ❌ Inventing a `cachedInput` price by dividing input by 4 (varies by provider — find an explicit number) +- ❌ Stamping `recommended: true` on the new model without removing it from the previous flagship +- ❌ Adding a BYOK-only model under `openai`/`anthropic`/`google` (silently enrolls it in hosted billing via `getHostedModels()`) +- ❌ Reporting "done" after only `bun run lint` when you touched a hosted (openai/anthropic/google) or flagship model with assertions in `providers/utils.test.ts` +- ❌ Reporting "done" with any UNVERIFIED row in the table diff --git a/.agents/skills/add-model/agents/openai.yaml b/.agents/skills/add-model/agents/openai.yaml new file mode 100644 index 00000000000..4ba3fc233e8 --- /dev/null +++ b/.agents/skills/add-model/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Add Model" + short_description: "Add an LLM model, specs verified" + brand_color: "#0EA5E9" + default_prompt: "Use $add-model to add a new LLM model to Sim with pricing and capabilities verified against the provider's live docs." diff --git a/.agents/skills/council/SKILL.md b/.agents/skills/council/SKILL.md new file mode 100644 index 00000000000..0df112728be --- /dev/null +++ b/.agents/skills/council/SKILL.md @@ -0,0 +1,13 @@ +--- +name: council +description: Spawn parallel task agents to explore a given area of the codebase from multiple angles, then use their findings to answer the question or build a plan. Use when a task needs broad fan-out exploration across many files before acting. +# No agents/openai.yaml by design: council is a meta/exploration utility (like cleanup, ship, you-might-not-need-*), not a service-integration builder, so it intentionally ships no standalone agent card. +--- + +Based on the given area of interest, please: + +1. Dig around the codebase in terms of that given area of interest, gather general information such as keywords and architecture overview. +2. Spawn off n=10 (unless specified otherwise) task agents to dig deeper into the codebase in terms of that given area of interest, some of them should be out of the box for variance. +3. Once the task agents are done, use the information to do what the user wants. + +If user is in plan mode, use the information to create the plan. diff --git a/.agents/skills/validate-model/SKILL.md b/.agents/skills/validate-model/SKILL.md new file mode 100644 index 00000000000..c05b2e3527b --- /dev/null +++ b/.agents/skills/validate-model/SKILL.md @@ -0,0 +1,170 @@ +--- +name: validate-model +description: Validate a model entry (or every model in a provider) in `apps/sim/providers/models.ts` against the provider's live API docs, reporting pricing and capability drift, dead capability flags, hosting/billing intent, and any field that cannot be verified. Use when auditing or repairing model entries under `apps/sim/providers/models.ts`. +--- + +# Validate Model Skill + +You audit one or more model entries in `apps/sim/providers/models.ts` against the provider's official live API docs. **Hallucinated pricing and capabilities are the #1 failure mode in this file.** Every numeric and capability claim must be re-derived from a live web fetch in this session — not from memory, not from training data, not from the user's marketing email. + +## Hard rules (do not skip) + +1. **Live-fetch or report unverified.** Each field must be backed by a live WebFetch in this session. If you cannot reach an authoritative URL for a field, mark it **UNVERIFIED** in the report — do not silently confirm it from memory. +2. **Cite every fact.** Every value in the report must show the source URL it was checked against. No URL → mark UNVERIFIED. +3. **Two-source rule for pricing.** Cross-check input/output/cached against at least one secondary source (OpenRouter, Artificial Analysis, CloudPrice). If sources disagree, the provider's own docs win — flag the disagreement. +4. **Inspect provider implementation before flagging capability mismatches.** A capability flag in `models.ts` is dead unless the provider's code under `apps/sim/providers/{provider}/` consumes it (see Consumption Matrix below). Setting a flag the provider ignores is a warning, not a critical. +5. **Never auto-fix without printing the diff.** Show the user the proposed diff before applying. Get confirmation. + +## Your Task + +When invoked as `/validate-model [model-id]`: + +1. Read the target entries from `models.ts` +2. Live-fetch the provider's official models, pricing, and capability/reasoning pages + at least one secondary source for pricing +3. Inspect the provider implementation to know which flags are actually consumed +4. Run the checklist below per model +5. Report findings (critical / warning / suggestion / unverified) with every cell linked to its source URL +6. Offer to fix; on confirm, edit `models.ts` in a single pass and re-lint + +If `model-id` is omitted, validate every model in the provider. + +## Step 1: Read entries from `models.ts` + +Capture per model: `id`, full `pricing`, full `capabilities`, `contextWindow`, `releaseDate`, `recommended`, `speedOptimized`, `deprecated`. + +## Step 2: Live-fetch authoritative sources + +Use the canonical provider URL table in the `add-model` skill (`.claude/commands/add-model.md`, or its mirror `.agents/skills/add-model/SKILL.md`), Step 1, as the single source of truth — fetch the models index, pricing, and reasoning/parameter caveats pages listed there for the target provider. If you update one table, update the other in the same change. + +Secondary cross-check (use at least one): OpenRouter, Artificial Analysis, CloudPrice. + +If a fetch fails (404, timeout, paywall), record the URL attempted and mark dependent fields UNVERIFIED. + +## Step 3: Build the consumption map for this provider + +Re-grep before trusting the snapshot below: + +```bash +rg "reasoningEffort|reasoning_effort" apps/sim/providers// +rg "verbosity" apps/sim/providers// +rg "request\.thinking|thinking:" apps/sim/providers// +rg "supportsNativeStructuredOutputs|nativeStructuredOutputs" apps/sim/providers// +``` + +Snapshot (verify before relying): + +| Capability | Consumed by | +|---|---| +| `reasoningEffort` | `openai/core.ts`, `azure-openai`, `anthropic/core.ts` (mapped via thinking), `gemini/core.ts` | +| `verbosity` | `openai/core.ts`, `azure-openai/index.ts` | +| `thinking` | `anthropic/core.ts`, `gemini/core.ts` | +| `nativeStructuredOutputs` | `anthropic/core.ts`, `fireworks/index.ts`, `openrouter/index.ts` | +| `computerUse` | `anthropic/core.ts` | +| `temperature` | All providers (passthrough) | + +A flag set in `models.ts` but not in the consumption list for this provider = **warning: dead flag**. + +## Step 4: Run the checklist + +For each model, evaluate every row. Statuses: ✓ matches docs, ✗ disagrees, ⚠️ single-source, ❓ UNVERIFIED (could not fetch). + +### Identity +- [ ] `id` exactly matches provider's API model identifier (case, dots, dashes, prefix for resellers) +- [ ] `releaseDate` matches launch announcement +- [ ] `deprecated: true` set if provider has announced retirement (or removed from active list) + +### Pricing (per 1M tokens, USD) +- [ ] `pricing.input` matches provider pricing page +- [ ] `pricing.output` matches provider pricing page +- [ ] `pricing.cachedInput` matches provider's documented cached/prompt-cache rate (or is correctly omitted if no caching offered) +- [ ] `pricing.updatedAt` is recent — warn if older than 60 days + +### Context & output limits +- [ ] `contextWindow` matches docs (in tokens) +- [ ] `capabilities.maxOutputTokens` matches documented output cap (or is correctly omitted if "no output limit") + +### Capabilities (each must be DOCUMENTED-AS-SUPPORTED **and** CONSUMED-BY-PROVIDER-CODE) +- [ ] `temperature` — provider accepts it for this model (reasoning-always-on models often reject) +- [ ] `reasoningEffort.values` — list matches docs; **omitted** for always-reasoning models that reject the parameter (e.g., grok-4.3, where xAI docs explicitly state `reasoning_effort` is not supported). Verify per model — some always-reasoning models (e.g., OpenAI's o-series) DO accept `reasoning_effort` and should keep the flag. +- [ ] `verbosity.values` — only on OpenAI gpt-5.x family; values match docs +- [ ] `thinking.levels` + `thinking.default` — only on Anthropic/Gemini; values match docs +- [ ] `nativeStructuredOutputs` — only on anthropic/fireworks/openrouter; provider must document Structured Outputs / JSON-mode for this model +- [ ] `toolUsageControl` — provider supports `tool_choice` semantics +- [ ] `computerUse` — provider implements computer-use loop AND model is a computer-use SKU +- [ ] `deepResearch` — only on actual deep-research SKUs +- [ ] `memory: false` — only when the model genuinely cannot maintain conversation history + +### Flags +- [ ] `recommended: true` — at most one or two per provider; should be current flagship +- [ ] `speedOptimized: true` — only on smallest/fastest tier (nano / flash-lite / haiku class) + +### Hosting / billing +- [ ] If the model is under `openai`/`anthropic`/`google`, it is automatically in `getHostedModels()` → served with Sim's rotating key and billed via `shouldBillModelUsage()`. Confirm that is the intent (a BYOK-only model parked under one of these providers is a billing bug — warning). +- [ ] If the model is hosted, the deployment is expected to have its `{PREFIX}_COUNT` / `{PREFIX}_1..N` env vars set (ops concern; note if it looks unset for a model claiming hosted support). + +## Step 5: Report (mandatory format) + +For each model, emit a table with one row per checklist item. Every row that claims ✓ must have a URL. + +```markdown +### Validation — + +| Field | Repo | Live docs | Source URL | Status | +|---|---|---|---|---| +| `input` | $1.25/M | $1.25/M | https://docs.x.ai/... | ✓ | +| `cachedInput` | $0.50/M | $0.20/M | https://cloudprice.net/... | ✗ stale (price cut not picked up) | +| `reasoningEffort` | low/medium/high | rejected by API | https://docs.x.ai/.../reasoning | ✗ inert — selecting silently no-ops | +| `contextWindow` | 1,000,000 | 1,000,000 | https://docs.x.ai/... + https://openrouter.ai/... | ✓ (2 sources) | +| `releaseDate` | 2026-04-30 | not found in scraped pages | _attempted: docs.x.ai, x.ai/news_ | ❓ UNVERIFIED | + +**Findings** +- 🔴 critical — `cachedInput` is wrong: docs say $0.20/M, repo has $0.50/M +- 🟡 warning — `reasoningEffort` is set but provider rejects it for this model (xAI docs explicitly: "reasoning_effort is not supported by grok-4.3") +- 🔵 suggestion — `pricing.updatedAt` is 90 days old; refresh +- ❓ unverified — `releaseDate` could not be confirmed from any fetched page; ask user + +**Disagreements between sources** +- _none_ OR _OpenRouter says $X, provider docs say $Y — went with provider docs_ +``` + +End each multi-model run with a summary count: `N models checked · X critical · Y warnings · Z suggestions · W unverified`. + +## Step 6: Offer to fix + +After reporting, ask: *"Want me to fix the critical and warning items? I'll print the diff first."* On yes: + +1. Print the proposed diff (do not apply yet) +2. Get user confirmation +3. Edit `models.ts` in a single pass +4. Run `bun run lint` +5. Re-run only the failed rows of the checklist on the new state + +## Severity definitions + +- 🔴 **critical** — wrong number or wrong identifier that misleads users about cost or breaks API calls. Examples: incorrect pricing, wrong model id, wrong context window, capability the API rejects. +- 🟡 **warning** — dead code or internal inconsistency. Examples: capability flag the provider ignores, multiple `recommended: true` per provider, `pricing.updatedAt` >60 days old, missing `deprecated: true` on retired model. +- 🔵 **suggestion** — style/consistency. Examples: field order, missing `speedOptimized` on a clearly smallest-tier model. +- ❓ **unverified** — could not fetch an authoritative source for this field. Surface it; never silently confirm. + +## Common bugs this skill catches + +- Pricing drift after a provider price cut (very common — providers cut quarterly) +- `reasoningEffort` set on always-reasoning models that reject the parameter (grok-4.3, o3-pro pattern) +- `nativeStructuredOutputs` set on providers that don't consume the flag (dead) +- `thinking` set on non-Anthropic/non-Gemini providers +- `verbosity` set on non-gpt-5.x models +- Wrong context window (e.g., 128k claimed vs 200k actual) +- Stale `pricing.updatedAt` +- Multiple `recommended: true` per provider after a flagship swap +- Missing `deprecated: true` on retired models (e.g., the xAI batch retiring May 15, 2026) + +## What "I cannot verify this" looks like + +If, after fetching the documented sources, a field cannot be confirmed: + +- Mark the row ❓ UNVERIFIED with the URL(s) attempted +- Surface it in the **Findings** section with severity ❓ +- Do NOT mark the validation as passed +- Ask the user for a docs URL or guidance before changing anything + +The skill is allowed to say *"I could not verify the cached input price for grok-4.3 from the official xAI docs in this session — I attempted [URLs] without finding the value. Third-party sources [URL1, URL2] both report $0.20/M. Confirm before I update."* That is correct behavior. Hallucinating a number is not. diff --git a/.agents/skills/validate-model/agents/openai.yaml b/.agents/skills/validate-model/agents/openai.yaml new file mode 100644 index 00000000000..fa58d32ca8b --- /dev/null +++ b/.agents/skills/validate-model/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Validate Model" + short_description: "Audit model entries vs live docs" + brand_color: "#0891B2" + default_prompt: "Use $validate-model to audit Sim model entries against the provider's live API docs." diff --git a/.claude/commands/add-block.md b/.claude/commands/add-block.md index e07600c2655..23930702c08 100644 --- a/.claude/commands/add-block.md +++ b/.claude/commands/add-block.md @@ -798,6 +798,33 @@ Use `wandConfig` for fields that are hard to fill out manually, such as timestam All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MUST use `snake_case` (e.g., `x_create_tweet`, `slack_send_message`). Never use camelCase or PascalCase. +## BlockMeta (Required) + +Every block file must export a `{Service}BlockMeta` alongside the block — **minimum 7 templates**. Look at existing examples in `apps/sim/blocks/blocks/` (e.g. `browser_use.ts`, `google_sheets.ts`) for the pattern. + +```typescript +import type { BlockMeta } from '@/blocks/types' + +export const {Service}BlockMeta = { + tags: ['tag1', 'tag2'], // IntegrationTag[] + templates: [ + { + icon: {Service}Icon, + title: '{Service} ', // 2–5 words + prompt: 'Build a workflow that...', // specific use case, 1–3 sentences + modules: ['agent', 'workflows'], // 'agent' | 'workflows' | 'tables' | 'files' | 'scheduled' | 'knowledge-base' + category: 'operations', // 'operations' | 'marketing' | 'sales' | 'engineering' | 'productivity' | 'support' | 'popular' + tags: ['automation'], + alsoIntegrations: ['slack'], // optional — other block IDs referenced in the prompt + featured: true, // optional + }, + // ... at least 6 more + ], +} as const satisfies BlockMeta +``` + +Derive templates from the service's real use cases. Each prompt should name a concrete trigger, transformation, and output — not a generic description of what the service does. + ## Checklist Before Finishing - [ ] `integrationType` is set to the correct `IntegrationType` enum value @@ -816,6 +843,7 @@ All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MU - [ ] If triggers exist: `triggers` config set, trigger subBlocks spread - [ ] Optional/rarely-used fields set to `mode: 'advanced'` - [ ] Timestamps and complex inputs have `wandConfig` enabled +- [ ] Exported `{Service}BlockMeta` with at least 7 templates ## Final Validation (Required) @@ -829,3 +857,4 @@ After creating the block, you MUST validate it against every tool it references: - Type coercions in `tools.config.params` for any params that need conversion (Number(), Boolean(), JSON.parse()) 3. **Verify block outputs** cover the key fields returned by all tools 4. **Verify conditions** — each subBlock should only show for the operations that actually use it +5. **Verify `{Service}BlockMeta` is exported** with at least 7 templates, each having `icon`, `title`, `prompt`, `modules`, `category`, and `tags` diff --git a/.claude/commands/add-connector.md b/.claude/commands/add-connector.md index 22c8c52e1c8..81823675a72 100644 --- a/.claude/commands/add-connector.md +++ b/.claude/commands/add-connector.md @@ -463,6 +463,24 @@ const response = await fetchWithRetry(url, { ... }, VALIDATE_RETRY_OPTIONS) If `ExternalDocument.sourceUrl` is set, the sync engine stores it on the document record. Always construct the full URL (not a relative path). +## Capped or Incomplete Listings — `syncContext.listingCapped` (REQUIRED) + +If `listDocuments` can ever return **less than the full source set** on a non-incremental sync — a `maxItems`/`maxDocuments`-style cap, or a transient per-item error that drops a still-existing document from the listing — it MUST set `syncContext.listingCapped = true` when that happens. + +The sync engine reconciles deletions by comparing the full listing against stored documents: anything not seen is **hard-deleted** (sync-engine.ts, gated on `!syncContext?.listingCapped`). A truncated listing without this flag deletes every real document beyond the cap. This was the single most common bug found when auditing connectors — do not omit it. + +```typescript +if (hitLimit && syncContext) { + syncContext.listingCapped = true +} +``` + +Rules: +- Set it when a user-configured cap truncates the listing while more documents exist +- Set it when a thrown error caused a still-present document to be skipped during listing +- Do NOT set it when the source is genuinely exhausted (deleted documents must still reconcile) +- Do NOT set it for intentional scope filters (e.g. a date cutoff) — out-of-scope documents should be reconciled normally + ## Sync Engine Behavior (Do Not Modify) The sync engine (`lib/knowledge/connectors/sync-engine.ts`) is connector-agnostic. It: @@ -515,6 +533,7 @@ export const CONNECTOR_REGISTRY: ConnectorRegistry = { - `dependsOn` references selector field IDs (not `canonicalParamId`) - Dependency `canonicalParamId` values exist in `SELECTOR_CONTEXT_FIELDS` - [ ] `listDocuments` handles pagination with metadata-based content hashes +- [ ] `syncContext.listingCapped = true` set whenever the listing is truncated (max-items cap or transient per-item error) — required to prevent the engine's deletion reconciliation from removing unseen documents - [ ] `contentDeferred: true` used if content requires per-doc API calls (file download, export, blocks fetch) - [ ] `contentHash` is metadata-based (not content-based) and identical between stub and `getDocument` - [ ] `sourceUrl` set on each ExternalDocument (full URL, not relative) diff --git a/.claude/commands/add-integration.md b/.claude/commands/add-integration.md index c0fb91e7fa9..e7de9bd8231 100644 --- a/.claude/commands/add-integration.md +++ b/.claude/commands/add-integration.md @@ -221,6 +221,28 @@ export const {Service}Block: BlockConfig = { - **Inputs section:** Must list canonical param IDs (e.g., `fileId`), NOT raw subblock IDs (e.g., `fileSelector`, `manualFileId`) - **Params function:** Must use canonical param IDs, NOT raw subblock IDs (raw IDs are deleted after canonical transformation) +### BlockMeta (Required) + +Export a `{Service}BlockMeta` in the same file as the block — **minimum 7 templates**. See `add-block.md` → "BlockMeta (Required)" for valid `modules` and `category` values and the full pattern. + +```typescript +export const {Service}BlockMeta = { + tags: ['tag1', 'tag2'], + templates: [ + { + icon: {Service}Icon, + title: '{Service} ', + prompt: 'Build a workflow that...', // concrete trigger → transformation → output + modules: ['agent', 'workflows'], + category: 'operations', + tags: ['automation'], + alsoIntegrations: ['slack'], // when the prompt references another service + }, + // ... at least 6 more + ], +} as const satisfies BlockMeta +``` + ## Step 4: Add Icon ### File Location @@ -424,6 +446,7 @@ If creating V2 versions (API-aligned outputs): - [ ] Registered block in `blocks/registry.ts` - [ ] If triggers: set `triggers.enabled` and `triggers.available` - [ ] If triggers: spread trigger subBlocks with `getTrigger()` +- [ ] Exported `{Service}BlockMeta` with at least 7 templates ### OAuth Scopes (if OAuth service) - [ ] Defined scopes in `lib/oauth/oauth.ts` under `OAUTH_PROVIDERS` @@ -454,6 +477,7 @@ If creating V2 versions (API-aligned outputs): - [ ] Verified block subBlocks cover all required tool params with correct conditions - [ ] Verified block outputs match what the tools actually return - [ ] Verified `tools.config.params` correctly maps and coerces all param types +- [ ] `{Service}BlockMeta` exported with at least 7 templates, each having `icon`, `title`, `prompt`, `modules`, `category`, and `tags` ## Example Command diff --git a/.claude/commands/add-model.md b/.claude/commands/add-model.md index 1fcf828537c..c52e1b451f9 100644 --- a/.claude/commands/add-model.md +++ b/.claude/commands/add-model.md @@ -20,7 +20,8 @@ You add a new model entry to `apps/sim/providers/models.ts`. **Every numeric and 2. Live-fetch official docs + pricing page + capability/parameter pages + at least one secondary source 3. Apply the Consumption Matrix to know which capability flags are real 4. Read 2-3 sibling entries in `models.ts` and match their pattern exactly -5. Insert the entry, run `bun run lint`, print the verification report +5. Check the repo-side touchpoints that are NOT data-driven (hosted-key billing, tests, provider code) +6. Insert the entry, run `bun run lint`, print the verification report ## Step 1: Live source-of-truth lookup @@ -103,7 +104,53 @@ Within a family, newest first (matches existing convention: GPT-5.5 above GPT-5. - If you're adding a new flagship, ask the user before removing `recommended` from the previous flagship. Never silently flip it. - `speedOptimized: true` only on the smallest/fastest tier (nano, flash-lite, haiku class). -## Step 4: Write, lint +## Step 4: Repo-side touchpoints beyond the entry + +Adding the `models.ts` entry is most of the job because nearly every consumer is **data-driven** and picks the model up automatically: the ~40 query helpers in `models.ts` / `providers/utils.ts`, the public `/models` catalog (`app/(landing)/models/utils.ts` iterates `PROVIDER_DEFINITIONS`), the agent-block model dropdown, and copilot's `isKnownModelId` / `suggestModelIdsForUnknownModel` validation. The touchpoints below are the exceptions — they are **not** data-driven, so check each one. + +### Hosted = auto-billed, by provider + +`getHostedModels()` in `apps/sim/providers/models.ts` returns **every** model under `openai`, `anthropic`, and `google`: + +```ts +export function getHostedModels(): string[] { + return [ + ...getProviderModels('openai'), + ...getProviderModels('anthropic'), + ...getProviderModels('google'), + ] +} +``` + +So a model added to any of those three providers is **automatically served with Sim's rotating hosted key and billed** to the workspace via `shouldBillModelUsage()` (`providers/utils.ts`). Before you insert: + +- **If the model should be BYOK-only / never-billed**, do NOT drop it under `openai`/`anthropic`/`google` as-is — that silently enrolls it in hosted billing. Confirm hosting/billing intent with the user. (Precedent: Ollama Cloud is a deliberately separate `isReseller` provider specifically to stay BYOK-only/never-billed.) +- **If the model should be hosted**, the deployment must actually have a key for it — the provider's `{PREFIX}_COUNT` / `{PREFIX}_1..N` env vars must be set, or hosted runs fail at execution time. +- State the hosted/billing status explicitly in the verification report. + +### Tests with hardcoded model IDs + +`bun run lint` does **not** run tests. A few tests assert specific model IDs and can break or need updating when you touch a hosted or flagship model: + +- `apps/sim/providers/utils.test.ts` — asserts membership of `getHostedModels()` / `shouldBillModelUsage()` +- `apps/sim/providers/index.test.ts` and serializer tests — reference concrete model IDs + +```bash +rg "|getHostedModels|shouldBillModelUsage" apps/sim/providers/*.test.ts +``` + +If anything matches, run the affected provider tests and update assertions as needed. + +### New API behavior is NOT data-driven + +The Consumption Matrix (Step 2) tells you which capability *flags* are honored by existing provider code. But if the new model needs **net-new** request handling that the provider doesn't implement yet — a new beta header (e.g. Anthropic's `anthropic-beta` structured-outputs header in `anthropic/index.ts`), a new thinking/reasoning encoding, a Responses-API quirk — you must edit `apps/sim/providers//core.ts` / `index.ts`. Setting a flag whose behavior isn't implemented is a silent no-op. + +### Wrong family entirely? + +- **Embedding or rerank model** → it does NOT go in the `models[]` array. Use `EMBEDDING_MODEL_PRICING` / `RERANK_MODEL_PRICING` in `models.ts` instead. +- **Brand-new provider** (not just a new model under an existing one) → much larger surface: add the id to `ProviderId` in `providers/types.ts`, a registry entry in `providers/registry.ts`, a provider implementation under `providers//`, an icon in `components/icons.tsx`, and the `PROVIDER_DEFINITIONS` block. That is beyond this skill — tell the user. + +## Step 5: Write, lint ```bash bun run lint @@ -111,7 +158,7 @@ bun run lint Lint must pass before reporting done. **If lint fails:** read the error, fix the syntax/typing issue in the entry you just wrote (do not delete the entry — it's the work product), re-run lint, and note the fix in a "Lint adjustments" line in the verification report. Never report done with lint failing. -## Step 5: Verification report (mandatory format) +## Step 6: Verification report (mandatory format) End with this exact structure: @@ -128,6 +175,7 @@ End with this exact structure: | `capabilities.temperature` | `{ min: 0, max: 1 }` | matches sibling entries | — pattern-match only | | `capabilities.reasoningEffort` | NOT SET | provider docs say API rejects it for this model | ✓ correctly omitted | | `releaseDate` | 2026-04-30 | https://docs.x.ai/... announcement | ✓ verified | +| hosted/billing | BYOK-only (xai not in `getHostedModels`) | `providers/models.ts` | — confirmed intent | **Disagreements** - _none_ OR _OpenRouter says X, provider docs say Y — used Y per provider rule_ @@ -156,4 +204,6 @@ Omitting a field is **not the same as verifying it**. Any field you cannot confi - ❌ Copying `pricing.updatedAt` from a sibling instead of using today's date - ❌ Inventing a `cachedInput` price by dividing input by 4 (varies by provider — find an explicit number) - ❌ Stamping `recommended: true` on the new model without removing it from the previous flagship +- ❌ Adding a BYOK-only model under `openai`/`anthropic`/`google` (silently enrolls it in hosted billing via `getHostedModels()`) +- ❌ Reporting "done" after only `bun run lint` when you touched a hosted (openai/anthropic/google) or flagship model with assertions in `providers/utils.test.ts` - ❌ Reporting "done" with any UNVERIFIED row in the table diff --git a/.claude/commands/validate-connector.md b/.claude/commands/validate-connector.md index adcbf61b12b..3aa5da34f93 100644 --- a/.claude/commands/validate-connector.md +++ b/.claude/commands/validate-connector.md @@ -135,6 +135,13 @@ For each API endpoint the connector calls: - [ ] No off-by-one errors in pagination tracking - [ ] The connector does NOT hit known API pagination limits silently (e.g., HubSpot search 10k cap) +### Deletion-Reconciliation Safety (`listingCapped`) — CRITICAL +The sync engine hard-deletes any stored document absent from a full listing. Audit every path where `listDocuments` can return less than the full source set: +- [ ] `syncContext.listingCapped = true` is set when a `maxItems`-style cap truncates the listing while more documents exist +- [ ] `listingCapped` is set when a transient per-item error drops a still-existing document from the listing +- [ ] `listingCapped` is NOT set when the source is genuinely exhausted (deleted documents must reconcile) or for intentional scope filters (date cutoffs) +This is the most common connector bug class — verify it explicitly against `sync-engine.ts`'s reconciliation gate. + ### Pagination State Across Pages - [ ] `syncContext` is used to cache state across pages (user names, field maps, instance URLs, portal IDs, etc.) - [ ] Cached state in `syncContext` is correctly initialized on first page and reused on subsequent pages diff --git a/.claude/commands/validate-integration.md b/.claude/commands/validate-integration.md index 0de683ffebb..c1a9cfe1207 100644 --- a/.claude/commands/validate-integration.md +++ b/.claude/commands/validate-integration.md @@ -192,6 +192,12 @@ For **each tool** in `tools.access`: - [ ] `authMode` is set correctly (`AuthMode.OAuth` or `AuthMode.ApiKey`) - [ ] Block is registered in `blocks/registry.ts` alphabetically +### BlockMeta +- [ ] `{Service}BlockMeta` is exported in the same file as the block +- [ ] Has at least 7 templates, each with `icon`, `title`, `prompt`, `modules`, `category`, and `tags` +- [ ] Prompts describe concrete use cases, not generic descriptions of what the service does +- [ ] `alsoIntegrations` is set on any template whose prompt references another service + ### Block Inputs - [ ] `inputs` section lists all subBlock params that the block accepts - [ ] Input types match the subBlock types @@ -282,6 +288,7 @@ After fixing, confirm: - [ ] Validated pagination consistency across tools and block - [ ] Validated error handling (error checks, meaningful messages) - [ ] Validated registry entries (tools and block, alphabetical, correct imports) +- [ ] Validated `{Service}BlockMeta` exported with at least 7 templates - [ ] Reported all issues grouped by severity - [ ] Fixed all critical and warning issues - [ ] Ran `bun run lint` after fixes diff --git a/.claude/commands/validate-model.md b/.claude/commands/validate-model.md index 10c6aaa0b27..bf1d30745b6 100644 --- a/.claude/commands/validate-model.md +++ b/.claude/commands/validate-model.md @@ -34,7 +34,7 @@ Capture per model: `id`, full `pricing`, full `capabilities`, `contextWindow`, ` ## Step 2: Live-fetch authoritative sources -Use the canonical provider URL table in `add-model.md` (Step 1) as the single source of truth — fetch the models index, pricing, and reasoning/parameter caveats pages listed there for the target provider. If you update one table, update the other in the same change. +Use the canonical provider URL table in the `add-model` skill (`.claude/commands/add-model.md`, or its mirror `.agents/skills/add-model/SKILL.md`), Step 1, as the single source of truth — fetch the models index, pricing, and reasoning/parameter caveats pages listed there for the target provider. If you update one table, update the other in the same change. Secondary cross-check (use at least one): OpenRouter, Artificial Analysis, CloudPrice. @@ -98,6 +98,10 @@ For each model, evaluate every row. Statuses: ✓ matches docs, ✗ disagrees, - [ ] `recommended: true` — at most one or two per provider; should be current flagship - [ ] `speedOptimized: true` — only on smallest/fastest tier (nano / flash-lite / haiku class) +### Hosting / billing +- [ ] If the model is under `openai`/`anthropic`/`google`, it is automatically in `getHostedModels()` → served with Sim's rotating key and billed via `shouldBillModelUsage()`. Confirm that is the intent (a BYOK-only model parked under one of these providers is a billing bug — warning). +- [ ] If the model is hosted, the deployment is expected to have its `{PREFIX}_COUNT` / `{PREFIX}_1..N` env vars set (ops concern; note if it looks unset for a model claiming hosted support). + ## Step 5: Report (mandatory format) For each model, emit a table with one row per checklist item. Every row that claims ✓ must have a URL. diff --git a/README.md b/README.md index 989452870fd..6a8508bcc3c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@

-

The open-source platform to build AI agents and run your agentic workforce. Connect 1,000+ integrations and LLMs to orchestrate agentic workflows.

+

The open-source AI workspace where teams build, deploy, and manage AI agents. Build conversationally, visually, or with code. Connect 1,000+ integrations and every major LLM to automate real work.

Sim.ai @@ -21,25 +21,39 @@ Ask DeepWiki Set Up with Cursor

-### Build Workflows with Ease -Design agent workflows visually on a canvas—connect agents, tools, and blocks, then run them instantly. +### Build everything in Mothership +Your AI command center. Describe what you want in plain language. Mothership knows your entire workspace and takes action: building agents, running them, querying data, and more.

- Workflow Builder Demo + Mothership building and running an agent from chat

-### Supercharge with Copilot -Leverage Copilot to generate nodes, fix errors, and iterate on flows directly from natural language. +### Create files and documents +Generate documents, reports, and presentations from a single prompt, grounded in your workspace data.

- Copilot Demo + Mothership generating a document from a prompt

-### Integrate Vector Databases -Upload documents to a vector store and let agents answer questions grounded in your specific content. +### Ground agents in your knowledge +Upload documents to a knowledge base and let agents answer questions from your own content.

- Knowledge Uploads and Retrieval Demo + Creating a knowledge base +

+ +### Structured data with Tables +A database, built in. Store, query, and wire structured data into agent runs. + +

+ Tables view with typed columns +

+ +### Build visually with Workflows +Prefer a canvas? Design agents block by block in the visual builder, and let Copilot generate blocks, wire variables, and fix errors from natural language. + +

+ Workflow builder demo

## Quickstart @@ -74,7 +88,7 @@ docker compose -f docker-compose.prod.yml up -d Open [http://localhost:3000](http://localhost:3000) -Sim also supports local models via [Ollama](https://ollama.ai) and [vLLM](https://docs.vllm.ai/) — see the [Docker self-hosting docs](https://docs.sim.ai/self-hosting/docker) for setup details. +Sim also supports local models via [Ollama](https://ollama.ai) and [vLLM](https://docs.vllm.ai/). See the [Docker self-hosting docs](https://docs.sim.ai/self-hosting/docker) for setup details. ### Self-hosted: Manual Setup diff --git a/apps/docs/app/api/og/route.tsx b/apps/docs/app/api/og/route.tsx index 219d3ed40ae..18e021018b5 100644 --- a/apps/docs/app/api/og/route.tsx +++ b/apps/docs/app/api/og/route.tsx @@ -33,7 +33,7 @@ const OG_FOOTER_STYLE = { width: '100%', } satisfies CSSProperties const OG_DOMAIN_STYLE = { - fontSize: 20, + fontSize: 24, fontWeight: 400, color: '#71717a', } satisfies CSSProperties @@ -84,7 +84,7 @@ async function loadGoogleFont(font: string, weights: string, text: string): Prom */ function SimLogoFull() { return ( - + {/* Green icon - top left shape with cutout */} ) { ) } +export function ClickHouseIcon(props: SVGProps) { + return ( + + + + + ) +} + export function MicrosoftIcon(props: SVGProps) { return ( @@ -3365,7 +3377,18 @@ export const OllamaIcon = (props: SVGProps) => ( xmlns='http://www.w3.org/2000/svg' > Ollama - + + +) +export const FalIcon = (props: SVGProps) => ( + + Fal + ) export function ShieldCheckIcon(props: SVGProps) { @@ -3982,16 +4005,16 @@ export function FireworksIcon(props: SVGProps) { return ( ) diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index d22e1caf00f..159c4501262 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -4,7 +4,6 @@ import type { ComponentType, SVGProps } from 'react' import { - A2AIcon, AgentMailIcon, AgentPhoneIcon, AgiloftIcon, @@ -31,6 +30,7 @@ import { CirclebackIcon, ClayIcon, ClerkIcon, + ClickHouseIcon, CloudFormationIcon, CloudflareIcon, CloudWatchIcon, @@ -96,7 +96,6 @@ import { HunterIOIcon, IAMIcon, IdentityCenterIcon, - ImageIcon, IncidentioIcon, InfisicalIcon, InstantlyIcon, @@ -128,7 +127,6 @@ import { MistralIcon, MondayIcon, MongoDBIcon, - MySQLIcon, Neo4jIcon, NewRelicIcon, NotionIcon, @@ -145,7 +143,6 @@ import { PineconeIcon, PipedriveIcon, PolymarketIcon, - PostgresIcon, PosthogIcon, ProfoundIcon, ProspeoIcon, @@ -167,20 +164,16 @@ import { SapConcurIcon, SapS4HanaIcon, SESIcon, - SearchIcon, SecretsManagerIcon, SendgridIcon, SentryIcon, SerperIcon, ServiceNowIcon, - SftpIcon, ShopifyIcon, SimilarwebIcon, SixtyfourIcon, SlackIcon, - SmtpIcon, SQSIcon, - SshIcon, STSIcon, STTIcon, StagehandIcon, @@ -191,9 +184,7 @@ import { TelegramIcon, TextractIcon, TinybirdIcon, - TranslateIcon, TrelloIcon, - TTSIcon, TwilioIcon, TypeformIcon, UpstashIcon, @@ -217,7 +208,6 @@ import { type IconComponent = ComponentType> export const blockTypeToIconMap: Record = { - a2a: A2AIcon, agentmail: AgentMailIcon, agentphone: AgentPhoneIcon, agiloft: AgiloftIcon, @@ -243,6 +233,7 @@ export const blockTypeToIconMap: Record = { circleback: CirclebackIcon, clay: ClayIcon, clerk: ClerkIcon, + clickhouse: ClickHouseIcon, cloudflare: CloudflareIcon, cloudformation: CloudFormationIcon, cloudwatch: CloudWatchIcon, @@ -274,7 +265,6 @@ export const blockTypeToIconMap: Record = { fathom: FathomIcon, file: DocumentIcon, file_v2: DocumentIcon, - file_v3: DocumentIcon, file_v4: DocumentIcon, findymail: FindymailIcon, firecrawl: FirecrawlIcon, @@ -319,8 +309,6 @@ export const blockTypeToIconMap: Record = { hunter: HunterIOIcon, iam: IAMIcon, identity_center: IdentityCenterIcon, - image_generator: ImageIcon, - image_generator_v2: ImageIcon, imap: MailServerIcon, incidentio: IncidentioIcon, infisical: InfisicalIcon, @@ -359,7 +347,6 @@ export const blockTypeToIconMap: Record = { mistral_parse_v3: MistralIcon, monday: MondayIcon, mongodb: MongoDBIcon, - mysql: MySQLIcon, neo4j: Neo4jIcon, new_relic: NewRelicIcon, notion: NotionIcon, @@ -377,7 +364,6 @@ export const blockTypeToIconMap: Record = { pinecone: PineconeIcon, pipedrive: PipedriveIcon, polymarket: PolymarketIcon, - postgresql: PostgresIcon, posthog: PosthogIcon, profound: ProfoundIcon, prospeo: ProspeoIcon, @@ -400,23 +386,19 @@ export const blockTypeToIconMap: Record = { salesforce: SalesforceIcon, sap_concur: SapConcurIcon, sap_s4hana: SapS4HanaIcon, - search: SearchIcon, secrets_manager: SecretsManagerIcon, sendgrid: SendgridIcon, sentry: SentryIcon, serper: SerperIcon, servicenow: ServiceNowIcon, ses: SESIcon, - sftp: SftpIcon, sharepoint: MicrosoftSharepointIcon, sharepoint_v2: MicrosoftSharepointIcon, shopify: ShopifyIcon, similarweb: SimilarwebIcon, sixtyfour: SixtyfourIcon, slack: SlackIcon, - smtp: SmtpIcon, sqs: SQSIcon, - ssh: SshIcon, stagehand: StagehandIcon, stripe: StripeIcon, sts: STSIcon, @@ -429,9 +411,7 @@ export const blockTypeToIconMap: Record = { textract: TextractIcon, textract_v2: TextractIcon, tinybird: TinybirdIcon, - translate: TranslateIcon, trello: TrelloIcon, - tts: TTSIcon, twilio_sms: TwilioIcon, twilio_voice: TwilioIcon, typeform: TypeformIcon, @@ -439,7 +419,6 @@ export const blockTypeToIconMap: Record = { vercel: VercelIcon, video_generator: VideoIcon, video_generator_v2: VideoIcon, - video_generator_v3: VideoIcon, vision: EyeIcon, vision_v2: EyeIcon, wealthbox: WealthboxIcon, diff --git a/apps/docs/content/docs/de/execution/form.mdx b/apps/docs/content/docs/de/execution/form.mdx deleted file mode 100644 index ff87d880b73..00000000000 --- a/apps/docs/content/docs/de/execution/form.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Formular-Bereitstellung ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { Tab, Tabs } from 'fumadocs-ui/components/tabs' - -Stellen Sie Ihren Workflow als einbettbares Formular bereit, das Benutzer auf Ihrer Website ausfüllen oder per Link teilen können. Formularübermittlungen lösen Ihren Workflow mit dem `form` Trigger-Typ aus. - -## Übersicht - -Die Formular-Bereitstellung verwandelt das Eingabeformat Ihres Workflows in ein responsives Formular, das: -- Per Direktlink geteilt werden kann (z. B. `https://sim.ai/form/my-survey`) -- Mit einem iframe in jede Website eingebettet werden kann - -Wenn ein Benutzer das Formular absendet, wird Ihr Workflow mit den Formulardaten ausgelöst. - - -Formulare leiten ihre Felder vom Eingabeformat des Start-Blocks Ihres Workflows ab. Jedes Feld wird zu einer Formulareingabe mit dem entsprechenden Typ. - - -## Erstellen eines Formulars - -1. Öffnen Sie Ihren Workflow und klicken Sie auf **Bereitstellen** -2. Wählen Sie den Tab **Formular** -3. Konfigurieren Sie: - - **URL**: Eindeutige Kennung (z. B. `contact-form` → `sim.ai/form/contact-form`) - - **Titel**: Formularüberschrift - - **Beschreibung**: Optionaler Untertitel - - **Formularfelder**: Passen Sie Beschriftungen und Beschreibungen für jedes Feld an - - **Authentifizierung**: Öffentlich, passwortgeschützt oder E-Mail-Whitelist - - **Dankesnachricht**: Wird nach der Übermittlung angezeigt -4. Klicken Sie auf **Starten** - -## Feldzuordnung - -| Eingabeformat-Typ | Formularfeld | -|------------------|------------| -| `string` | Texteingabe | -| `number` | Zahleneingabe | -| `boolean` | Umschalter | -| `object` | JSON-Editor | -| `array` | JSON-Array-Editor | -| `files` | Datei-Upload | - -## Zugriffskontrolle - -| Modus | Beschreibung | -|------|-------------| -| **Öffentlich** | Jeder mit dem Link kann absenden | -| **Passwort** | Benutzer müssen ein Passwort eingeben | -| **E-Mail-Whitelist** | Nur angegebene E-Mails/Domains können absenden | - -Für E-Mail-Whitelist: -- Exakt: `user@example.com` -- Domain: `@example.com` (alle E-Mails von der Domain) - -## Einbettung - -### Direkter Link - -``` -https://sim.ai/form/your-identifier -``` - -### Iframe - -```html - -``` - -## API-Übermittlung - -Formulare programmatisch übermitteln: - - - - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ - "formData": { - "name": "John Doe", - "email": "john@example.com" - } - }' -``` - - - - -```typescript -const response = await fetch('https://sim.ai/api/form/your-identifier', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - formData: { - name: 'John Doe', - email: 'john@example.com' - } - }) -}); - -const result = await response.json(); -// { success: true, data: { executionId: '...' } } -``` - - - - -### Geschützte Formulare - -Für passwortgeschützte Formulare: - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "password": "secret", "formData": { "name": "John" } }' -``` - -Für E-Mail-geschützte Formulare: - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "email": "allowed@example.com", "formData": { "name": "John" } }' -``` - -## Fehlerbehebung - -**"Keine Eingabefelder konfiguriert"** - Fügen Sie Eingabeformat-Felder zu Ihrem Start-Block hinzu. - -**Formular lädt nicht im Iframe** - Überprüfen Sie, ob die CSP Ihrer Website Iframes von `sim.ai` erlaubt. - -**Übermittlungen schlagen fehl** - Überprüfen Sie, ob die Kennung korrekt ist und erforderliche Felder ausgefüllt sind. diff --git a/apps/docs/content/docs/en/tools/knowledge.mdx b/apps/docs/content/docs/en/blocks/knowledge.mdx similarity index 100% rename from apps/docs/content/docs/en/tools/knowledge.mdx rename to apps/docs/content/docs/en/blocks/knowledge.mdx diff --git a/apps/docs/content/docs/en/blocks/meta.json b/apps/docs/content/docs/en/blocks/meta.json index 225d3ff8fb5..2e1ad2ccad4 100644 --- a/apps/docs/content/docs/en/blocks/meta.json +++ b/apps/docs/content/docs/en/blocks/meta.json @@ -9,10 +9,12 @@ "function", "guardrails", "human-in-the-loop", + "knowledge", "loop", "parallel", "response", "router", + "table", "variables", "wait", "webhook", diff --git a/apps/docs/content/docs/en/tools/table.mdx b/apps/docs/content/docs/en/blocks/table.mdx similarity index 100% rename from apps/docs/content/docs/en/tools/table.mdx rename to apps/docs/content/docs/en/blocks/table.mdx diff --git a/apps/docs/content/docs/en/execution/form.mdx b/apps/docs/content/docs/en/execution/form.mdx deleted file mode 100644 index 3df49004e51..00000000000 --- a/apps/docs/content/docs/en/execution/form.mdx +++ /dev/null @@ -1,136 +0,0 @@ ---- -title: Form Deployment ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { Tab, Tabs } from 'fumadocs-ui/components/tabs' - -Deploy your workflow as an embeddable form that users can fill out on your website or share via link. Form submissions trigger your workflow with the `form` trigger type. - -## Overview - -Form deployment turns your workflow's Input Format into a responsive form that can be: -- Shared via a direct link (e.g., `https://sim.ai/form/my-survey`) -- Embedded in any website using an iframe - -When a user submits the form, it triggers your workflow with the form data. - - -Forms derive their fields from your workflow's Start block Input Format. Each field becomes a form input with the appropriate type. - - -## Creating a Form - -1. Open your workflow and click **Deploy** -2. Select the **Form** tab -3. Configure: - - **URL**: Unique identifier (e.g., `contact-form` → `sim.ai/form/contact-form`) - - **Title**: Form heading - - **Description**: Optional subtitle - - **Form Fields**: Customize labels and descriptions for each field - - **Authentication**: Public, password-protected, or email whitelist - - **Thank You Message**: Shown after submission -4. Click **Launch** - -## Field Type Mapping - -| Input Format Type | Form Field | -|------------------|------------| -| `string` | Text input | -| `number` | Number input | -| `boolean` | Toggle switch | -| `object` | JSON editor | -| `array` | JSON array editor | -| `files` | File upload | - -## Access Control - -| Mode | Description | -|------|-------------| -| **Public** | Anyone with the link can submit | -| **Password** | Users must enter a password | -| **Email Whitelist** | Only specified emails/domains can submit | - -For email whitelist: -- Exact: `user@example.com` -- Domain: `@example.com` (all emails from domain) - -## Embedding - -### Direct Link - -``` -https://sim.ai/form/your-identifier -``` - -### Iframe - -```html - -``` - -## API Submission - -Submit forms programmatically: - - - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ - "formData": { - "name": "John Doe", - "email": "john@example.com" - } - }' -``` - - -```typescript -const response = await fetch('https://sim.ai/api/form/your-identifier', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - formData: { - name: 'John Doe', - email: 'john@example.com' - } - }) -}); - -const result = await response.json(); -// { success: true, data: { executionId: '...' } } -``` - - - -### Protected Forms - -For password-protected forms: -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "password": "secret", "formData": { "name": "John" } }' -``` - -For email-protected forms: -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "email": "allowed@example.com", "formData": { "name": "John" } }' -``` - -## Troubleshooting - -**"No input fields configured"** - Add Input Format fields to your Start block. - -**Form not loading in iframe** - Check your site's CSP allows iframes from `sim.ai`. - -**Submissions failing** - Verify the identifier is correct and required fields are filled. diff --git a/apps/docs/content/docs/en/knowledgebase/connectors.mdx b/apps/docs/content/docs/en/knowledgebase/connectors.mdx index 88a62383027..2f9de16cfa2 100644 --- a/apps/docs/content/docs/en/knowledgebase/connectors.mdx +++ b/apps/docs/content/docs/en/knowledgebase/connectors.mdx @@ -14,21 +14,23 @@ Connectors continuously sync documents from external services into your knowledg -Sim ships with 30 built-in connectors: +Sim ships with 49 built-in connectors: | Category | Connectors | |----------|-----------| -| **Productivity** | Notion, Confluence, Asana, Linear, Jira, Google Calendar, Google Sheets | -| **Cloud Storage** | Google Drive, Dropbox, OneDrive, SharePoint | -| **Documents** | Google Docs, WordPress, Webflow | -| **Development** | GitHub | -| **Communication** | Slack, Discord, Microsoft Teams, Reddit | +| **Productivity** | Notion, Confluence, Asana, Linear, Jira, Jira Service Management, Monday, Google Calendar, Google Sheets, Google Forms, Typeform | +| **Cloud Storage** | Google Drive, Dropbox, OneDrive, SharePoint, Amazon S3 | +| **Documents** | Google Docs, WordPress, Webflow, DocuSign | +| **Development** | GitHub, GitLab, Azure DevOps, Sentry | +| **Communication** | Slack, Discord, Microsoft Teams, Reddit, YouTube | | **Email** | Gmail, Outlook | | **CRM** | HubSpot, Salesforce | | **Support** | Intercom, ServiceNow, Zendesk | +| **Incident Management** | incident.io, Rootly | | **Data** | Airtable | | **Note-taking** | Evernote, Obsidian | -| **Meetings** | Fireflies | +| **Meetings** | Zoom, Gong, Grain, Granola, Fathom, Fireflies | +| **Recruiting** | Greenhouse, Ashby | ## Adding a Connector @@ -41,13 +43,18 @@ From inside a knowledge base, click **+ New connector** in the top right to open Most connectors use **OAuth** — select an existing credential from the dropdown or click **Connect new account** to authorize through the service. Tokens are refreshed automatically. -A few connectors use **API keys** instead: +Other connectors use **API keys** or **personal access tokens** instead. The setup modal tells you which credential each connector expects — for example: | Connector | Where to get the key | |-----------|---------------------| | **Evernote** | Developer Token (starts with `S=`) from your Evernote account settings | | **Obsidian** | Install the [Local REST API](https://github.com/coddingtonbear/obsidian-local-rest-api) plugin, then copy the key from its settings | | **Fireflies** | Generate from the Integrations page in your Fireflies account | +| **Typeform** | Personal access token from your Typeform account settings | +| **Azure DevOps** | Personal access token with Wiki (Read), Work Items (Read), and Code (Read) scopes | +| **YouTube** | YouTube Data API key from the Google Cloud Console | +| **Amazon S3** | Secret Access Key (the Access Key ID, region, and bucket are entered as config fields) | +| **Sentry** | Auth token with `project:read` and `event:read` scopes | If you rotate an API key in the external service, update it in Sim as well — OAuth tokens refresh automatically, but API keys do not. @@ -63,6 +70,10 @@ Each connector has source-specific fields that control what gets synced. Example - **Notion** — sync an entire workspace, a specific database, or a single page tree - **GitHub** — specify a repository, branch, and optional file extension filter - **Confluence** — enter your Atlassian domain and optionally filter by space key or content type +- **Azure DevOps** — choose what to sync (wiki pages, work items, repository files, or all), with optional work item type/state filters, a custom WIQL query, and repository/branch/path filters +- **Amazon S3** — point at a bucket with an optional key prefix and a customizable file extension allowlist; S3-compatible stores (Cloudflare R2, MinIO) are supported via a custom endpoint +- **YouTube** — sync a channel (by `@handle` or ID) or playlist, with an optional published-after date filter and the option to exclude Shorts +- **Sentry** — filter issues by search query (e.g. `is:unresolved`), environment, and time window; self-hosted Sentry is supported via a custom host - **Obsidian** — provide your vault URL (`https://127.0.0.1:27124` by default) and optionally restrict to a folder path - **Fireflies** — optionally filter by host email or cap the number of transcripts synced @@ -188,5 +199,5 @@ You can add as many connectors as you need to a single knowledge base. Each mana { question: "What happens when I delete a connector?", answer: "The connector is removed and future syncs stop. You're given the option to also delete all documents that were synced by that connector. If you don't check that option, they stay in the knowledge base as-is." }, { question: "What does the Disabled status mean?", answer: "After 10 consecutive full-sync failures, the connector is automatically disabled to stop retrying. Reconnect the OAuth account or click Resume to re-enable it." }, { question: "Do metadata tags count against a limit?", answer: "Yes. Tag slots are shared across all documents in a knowledge base — 17 slots total. Multiple connectors draw from the same pool, so plan accordingly if several connectors each auto-populate tags." }, - { question: "Do I need to re-authenticate connectors?", answer: "OAuth connectors refresh tokens automatically. API key connectors (Evernote, Obsidian, Fireflies) need manual updates if you rotate the key in the external service." }, + { question: "Do I need to re-authenticate connectors?", answer: "OAuth connectors refresh tokens automatically. API key and personal access token connectors need manual updates if you rotate the credential in the external service." }, ]} /> diff --git a/apps/docs/content/docs/en/mothership/knowledge.mdx b/apps/docs/content/docs/en/mothership/knowledge.mdx index ab17e6e6a78..008c050b5c2 100644 --- a/apps/docs/content/docs/en/mothership/knowledge.mdx +++ b/apps/docs/content/docs/en/mothership/knowledge.mdx @@ -49,7 +49,7 @@ For knowledge bases that should stay current automatically, connectors sync cont Connectors are configured through the knowledge base settings, not through Mothership chat. Once connected, all synced content is immediately searchable by Mothership and by any Agent block with the knowledge base attached. -Sim ships with 30 built-in connectors, including Notion, Google Drive, Slack, GitHub, Confluence, HubSpot, Salesforce, Gmail, and more. +Sim ships with 49 built-in connectors, including Notion, Google Drive, Slack, GitHub, Confluence, HubSpot, Salesforce, Gmail, and more. Examples of what you can sync: diff --git a/apps/docs/content/docs/en/mothership/tables.mdx b/apps/docs/content/docs/en/mothership/tables.mdx index 13870276783..59add7b2e2d 100644 --- a/apps/docs/content/docs/en/mothership/tables.mdx +++ b/apps/docs/content/docs/en/mothership/tables.mdx @@ -51,10 +51,10 @@ Export a full table or a filtered subset as a CSV. The file is saved to your wor ## Using Tables in Workflows -Tables created in Mothership are immediately available in workflows via the [Table tool](/tools/table). Reference a table by name — no additional configuration needed. +Tables created in Mothership are immediately available in workflows via the [Table block](/blocks/table). Reference a table by name — no additional configuration needed. diff --git a/apps/docs/content/docs/en/tools/a2a.mdx b/apps/docs/content/docs/en/tools/a2a.mdx deleted file mode 100644 index 01dca23691a..00000000000 --- a/apps/docs/content/docs/en/tools/a2a.mdx +++ /dev/null @@ -1,212 +0,0 @@ ---- -title: A2A -description: Interact with external A2A-compatible agents ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -The A2A (Agent-to-Agent) protocol enables Sim to interact with external AI agents and systems that implement A2A-compatible APIs. With A2A, you can connect Sim’s automations and workflows to remote agents—such as LLM-powered bots, microservices, and other AI-based tools—using a standardized messaging format. - -Using the A2A tools in Sim, you can: - -- **Send Messages to External Agents**: Communicate directly with remote agents, providing prompts, commands, or data. -- **Receive and Stream Responses**: Get structured responses, artifacts, or real-time updates from the agent as the task progresses. -- **Continue Conversations or Tasks**: Carry on multi-turn conversations or workflows by referencing task and context IDs. -- **Integrate Third-Party AI and Automation**: Leverage external A2A-compatible services as part of your Sim workflows. - -These features allow you to build advanced workflows that combine Sim’s native capabilities with the intelligence and automation of external AIs or custom agents. To use A2A integrations, you’ll need the external agent’s endpoint URL and, if required, an API key or credentials. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Use the A2A (Agent-to-Agent) protocol to interact with external AI agents. - - - -## Tools - -### `a2a_send_message` - -Send a message to an external A2A-compatible agent. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `agentUrl` | string | Yes | The A2A agent endpoint URL | -| `message` | string | Yes | Message to send to the agent | -| `taskId` | string | No | Task ID for continuing an existing task | -| `contextId` | string | No | Context ID for conversation continuity | -| `data` | string | No | Structured data to include with the message \(JSON string\) | -| `files` | array | No | Files to include with the message | -| `apiKey` | string | No | API key for authentication | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `content` | string | Text response content from the agent | -| `taskId` | string | Unique task identifier | -| `contextId` | string | Groups related tasks/messages | -| `state` | string | Current lifecycle state \(working, completed, failed, canceled, rejected, input_required, auth_required\) | -| `artifacts` | array | Task output artifacts | -| `history` | array | Conversation history \(Message array\) | - -### `a2a_get_task` - -Query the status of an existing A2A task. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `agentUrl` | string | Yes | The A2A agent endpoint URL | -| `taskId` | string | Yes | Task ID to query | -| `apiKey` | string | No | API key for authentication | -| `historyLength` | number | No | Number of history messages to include | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `taskId` | string | Unique task identifier | -| `contextId` | string | Groups related tasks/messages | -| `state` | string | Current lifecycle state \(working, completed, failed, canceled, rejected, input_required, auth_required\) | -| `artifacts` | array | Task output artifacts | -| `history` | array | Conversation history \(Message array\) | - -### `a2a_cancel_task` - -Cancel a running A2A task. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `agentUrl` | string | Yes | The A2A agent endpoint URL | -| `taskId` | string | Yes | Task ID to cancel | -| `apiKey` | string | No | API key for authentication | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `cancelled` | boolean | Whether cancellation was successful | -| `state` | string | Current lifecycle state \(working, completed, failed, canceled, rejected, input_required, auth_required\) | - -### `a2a_get_agent_card` - -Fetch the Agent Card (discovery document) for an A2A agent. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `agentUrl` | string | Yes | The A2A agent endpoint URL | -| `apiKey` | string | No | API key for authentication \(if required\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `name` | string | Agent display name | -| `description` | string | Agent purpose/capabilities | -| `url` | string | Service endpoint URL | -| `provider` | object | Creator organization details | -| `capabilities` | object | Feature support matrix | -| `skills` | array | Available operations | -| `version` | string | A2A protocol version supported by the agent | -| `defaultInputModes` | array | Default input content types accepted by the agent | -| `defaultOutputModes` | array | Default output content types produced by the agent | - -### `a2a_resubscribe` - -Reconnect to an ongoing A2A task stream after connection interruption. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `agentUrl` | string | Yes | The A2A agent endpoint URL | -| `taskId` | string | Yes | Task ID to resubscribe to | -| `apiKey` | string | No | API key for authentication | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `taskId` | string | Unique task identifier | -| `contextId` | string | Groups related tasks/messages | -| `state` | string | Current lifecycle state \(working, completed, failed, canceled, rejected, input_required, auth_required\) | -| `isRunning` | boolean | Whether the task is still running | -| `artifacts` | array | Task output artifacts | -| `history` | array | Conversation history \(Message array\) | - -### `a2a_set_push_notification` - -Configure a webhook to receive task update notifications. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `agentUrl` | string | Yes | The A2A agent endpoint URL | -| `taskId` | string | Yes | Task ID to configure notifications for | -| `webhookUrl` | string | Yes | HTTPS webhook URL to receive notifications | -| `token` | string | No | Token for webhook validation | -| `apiKey` | string | No | API key for authentication | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `url` | string | HTTPS webhook URL for notifications | -| `token` | string | Authentication token for webhook validation | -| `success` | boolean | Whether the operation was successful | - -### `a2a_get_push_notification` - -Get the push notification webhook configuration for a task. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `agentUrl` | string | Yes | The A2A agent endpoint URL | -| `taskId` | string | Yes | Task ID to get notification config for | -| `apiKey` | string | No | API key for authentication | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `token` | string | Authentication token for webhook validation | -| `exists` | boolean | Whether the resource exists | - -### `a2a_delete_push_notification` - -Delete the push notification webhook configuration for a task. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `agentUrl` | string | Yes | The A2A agent endpoint URL | -| `taskId` | string | Yes | Task ID to delete notification config for | -| `pushNotificationConfigId` | string | No | Push notification configuration ID to delete \(optional - server can derive from taskId\) | -| `apiKey` | string | No | API key for authentication | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the operation was successful | - - diff --git a/apps/docs/content/docs/en/tools/agentphone.mdx b/apps/docs/content/docs/en/tools/agentphone.mdx index 11dea1cd61c..fa8d016c77f 100644 --- a/apps/docs/content/docs/en/tools/agentphone.mdx +++ b/apps/docs/content/docs/en/tools/agentphone.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/ahrefs.mdx b/apps/docs/content/docs/en/tools/ahrefs.mdx index d965e1f5b09..963d852eb8e 100644 --- a/apps/docs/content/docs/en/tools/ahrefs.mdx +++ b/apps/docs/content/docs/en/tools/ahrefs.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/airtable.mdx b/apps/docs/content/docs/en/tools/airtable.mdx index 73fbcb920bb..1d2c191534e 100644 --- a/apps/docs/content/docs/en/tools/airtable.mdx +++ b/apps/docs/content/docs/en/tools/airtable.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/apify.mdx b/apps/docs/content/docs/en/tools/apify.mdx index 40c30ec70bd..7b25679ca68 100644 --- a/apps/docs/content/docs/en/tools/apify.mdx +++ b/apps/docs/content/docs/en/tools/apify.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/arxiv.mdx b/apps/docs/content/docs/en/tools/arxiv.mdx index 011a79929b8..eb5e3ef8162 100644 --- a/apps/docs/content/docs/en/tools/arxiv.mdx +++ b/apps/docs/content/docs/en/tools/arxiv.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/asana.mdx b/apps/docs/content/docs/en/tools/asana.mdx index 2664696104c..4ab78d9478a 100644 --- a/apps/docs/content/docs/en/tools/asana.mdx +++ b/apps/docs/content/docs/en/tools/asana.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/brightdata.mdx b/apps/docs/content/docs/en/tools/brightdata.mdx index 65f8327e862..f3d1772779b 100644 --- a/apps/docs/content/docs/en/tools/brightdata.mdx +++ b/apps/docs/content/docs/en/tools/brightdata.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" ## Usage Instructions diff --git a/apps/docs/content/docs/en/tools/circleback.mdx b/apps/docs/content/docs/en/tools/circleback.mdx deleted file mode 100644 index 662ac1561f2..00000000000 --- a/apps/docs/content/docs/en/tools/circleback.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Circleback -description: AI-powered meeting notes and action items ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -[Circleback](https://circleback.ai/) is an AI-powered platform that automates meeting notes, action items, transcripts, and recordings for your team. When a meeting is completed, Circleback processes the conversation and provides detailed notes and action items, along with a transcript and a recording (when available). This helps teams efficiently capture insights, distribute action items, and ensure nothing is missed—all seamlessly integrated into your workflows. - -With the Sim Circleback integration, you can: - -- **Receive detailed meeting notes and action items**: Automatically collect well-formatted meeting summaries and track actionable tasks discussed during your calls. -- **Access complete meeting recordings and transcripts**: Get the full conversation and the associated recording, making it easy to review key moments or share with colleagues. -- **Capture attendee information and meeting context**: Attendee lists, meeting metadata, and tags help keep your data organized and actionable. -- **Deliver insights directly into your workflows**: Trigger automations or send Circleback data to other systems the moment a meeting is done, using Sim’s powerful webhook triggers. - -**How it works in Sim:** -Circleback uses webhook triggers: whenever a meeting is processed, data is pushed automatically to your agent or automation. You can build further automations based on: - -- Meeting completed (all processed data available) -- New notes (notes ready even before full meeting is processed) -- Raw webhook integration for advanced use cases - -**The following information is available in the Circleback meeting webhook payload:** - -| Field | Type | Description | -|----------------|---------|----------------------------------------------------| -| `id` | number | Circleback meeting ID | -| `name` | string | Meeting title | -| `url` | string | Virtual meeting URL (Zoom, Meet, Teams, etc.) | -| `createdAt` | string | Meeting creation timestamp | -| `duration` | number | Duration in seconds | -| `recordingUrl` | string | Recording URL (valid 24 hours) | -| `tags` | json | Array of tags | -| `icalUid` | string | Calendar event ID | -| `attendees` | json | Array of attendee objects | -| `notes` | string | Meeting notes in Markdown | -| `actionItems` | json | Array of action items | -| `transcript` | json | Array of transcript segments | -| `insights` | json | User-created insights | -| `meeting` | json | Full meeting payload | - -Whether you want to distribute instant summaries, log action items, or build custom workflows triggered by new meeting data, Circleback and Sim make it seamless to handle everything related to your meetings—automatically. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Receive meeting notes, action items, transcripts, and recordings when meetings are processed. Circleback uses webhooks to push data to your workflows. - - - - diff --git a/apps/docs/content/docs/en/tools/clay.mdx b/apps/docs/content/docs/en/tools/clay.mdx index 8b06513171f..7b20f02b1fb 100644 --- a/apps/docs/content/docs/en/tools/clay.mdx +++ b/apps/docs/content/docs/en/tools/clay.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/clickhouse.mdx b/apps/docs/content/docs/en/tools/clickhouse.mdx new file mode 100644 index 00000000000..f3c9837525b --- /dev/null +++ b/apps/docs/content/docs/en/tools/clickhouse.mdx @@ -0,0 +1,559 @@ +--- +title: ClickHouse +description: Connect to a ClickHouse database +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[ClickHouse](https://clickhouse.com) is an open-source, column-oriented database management system for online analytical processing (OLAP). It is built for speed at scale — running aggregations and analytical queries over billions of rows in real time. + +The ClickHouse block connects to any ClickHouse deployment (ClickHouse Cloud or self-hosted) over the [HTTP interface](https://clickhouse.com/docs/interfaces/http). Use it to run analytical queries, stream rows into tables, manage schemas, inspect system state, and execute arbitrary SQL — all from within a workflow. + +**Connection details** + +- **Host** — your ClickHouse hostname (e.g. `your-instance.clickhouse.cloud` or your server address). +- **Port** — the HTTP interface port. Use `8443` for HTTPS (ClickHouse Cloud) or `8123` for plain HTTP (self-hosted). +- **Database** / **Username** — default to `default` if not specified. +- **Password** — optional for unauthenticated local instances. +- **Use HTTPS** — keep enabled for any remote or Cloud instance. + +**Things to know** + +- `UPDATE` and `DELETE` are implemented as ClickHouse [mutations](https://clickhouse.com/docs/sql-reference/statements/alter/update) (`ALTER TABLE ... UPDATE/DELETE`). Mutations run **asynchronously** in the background, so the affected row count is not returned immediately. +- ClickHouse is optimized for bulk inserts. Prefer batching many rows per insert over many single-row inserts. +- The connection host is validated to block private/internal addresses, so the block cannot reach `localhost` or internal-only hosts. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate ClickHouse into the workflow. Query and insert data, manage databases and tables, inspect schemas, monitor mutations and running queries, manage partitions, and execute raw SQL over the ClickHouse HTTP interface. + + + +## Tools + +### `clickhouse_query` + +Execute a SELECT query on a ClickHouse database + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | ClickHouse server hostname \(e.g., your-instance.clickhouse.cloud\) | +| `port` | number | Yes | ClickHouse HTTP interface port \(8443 for HTTPS, 8123 for HTTP\) | +| `database` | string | Yes | Database name to connect to | +| `username` | string | Yes | ClickHouse username | +| `password` | string | No | ClickHouse password | +| `secure` | boolean | No | Use a secure HTTPS connection \(default: true\) | +| `query` | string | Yes | SQL SELECT query to execute | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Operation status message | +| `rows` | array | Array of rows returned from the query | +| `rowCount` | number | Number of rows returned | + +### `clickhouse_execute` + +Execute raw SQL (DDL, mutations, or queries) on a ClickHouse database + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | ClickHouse server hostname \(e.g., your-instance.clickhouse.cloud\) | +| `port` | number | Yes | ClickHouse HTTP interface port \(8443 for HTTPS, 8123 for HTTP\) | +| `database` | string | Yes | Database name to connect to | +| `username` | string | Yes | ClickHouse username | +| `password` | string | No | ClickHouse password | +| `secure` | boolean | No | Use a secure HTTPS connection \(default: true\) | +| `query` | string | Yes | Raw SQL statement to execute | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Operation status message | +| `rows` | array | Array of rows returned from the statement | +| `rowCount` | number | Number of rows returned or affected | + +### `clickhouse_insert` + +Insert a row into a ClickHouse table + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | ClickHouse server hostname \(e.g., your-instance.clickhouse.cloud\) | +| `port` | number | Yes | ClickHouse HTTP interface port \(8443 for HTTPS, 8123 for HTTP\) | +| `database` | string | Yes | Database name to connect to | +| `username` | string | Yes | ClickHouse username | +| `password` | string | No | ClickHouse password | +| `secure` | boolean | No | Use a secure HTTPS connection \(default: true\) | +| `table` | string | Yes | Table name to insert data into | +| `data` | object | Yes | Data object to insert \(key-value pairs mapping column names to values\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Operation status message | +| `rows` | array | Inserted rows \(empty for ClickHouse inserts\) | +| `rowCount` | number | Number of rows inserted | + +### `clickhouse_insert_rows` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_update` + +Update rows in a ClickHouse table via an ALTER TABLE ... UPDATE mutation + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | ClickHouse server hostname \(e.g., your-instance.clickhouse.cloud\) | +| `port` | number | Yes | ClickHouse HTTP interface port \(8443 for HTTPS, 8123 for HTTP\) | +| `database` | string | Yes | Database name to connect to | +| `username` | string | Yes | ClickHouse username | +| `password` | string | No | ClickHouse password | +| `secure` | boolean | No | Use a secure HTTPS connection \(default: true\) | +| `table` | string | Yes | Table name to update data in | +| `data` | object | Yes | Data object with fields to update \(key-value pairs\) | +| `where` | string | Yes | WHERE clause condition \(without the WHERE keyword\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Operation status message | +| `rows` | array | Updated rows \(empty for ClickHouse mutations\) | +| `rowCount` | number | Number of rows written by the mutation | + +### `clickhouse_delete` + +Delete rows from a ClickHouse table via an ALTER TABLE ... DELETE mutation + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | ClickHouse server hostname \(e.g., your-instance.clickhouse.cloud\) | +| `port` | number | Yes | ClickHouse HTTP interface port \(8443 for HTTPS, 8123 for HTTP\) | +| `database` | string | Yes | Database name to connect to | +| `username` | string | Yes | ClickHouse username | +| `password` | string | No | ClickHouse password | +| `secure` | boolean | No | Use a secure HTTPS connection \(default: true\) | +| `table` | string | Yes | Table name to delete data from | +| `where` | string | Yes | WHERE clause condition \(without the WHERE keyword\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Operation status message | +| `rows` | array | Deleted rows \(empty for ClickHouse mutations\) | +| `rowCount` | number | Number of rows affected by the mutation | + +### `clickhouse_list_databases` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_list_tables` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_describe_table` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_show_create_table` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_count_rows` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_introspect` + +Introspect a ClickHouse database to retrieve table structures, columns, and engines + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | ClickHouse server hostname \(e.g., your-instance.clickhouse.cloud\) | +| `port` | number | Yes | ClickHouse HTTP interface port \(8443 for HTTPS, 8123 for HTTP\) | +| `database` | string | Yes | Database name to introspect | +| `username` | string | Yes | ClickHouse username | +| `password` | string | No | ClickHouse password | +| `secure` | boolean | No | Use a secure HTTPS connection \(default: true\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Operation status message | +| `tables` | array | Array of table schemas with columns and engines | +| ↳ `name` | string | Table name | +| ↳ `database` | string | Database the table belongs to | +| ↳ `engine` | string | Table engine \(e.g., MergeTree, Log\) | +| ↳ `totalRows` | number | Approximate total number of rows in the table | +| ↳ `columns` | array | Table columns | +| ↳ `name` | string | Column name | +| ↳ `type` | string | ClickHouse data type \(e.g., UInt32, String, DateTime\) | +| ↳ `defaultKind` | string | Kind of default expression \(DEFAULT, MATERIALIZED, ALIAS\) | +| ↳ `defaultExpression` | string | Default value expression for the column | +| ↳ `isInPrimaryKey` | boolean | Whether the column is part of the primary key | +| ↳ `isInSortingKey` | boolean | Whether the column is part of the sorting key | + +### `clickhouse_create_database` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_drop_database` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_create_table` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_drop_table` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_truncate_table` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_rename_table` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_optimize_table` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_list_partitions` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_drop_partition` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_list_mutations` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_list_running_queries` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_kill_query` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_table_stats` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + +### `clickhouse_list_clusters` + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success or error message describing the operation outcome | +| `rows` | array | Array of rows returned from the operation | +| `rowCount` | number | Number of rows returned or affected by the operation | +| `count` | number | Row count \(count rows operation\) | +| `ddl` | string | CREATE TABLE statement \(show create table operation\) | +| `tables` | array | Array of table schemas with columns and engines \(introspect operation\) | + + diff --git a/apps/docs/content/docs/en/tools/confluence.mdx b/apps/docs/content/docs/en/tools/confluence.mdx index 967275020e4..8f49145ad31 100644 --- a/apps/docs/content/docs/en/tools/confluence.mdx +++ b/apps/docs/content/docs/en/tools/confluence.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/custom-tools.mdx b/apps/docs/content/docs/en/tools/custom-tools.mdx deleted file mode 100644 index a6455f832b6..00000000000 --- a/apps/docs/content/docs/en/tools/custom-tools.mdx +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: Custom Tools -description: Create your own tools with JavaScript code and use them in Agent blocks ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { Step, Steps } from 'fumadocs-ui/components/steps' -import { FAQ } from '@/components/ui/faq' - -Custom tools let you write your own JavaScript functions and make them available as callable tools in Agent blocks. This is useful when you need functionality that isn't covered by Sim's built-in integrations — for example, calling an internal API, performing a custom calculation, or transforming data in a specific way. - -## How Custom Tools Work - -A custom tool has two parts: - -1. **Schema** — A JSON definition describing the tool's name, description, and parameters (using the OpenAI function-calling format). This tells the AI agent what the tool does and what inputs it expects. -2. **Code** — A JavaScript function body that runs when the agent calls the tool. Parameters defined in the schema are available as variables in your code. - -When an Agent block has access to a custom tool, the AI model decides when to call it based on the schema description and the conversation context — just like built-in tools. - -## Creating a Custom Tool - - - - -### Open Custom Tools settings - -Navigate to **Settings → Custom Tools** in your workspace and click **Add**. - - - - -### Define the schema - -In the **Schema** tab, define your tool using JSON in the OpenAI function-calling format: - -```json -{ - "type": "function", - "function": { - "name": "get_weather", - "description": "Get the current weather for a city", - "parameters": { - "type": "object", - "properties": { - "city": { - "type": "string", - "description": "The city name" - }, - "units": { - "type": "string", - "enum": ["celsius", "fahrenheit"], - "description": "Temperature units" - } - }, - "required": ["city"] - } - } -} -``` - - - You can use the AI wand button to generate a schema from a natural language description of what the tool should do. - - - - - -### Write the code - -Switch to the **Code** tab and write the JavaScript function body. Parameters from your schema are available directly as variables: - -```javascript -const response = await fetch( - `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units === 'celsius' ? 'metric' : 'imperial'}&appid={{OPENWEATHER_API_KEY}}` -); - -const data = await response.json(); - -return { - temperature: data.main.temp, - description: data.weather[0].description, - humidity: data.main.humidity -}; -``` - - - You can also use the AI wand to generate code from a description. Environment variables are referenced with `{{KEY}}` syntax. - - - - - -### Save - -Click **Save** to create the tool. It's now available to use in any Agent block across your workspace. - - - - -## Using Custom Tools in Workflows - -Once created, custom tools appear alongside built-in tools when configuring an Agent block: - -1. Open an Agent block -2. Click **Add Tools** -3. Find your custom tool in the tool list -4. The agent will call the tool when it determines it's relevant to the task - -## Code Environment - -### Available Features - -- **Async/await** — Your code runs in an async context, so you can use `await` directly -- **fetch()** — Make HTTP requests to external APIs -- **Node.js built-ins** — Access to `crypto`, `Buffer`, and other standard modules -- **Environment variables** — Use `{{KEY}}` syntax to inject secrets - -### Limitations - -- **No npm packages** — External libraries like `axios` or `lodash` are not available. Use built-in APIs instead -- **Parameters by name** — Schema parameters are available directly as variables (e.g., `city`), not via a `params` object - -### Returning Results - -Return a value from your code to send it back to the agent: - -```javascript -const result = await fetch(`https://api.example.com/data?q=${query}`); -const data = await result.json(); -return data; -``` - -The returned value becomes the tool output that the agent sees and can use in its response. - -## Managing Custom Tools - -From **Settings → Custom Tools** you can: - -- **Search** tools by name, function name, or description -- **Edit** any tool's schema or code -- **Delete** tools that are no longer needed - - - Deleting a custom tool removes it from all Agent blocks that reference it. Make sure no active workflows depend on the tool before deleting. - - -## Permissions - -| Action | Required Permission | -|--------|-------------------| -| View custom tools | **Read**, **Write**, or **Admin** | -| Create or edit tools | **Write** or **Admin** | -| Delete tools | **Admin** | - - diff --git a/apps/docs/content/docs/en/tools/dagster.mdx b/apps/docs/content/docs/en/tools/dagster.mdx index b82c1a7f4ab..ef78e695e6e 100644 --- a/apps/docs/content/docs/en/tools/dagster.mdx +++ b/apps/docs/content/docs/en/tools/dagster.mdx @@ -73,8 +73,15 @@ Get the status and details of a Dagster run by its ID. | `runId` | string | Run ID | | `jobName` | string | Name of the job this run belongs to | | `status` | string | Run status \(QUEUED, NOT_STARTED, STARTING, MANAGED, STARTED, SUCCESS, FAILURE, CANCELING, CANCELED\) | +| `mode` | string | Execution mode of the run | | `startTime` | number | Run start time as Unix timestamp | | `endTime` | number | Run end time as Unix timestamp | +| `creationTime` | number | Time the run was created as Unix timestamp | +| `updateTime` | number | Time the run was last updated as Unix timestamp | +| `parentRunId` | string | ID of the immediate parent run \(for re-executions\) | +| `rootRunId` | string | ID of the root run in the re-execution group | +| `canTerminate` | boolean | Whether the run can currently be terminated | +| `assetSelection` | json | Asset keys targeted by the run, as slash-joined strings | | `runConfigYaml` | string | Run configuration as YAML | | `tags` | json | Run tags as array of \{key, value\} objects | @@ -108,7 +115,7 @@ Fetch execution event logs for a Dagster run. ### `dagster_list_runs` -List recent Dagster runs, optionally filtered by job name. +List Dagster runs with optional filters by job name, status, and creation-time range, plus cursor pagination. #### Input @@ -118,6 +125,9 @@ List recent Dagster runs, optionally filtered by job name. | `apiKey` | string | No | Dagster+ API token \(leave blank for OSS / self-hosted\) | | `jobName` | string | No | Filter runs by job name \(optional\) | | `statuses` | string | No | Comma-separated run statuses to filter by, e.g. "SUCCESS,FAILURE" \(optional\) | +| `createdAfter` | number | No | Only return runs created at or after this Unix timestamp in seconds \(optional\) | +| `createdBefore` | number | No | Only return runs created at or before this Unix timestamp in seconds \(optional\) | +| `cursor` | string | No | Run ID to page after, from a previous response cursor \(optional\) | | `limit` | number | No | Maximum number of runs to return \(default 20\) | #### Output @@ -131,6 +141,8 @@ List recent Dagster runs, optionally filtered by job name. | ↳ `tags` | json | Run tags as array of \{key, value\} objects | | ↳ `startTime` | number | Start time as Unix timestamp | | ↳ `endTime` | number | End time as Unix timestamp | +| `cursor` | string | Run ID of the last returned run — pass as cursor to fetch the next page | +| `hasMore` | boolean | Whether more runs are likely available beyond this page | ### `dagster_list_jobs` @@ -295,7 +307,7 @@ List all sensors in a Dagster repository, optionally filtered by status. | --------- | ---- | ----------- | | `sensors` | json | Array of sensors \(name, sensorType, status, id, description\) | | ↳ `name` | string | Sensor name | -| ↳ `sensorType` | string | Sensor type \(ASSET, AUTO_MATERIALIZE, FRESHNESS_POLICY, MULTI_ASSET, RUN_STATUS, STANDARD\) | +| ↳ `sensorType` | string | Sensor type \(ASSET, AUTO_MATERIALIZE, FRESHNESS_POLICY, MULTI_ASSET, RUN_STATUS, STANDARD, UNKNOWN\) | | ↳ `status` | string | Sensor status: RUNNING or STOPPED | | ↳ `id` | string | Instigator state ID — use this to start or stop the sensor | | ↳ `description` | string | Human-readable sensor description | @@ -340,4 +352,120 @@ Disable (stop) a running sensor in Dagster. | `id` | string | Instigator state ID of the sensor | | `status` | string | Updated sensor status \(RUNNING or STOPPED\) | +### `dagster_list_assets` + +List assets tracked by a Dagster instance, optionally filtered by key prefix. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | Dagster host URL \(e.g., https://myorg.dagster.cloud/prod or http://localhost:3001\) | +| `apiKey` | string | No | Dagster+ API token \(leave blank for OSS / self-hosted\) | +| `prefix` | string | No | Slash-delimited asset key prefix to filter by, e.g. "raw" or "raw/events" \(optional\) | +| `cursor` | string | No | Asset key cursor from a previous response, for pagination \(optional\) | +| `limit` | number | No | Maximum number of assets to return \(optional\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `assets` | json | Array of assets \(assetKey, path\) | +| ↳ `assetKey` | string | Slash-joined asset key | +| ↳ `path` | json | Asset key path segments | +| `cursor` | string | Cursor to pass on the next call to fetch more assets | +| `hasMore` | boolean | Whether more assets are likely available beyond this page | + +### `dagster_get_asset` + +Get an asset definition and its latest materialization by asset key. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | Dagster host URL \(e.g., https://myorg.dagster.cloud/prod or http://localhost:3001\) | +| `apiKey` | string | No | Dagster+ API token \(leave blank for OSS / self-hosted\) | +| `assetKey` | string | Yes | Slash-delimited asset key, e.g. "my_asset" or "raw/events" | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `assetKey` | string | Slash-joined asset key | +| `path` | json | Asset key path segments | +| `groupName` | string | Asset group the definition belongs to | +| `description` | string | Asset description | +| `jobNames` | json | Names of jobs that can materialize this asset | +| `computeKind` | string | Compute kind tag \(e.g., python, dbt, spark\) | +| `isPartitioned` | boolean | Whether the asset is partitioned | +| `latestMaterialization` | json | Most recent materialization \(runId, timestamp, partition, stepKey\) | +| ↳ `runId` | string | Run that produced the materialization | +| ↳ `timestamp` | string | Materialization timestamp \(epoch ms string\) | +| ↳ `partition` | string | Partition key, if partitioned | +| ↳ `stepKey` | string | Step key that emitted it | + +### `dagster_materialize_assets` + +Materialize selected assets by launching their asset job with an asset selection. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | Dagster host URL \(e.g., https://myorg.dagster.cloud/prod or http://localhost:3001\) | +| `apiKey` | string | No | Dagster+ API token \(leave blank for OSS / self-hosted\) | +| `repositoryLocationName` | string | Yes | Repository location \(code location\) name | +| `repositoryName` | string | Yes | Repository name within the code location | +| `jobName` | string | Yes | Asset job that contains the assets, e.g. "__ASSET_JOB" or a named asset job | +| `assetSelection` | string | Yes | Comma- or newline-separated asset keys to materialize, each slash-delimited \(e.g. "raw/events, summary"\) | +| `tags` | string | No | Tags as a JSON array of \{key, value\} objects \(optional\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `runId` | string | The globally unique ID of the launched materialization run | + +### `dagster_report_asset_materialization` + +Report an external (runless) materialization or observation for an asset. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | Dagster host URL \(e.g., https://myorg.dagster.cloud/prod or http://localhost:3001\) | +| `apiKey` | string | No | Dagster+ API token \(leave blank for OSS / self-hosted\) | +| `assetKey` | string | Yes | Slash-delimited asset key to report against, e.g. "my_asset" or "raw/events" | +| `eventType` | string | No | Event type to report: ASSET_MATERIALIZATION \(default\) or ASSET_OBSERVATION | +| `partitionKeys` | string | No | Comma-separated partition keys to report against \(optional\) | +| `description` | string | No | Human-readable description for the reported event \(optional\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the event was reported successfully | +| `assetKey` | string | Slash-joined asset key the event was reported against | + +### `dagster_wipe_asset` + +DESTRUCTIVE: permanently wipes ALL materialization history (every partition) for an asset. This cannot be undone. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `host` | string | Yes | Dagster host URL \(e.g., https://myorg.dagster.cloud/prod or http://localhost:3001\) | +| `apiKey` | string | No | Dagster+ API token \(leave blank for OSS / self-hosted\) | +| `assetKey` | string | Yes | Slash-delimited asset key to wipe, e.g. "my_asset" or "raw/events" | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the asset was wiped successfully | +| `assetKey` | string | Slash-joined asset key that was wiped | + diff --git a/apps/docs/content/docs/en/tools/dspy.mdx b/apps/docs/content/docs/en/tools/dspy.mdx index 5730c4e5477..a73007d739e 100644 --- a/apps/docs/content/docs/en/tools/dspy.mdx +++ b/apps/docs/content/docs/en/tools/dspy.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/elasticsearch.mdx b/apps/docs/content/docs/en/tools/elasticsearch.mdx index 5eaf4ae42e6..bf84fc77a21 100644 --- a/apps/docs/content/docs/en/tools/elasticsearch.mdx +++ b/apps/docs/content/docs/en/tools/elasticsearch.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/evernote.mdx b/apps/docs/content/docs/en/tools/evernote.mdx index a54840288f1..3a31f07459d 100644 --- a/apps/docs/content/docs/en/tools/evernote.mdx +++ b/apps/docs/content/docs/en/tools/evernote.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/file.mdx b/apps/docs/content/docs/en/tools/file.mdx deleted file mode 100644 index d167ae3f8a7..00000000000 --- a/apps/docs/content/docs/en/tools/file.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: File -description: Read, fetch, write, and append files ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -The File Parser tool provides a powerful way to extract and process content from various file formats, making it easy to incorporate document data into your agent workflows. This tool supports multiple file formats and can handle files up to 200MB in size. - -With the File Parser, you can: - -- **Process multiple file formats**: Extract text from PDFs, CSVs, Word documents (DOCX), text files, and more -- **Handle large files**: Process documents up to 200MB in size -- **Parse files from URLs**: Directly extract content from files hosted online by providing their URLs -- **Process multiple files at once**: Upload and parse several files in a single operation -- **Extract structured data**: Maintain formatting and structure from the original documents when possible - -The File Parser tool is particularly useful for scenarios where your agents need to work with document content, such as analyzing reports, extracting data from spreadsheets, or processing text from various document sources. It simplifies the process of making document content available to your agents, allowing them to work with information stored in files just as easily as with direct text input. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Read workspace files by picker or canonical ID, fetch and parse files from URLs with optional headers, write new workspace files, or append content to existing files. - - - -## Tools - -### `file_fetch` - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `file` | file | First workspace file object \(read\) | -| `files` | file[] | Workspace file objects \(read\) or fetched file objects \(fetch\) | -| `combinedContent` | string | All fetched file contents merged into a single text string \(fetch\) | -| `id` | string | File ID \(write\) | -| `name` | string | File name \(write\) | -| `size` | number | File size in bytes \(write\) | -| `url` | string | URL to access the file \(write\) | - -### `file_read` - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `file` | file | First workspace file object \(read\) | -| `files` | file[] | Workspace file objects \(read\) or fetched file objects \(fetch\) | -| `combinedContent` | string | All fetched file contents merged into a single text string \(fetch\) | -| `id` | string | File ID \(write\) | -| `name` | string | File name \(write\) | -| `size` | number | File size in bytes \(write\) | -| `url` | string | URL to access the file \(write\) | - -### `file_write` - -Create a new workspace file. If a file with the same name already exists, a numeric suffix is added (e.g., - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `fileName` | string | Yes | File name \(e.g., "data.csv"\). If a file with this name exists, a numeric suffix is added automatically. | -| `content` | string | Yes | The text content to write to the file. | -| `contentType` | string | No | MIME type for new files \(e.g., "text/plain"\). Auto-detected from file extension if omitted. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `id` | string | File ID | -| `name` | string | File name | -| `size` | number | File size in bytes | -| `url` | string | URL to access the file | - -### `file_append` - -Append content to an existing workspace file. The file must already exist. Content is added to the end of the file. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `fileName` | string | Yes | Name of an existing workspace file to append to. | -| `content` | string | Yes | The text content to append to the file. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `id` | string | File ID | -| `name` | string | File name | -| `size` | number | File size in bytes | -| `url` | string | URL to access the file | - - diff --git a/apps/docs/content/docs/en/tools/gitlab.mdx b/apps/docs/content/docs/en/tools/gitlab.mdx index e1b68a35ef0..64395a4178e 100644 --- a/apps/docs/content/docs/en/tools/gitlab.mdx +++ b/apps/docs/content/docs/en/tools/gitlab.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/gmail.mdx b/apps/docs/content/docs/en/tools/gmail.mdx index 5aceafc2f6e..2a19aecc6f1 100644 --- a/apps/docs/content/docs/en/tools/gmail.mdx +++ b/apps/docs/content/docs/en/tools/gmail.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_ads.mdx b/apps/docs/content/docs/en/tools/google_ads.mdx index cadc9af6fe4..5972f683e8f 100644 --- a/apps/docs/content/docs/en/tools/google_ads.mdx +++ b/apps/docs/content/docs/en/tools/google_ads.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_bigquery.mdx b/apps/docs/content/docs/en/tools/google_bigquery.mdx index 609a6928559..048407c0fcf 100644 --- a/apps/docs/content/docs/en/tools/google_bigquery.mdx +++ b/apps/docs/content/docs/en/tools/google_bigquery.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_books.mdx b/apps/docs/content/docs/en/tools/google_books.mdx index 6ab604483d2..7b3c77df1d3 100644 --- a/apps/docs/content/docs/en/tools/google_books.mdx +++ b/apps/docs/content/docs/en/tools/google_books.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_calendar.mdx b/apps/docs/content/docs/en/tools/google_calendar.mdx index 875b56d5d5d..825c2e109db 100644 --- a/apps/docs/content/docs/en/tools/google_calendar.mdx +++ b/apps/docs/content/docs/en/tools/google_calendar.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_contacts.mdx b/apps/docs/content/docs/en/tools/google_contacts.mdx index b68c303a578..461aa7d4563 100644 --- a/apps/docs/content/docs/en/tools/google_contacts.mdx +++ b/apps/docs/content/docs/en/tools/google_contacts.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" ## Usage Instructions diff --git a/apps/docs/content/docs/en/tools/google_docs.mdx b/apps/docs/content/docs/en/tools/google_docs.mdx index 069c91f8f6c..b4b17f34992 100644 --- a/apps/docs/content/docs/en/tools/google_docs.mdx +++ b/apps/docs/content/docs/en/tools/google_docs.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_drive.mdx b/apps/docs/content/docs/en/tools/google_drive.mdx index 629296fe92d..5e5b3d409be 100644 --- a/apps/docs/content/docs/en/tools/google_drive.mdx +++ b/apps/docs/content/docs/en/tools/google_drive.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_forms.mdx b/apps/docs/content/docs/en/tools/google_forms.mdx index fd463521fab..a828ec9c61b 100644 --- a/apps/docs/content/docs/en/tools/google_forms.mdx +++ b/apps/docs/content/docs/en/tools/google_forms.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_maps.mdx b/apps/docs/content/docs/en/tools/google_maps.mdx index 5439d99cbf1..958c36165a4 100644 --- a/apps/docs/content/docs/en/tools/google_maps.mdx +++ b/apps/docs/content/docs/en/tools/google_maps.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_meet.mdx b/apps/docs/content/docs/en/tools/google_meet.mdx index f7b94f5db60..d7a294dbf8a 100644 --- a/apps/docs/content/docs/en/tools/google_meet.mdx +++ b/apps/docs/content/docs/en/tools/google_meet.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_pagespeed.mdx b/apps/docs/content/docs/en/tools/google_pagespeed.mdx index d2cd247c851..6ce1231e5fd 100644 --- a/apps/docs/content/docs/en/tools/google_pagespeed.mdx +++ b/apps/docs/content/docs/en/tools/google_pagespeed.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_search.mdx b/apps/docs/content/docs/en/tools/google_search.mdx index 480ea4a1313..f6b8461b1d2 100644 --- a/apps/docs/content/docs/en/tools/google_search.mdx +++ b/apps/docs/content/docs/en/tools/google_search.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_sheets.mdx b/apps/docs/content/docs/en/tools/google_sheets.mdx index ac2f470a04b..e7efb3a8804 100644 --- a/apps/docs/content/docs/en/tools/google_sheets.mdx +++ b/apps/docs/content/docs/en/tools/google_sheets.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_slides.mdx b/apps/docs/content/docs/en/tools/google_slides.mdx index ef62d931d49..c199362415d 100644 --- a/apps/docs/content/docs/en/tools/google_slides.mdx +++ b/apps/docs/content/docs/en/tools/google_slides.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_tasks.mdx b/apps/docs/content/docs/en/tools/google_tasks.mdx index d18f69defc6..c6997c3490b 100644 --- a/apps/docs/content/docs/en/tools/google_tasks.mdx +++ b/apps/docs/content/docs/en/tools/google_tasks.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/google_translate.mdx b/apps/docs/content/docs/en/tools/google_translate.mdx index a3b835f11be..288ce7a6698 100644 --- a/apps/docs/content/docs/en/tools/google_translate.mdx +++ b/apps/docs/content/docs/en/tools/google_translate.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/grafana.mdx b/apps/docs/content/docs/en/tools/grafana.mdx index 47cbd9983d9..0636bf3726d 100644 --- a/apps/docs/content/docs/en/tools/grafana.mdx +++ b/apps/docs/content/docs/en/tools/grafana.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/hunter.mdx b/apps/docs/content/docs/en/tools/hunter.mdx index 113cbcc7e63..492edc864ca 100644 --- a/apps/docs/content/docs/en/tools/hunter.mdx +++ b/apps/docs/content/docs/en/tools/hunter.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/image_generator.mdx b/apps/docs/content/docs/en/tools/image_generator.mdx deleted file mode 100644 index 360d0a4ca3f..00000000000 --- a/apps/docs/content/docs/en/tools/image_generator.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: Image Generator -description: Generate images ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -The Image Generator block creates images from text prompts using leading image generation providers. Choose OpenAI for GPT Image models, Google Gemini for Nano Banana models, or Fal.ai for a multi-model catalog that includes Nano Banana, GPT Image, Seedream, FLUX, and Grok Imagine. - -Use it to: - -- **Generate production images**: Create polished visuals from workflow prompts -- **Choose the right provider**: Route requests to OpenAI, Gemini, or Fal.ai based on model availability and cost -- **Control output shape**: Set provider-specific size, aspect ratio, resolution, quality, background, and output format options -- **Use advanced Fal.ai features**: Configure safety tolerance, safety checking, web search grounding, seeds, and thinking level when supported -- **Pass generated files downstream**: Use the returned image file or URL in later workflow steps - -In Sim, the Image Generator block lets agents create visual assets programmatically as part of automated workflows. This is useful for content creation, design mockups, product visuals, creative ideation, and any flow that needs generated imagery without a manual handoff. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Generate images using OpenAI GPT Image, Google Nano Banana, or Fal.ai image models. - - - -## Tools - -### `image_generate` - -Generate images with OpenAI GPT Image, Google Nano Banana, or Fal.ai image models - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | Image generation provider: openai, gemini, or falai | -| `apiKey` | string | Yes | Provider API key | -| `model` | string | Yes | Provider model ID, such as gpt-image-1.5, gemini-3.1-flash-image-preview, or nano-banana-2 | -| `prompt` | string | Yes | Text prompt describing the image to generate | -| `size` | string | No | Provider-specific image size | -| `aspectRatio` | string | No | Aspect ratio, such as auto, 1:1, 16:9, or 9:16 | -| `resolution` | string | No | Provider-specific image resolution, such as 1K, 2K, 4K, 1k, or 2k | -| `quality` | string | No | Provider-specific image quality | -| `background` | string | No | Background setting when supported | -| `outputFormat` | string | No | Output image format: png, jpeg, or webp where supported | -| `moderation` | string | No | OpenAI moderation level: auto or low | -| `safetyTolerance` | string | No | Fal.ai safety tolerance when supported | -| `numImages` | number | No | Number of images to generate, subject to provider limits | -| `seed` | number | No | Random seed when supported | -| `enableSafetyChecker` | boolean | No | Enable the Fal.ai safety checker when supported | -| `enableWebSearch` | boolean | No | Enable web search grounding when supported by the selected Fal.ai model | -| `thinkingLevel` | string | No | Fal.ai thinking level when supported: minimal or high | -| `pricing` | custom | No | No description | -| `metadata` | string | No | No description | -| `rateLimit` | string | No | No description | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `content` | string | Generated image URL or identifier | -| `image` | file | Generated image file | -| `imageUrl` | string | Generated image URL | -| `provider` | string | Provider used | -| `model` | string | Model used | -| `metadata` | json | Generation metadata | -| ↳ `provider` | string | Provider used | -| ↳ `model` | string | Model used | -| ↳ `description` | string | Provider description | -| ↳ `revisedPrompt` | string | Revised prompt | -| ↳ `seed` | number | Seed used for generation | -| ↳ `jobId` | string | Provider job ID | -| ↳ `contentType` | string | Image MIME type | - - diff --git a/apps/docs/content/docs/en/tools/imap.mdx b/apps/docs/content/docs/en/tools/imap.mdx deleted file mode 100644 index 37bb0016a81..00000000000 --- a/apps/docs/content/docs/en/tools/imap.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: IMAP Email -description: Trigger workflows when new emails arrive via IMAP (works with any email provider) ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -The IMAP Email trigger allows your Sim workflows to start automatically whenever a new email is received in any mailbox that supports the IMAP protocol. This works with Gmail, Outlook, Yahoo, and most other email providers. - -With the IMAP trigger, you can: - -- **Automate email processing**: Start workflows in real time when new messages arrive in your inbox. -- **Filter by sender, subject, or folder**: Configure your trigger to react only to emails that match certain conditions. -- **Extract and process attachments**: Automatically download and use file attachments in your automated flows. -- **Parse and use email content**: Access the subject, sender, recipients, full body, and other metadata in downstream workflow steps. -- **Integrate with any email provider**: Works with any service that provides standard IMAP access, without vendor lock-in. -- **Trigger on unread, flagged, or custom criteria**: Set up advanced filters for the kinds of emails that start your workflows. - -With Sim, the IMAP integration gives you the power to turn email into an actionable source of automation. Respond to customer inquiries, process notifications, kick off data pipelines, and more—directly from your email inbox, with no manual intervention. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Connect to any email server via IMAP protocol to trigger workflows when new emails are received. Supports Gmail, Outlook, Yahoo, and any other IMAP-compatible email provider. - - - - diff --git a/apps/docs/content/docs/en/tools/incidentio.mdx b/apps/docs/content/docs/en/tools/incidentio.mdx index 5d10442a33b..9c97413810e 100644 --- a/apps/docs/content/docs/en/tools/incidentio.mdx +++ b/apps/docs/content/docs/en/tools/incidentio.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/intercom.mdx b/apps/docs/content/docs/en/tools/intercom.mdx index 6330cb03655..2183765ba07 100644 --- a/apps/docs/content/docs/en/tools/intercom.mdx +++ b/apps/docs/content/docs/en/tools/intercom.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/jira.mdx b/apps/docs/content/docs/en/tools/jira.mdx index 7164372612f..6df2f92b602 100644 --- a/apps/docs/content/docs/en/tools/jira.mdx +++ b/apps/docs/content/docs/en/tools/jira.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/jira_service_management.mdx b/apps/docs/content/docs/en/tools/jira_service_management.mdx index 04aed8404ca..efd1ca28a4f 100644 --- a/apps/docs/content/docs/en/tools/jira_service_management.mdx +++ b/apps/docs/content/docs/en/tools/jira_service_management.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/mailgun.mdx b/apps/docs/content/docs/en/tools/mailgun.mdx index 547f525785e..ef501aa628c 100644 --- a/apps/docs/content/docs/en/tools/mailgun.mdx +++ b/apps/docs/content/docs/en/tools/mailgun.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/memory.mdx b/apps/docs/content/docs/en/tools/memory.mdx deleted file mode 100644 index ba5fcddf87a..00000000000 --- a/apps/docs/content/docs/en/tools/memory.mdx +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Memory -description: Add memory store ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -The Memory tool enables your agents to store, retrieve, and manage conversation memories across workflows. It acts as a persistent memory store that agents can access to maintain conversation context, recall facts, or track actions over time. - -With the Memory tool, you can: - -- **Add new memories**: Store relevant information, events, or conversation history by saving agent or user messages into a structured memory database -- **Retrieve memories**: Fetch specific memories or all memories tied to a conversation, helping agents recall previous interactions or facts -- **Delete memories**: Remove outdated or incorrect memories from the database to maintain accurate context -- **Append to existing conversations**: Update or expand on existing memory threads by appending new messages with the same conversation identifier - -Sim’s Memory block is especially useful for building agents that require persistent state—helping them remember what was said earlier in a conversation, persist facts between tasks, or apply long-term history in decision-making. By integrating Memory, you enable richer, more contextual, and more dynamic workflows for your agents. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Integrate Memory into the workflow. Can add, get a memory, get all memories, and delete memories. - - - -## Tools - -### `memory_add` - -Add a new memory to the database or append to existing memory with the same ID. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `conversationId` | string | No | Conversation identifier \(e.g., user-123, session-abc\). If a memory with this conversationId already exists, the new message will be appended to it. | -| `id` | string | No | Legacy parameter for conversation identifier. Use conversationId instead. Provided for backwards compatibility. | -| `role` | string | Yes | Role for agent memory \(user, assistant, or system\) | -| `content` | string | Yes | Content for agent memory | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the memory was added successfully | -| `memories` | array | Array of memory objects including the new or updated memory | -| `error` | string | Error message if operation failed | - -### `memory_get` - -Retrieve memory by conversationId. Returns matching memories. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `conversationId` | string | No | Conversation identifier \(e.g., user-123, session-abc\). Returns memories for this conversation. | -| `id` | string | No | Legacy parameter for conversation identifier. Use conversationId instead. Provided for backwards compatibility. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the memory was retrieved successfully | -| `memories` | array | Array of memory objects with conversationId and data fields | -| `message` | string | Success or error message | -| `error` | string | Error message if operation failed | - -### `memory_get_all` - -Retrieve all memories from the database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether all memories were retrieved successfully | -| `memories` | array | Array of all memory objects with key, conversationId, and data fields | -| `message` | string | Success or error message | -| `error` | string | Error message if operation failed | - -### `memory_delete` - -Delete memories by conversationId. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `conversationId` | string | No | Conversation identifier \(e.g., user-123, session-abc\). Deletes all memories for this conversation. | -| `id` | string | No | Legacy parameter for conversation identifier. Use conversationId instead. Provided for backwards compatibility. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the memory was deleted successfully | -| `message` | string | Success or error message | -| `error` | string | Error message if operation failed | - - diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index a17c92d28e7..34f971e492b 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -1,7 +1,6 @@ { "pages": [ "index", - "a2a", "agentmail", "agentphone", "agiloft", @@ -24,16 +23,15 @@ "browser_use", "calcom", "calendly", - "circleback", "clay", "clerk", + "clickhouse", "cloudflare", "cloudformation", "cloudwatch", "confluence", "crowdstrike", "cursor", - "custom-tools", "dagster", "databricks", "datadog", @@ -54,7 +52,6 @@ "exa", "extend", "fathom", - "file", "findymail", "firecrawl", "fireflies", @@ -92,8 +89,6 @@ "hunter", "iam", "identity_center", - "image_generator", - "imap", "incidentio", "infisical", "instantly", @@ -103,7 +98,6 @@ "jira_service_management", "kalshi", "ketch", - "knowledge", "langsmith", "launchdarkly", "lemlist", @@ -116,7 +110,6 @@ "mailchimp", "mailgun", "mem0", - "memory", "microsoft_ad", "microsoft_dataverse", "microsoft_excel", @@ -125,7 +118,6 @@ "mistral_parse", "monday", "mongodb", - "mysql", "neo4j", "new_relic", "notion", @@ -142,7 +134,6 @@ "pinecone", "pipedrive", "polymarket", - "postgresql", "posthog", "profound", "prospeo", @@ -163,42 +154,33 @@ "salesforce", "sap_concur", "sap_s4hana", - "search", "secrets_manager", "sendgrid", "sentry", "serper", "servicenow", "ses", - "sftp", "sharepoint", "shopify", "similarweb", "sixtyfour", "slack", - "smtp", "sqs", - "ssh", "stagehand", "stripe", "sts", - "stt", "supabase", - "table", "tailscale", "tavily", "telegram", "textract", "tinybird", - "translate", "trello", - "tts", "twilio_sms", "twilio_voice", "typeform", "upstash", "vercel", - "video_generator", "wealthbox", "webflow", "whatsapp", diff --git a/apps/docs/content/docs/en/tools/microsoft_dataverse.mdx b/apps/docs/content/docs/en/tools/microsoft_dataverse.mdx index e548c0ea0ef..eb3a5051f23 100644 --- a/apps/docs/content/docs/en/tools/microsoft_dataverse.mdx +++ b/apps/docs/content/docs/en/tools/microsoft_dataverse.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/microsoft_excel.mdx b/apps/docs/content/docs/en/tools/microsoft_excel.mdx index 08733e5eb30..35912dae3dd 100644 --- a/apps/docs/content/docs/en/tools/microsoft_excel.mdx +++ b/apps/docs/content/docs/en/tools/microsoft_excel.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/microsoft_planner.mdx b/apps/docs/content/docs/en/tools/microsoft_planner.mdx index df2a1259278..9e88d5a50b7 100644 --- a/apps/docs/content/docs/en/tools/microsoft_planner.mdx +++ b/apps/docs/content/docs/en/tools/microsoft_planner.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/microsoft_teams.mdx b/apps/docs/content/docs/en/tools/microsoft_teams.mdx index 0d86d9aaa72..5523fe8d148 100644 --- a/apps/docs/content/docs/en/tools/microsoft_teams.mdx +++ b/apps/docs/content/docs/en/tools/microsoft_teams.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/mongodb.mdx b/apps/docs/content/docs/en/tools/mongodb.mdx index e785fa34c3b..b04d6337415 100644 --- a/apps/docs/content/docs/en/tools/mongodb.mdx +++ b/apps/docs/content/docs/en/tools/mongodb.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/mysql.mdx b/apps/docs/content/docs/en/tools/mysql.mdx deleted file mode 100644 index 27e34d190db..00000000000 --- a/apps/docs/content/docs/en/tools/mysql.mdx +++ /dev/null @@ -1,183 +0,0 @@ ---- -title: MySQL -description: Connect to MySQL database ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -The [MySQL](https://www.mysql.com/) tool enables you to connect to any MySQL database and perform a wide range of database operations directly within your agentic workflows. With secure connection handling and flexible configuration, you can easily manage and interact with your data. - -With the MySQL tool, you can: - -- **Query data**: Execute SELECT queries to retrieve data from your MySQL tables using the `mysql_query` operation. -- **Insert records**: Add new rows to your tables with the `mysql_insert` operation by specifying the table and data to insert. -- **Update records**: Modify existing data in your tables using the `mysql_update` operation, providing the table, new data, and WHERE conditions. -- **Delete records**: Remove rows from your tables with the `mysql_delete` operation, specifying the table and WHERE conditions. -- **Execute raw SQL**: Run any custom SQL command using the `mysql_execute` operation for advanced use cases. - -The MySQL tool is ideal for scenarios where your agents need to interact with structured data—such as automating reporting, syncing data between systems, or powering data-driven workflows. It streamlines database access, making it easy to read, write, and manage your MySQL data programmatically. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Integrate MySQL into the workflow. Can query, insert, update, delete, and execute raw SQL. - - - -## Tools - -### `mysql_query` - -Execute SELECT query on MySQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | MySQL server hostname or IP address | -| `port` | number | Yes | MySQL server port \(default: 3306\) | -| `database` | string | Yes | Database name to connect to \(e.g., my_database\) | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `query` | string | Yes | SQL SELECT query to execute \(e.g., SELECT * FROM users WHERE active = 1\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Array of rows returned from the query | -| `rowCount` | number | Number of rows returned | - -### `mysql_insert` - -Insert new record into MySQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | MySQL server hostname or IP address | -| `port` | number | Yes | MySQL server port \(default: 3306\) | -| `database` | string | Yes | Database name to connect to \(e.g., my_database\) | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `table` | string | Yes | Table name to insert into \(e.g., users, orders\) | -| `data` | object | Yes | Data to insert as key-value pairs | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Array of inserted rows | -| `rowCount` | number | Number of rows inserted | - -### `mysql_update` - -Update existing records in MySQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | MySQL server hostname or IP address | -| `port` | number | Yes | MySQL server port \(default: 3306\) | -| `database` | string | Yes | Database name to connect to \(e.g., my_database\) | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `table` | string | Yes | Table name to update \(e.g., users, orders\) | -| `data` | object | Yes | Data to update as key-value pairs | -| `where` | string | Yes | WHERE clause condition \(without WHERE keyword\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Array of updated rows | -| `rowCount` | number | Number of rows updated | - -### `mysql_delete` - -Delete records from MySQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | MySQL server hostname or IP address | -| `port` | number | Yes | MySQL server port \(default: 3306\) | -| `database` | string | Yes | Database name to connect to \(e.g., my_database\) | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `table` | string | Yes | Table name to delete from \(e.g., users, orders\) | -| `where` | string | Yes | WHERE clause condition \(without WHERE keyword\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Array of deleted rows | -| `rowCount` | number | Number of rows deleted | - -### `mysql_execute` - -Execute raw SQL query on MySQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | MySQL server hostname or IP address | -| `port` | number | Yes | MySQL server port \(default: 3306\) | -| `database` | string | Yes | Database name to connect to \(e.g., my_database\) | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `query` | string | Yes | Raw SQL query to execute \(e.g., CREATE TABLE users \(id INT PRIMARY KEY, name VARCHAR\(255\)\)\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Array of rows returned from the query | -| `rowCount` | number | Number of rows affected | - -### `mysql_introspect` - -Introspect MySQL database schema to retrieve table structures, columns, and relationships - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | MySQL server hostname or IP address | -| `port` | number | Yes | MySQL server port \(default: 3306\) | -| `database` | string | Yes | Database name to connect to \(e.g., my_database\) | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `tables` | array | Array of table schemas with columns, keys, and indexes | -| `databases` | array | List of available databases on the server | - - diff --git a/apps/docs/content/docs/en/tools/onedrive.mdx b/apps/docs/content/docs/en/tools/onedrive.mdx index 2326f5e0f0b..b20dea513cb 100644 --- a/apps/docs/content/docs/en/tools/onedrive.mdx +++ b/apps/docs/content/docs/en/tools/onedrive.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/onepassword.mdx b/apps/docs/content/docs/en/tools/onepassword.mdx index 7d35c55b47b..c9723cdaced 100644 --- a/apps/docs/content/docs/en/tools/onepassword.mdx +++ b/apps/docs/content/docs/en/tools/onepassword.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/outlook.mdx b/apps/docs/content/docs/en/tools/outlook.mdx index aa31a8ff5e9..04f4075aea9 100644 --- a/apps/docs/content/docs/en/tools/outlook.mdx +++ b/apps/docs/content/docs/en/tools/outlook.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/parallel_ai.mdx b/apps/docs/content/docs/en/tools/parallel_ai.mdx index 55dbfaf10e3..b693afa7e72 100644 --- a/apps/docs/content/docs/en/tools/parallel_ai.mdx +++ b/apps/docs/content/docs/en/tools/parallel_ai.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/postgresql.mdx b/apps/docs/content/docs/en/tools/postgresql.mdx deleted file mode 100644 index ee4a7678372..00000000000 --- a/apps/docs/content/docs/en/tools/postgresql.mdx +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: PostgreSQL -description: Connect to PostgreSQL database ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -The [PostgreSQL](https://www.postgresql.org/) tool enables you to connect to any PostgreSQL database and perform a wide range of database operations directly within your agentic workflows. With secure connection handling and flexible configuration, you can easily manage and interact with your data. - -With the PostgreSQL tool, you can: - -- **Query data**: Execute SELECT queries to retrieve data from your PostgreSQL tables using the `postgresql_query` operation. -- **Insert records**: Add new rows to your tables with the `postgresql_insert` operation by specifying the table and data to insert. -- **Update records**: Modify existing data in your tables using the `postgresql_update` operation, providing the table, new data, and WHERE conditions. -- **Delete records**: Remove rows from your tables with the `postgresql_delete` operation, specifying the table and WHERE conditions. -- **Execute raw SQL**: Run any custom SQL command using the `postgresql_execute` operation for advanced use cases. - -The PostgreSQL tool is ideal for scenarios where your agents need to interact with structured data—such as automating reporting, syncing data between systems, or powering data-driven workflows. It streamlines database access, making it easy to read, write, and manage your PostgreSQL data programmatically. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Integrate PostgreSQL into the workflow. Can query, insert, update, delete, and execute raw SQL. - - - -## Tools - -### `postgresql_query` - -Execute a SELECT query on PostgreSQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | PostgreSQL server hostname or IP address | -| `port` | number | Yes | PostgreSQL server port \(default: 5432\) | -| `database` | string | Yes | Database name to connect to | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `query` | string | Yes | SQL SELECT query to execute | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Array of rows returned from the query | -| `rowCount` | number | Number of rows returned | - -### `postgresql_insert` - -Insert data into PostgreSQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | PostgreSQL server hostname or IP address | -| `port` | number | Yes | PostgreSQL server port \(default: 5432\) | -| `database` | string | Yes | Database name to connect to | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `table` | string | Yes | Table name to insert data into | -| `data` | object | Yes | Data object to insert \(key-value pairs\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Inserted data \(if RETURNING clause used\) | -| `rowCount` | number | Number of rows inserted | - -### `postgresql_update` - -Update data in PostgreSQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | PostgreSQL server hostname or IP address | -| `port` | number | Yes | PostgreSQL server port \(default: 5432\) | -| `database` | string | Yes | Database name to connect to | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `table` | string | Yes | Table name to update data in | -| `data` | object | Yes | Data object with fields to update \(key-value pairs\) | -| `where` | string | Yes | WHERE clause condition \(without WHERE keyword\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Updated data \(if RETURNING clause used\) | -| `rowCount` | number | Number of rows updated | - -### `postgresql_delete` - -Delete data from PostgreSQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | PostgreSQL server hostname or IP address | -| `port` | number | Yes | PostgreSQL server port \(default: 5432\) | -| `database` | string | Yes | Database name to connect to | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `table` | string | Yes | Table name to delete data from | -| `where` | string | Yes | WHERE clause condition \(without WHERE keyword\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Deleted data \(if RETURNING clause used\) | -| `rowCount` | number | Number of rows deleted | - -### `postgresql_execute` - -Execute raw SQL query on PostgreSQL database - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | PostgreSQL server hostname or IP address | -| `port` | number | Yes | PostgreSQL server port \(default: 5432\) | -| `database` | string | Yes | Database name to connect to | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `query` | string | Yes | Raw SQL query to execute | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `rows` | array | Array of rows returned from the query | -| `rowCount` | number | Number of rows affected | - -### `postgresql_introspect` - -Introspect PostgreSQL database schema to retrieve table structures, columns, and relationships - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | PostgreSQL server hostname or IP address | -| `port` | number | Yes | PostgreSQL server port \(default: 5432\) | -| `database` | string | Yes | Database name to connect to | -| `username` | string | Yes | Database username | -| `password` | string | Yes | Database password | -| `ssl` | string | No | SSL connection mode \(disabled, required, preferred\) | -| `schema` | string | No | Schema to introspect \(default: public\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `message` | string | Operation status message | -| `tables` | array | Array of table schemas with columns, keys, and indexes | -| ↳ `name` | string | Table name | -| ↳ `schema` | string | Schema name \(e.g., public\) | -| ↳ `columns` | array | Table columns | -| ↳ `name` | string | Column name | -| ↳ `type` | string | Data type \(e.g., integer, varchar, timestamp\) | -| ↳ `nullable` | boolean | Whether the column allows NULL values | -| ↳ `default` | string | Default value expression | -| ↳ `isPrimaryKey` | boolean | Whether the column is part of the primary key | -| ↳ `isForeignKey` | boolean | Whether the column is a foreign key | -| ↳ `references` | object | Foreign key reference information | -| ↳ `table` | string | Referenced table name | -| ↳ `column` | string | Referenced column name | -| ↳ `primaryKey` | array | Primary key column names | -| ↳ `foreignKeys` | array | Foreign key constraints | -| ↳ `column` | string | Local column name | -| ↳ `referencesTable` | string | Referenced table name | -| ↳ `referencesColumn` | string | Referenced column name | -| ↳ `indexes` | array | Table indexes | -| ↳ `name` | string | Index name | -| ↳ `columns` | array | Columns included in the index | -| ↳ `unique` | boolean | Whether the index enforces uniqueness | -| `schemas` | array | List of available schemas in the database | - - diff --git a/apps/docs/content/docs/en/tools/posthog.mdx b/apps/docs/content/docs/en/tools/posthog.mdx index 6b471ef60fb..f0fd26081c6 100644 --- a/apps/docs/content/docs/en/tools/posthog.mdx +++ b/apps/docs/content/docs/en/tools/posthog.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/pulse.mdx b/apps/docs/content/docs/en/tools/pulse.mdx index 46b275cb598..e924a9f4774 100644 --- a/apps/docs/content/docs/en/tools/pulse.mdx +++ b/apps/docs/content/docs/en/tools/pulse.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/salesforce.mdx b/apps/docs/content/docs/en/tools/salesforce.mdx index 4cb3e0103c2..ce4f86ff31b 100644 --- a/apps/docs/content/docs/en/tools/salesforce.mdx +++ b/apps/docs/content/docs/en/tools/salesforce.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/search.mdx b/apps/docs/content/docs/en/tools/search.mdx deleted file mode 100644 index 882a18714d2..00000000000 --- a/apps/docs/content/docs/en/tools/search.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Search -description: Search the web ($0.01 per search) ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -The **Search** tool lets you search the web from within your Sim workflows using state-of-the-art search engines. Use it to pull in the latest information, news, facts, and web content directly into your agents, automations, or conversations. - -- **General web search**: Find up-to-date information from the internet to supplement your workflows. -- **Automated queries**: Let agents or program logic submit search queries and handle the results automatically. -- **Structured results**: Returns the most relevant web results, including title, link, snippet, and date for each result. - -> **Note:** Each search costs **$0.01** per query. - -This tool is ideal for any workflow where your agents need access to live web data or must reference current events, perform research, or fetch supplemental content. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Search the web using the Search tool. Each search costs $0.01 per query. - - - -## Tools - -### `search_tool` - -Search the web. Returns the most relevant web results, including title, link, snippet, and date for each result. - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `query` | string | Yes | The search query | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `results` | json | Search results | -| `query` | string | The search query | -| `totalResults` | number | Total number of results | -| `source` | string | Search source \(exa\) | -| `cost` | json | Cost information \($0.01\) | - - diff --git a/apps/docs/content/docs/en/tools/sentry.mdx b/apps/docs/content/docs/en/tools/sentry.mdx index 724915e9855..c2802cc02ec 100644 --- a/apps/docs/content/docs/en/tools/sentry.mdx +++ b/apps/docs/content/docs/en/tools/sentry.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/sftp.mdx b/apps/docs/content/docs/en/tools/sftp.mdx deleted file mode 100644 index fd0ef6aa7f1..00000000000 --- a/apps/docs/content/docs/en/tools/sftp.mdx +++ /dev/null @@ -1,184 +0,0 @@ ---- -title: SFTP -description: Transfer files via SFTP (SSH File Transfer Protocol) ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -[SFTP (SSH File Transfer Protocol)](https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) is a secure network protocol that enables you to upload, download, and manage files on remote servers. SFTP operates over SSH, making it ideal for automated, encrypted file transfers and remote file management within modern workflows. - -With SFTP tools integrated into Sim, you can easily automate the movement of files between your AI agents and external systems or servers. This empowers your agents to manage critical data exchanges, backups, document generation, and remote system orchestration—all with robust security. - -**Key functionality available via SFTP tools:** - -- **Upload Files:** Seamlessly transfer files of any type from your workflow to a remote server, with support for both password and SSH private key authentication. -- **Download Files:** Retrieve files from remote SFTP servers directly for processing, archiving, or further automation. -- **List & Manage Files:** Enumerate directories, delete or create files and folders, and manage file system permissions remotely. -- **Flexible Authentication:** Connect using either traditional passwords or SSH keys, with support for passphrases and permissions control. -- **Large File Support:** Programmatically manage large file uploads and downloads, with built-in size limits for safety. - -By integrating SFTP into Sim, you can automate secure file operations as part of any workflow, whether it’s data collection, reporting, remote system maintenance, or dynamic content exchange between platforms. - -The sections below describe the key SFTP tools available: - -- **sftp_upload:** Upload one or more files to a remote server. -- **sftp_download:** Download files from a remote server to your workflow. -- **sftp_list:** List directory contents on a remote SFTP server. -- **sftp_delete:** Delete files or directories from a remote server. -- **sftp_create:** Create new files on a remote SFTP server. -- **sftp_mkdir:** Create new directories remotely. - -See the tool documentation below for detailed input and output parameters for each operation. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Upload, download, list, and manage files on remote servers via SFTP. Supports both password and private key authentication for secure file transfers. - - - -## Tools - -### `sftp_upload` - -Upload files to a remote SFTP server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SFTP server hostname or IP address | -| `port` | number | Yes | SFTP server port \(default: 22\) | -| `username` | string | Yes | SFTP username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `remotePath` | string | Yes | Destination directory on the remote server | -| `files` | file[] | No | Files to upload | -| `fileContent` | string | No | Direct file content to upload \(for text files\) | -| `fileName` | string | No | File name when using direct content | -| `overwrite` | boolean | No | Whether to overwrite existing files \(default: true\) | -| `permissions` | string | No | File permissions \(e.g., 0644\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the upload was successful | -| `uploadedFiles` | json | Array of uploaded file details \(name, remotePath, size\) | -| `message` | string | Operation status message | - -### `sftp_download` - -Download a file from a remote SFTP server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SFTP server hostname or IP address | -| `port` | number | Yes | SFTP server port \(default: 22\) | -| `username` | string | Yes | SFTP username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `remotePath` | string | Yes | Path to the file on the remote server | -| `encoding` | string | No | Output encoding: utf-8 for text, base64 for binary \(default: utf-8\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the download was successful | -| `file` | file | Downloaded file stored in execution files | -| `fileName` | string | Name of the downloaded file | -| `content` | string | File content \(text or base64 encoded\) | -| `size` | number | File size in bytes | -| `encoding` | string | Content encoding \(utf-8 or base64\) | -| `message` | string | Operation status message | - -### `sftp_list` - -List files and directories on a remote SFTP server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SFTP server hostname or IP address | -| `port` | number | Yes | SFTP server port \(default: 22\) | -| `username` | string | Yes | SFTP username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `remotePath` | string | Yes | Directory path on the remote server | -| `detailed` | boolean | No | Include detailed file information \(size, permissions, modified date\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the operation was successful | -| `path` | string | Directory path that was listed | -| `entries` | json | Array of directory entries with name, type, size, permissions, modifiedAt | -| `count` | number | Number of entries in the directory | -| `message` | string | Operation status message | - -### `sftp_delete` - -Delete a file or directory on a remote SFTP server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SFTP server hostname or IP address | -| `port` | number | Yes | SFTP server port \(default: 22\) | -| `username` | string | Yes | SFTP username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `remotePath` | string | Yes | Path to the file or directory to delete | -| `recursive` | boolean | No | Delete directories recursively | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the deletion was successful | -| `deletedPath` | string | Path that was deleted | -| `message` | string | Operation status message | - -### `sftp_mkdir` - -Create a directory on a remote SFTP server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SFTP server hostname or IP address | -| `port` | number | Yes | SFTP server port \(default: 22\) | -| `username` | string | Yes | SFTP username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `remotePath` | string | Yes | Path for the new directory | -| `recursive` | boolean | No | Create parent directories if they do not exist | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the directory was created successfully | -| `createdPath` | string | Path of the created directory | -| `message` | string | Operation status message | - - diff --git a/apps/docs/content/docs/en/tools/sharepoint.mdx b/apps/docs/content/docs/en/tools/sharepoint.mdx index 05a425ba35e..7cb84dfb326 100644 --- a/apps/docs/content/docs/en/tools/sharepoint.mdx +++ b/apps/docs/content/docs/en/tools/sharepoint.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/smtp.mdx b/apps/docs/content/docs/en/tools/smtp.mdx deleted file mode 100644 index 098deb7b2c1..00000000000 --- a/apps/docs/content/docs/en/tools/smtp.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: SMTP -description: Send emails via any SMTP mail server ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -[SMTP (Simple Mail Transfer Protocol)](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) is the foundational standard for email transmission across the Internet. By connecting to any SMTP-compatible server—such as Gmail, Outlook, or your organization's own mail infrastructure—you can send emails programmatically and automate your outbound communications. - -SMTP integration allows you to fully customize email sending through direct server connectivity, supporting both basic and advanced email use cases. With SMTP, you can control every aspect of message delivery, recipient management, and content formatting, making it suitable for transactional notifications, bulk mailings, and any automated workflow requiring robust outbound email delivery. - -**Key features available via SMTP integration include:** - -- **Universal Email Delivery:** Send emails using any SMTP server by configuring standard server connection parameters. -- **Customizable Sender and Recipients:** Specify sender address, display name, primary recipients, as well as CC and BCC fields. -- **Rich Content Support:** Send plain text or richly formatted HTML emails according to your requirements. -- **Attachments:** Include multiple files as attachments in outgoing emails. -- **Flexible Security:** Connect using TLS, SSL, or standard (unencrypted) protocols as supported by your SMTP provider. -- **Advanced Headers:** Set reply-to headers and other advanced email options to cater for complex mailflows and user interactions. - -By integrating SMTP with Sim, agents and workflows can programmatically send emails as part of any automated process—ranging from sending notifications and confirmations, to automating external communications, reporting, and document delivery. This offers a highly flexible, provider-agnostic approach to managing email directly within your AI-driven processes. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Send emails using any SMTP server (Gmail, Outlook, custom servers, etc.). Configure SMTP connection settings and send emails with full control over content, recipients, and attachments. - - - -## Tools - -### `smtp_send_mail` - -Send emails via SMTP server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `smtpHost` | string | Yes | SMTP server hostname \(e.g., smtp.gmail.com\) | -| `smtpPort` | number | Yes | SMTP server port \(587 for TLS, 465 for SSL\) | -| `smtpUsername` | string | Yes | SMTP authentication username | -| `smtpPassword` | string | Yes | SMTP authentication password | -| `smtpSecure` | string | Yes | Security protocol \(TLS, SSL, or None\) | -| `from` | string | Yes | Sender email address | -| `to` | string | Yes | Recipient email address | -| `subject` | string | Yes | Email subject | -| `body` | string | Yes | Email body content | -| `contentType` | string | No | Content type \(text or html\) | -| `fromName` | string | No | Display name for sender | -| `cc` | string | No | CC recipients \(comma-separated\) | -| `bcc` | string | No | BCC recipients \(comma-separated\) | -| `replyTo` | string | No | Reply-to email address | -| `attachments` | file[] | No | Files to attach to the email | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `success` | boolean | Whether the email was sent successfully | -| `messageId` | string | Message ID from SMTP server | -| `to` | string | Recipient email address | -| `subject` | string | Email subject | -| `error` | string | Error message if sending failed | - - diff --git a/apps/docs/content/docs/en/tools/ssh.mdx b/apps/docs/content/docs/en/tools/ssh.mdx deleted file mode 100644 index a8bd9809349..00000000000 --- a/apps/docs/content/docs/en/tools/ssh.mdx +++ /dev/null @@ -1,403 +0,0 @@ ---- -title: SSH -description: Connect to remote servers via SSH ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -[SSH (Secure Shell)](https://en.wikipedia.org/wiki/Secure_Shell) is a widely-used protocol for securely connecting to remote servers, allowing you to execute commands, transfer files, and manage systems over encrypted channels. - -With SSH support in Sim, your agents can: - -- **Execute remote commands**: Run shell commands on any SSH-accessible server -- **Upload and run scripts**: Easily transfer and execute multi-line scripts for advanced automation -- **Transfer files securely**: Upload and download files as part of your workflows (coming soon or via command) -- **Automate server management**: Perform updates, maintenance, monitoring, deployments, and configuration tasks programmatically -- **Use flexible authentication**: Connect with password or private key authentication, including support for encrypted keys - -The following Sim SSH tools enable your agents to interact with servers as part of larger automations: - -- `ssh_execute_command`: Run any single shell command remotely and capture output, status, and errors. -- `ssh_execute_script`: Upload and execute a full multi-line script on the remote system. -- (Additional tools coming soon, such as file transfer.) - -By integrating SSH into your agent workflows, you can automate secure access, remote operations, and server orchestration—streamlining DevOps, IT automation, and custom remote management, all from within Sim. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Execute commands, transfer files, and manage remote servers via SSH. Supports password and private key authentication for secure server access. - - - -## Tools - -### `ssh_execute_command` - -Execute a shell command on a remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `command` | string | Yes | Shell command to execute on the remote server | -| `workingDirectory` | string | No | Working directory for command execution | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `stdout` | string | Standard output from command | -| `stderr` | string | Standard error output | -| `exitCode` | number | Command exit code | -| `success` | boolean | Whether command succeeded \(exit code 0\) | -| `message` | string | Operation status message | - -### `ssh_execute_script` - -Upload and execute a multi-line script on a remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `script` | string | Yes | Script content to execute \(bash, python, etc.\) | -| `interpreter` | string | No | Script interpreter \(default: /bin/bash\) | -| `workingDirectory` | string | No | Working directory for script execution | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `stdout` | string | Standard output from script | -| `stderr` | string | Standard error output | -| `exitCode` | number | Script exit code | -| `success` | boolean | Whether script succeeded \(exit code 0\) | -| `scriptPath` | string | Temporary path where script was uploaded | -| `message` | string | Operation status message | - -### `ssh_check_command_exists` - -Check if a command/program exists on the remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `commandName` | string | Yes | Command name to check \(e.g., docker, git, python3\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `commandExists` | boolean | Whether the command exists | -| `commandPath` | string | Full path to the command \(if found\) | -| `version` | string | Command version output \(if applicable\) | -| `message` | string | Operation status message | - -### `ssh_upload_file` - -Upload a file to a remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `fileContent` | string | Yes | File content to upload \(base64 encoded for binary files\) | -| `fileName` | string | Yes | Name of the file being uploaded | -| `remotePath` | string | Yes | Destination path on the remote server | -| `permissions` | string | No | File permissions \(e.g., 0644\) | -| `overwrite` | boolean | No | Whether to overwrite existing files \(default: true\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `uploaded` | boolean | Whether the file was uploaded successfully | -| `remotePath` | string | Final path on the remote server | -| `size` | number | File size in bytes | -| `message` | string | Operation status message | - -### `ssh_download_file` - -Download a file from a remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `remotePath` | string | Yes | Path of the file on the remote server | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `downloaded` | boolean | Whether the file was downloaded successfully | -| `file` | file | Downloaded file stored in execution files | -| `fileContent` | string | File content \(base64 encoded for binary files\) | -| `fileName` | string | Name of the downloaded file | -| `remotePath` | string | Source path on the remote server | -| `size` | number | File size in bytes | -| `message` | string | Operation status message | - -### `ssh_list_directory` - -List files and directories in a remote directory - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `path` | string | Yes | Remote directory path to list | -| `detailed` | boolean | No | Include file details \(size, permissions, modified date\) | -| `recursive` | boolean | No | List subdirectories recursively \(default: false\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `entries` | array | Array of file and directory entries | -| ↳ `name` | string | File or directory name | -| ↳ `type` | string | Entry type \(file, directory, symlink\) | -| ↳ `size` | number | File size in bytes | -| ↳ `permissions` | string | File permissions | -| ↳ `modified` | string | Last modified timestamp | -| `totalFiles` | number | Total number of files | -| `totalDirectories` | number | Total number of directories | -| `message` | string | Operation status message | - -### `ssh_check_file_exists` - -Check if a file or directory exists on the remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `path` | string | Yes | Remote file or directory path to check | -| `type` | string | No | Expected type: file, directory, or any \(default: any\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `exists` | boolean | Whether the path exists | -| `type` | string | Type of path \(file, directory, symlink, not_found\) | -| `size` | number | File size if it is a file | -| `permissions` | string | File permissions \(e.g., 0755\) | -| `modified` | string | Last modified timestamp | -| `message` | string | Operation status message | - -### `ssh_create_directory` - -Create a directory on the remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `path` | string | Yes | Directory path to create | -| `recursive` | boolean | No | Create parent directories if they do not exist \(default: true\) | -| `permissions` | string | No | Directory permissions \(default: 0755\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `created` | boolean | Whether the directory was created successfully | -| `remotePath` | string | Created directory path | -| `alreadyExists` | boolean | Whether the directory already existed | -| `message` | string | Operation status message | - -### `ssh_delete_file` - -Delete a file or directory from the remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `path` | string | Yes | Path to delete | -| `recursive` | boolean | No | Recursively delete directories \(default: false\) | -| `force` | boolean | No | Force deletion without confirmation \(default: false\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `deleted` | boolean | Whether the path was deleted successfully | -| `remotePath` | string | Deleted path | -| `message` | string | Operation status message | - -### `ssh_move_rename` - -Move or rename a file or directory on the remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `sourcePath` | string | Yes | Current path of the file or directory | -| `destinationPath` | string | Yes | New path for the file or directory | -| `overwrite` | boolean | No | Overwrite destination if it exists \(default: false\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `moved` | boolean | Whether the operation was successful | -| `sourcePath` | string | Original path | -| `destinationPath` | string | New path | -| `message` | string | Operation status message | - -### `ssh_get_system_info` - -Retrieve system information from the remote SSH server - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `hostname` | string | Server hostname | -| `os` | string | Operating system \(e.g., Linux, Darwin\) | -| `architecture` | string | CPU architecture \(e.g., x64, arm64\) | -| `uptime` | number | System uptime in seconds | -| `memory` | json | Memory information \(total, free, used\) | -| `diskSpace` | json | Disk space information \(total, free, used\) | -| `message` | string | Operation status message | - -### `ssh_read_file_content` - -Read the contents of a remote file - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `path` | string | Yes | Remote file path to read | -| `encoding` | string | No | File encoding \(default: utf-8\) | -| `maxSize` | number | No | Maximum file size to read in MB \(default: 10\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `content` | string | File content as string | -| `size` | number | File size in bytes | -| `lines` | number | Number of lines in file | -| `remotePath` | string | Remote file path | -| `message` | string | Operation status message | - -### `ssh_write_file_content` - -Write or append content to a remote file - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | Yes | SSH server hostname or IP address | -| `port` | number | Yes | SSH server port \(default: 22\) | -| `username` | string | Yes | SSH username | -| `password` | string | No | Password for authentication \(if not using private key\) | -| `privateKey` | string | No | Private key for authentication \(OpenSSH format\) | -| `passphrase` | string | No | Passphrase for encrypted private key | -| `path` | string | Yes | Remote file path to write to | -| `content` | string | Yes | Content to write to the file | -| `mode` | string | No | Write mode: overwrite, append, or create \(default: overwrite\) | -| `permissions` | string | No | File permissions \(e.g., 0644\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `written` | boolean | Whether the file was written successfully | -| `remotePath` | string | File path | -| `size` | number | Final file size in bytes | -| `message` | string | Operation status message | - - diff --git a/apps/docs/content/docs/en/tools/stt.mdx b/apps/docs/content/docs/en/tools/stt.mdx deleted file mode 100644 index eecd270fe1c..00000000000 --- a/apps/docs/content/docs/en/tools/stt.mdx +++ /dev/null @@ -1,212 +0,0 @@ ---- -title: Speech-to-Text -description: Convert speech to text using AI ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -Transcribe speech to text using the latest AI models from world-class providers. Sim's Speech-to-Text (STT) tools empower you to turn audio and video into accurate, timestamped, and optionally translated transcripts—supporting a diversity of languages and enhanced with advanced features such as diarization and speaker identification. - -**Supported Providers & Models:** - -- **[OpenAI Whisper](https://platform.openai.com/docs/guides/speech-to-text/overview)** (OpenAI): - OpenAI’s Whisper is an open-source deep learning model renowned for its robustness across languages and audio conditions. It supports advanced models such as `whisper-1`, excelling in transcription, translation, and tasks demanding high model generalization. Backed by OpenAI—the company known for ChatGPT and leading AI research—Whisper is widely used in research and as a baseline for comparative evaluation. - -- **[Deepgram](https://deepgram.com/)** (Deepgram Inc.): - Based in San Francisco, Deepgram offers scalable, production-grade speech recognition APIs for developers and enterprises. Deepgram’s models include `nova-3`, `nova-2`, and `whisper-large`, offering real-time and batch transcription with industry-leading accuracy, multi-language support, automatic punctuation, intelligent diarization, call analytics, and features for use cases ranging from telephony to media production. - -- **[ElevenLabs](https://elevenlabs.io/)** (ElevenLabs): - A leader in voice AI, ElevenLabs is especially known for premium voice synthesis and recognition. Its STT product delivers high-accuracy, natural understanding of numerous languages, dialects, and accents. Recent ElevenLabs STT models are optimized for clarity, speaker distinction, and are suitable for both creative and accessibility scenarios. ElevenLabs is recognized for cutting-edge advancements in AI-powered speech technologies. - -- **[AssemblyAI](https://www.assemblyai.com/)** (AssemblyAI Inc.): - AssemblyAI provides API-driven, highly accurate speech recognition, with features such as auto chaptering, topic detection, summarization, sentiment analysis, and content moderation alongside transcription. Its proprietary model, including the acclaimed `Conformer-2`, powers some of the largest media, call center, and compliance applications in the industry. AssemblyAI is trusted by Fortune 500s and leading AI startups globally. - -- **[Google Cloud Speech-to-Text](https://cloud.google.com/speech-to-text)** (Google Cloud): - Google’s enterprise-grade Speech-to-Text API supports over 125 languages and variants, offering high accuracy and features such as real-time streaming, word-level confidence, speaker diarization, automatic punctuation, custom vocabulary, and domain-specific tuning. Models such as `latest_long`, `video`, and domain-optimized models are available, powered by Google’s years of research and deployed for global scalability. - -- **[AWS Transcribe](https://aws.amazon.com/transcribe/)** (Amazon Web Services): - AWS Transcribe leverages Amazon’s cloud infrastructure to deliver robust speech recognition as an API. It supports multiple languages and features such as speaker identification, custom vocabulary, channel identification (for call center audio), and medical-specific transcription. Popular models include `standard` and domain-specific variations. AWS Transcribe is ideal for organizations already using Amazon’s cloud. - -**How to Choose:** -Select the provider and model that fits your application—whether you need fast, enterprise-ready transcription with extra analytics (Deepgram, AssemblyAI, Google, AWS), high versatility and open-source access (OpenAI Whisper), or advanced speaker/contextual understanding (ElevenLabs). Consider the pricing, language coverage, accuracy, and any special features (like summarization, chaptering, or sentiment analysis) you might need. - -For more details on capabilities, pricing, feature highlights, and fine-tuning options, refer to each provider’s official documentation via the links above. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Transcribe audio and video files to text using leading AI providers. Supports multiple languages, timestamps, and speaker diarization. - - - -## Tools - -### `stt_whisper` - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | STT provider \(whisper\) | -| `apiKey` | string | Yes | OpenAI API key | -| `model` | string | No | Whisper model to use \(default: whisper-1\) | -| `audioFile` | file | No | Audio or video file to transcribe \(e.g., MP3, WAV, M4A, WEBM\) | -| `audioFileReference` | file | No | Reference to audio/video file from previous blocks | -| `audioUrl` | string | No | URL to audio or video file | -| `language` | string | No | Language code \(e.g., "en", "es", "fr"\) or "auto" for auto-detection | -| `timestamps` | string | No | Timestamp granularity: none, sentence, or word | -| `translateToEnglish` | boolean | No | Translate audio to English | -| `prompt` | string | No | Optional text to guide the model's style or continue a previous audio segment. Helps with proper nouns and context. | -| `temperature` | number | No | Sampling temperature between 0 and 1. Higher values make output more random, lower values more focused and deterministic. | -| `responseFormat` | string | No | Output format for the transcription \(e.g., "json", "text", "srt", "verbose_json", "vtt"\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `transcript` | string | Full transcribed text | -| `segments` | array | Timestamped segments | -| ↳ `text` | string | Transcribed text for this segment | -| ↳ `start` | number | Start time in seconds | -| ↳ `end` | number | End time in seconds | -| ↳ `speaker` | string | Speaker identifier \(if diarization enabled\) | -| ↳ `confidence` | number | Confidence score \(0-1\) | -| `language` | string | Detected or specified language | -| `duration` | number | Audio duration in seconds | - -### `stt_deepgram` - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | STT provider \(deepgram\) | -| `apiKey` | string | Yes | Deepgram API key | -| `model` | string | No | Deepgram model to use \(nova-3, nova-2, whisper-large, etc.\) | -| `audioFile` | file | No | Audio or video file to transcribe \(e.g., MP3, WAV, M4A, WEBM\) | -| `audioFileReference` | file | No | Reference to audio/video file from previous blocks | -| `audioUrl` | string | No | URL to audio or video file | -| `language` | string | No | Language code \(e.g., "en", "es", "fr"\) or "auto" for auto-detection | -| `timestamps` | string | No | Timestamp granularity: none, sentence, or word | -| `diarization` | boolean | No | Enable speaker diarization | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `transcript` | string | Full transcribed text | -| `segments` | array | Timestamped segments with speaker labels | -| ↳ `text` | string | Transcribed text for this segment | -| ↳ `start` | number | Start time in seconds | -| ↳ `end` | number | End time in seconds | -| ↳ `speaker` | string | Speaker identifier \(if diarization enabled\) | -| ↳ `confidence` | number | Confidence score \(0-1\) | -| `language` | string | Detected or specified language | -| `duration` | number | Audio duration in seconds | -| `confidence` | number | Overall confidence score | - -### `stt_elevenlabs` - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | STT provider \(elevenlabs\) | -| `apiKey` | string | Yes | ElevenLabs API key | -| `model` | string | No | ElevenLabs model to use \(scribe_v2\) | -| `audioFile` | file | No | Audio or video file to transcribe \(e.g., MP3, WAV, M4A, WEBM\) | -| `audioFileReference` | file | No | Reference to audio/video file from previous blocks | -| `audioUrl` | string | No | URL to audio or video file | -| `language` | string | No | Language code \(e.g., "en", "es", "fr"\) or "auto" for auto-detection | -| `timestamps` | string | No | Timestamp granularity: none, sentence, or word | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `transcript` | string | Full transcribed text | -| `segments` | array | Timestamped segments | -| `language` | string | Detected or specified language | -| `duration` | number | Audio duration in seconds | -| `confidence` | number | Overall confidence score | - -### `stt_assemblyai` - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | STT provider \(assemblyai\) | -| `apiKey` | string | Yes | AssemblyAI API key | -| `model` | string | No | AssemblyAI model to use \(default: best\) | -| `audioFile` | file | No | Audio or video file to transcribe \(e.g., MP3, WAV, M4A, WEBM\) | -| `audioFileReference` | file | No | Reference to audio/video file from previous blocks | -| `audioUrl` | string | No | URL to audio or video file | -| `language` | string | No | Language code \(e.g., "en", "es", "fr"\) or "auto" for auto-detection | -| `timestamps` | string | No | Timestamp granularity: none, sentence, or word | -| `diarization` | boolean | No | Enable speaker diarization | -| `sentiment` | boolean | No | Enable sentiment analysis | -| `entityDetection` | boolean | No | Enable entity detection | -| `piiRedaction` | boolean | No | Enable PII redaction | -| `summarization` | boolean | No | Enable automatic summarization | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `transcript` | string | Full transcribed text | -| `segments` | array | Timestamped segments with speaker labels | -| ↳ `text` | string | Transcribed text for this segment | -| ↳ `start` | number | Start time in seconds | -| ↳ `end` | number | End time in seconds | -| ↳ `speaker` | string | Speaker identifier \(if diarization enabled\) | -| ↳ `confidence` | number | Confidence score \(0-1\) | -| `language` | string | Detected or specified language | -| `duration` | number | Audio duration in seconds | -| `confidence` | number | Overall confidence score | -| `sentiment` | array | Sentiment analysis results | -| ↳ `text` | string | Text that was analyzed | -| ↳ `sentiment` | string | Sentiment \(POSITIVE, NEGATIVE, NEUTRAL\) | -| ↳ `confidence` | number | Confidence score | -| ↳ `start` | number | Start time in milliseconds | -| ↳ `end` | number | End time in milliseconds | -| `entities` | array | Detected entities | -| ↳ `entity_type` | string | Entity type \(e.g., person_name, location, organization\) | -| ↳ `text` | string | Entity text | -| ↳ `start` | number | Start time in milliseconds | -| ↳ `end` | number | End time in milliseconds | -| `summary` | string | Auto-generated summary | - -### `stt_gemini` - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | STT provider \(gemini\) | -| `apiKey` | string | Yes | Google API key | -| `model` | string | No | Gemini model to use \(default: gemini-2.5-flash\) | -| `audioFile` | file | No | Audio or video file to transcribe \(e.g., MP3, WAV, M4A, WEBM\) | -| `audioFileReference` | file | No | Reference to audio/video file from previous blocks | -| `audioUrl` | string | No | URL to audio or video file | -| `language` | string | No | Language code \(e.g., "en", "es", "fr"\) or "auto" for auto-detection | -| `timestamps` | string | No | Timestamp granularity: none, sentence, or word | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `transcript` | string | Full transcribed text | -| `segments` | array | Timestamped segments | -| `language` | string | Detected or specified language | -| `duration` | number | Audio duration in seconds | -| `confidence` | number | Overall confidence score | - - diff --git a/apps/docs/content/docs/en/tools/telegram.mdx b/apps/docs/content/docs/en/tools/telegram.mdx index 685cf2fb3de..14b61ff1759 100644 --- a/apps/docs/content/docs/en/tools/telegram.mdx +++ b/apps/docs/content/docs/en/tools/telegram.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/tinybird.mdx b/apps/docs/content/docs/en/tools/tinybird.mdx index 0c3d74a9341..f67ac0c2ff0 100644 --- a/apps/docs/content/docs/en/tools/tinybird.mdx +++ b/apps/docs/content/docs/en/tools/tinybird.mdx @@ -1,6 +1,6 @@ --- title: Tinybird -description: Send events and query data with Tinybird +description: Send events, query data, and manage Data Sources with Tinybird --- import { BlockInfoCard } from "@/components/ui/block-info-card" @@ -30,7 +30,7 @@ Connect Tinybird to your workflows today to accelerate data-driven features, aut ## Usage Instructions -Interact with Tinybird using the Events API to stream JSON or NDJSON events, or use the Query API to execute SQL queries against Pipes and Data Sources. +Interact with Tinybird: stream JSON or NDJSON events with the Events API, run SQL with the Query API, call published Pipe API Endpoints by name with dynamic parameters, and manage Data Sources by appending from a URL, truncating, or deleting rows by condition. @@ -77,7 +77,110 @@ Execute SQL queries against Tinybird Pipes and Data Sources using the Query API. | Parameter | Type | Description | | --------- | ---- | ----------- | | `data` | json | Query result data. For FORMAT JSON: array of objects. For other formats \(CSV, TSV, etc.\): raw text string. | +| `meta` | array | Column metadata for the result set \(only available with FORMAT JSON\) | +| ↳ `name` | string | Column name | +| ↳ `type` | string | Column data type | | `rows` | number | Number of rows returned \(only available with FORMAT JSON\) | +| `rows_before_limit_at_least` | number | Minimum number of rows there would be without a LIMIT clause \(only available with FORMAT JSON\) | | `statistics` | json | Query execution statistics - elapsed time, rows read, bytes read \(only available with FORMAT JSON\) | +### `tinybird_query_pipe` + +Call a published Tinybird Pipe API Endpoint by name, passing dynamic parameters and receiving structured JSON results. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `base_url` | string | Yes | Tinybird API base URL \(e.g., https://api.tinybird.co\) | +| `pipe` | string | Yes | Name of the published Pipe API Endpoint to call. Example: "top_pages" | +| `parameters` | json | No | Dynamic Pipe parameters as a JSON object, sent as query-string arguments. Example: \{"start_date": "2024-01-01", "limit": 10\} | +| `q` | string | No | Optional SQL to run on top of the Pipe result. Use "_" to reference the Pipe. Example: "SELECT count\(\) FROM _" | +| `token` | string | Yes | Tinybird API Token with PIPE:READ scope | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `data` | json | Pipe result data as an array of row objects | +| `meta` | array | Column metadata for the result set | +| ↳ `name` | string | Column name | +| ↳ `type` | string | Column data type | +| `rows` | number | Number of rows returned | +| `rows_before_limit_at_least` | number | Minimum number of rows there would be without a LIMIT clause | +| `statistics` | json | Query execution statistics - elapsed time, rows read, bytes read | +| ↳ `elapsed` | number | Query execution time in seconds | +| ↳ `rows_read` | number | Number of rows processed | +| ↳ `bytes_read` | number | Number of bytes processed | + +### `tinybird_append_datasource` + +Append data to a Tinybird Data Source from a remote file URL (CSV, NDJSON, Parquet). + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `base_url` | string | Yes | Tinybird API base URL \(e.g., https://api.tinybird.co\) | +| `datasource` | string | Yes | Name of the existing Data Source to append to. Example: "events_raw" | +| `url` | string | Yes | Publicly accessible URL of the file to append. Example: "https://example.com/data.csv" | +| `format` | string | No | Format of the source file: "csv" \(default\), "ndjson", or "parquet" | +| `token` | string | Yes | Tinybird API Token with DATASOURCES:CREATE scope | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Identifier of the append operation | +| `import_id` | string | Import identifier for the append job | +| `job_id` | string | Job identifier used to poll import status | +| `job_url` | string | URL to query the import job status | +| `status` | string | Initial job status \(e.g., "waiting"\) | +| `job` | json | Full import job details \(kind, id, status, created_at, datasource, ...\) | +| `datasource` | json | Target Data Source metadata \(id, name, ...\) | + +### `tinybird_truncate_datasource` + +Delete all rows from a Tinybird Data Source. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `base_url` | string | Yes | Tinybird API base URL \(e.g., https://api.tinybird.co\) | +| `datasource` | string | Yes | Name of the Data Source to truncate. Example: "events_raw" | +| `token` | string | Yes | Tinybird API Token with DATASOURCES:CREATE scope | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `truncated` | boolean | Whether the Data Source was truncated successfully | +| `result` | json | Raw response body from the truncate endpoint, if any | + +### `tinybird_delete_datasource_rows` + +Delete rows from a Tinybird Data Source matching a SQL condition. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `base_url` | string | Yes | Tinybird API base URL \(e.g., https://api.tinybird.co\) | +| `datasource` | string | Yes | Name of the Data Source to delete rows from. Example: "events_raw" | +| `delete_condition` | string | Yes | SQL WHERE-clause condition selecting the rows to delete. Example: "country = \'ES\'" or "event_date < \'2024-01-01\'" | +| `dry_run` | boolean | No | When true, returns how many rows would be deleted without deleting them. Defaults to false. | +| `token` | string | Yes | Tinybird API Token with DATASOURCES:CREATE scope | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Identifier of the delete operation | +| `job_id` | string | Job identifier used to poll delete status | +| `delete_id` | string | Deletion identifier | +| `job_url` | string | URL to query the delete job status | +| `status` | string | Current job status \(e.g., "waiting", "done"\) | +| `job` | json | Full delete job details \(kind, id, status, delete_condition, rows_affected, ...\) | + diff --git a/apps/docs/content/docs/en/tools/translate.mdx b/apps/docs/content/docs/en/tools/translate.mdx deleted file mode 100644 index 3c3f7dc75df..00000000000 --- a/apps/docs/content/docs/en/tools/translate.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Translate -description: Translate text to any language ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -Translate is a tool that allows you to translate text between languages. - -With Translate, you can: - -- **Translate text**: Translate text between languages -- **Translate documents**: Translate documents between languages -- **Translate websites**: Translate websites between languages -- **Translate images**: Translate images between languages -- **Translate audio**: Translate audio between languages -- **Translate videos**: Translate videos between languages -- **Translate speech**: Translate speech between languages -- **Translate text**: Translate text between languages -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Integrate Translate into the workflow. Can translate text to any language. - - - -## Tools - -### `llm_chat` - -Send a chat completion request to any supported LLM provider - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `model` | string | Yes | The model to use \(e.g., gpt-4o, claude-sonnet-4-5, gemini-2.0-flash\) | -| `systemPrompt` | string | No | System prompt to set the behavior of the assistant | -| `context` | string | Yes | The user message or context to send to the model | -| `apiKey` | string | No | API key for the provider \(uses platform key if not provided for hosted models\) | -| `temperature` | number | No | Temperature for response generation \(0-2\) | -| `maxTokens` | number | No | Maximum tokens in the response | -| `azureEndpoint` | string | No | Azure OpenAI endpoint URL | -| `azureApiVersion` | string | No | Azure OpenAI API version | -| `vertexProject` | string | No | Google Cloud project ID for Vertex AI | -| `vertexLocation` | string | No | Google Cloud location for Vertex AI \(defaults to us-central1\) | -| `vertexCredential` | string | No | Google Cloud OAuth credential ID for Vertex AI | -| `bedrockAccessKeyId` | string | No | AWS Access Key ID for Bedrock | -| `bedrockSecretKey` | string | No | AWS Secret Access Key for Bedrock | -| `bedrockRegion` | string | No | AWS region for Bedrock \(defaults to us-east-1\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `content` | string | The generated response content | -| `model` | string | The model used for generation | -| `tokens` | object | Token usage information | - - diff --git a/apps/docs/content/docs/en/tools/tts.mdx b/apps/docs/content/docs/en/tools/tts.mdx deleted file mode 100644 index 62d3f6ffb57..00000000000 --- a/apps/docs/content/docs/en/tools/tts.mdx +++ /dev/null @@ -1,256 +0,0 @@ ---- -title: Text-to-Speech -description: Convert text to speech using AI voices ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -Convert text to natural-sounding speech using the latest AI voices. Sim's Text-to-Speech (TTS) tools let you generate audio from written text in dozens of languages, with a choice of expressive voices, formats, and advanced controls like speed, style, emotion, and more. - -**Supported Providers & Models:** - -- **[OpenAI Text-to-Speech](https://platform.openai.com/docs/guides/text-to-speech/voice-options)** (OpenAI): - OpenAI's TTS API offers ultra-realistic voices using advanced AI models like `tts-1`, `tts-1-hd`, and `gpt-4o-mini-tts`. Voices include both male and female, with options such as alloy, echo, fable, onyx, nova, shimmer, ash, ballad, coral, sage, and verse. Supports multiple audio formats (mp3, opus, aac, flac, wav, pcm), adjustable speed and streaming synthesis. - -- **[Deepgram Aura](https://deepgram.com/products/text-to-speech)** (Deepgram Inc.): - Deepgram’s Aura provides expressive English and multilingual AI voices, optimized for conversational clarity, low latency, and customization. Models like `aura-asteria-en`, `aura-luna-en`, and others are available. Supports multiple encoding formats (linear16, mp3, opus, aac, flac) and fine tuning on speed, sample rate, and style. - -- **[ElevenLabs Text-to-Speech](https://elevenlabs.io/text-to-speech)** (ElevenLabs): - ElevenLabs leads in lifelike, emotionally rich TTS, offering dozens of voices in 29+ languages and the ability to clone custom voices. Models support voice design, speech synthesis, and direct API access, with advanced controls for style, emotion, stability, and similarity. Suitable for audiobooks, content creation, accessibility, and more. - -- **[Cartesia TTS](https://docs.cartesia.ai/)** (Cartesia): - Cartesia offers high-quality, fast, and secure text-to-speech with a focus on privacy and flexible deployment. It provides instant streaming, real-time synthesis, and supports multiple international voices and accents, accessible through a simple API. - -- **[Google Cloud Text-to-Speech](https://cloud.google.com/text-to-speech)** (Google Cloud): - Google uses DeepMind WaveNet and Neural2 models to power high-fidelity voices in 50+ languages and variants. Features include voice selection, pitch, speaking rate, volume control, SSML tags, and access to both standard and studio-grade premium voices. Widely used for accessibility, IVR, and media. - -- **[Microsoft Azure Speech](https://azure.microsoft.com/en-us/products/ai-services/text-to-speech)** (Microsoft Azure): - Azure provides over 400 neural voices across 140+ languages and locales, with unique voice customization, style, emotion, role, and real-time controls. Offers SSML support for pronunciation, intonation, and more. Ideal for global, enterprise, or creative TTS needs. - -- **[PlayHT](https://play.ht/)** (PlayHT): - PlayHT specializes in realistic voice synthesis, voice cloning, and instant streaming playback with 800+ voices in over 100 languages. Features include emotion, pitch and speed controls, multi-voice audio, and custom voice creation via the API or online studio. - -**How to Choose:** -Pick your provider and model by prioritizing languages, supported voice types, desired formats (mp3, wav, etc.), control granularity (speed, emotion, etc.), and specialized features (voice cloning, accent, streaming). For creative, accessibility, or developer use cases, ensure compatibility with your application's requirements and compare costs. - -Visit each provider’s official site for up-to-date capabilities, pricing, and documentation details! -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Generate natural-sounding speech from text using state-of-the-art AI voices from OpenAI, Deepgram, ElevenLabs, Cartesia, Google Cloud, Azure, and PlayHT. Supports multiple voices, languages, and audio formats. - - - -## Tools - -### `tts_openai` - -Convert text to speech using OpenAI TTS models - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | Yes | The text content to convert to speech \(e.g., "Hello, welcome to our service!"\) | -| `apiKey` | string | Yes | OpenAI API key | -| `model` | string | No | OpenAI TTS model identifier \(e.g., "tts-1", "tts-1-hd", "gpt-4o-mini-tts"\) | -| `voice` | string | No | OpenAI voice identifier \(e.g., "alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer"\) | -| `responseFormat` | string | No | Audio format \(mp3, opus, aac, flac, wav, pcm\) | -| `speed` | number | No | Speech speed multiplier from 0.25 to 4.0 \(e.g., 0.5 for slower, 1.0 for normal, 2.0 for faster\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `audioUrl` | string | URL to the generated audio file | -| `audioFile` | file | Generated audio file object | -| `duration` | number | Audio duration in seconds | -| `characterCount` | number | Number of characters processed | -| `format` | string | Audio format | -| `provider` | string | TTS provider used | - -### `tts_deepgram` - -Convert text to speech using Deepgram Aura - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | Yes | The text content to convert to speech \(e.g., "Hello, welcome to our service!"\) | -| `apiKey` | string | Yes | Deepgram API key | -| `model` | string | No | Deepgram model/voice identifier \(e.g., "aura-asteria-en", "aura-luna-en", "aura-2-luna-en"\) | -| `voice` | string | No | Deepgram voice identifier, alternative to model param \(e.g., "aura-asteria-en", "aura-orion-en"\) | -| `encoding` | string | No | Audio encoding \(linear16, mp3, opus, aac, flac\) | -| `sampleRate` | number | No | Sample rate \(8000, 16000, 24000, 48000\) | -| `bitRate` | number | No | Bit rate for compressed formats | -| `container` | string | No | Container format \(none, wav, ogg\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `audioUrl` | string | URL to the generated audio file | -| `audioFile` | file | Generated audio file object | -| `duration` | number | Audio duration in seconds | -| `characterCount` | number | Number of characters processed | -| `format` | string | Audio format | -| `provider` | string | TTS provider used | - -### `tts_elevenlabs` - -Convert text to speech using ElevenLabs voices - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | Yes | The text content to convert to speech \(e.g., "Hello, welcome to our service!"\) | -| `voiceId` | string | Yes | ElevenLabs voice identifier \(e.g., "21m00Tcm4TlvDq8ikWAM", "AZnzlk1XvdvUeBnXmlld"\) | -| `apiKey` | string | Yes | ElevenLabs API key | -| `modelId` | string | No | ElevenLabs model identifier \(e.g., "eleven_turbo_v2_5", "eleven_flash_v2_5", "eleven_multilingual_v2"\) | -| `stability` | number | No | Voice stability \(0.0 to 1.0, default: 0.5\) | -| `similarityBoost` | number | No | Similarity boost \(0.0 to 1.0, default: 0.8\) | -| `style` | number | No | Style exaggeration \(0.0 to 1.0\) | -| `useSpeakerBoost` | boolean | No | Use speaker boost \(default: true\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `audioUrl` | string | URL to the generated audio file | -| `audioFile` | file | Generated audio file object | -| `duration` | number | Audio duration in seconds | -| `characterCount` | number | Number of characters processed | -| `format` | string | Audio format | -| `provider` | string | TTS provider used | - -### `tts_cartesia` - -Convert text to speech using Cartesia Sonic (ultra-low latency) - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | Yes | The text content to convert to speech \(e.g., "Hello, welcome to our service!"\) | -| `apiKey` | string | Yes | Cartesia API key | -| `modelId` | string | No | Cartesia model identifier \(e.g., "sonic", "sonic-2", "sonic-3", "sonic-multilingual"\) | -| `voice` | string | No | Cartesia voice identifier or embedding \(e.g., "a0e99841-438c-4a64-b679-ae501e7d6091"\) | -| `language` | string | No | Language code for speech synthesis \(e.g., "en", "es", "fr", "de", "it", "pt"\) | -| `outputFormat` | json | No | Output format configuration \(container, encoding, sampleRate\) | -| `speed` | number | No | Speech speed multiplier \(e.g., 0.5 for slower, 1.0 for normal, 2.0 for faster\) | -| `emotion` | array | No | Emotion tags for Sonic-3 \(e.g., \['positivity:high'\]\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `audioUrl` | string | URL to the generated audio file | -| `audioFile` | file | Generated audio file object | -| `duration` | number | Audio duration in seconds | -| `characterCount` | number | Number of characters processed | -| `format` | string | Audio format | -| `provider` | string | TTS provider used | - -### `tts_google` - -Convert text to speech using Google Cloud Text-to-Speech - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | Yes | The text content to convert to speech \(e.g., "Hello, welcome to our service!"\) | -| `apiKey` | string | Yes | Google Cloud API key | -| `voiceId` | string | No | Google Cloud voice identifier \(e.g., "en-US-Neural2-A", "en-US-Wavenet-D", "en-GB-Neural2-B"\) | -| `languageCode` | string | Yes | BCP-47 language code for speech synthesis \(e.g., "en-US", "es-ES", "fr-FR", "de-DE"\) | -| `gender` | string | No | Voice gender \(MALE, FEMALE, NEUTRAL\) | -| `audioEncoding` | string | No | Audio encoding \(LINEAR16, MP3, OGG_OPUS, MULAW, ALAW\) | -| `speakingRate` | number | No | Speaking rate multiplier from 0.25 to 2.0 \(e.g., 0.5 for slower, 1.0 for normal, 1.5 for faster\) | -| `pitch` | number | No | Voice pitch \(-20.0 to 20.0, default: 0.0\) | -| `volumeGainDb` | number | No | Volume gain in dB \(-96.0 to 16.0\) | -| `sampleRateHertz` | number | No | Sample rate in Hz | -| `effectsProfileId` | array | No | Effects profile \(e.g., \['headphone-class-device'\]\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `audioUrl` | string | URL to the generated audio file | -| `audioFile` | file | Generated audio file object | -| `duration` | number | Audio duration in seconds | -| `characterCount` | number | Number of characters processed | -| `format` | string | Audio format | -| `provider` | string | TTS provider used | - -### `tts_azure` - -Convert text to speech using Azure Cognitive Services - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | Yes | The text content to convert to speech \(e.g., "Hello, welcome to our service!"\) | -| `apiKey` | string | Yes | Azure Speech Services API key | -| `voiceId` | string | No | Azure voice identifier \(e.g., "en-US-JennyNeural", "en-US-GuyNeural", "en-GB-SoniaNeural"\) | -| `region` | string | No | Azure region \(e.g., eastus, westus, westeurope\) | -| `outputFormat` | string | No | Output audio format | -| `rate` | string | No | Speaking rate \(e.g., +10%, -20%, 1.5\) | -| `pitch` | string | No | Voice pitch \(e.g., +5Hz, -2st, low\) | -| `style` | string | No | Speaking style \(e.g., cheerful, sad, angry - neural voices only\) | -| `styleDegree` | number | No | Style intensity \(0.01 to 2.0\) | -| `role` | string | No | Role \(e.g., Girl, Boy, YoungAdultFemale\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `audioUrl` | string | URL to the generated audio file | -| `audioFile` | file | Generated audio file object | -| `duration` | number | Audio duration in seconds | -| `characterCount` | number | Number of characters processed | -| `format` | string | Audio format | -| `provider` | string | TTS provider used | - -### `tts_playht` - -Convert text to speech using PlayHT (voice cloning) - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | Yes | The text content to convert to speech \(e.g., "Hello, welcome to our service!"\) | -| `apiKey` | string | Yes | PlayHT API key \(AUTHORIZATION header\) | -| `userId` | string | Yes | PlayHT user ID \(X-USER-ID header\) | -| `voice` | string | No | PlayHT voice identifier or manifest URL \(e.g., "s3://voice-cloning-zero-shot/..."\) | -| `quality` | string | No | Quality level \(draft, standard, premium\) | -| `outputFormat` | string | No | Output format \(mp3, wav, ogg, flac, mulaw\) | -| `speed` | number | No | Speech speed multiplier from 0.5 to 2.0 \(e.g., 0.5 for slower, 1.0 for normal, 1.5 for faster\) | -| `temperature` | number | No | Creativity/randomness \(0.0 to 2.0\) | -| `voiceGuidance` | number | No | Voice stability \(1.0 to 6.0\) | -| `textGuidance` | number | No | Text adherence \(1.0 to 6.0\) | -| `sampleRate` | number | No | Sample rate \(8000, 16000, 22050, 24000, 44100, 48000\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `audioUrl` | string | URL to the generated audio file | -| `audioFile` | file | Generated audio file object | -| `duration` | number | Audio duration in seconds | -| `characterCount` | number | Number of characters processed | -| `format` | string | Audio format | -| `provider` | string | TTS provider used | - - diff --git a/apps/docs/content/docs/en/tools/video_generator.mdx b/apps/docs/content/docs/en/tools/video_generator.mdx deleted file mode 100644 index 35f8b5fd424..00000000000 --- a/apps/docs/content/docs/en/tools/video_generator.mdx +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: Video Generator -description: Generate videos from text using AI ---- - -import { BlockInfoCard } from "@/components/ui/block-info-card" - - - -{/* MANUAL-CONTENT-START:intro */} -Create videos from text prompts using leading AI video providers. Sim's Video Generator supports direct provider integrations for Runway, Google Veo, Luma, and MiniMax, plus a Fal.ai multi-model provider for newer and specialized models. - -**Supported Providers & Models:** - -- **[Runway Gen-4](https://docs.dev.runwayml.com/)**: Generate image-to-video clips with a required reference image, 5 or 10 second durations, and landscape, portrait, or square output. - -- **[Google Veo](https://ai.google.dev/gemini-api/docs/video)**: Generate text-to-video clips with Veo 3 and Veo 3.1 models, portrait or landscape aspect ratios, 4, 6, or 8 second durations, and 720p or 1080p output. - -- **[Luma Dream Machine](https://docs.lumalabs.ai/docs/video-generation)**: Generate Ray 2 videos with 5 or 9 second durations, common aspect ratios, multiple resolutions, and optional camera concept controls. - -- **[MiniMax Hailuo](https://platform.minimax.io/docs/api-reference/video-generation-t2v)**: Generate Hailuo 2.3 or Hailuo-02 videos through MiniMax's platform API, with standard or pro quality endpoints and prompt optimization. - -- **[Fal.ai Multi-Model](https://fal.ai/docs/model-api-reference/video-generation-api/overview)**: Access Veo 3.1, Sora 2, Seedance 2.0, Kling 3.0 and O3, MiniMax Hailuo 2.3, WAN 2.2, LTX 2.3, and previously supported Fal.ai models from one provider option. - -**How to Choose:** -Pick the provider and model based on quality, speed, duration, audio support, reference image needs, resolution, and cost. Runway is best when you have a visual reference, Veo and Luma are strong general text-to-video options, MiniMax offers a direct Hailuo API path, and Fal.ai is the best choice when you need access to the broadest model catalog. - -For more details on features, restrictions, pricing, and model advances, see each provider’s official documentation above. -{/* MANUAL-CONTENT-END */} - - -## Usage Instructions - -Generate high-quality videos from text prompts using leading AI providers. Supports Runway, Google Veo, Luma, MiniMax, and Fal.ai multi-model generation with provider-specific durations, aspect ratios, resolutions, prompt optimization, and native audio controls. - - - -## Tools - -### `video_runway` - -Generate videos using Runway Gen-4 with world consistency and visual references - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | Video provider \(runway\) | -| `apiKey` | string | Yes | Runway API key | -| `model` | string | No | Runway model: gen-4 \(default, higher quality\) or gen-4-turbo \(faster\) | -| `prompt` | string | Yes | Text prompt describing the video to generate | -| `duration` | number | No | Video duration in seconds \(5 or 10, default: 5\) | -| `aspectRatio` | string | No | Aspect ratio: 16:9 \(landscape\), 9:16 \(portrait\), or 1:1 \(square\) | -| `resolution` | string | No | Video resolution \(720p output\). Note: Gen-4 Turbo outputs at 720p natively | -| `visualReference` | file | Yes | Reference image REQUIRED for Gen-4 \(UserFile object\). Gen-4 only supports image-to-video, not text-only generation | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `videoUrl` | string | Generated video URL | -| `videoFile` | file | Video file object with metadata | -| `duration` | number | Video duration in seconds | -| `width` | number | Video width in pixels | -| `height` | number | Video height in pixels | -| `provider` | string | Provider used \(runway\) | -| `model` | string | Model used | -| `jobId` | string | Runway job ID | - -### `video_veo` - -Generate videos using Google Veo 3/3.1 with native audio generation - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | Video provider \(veo\) | -| `apiKey` | string | Yes | Google Gemini API key | -| `model` | string | No | Veo model: veo-3 \(default, highest quality\), veo-3-fast \(faster\), or veo-3.1 \(latest\) | -| `prompt` | string | Yes | Text prompt describing the video to generate | -| `duration` | number | No | Video duration in seconds \(4, 6, or 8, default: 8\) | -| `aspectRatio` | string | No | Aspect ratio: 16:9 \(landscape\) or 9:16 \(portrait\) | -| `resolution` | string | No | Video resolution: 720p or 1080p \(default: 1080p\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `videoUrl` | string | Generated video URL | -| `videoFile` | file | Video file object with metadata | -| `duration` | number | Video duration in seconds | -| `width` | number | Video width in pixels | -| `height` | number | Video height in pixels | -| `provider` | string | Provider used \(veo\) | -| `model` | string | Model used | -| `jobId` | string | Veo job ID | - -### `video_luma` - -Generate videos using Luma Dream Machine with advanced camera controls - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | Video provider \(luma\) | -| `apiKey` | string | Yes | Luma AI API key | -| `model` | string | No | Luma model: ray-2 \(default\) | -| `prompt` | string | Yes | Text prompt describing the video to generate | -| `duration` | number | No | Video duration in seconds \(5 or 9, default: 5\) | -| `aspectRatio` | string | No | Aspect ratio: 16:9 \(landscape\), 9:16 \(portrait\), or 1:1 \(square\) | -| `resolution` | string | No | Video resolution: 540p, 720p, or 1080p \(default: 1080p\) | -| `cameraControl` | json | No | Camera controls as array of concept objects. Format: \[\{ "key": "concept_name" \}\]. Valid keys: truck_left, truck_right, pan_left, pan_right, tilt_up, tilt_down, zoom_in, zoom_out, push_in, pull_out, orbit_left, orbit_right, crane_up, crane_down, static, handheld, and 20+ more predefined options | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `videoUrl` | string | Generated video URL | -| `videoFile` | file | Video file object with metadata | -| `duration` | number | Video duration in seconds | -| `width` | number | Video width in pixels | -| `height` | number | Video height in pixels | -| `provider` | string | Provider used \(luma\) | -| `model` | string | Model used | -| `jobId` | string | Luma job ID | - -### `video_minimax` - -Generate videos using MiniMax Hailuo through MiniMax Platform API with advanced realism and prompt optimization - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | Video provider \(minimax\) | -| `apiKey` | string | Yes | MiniMax API key from platform.minimax.io | -| `model` | string | No | MiniMax model: hailuo-2.3 \(default\) or hailuo-02 | -| `prompt` | string | Yes | Text prompt describing the video to generate | -| `duration` | number | No | Video duration in seconds \(6 or 10, default: 6\) | -| `endpoint` | string | No | Quality endpoint: standard \(768P\) or pro \(1080P for 6s videos\) | -| `promptOptimizer` | boolean | No | Enable prompt optimization for better results \(default: true\) | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `videoUrl` | string | Generated video URL | -| `videoFile` | file | Video file object with metadata | -| `duration` | number | Video duration in seconds | -| `width` | number | Video width in pixels | -| `height` | number | Video height in pixels | -| `provider` | string | Provider used \(minimax\) | -| `model` | string | Model used | -| `jobId` | string | MiniMax job ID | - -### `video_falai` - -Generate videos using Fal.ai with access to Veo 3.1, Sora 2, Seedance 2.0, Kling 3.0, MiniMax Hailuo 2.3, WAN 2.2, LTX 2.3, and previously supported models - -#### Input - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `provider` | string | Yes | Video provider \(falai\) | -| `apiKey` | string | Yes | Fal.ai API key | -| `model` | string | Yes | Fal.ai model: veo-3.1, veo-3.1-fast, sora-2, sora-2-pro, seedance-2.0, seedance-2.0-fast, kling-v3-pro, kling-v3-4k, kling-o3-pro, kling-o3-4k, minimax-hailuo-2.3-pro, minimax-hailuo-2.3-standard, wan-2.2-a14b-turbo, ltx-2.3, ltx-2.3-fast, plus previously supported model IDs | -| `prompt` | string | Yes | Text prompt describing the video to generate | -| `duration` | number | No | Video duration in seconds \(varies by model\) | -| `aspectRatio` | string | No | Aspect ratio \(varies by model\): 16:9, 9:16, 1:1 | -| `resolution` | string | No | Video resolution \(varies by model\): 480p, 580p, 720p, 1080p, true_1080p, 1440p, 2160p, 4k | -| `promptOptimizer` | boolean | No | Enable prompt optimization for MiniMax models \(default: true\) | -| `generateAudio` | boolean | No | Generate native audio when supported by the selected Fal.ai model | -| `pricing` | custom | No | No description | -| `metadata` | string | No | No description | -| `rateLimit` | string | No | No description | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `videoUrl` | string | Generated video URL | -| `videoFile` | file | Video file object with metadata | -| `duration` | number | Video duration in seconds | -| `width` | number | Video width in pixels | -| `height` | number | Video height in pixels | -| `provider` | string | Provider used \(falai\) | -| `model` | string | Model used | -| `jobId` | string | Job ID | - - diff --git a/apps/docs/content/docs/en/tools/wealthbox.mdx b/apps/docs/content/docs/en/tools/wealthbox.mdx index 1a4db1c1329..0d62038f11f 100644 --- a/apps/docs/content/docs/en/tools/wealthbox.mdx +++ b/apps/docs/content/docs/en/tools/wealthbox.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/webflow.mdx b/apps/docs/content/docs/en/tools/webflow.mdx index def273f64ae..4d43da96c46 100644 --- a/apps/docs/content/docs/en/tools/webflow.mdx +++ b/apps/docs/content/docs/en/tools/webflow.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/tools/zendesk.mdx b/apps/docs/content/docs/en/tools/zendesk.mdx index 06b11c19be6..9cdd0f3658f 100644 --- a/apps/docs/content/docs/en/tools/zendesk.mdx +++ b/apps/docs/content/docs/en/tools/zendesk.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/en/triggers/airtable.mdx b/apps/docs/content/docs/en/triggers/airtable.mdx index f053764c544..72821490bdc 100644 --- a/apps/docs/content/docs/en/triggers/airtable.mdx +++ b/apps/docs/content/docs/en/triggers/airtable.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Airtable provides 1 trigger for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/confluence.mdx b/apps/docs/content/docs/en/triggers/confluence.mdx index c2b6ca0dfa3..e624e05af08 100644 --- a/apps/docs/content/docs/en/triggers/confluence.mdx +++ b/apps/docs/content/docs/en/triggers/confluence.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Confluence provides 23 triggers for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/gmail.mdx b/apps/docs/content/docs/en/triggers/gmail.mdx index f71569a9c1c..c4555771468 100644 --- a/apps/docs/content/docs/en/triggers/gmail.mdx +++ b/apps/docs/content/docs/en/triggers/gmail.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Gmail provides 1 trigger for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/google-calendar.mdx b/apps/docs/content/docs/en/triggers/google-calendar.mdx index 0d8bd87211b..b60b09843eb 100644 --- a/apps/docs/content/docs/en/triggers/google-calendar.mdx +++ b/apps/docs/content/docs/en/triggers/google-calendar.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Google Calendar provides 1 trigger for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/google-drive.mdx b/apps/docs/content/docs/en/triggers/google-drive.mdx index 80105f62f4a..b0f7b35f34a 100644 --- a/apps/docs/content/docs/en/triggers/google-drive.mdx +++ b/apps/docs/content/docs/en/triggers/google-drive.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Google Drive provides 1 trigger for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/google-sheets.mdx b/apps/docs/content/docs/en/triggers/google-sheets.mdx index eb48e512006..91c31509807 100644 --- a/apps/docs/content/docs/en/triggers/google-sheets.mdx +++ b/apps/docs/content/docs/en/triggers/google-sheets.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Google Sheets provides 1 trigger for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/google_forms.mdx b/apps/docs/content/docs/en/triggers/google_forms.mdx index 767d243316a..d60aa0d83d7 100644 --- a/apps/docs/content/docs/en/triggers/google_forms.mdx +++ b/apps/docs/content/docs/en/triggers/google_forms.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Google Forms provides 1 trigger for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/intercom.mdx b/apps/docs/content/docs/en/triggers/intercom.mdx index e377f21adbe..6dd7b68f86e 100644 --- a/apps/docs/content/docs/en/triggers/intercom.mdx +++ b/apps/docs/content/docs/en/triggers/intercom.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Intercom provides 6 triggers for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/jira.mdx b/apps/docs/content/docs/en/triggers/jira.mdx index eff9d92990c..5f467a2147c 100644 --- a/apps/docs/content/docs/en/triggers/jira.mdx +++ b/apps/docs/content/docs/en/triggers/jira.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Jira provides 15 triggers for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/microsoft-teams.mdx b/apps/docs/content/docs/en/triggers/microsoft-teams.mdx index 4bef68927b1..3af8b9e1344 100644 --- a/apps/docs/content/docs/en/triggers/microsoft-teams.mdx +++ b/apps/docs/content/docs/en/triggers/microsoft-teams.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Microsoft Teams provides 2 triggers for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/outlook.mdx b/apps/docs/content/docs/en/triggers/outlook.mdx index 42f1f9a54fe..1b304006d94 100644 --- a/apps/docs/content/docs/en/triggers/outlook.mdx +++ b/apps/docs/content/docs/en/triggers/outlook.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Outlook provides 1 trigger for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/salesforce.mdx b/apps/docs/content/docs/en/triggers/salesforce.mdx index bd228cf073b..a849dbb6e9f 100644 --- a/apps/docs/content/docs/en/triggers/salesforce.mdx +++ b/apps/docs/content/docs/en/triggers/salesforce.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Salesforce provides 6 triggers for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/start.mdx b/apps/docs/content/docs/en/triggers/start.mdx index 672da65024a..5ab88809ac1 100644 --- a/apps/docs/content/docs/en/triggers/start.mdx +++ b/apps/docs/content/docs/en/triggers/start.mdx @@ -44,7 +44,7 @@ Reference structured values downstream with expressions such as <start. ## How it behaves per entry point - + When you click Run in the editor, the Start block renders the Input Format as a form. Default values make it easy to retest without retyping data. Submitting the form triggers the workflow immediately and the values become available on <start.fieldName> (for example <start.sampleField>). @@ -64,13 +64,6 @@ Reference structured values downstream with expressions such as <start. If you launch chat with additional structured context (for example from an embed), it merges into the corresponding <start.fieldName> outputs, keeping downstream blocks consistent with API and manual runs. - - Form deployments render the Input Format as a standalone, embeddable form page. Each field becomes a form input with appropriate UI controls—text inputs for strings, number inputs for numbers, toggle switches for booleans, and file upload zones for files. - - When a user submits the form, values become available on <start.fieldName> just like other entry points. The workflow executes with trigger type form, and submitters see a customizable thank-you message upon completion. - - Forms can be embedded via iframe or shared as direct links, making them ideal for surveys, contact forms, and data collection workflows. - ## Referencing Start data downstream diff --git a/apps/docs/content/docs/en/triggers/telegram.mdx b/apps/docs/content/docs/en/triggers/telegram.mdx index 5447bf20792..ab945b8a821 100644 --- a/apps/docs/content/docs/en/triggers/telegram.mdx +++ b/apps/docs/content/docs/en/triggers/telegram.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Telegram provides 1 trigger for automating workflows based on events. diff --git a/apps/docs/content/docs/en/triggers/webflow.mdx b/apps/docs/content/docs/en/triggers/webflow.mdx index c72b6f49577..2db6961641e 100644 --- a/apps/docs/content/docs/en/triggers/webflow.mdx +++ b/apps/docs/content/docs/en/triggers/webflow.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" Webflow provides 4 triggers for automating workflows based on events. diff --git a/apps/docs/content/docs/es/execution/form.mdx b/apps/docs/content/docs/es/execution/form.mdx deleted file mode 100644 index 2baf26da3ad..00000000000 --- a/apps/docs/content/docs/es/execution/form.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Despliegue de formulario ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { Tab, Tabs } from 'fumadocs-ui/components/tabs' - -Despliega tu flujo de trabajo como un formulario embebible que los usuarios pueden completar en tu sitio web o compartir mediante enlace. Los envíos de formulario activan tu flujo de trabajo con el tipo de activador `form`. - -## Descripción general - -El despliegue de formulario convierte el formato de entrada de tu flujo de trabajo en un formulario responsivo que puede ser: -- Compartido mediante un enlace directo (ej., `https://sim.ai/form/my-survey`) -- Embebido en cualquier sitio web usando un iframe - -Cuando un usuario envía el formulario, activa tu flujo de trabajo con los datos del formulario. - - -Los formularios derivan sus campos del formato de entrada del bloque de inicio de tu flujo de trabajo. Cada campo se convierte en una entrada de formulario con el tipo apropiado. - - -## Crear un formulario - -1. Abre tu flujo de trabajo y haz clic en **Desplegar** -2. Selecciona la pestaña **Formulario** -3. Configura: - - **URL**: Identificador único (ej., `contact-form` → `sim.ai/form/contact-form`) - - **Título**: Encabezado del formulario - - **Descripción**: Subtítulo opcional - - **Campos del formulario**: Personaliza etiquetas y descripciones para cada campo - - **Autenticación**: Pública, protegida por contraseña o lista blanca de correos - - **Mensaje de agradecimiento**: Se muestra después del envío -4. Haz clic en **Lanzar** - -## Mapeo de tipos de campo - -| Tipo de formato de entrada | Campo de formulario | -|------------------|------------| -| `string` | Entrada de texto | -| `number` | Entrada numérica | -| `boolean` | Interruptor de alternancia | -| `object` | Editor JSON | -| `array` | Editor de array JSON | -| `files` | Carga de archivo | - -## Control de acceso - -| Modo | Descripción | -|------|-------------| -| **Público** | Cualquiera con el enlace puede enviar | -| **Contraseña** | Los usuarios deben ingresar una contraseña | -| **Lista blanca de correos** | Solo los correos/dominios especificados pueden enviar | - -Para lista blanca de correos: -- Exacto: `user@example.com` -- Dominio: `@example.com` (todos los correos del dominio) - -## Incrustación - -### Enlace directo - -``` -https://sim.ai/form/your-identifier -``` - -### Iframe - -```html - -``` - -## Envío por API - -Envía formularios de forma programática: - - - - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ - "formData": { - "name": "John Doe", - "email": "john@example.com" - } - }' -``` - - - - -```typescript -const response = await fetch('https://sim.ai/api/form/your-identifier', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - formData: { - name: 'John Doe', - email: 'john@example.com' - } - }) -}); - -const result = await response.json(); -// { success: true, data: { executionId: '...' } } -``` - - - - -### Formularios protegidos - -Para formularios protegidos con contraseña: - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "password": "secret", "formData": { "name": "John" } }' -``` - -Para formularios protegidos con correo: - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "email": "allowed@example.com", "formData": { "name": "John" } }' -``` - -## Solución de problemas - -**"No hay campos de entrada configurados"** - Añade campos de formato de entrada a tu bloque de inicio. - -**El formulario no se carga en el iframe** - Verifica que el CSP de tu sitio permita iframes desde `sim.ai`. - -**Los envíos fallan** - Verifica que el identificador sea correcto y que los campos obligatorios estén completos. diff --git a/apps/docs/content/docs/fr/execution/form.mdx b/apps/docs/content/docs/fr/execution/form.mdx deleted file mode 100644 index 505a0466100..00000000000 --- a/apps/docs/content/docs/fr/execution/form.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Déploiement de formulaire ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { Tab, Tabs } from 'fumadocs-ui/components/tabs' - -Déployez votre workflow sous forme de formulaire intégrable que les utilisateurs peuvent remplir sur votre site web ou partager via un lien. Les soumissions de formulaire déclenchent votre workflow avec le type de déclencheur `form`. - -## Vue d'ensemble - -Le déploiement de formulaire transforme le format d'entrée de votre workflow en un formulaire responsive qui peut être : -- Partagé via un lien direct (par exemple, `https://sim.ai/form/my-survey`) -- Intégré dans n'importe quel site web à l'aide d'une iframe - -Lorsqu'un utilisateur soumet le formulaire, cela déclenche votre workflow avec les données du formulaire. - - -Les formulaires dérivent leurs champs du format d'entrée du bloc de démarrage de votre workflow. Chaque champ devient une entrée de formulaire avec le type approprié. - - -## Créer un formulaire - -1. Ouvrez votre workflow et cliquez sur **Déployer** -2. Sélectionnez l'onglet **Formulaire** -3. Configurez : - - **URL** : identifiant unique (par exemple, `contact-form` → `sim.ai/form/contact-form`) - - **Titre** : en-tête du formulaire - - **Description** : sous-titre optionnel - - **Champs du formulaire** : personnalisez les libellés et descriptions de chaque champ - - **Authentification** : publique, protégée par mot de passe ou liste blanche d'emails - - **Message de remerciement** : affiché après la soumission -4. Cliquez sur **Lancer** - -## Correspondance des types de champs - -| Type de format d'entrée | Champ de formulaire | -|------------------|------------| -| `string` | Champ de texte | -| `number` | Champ numérique | -| `boolean` | Interrupteur | -| `object` | Éditeur JSON | -| `array` | Éditeur de tableau JSON | -| `files` | Téléchargement de fichier | - -## Contrôle d'accès - -| Mode | Description | -|------|-------------| -| **Public** | Toute personne disposant du lien peut soumettre | -| **Mot de passe** | Les utilisateurs doivent saisir un mot de passe | -| **Liste blanche d'emails** | Seuls les emails/domaines spécifiés peuvent soumettre | - -Pour la liste blanche d'e-mails : -- Exact : `user@example.com` -- Domaine : `@example.com` (tous les e-mails du domaine) - -## Intégration - -### Lien direct - -``` -https://sim.ai/form/your-identifier -``` - -### Iframe - -```html - -``` - -## Soumission par API - -Soumettre des formulaires par programmation : - - - - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ - "formData": { - "name": "John Doe", - "email": "john@example.com" - } - }' -``` - - - - -```typescript -const response = await fetch('https://sim.ai/api/form/your-identifier', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - formData: { - name: 'John Doe', - email: 'john@example.com' - } - }) -}); - -const result = await response.json(); -// { success: true, data: { executionId: '...' } } -``` - - - - -### Formulaires protégés - -Pour les formulaires protégés par mot de passe : - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "password": "secret", "formData": { "name": "John" } }' -``` - -Pour les formulaires protégés par e-mail : - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "email": "allowed@example.com", "formData": { "name": "John" } }' -``` - -## Dépannage - -**« Aucun champ de saisie configuré »** - Ajoutez des champs de format de saisie à votre bloc de démarrage. - -**Le formulaire ne se charge pas dans l'iframe** - Vérifiez que la CSP de votre site autorise les iframes provenant de `sim.ai`. - -**Échec des soumissions** - Vérifiez que l'identifiant est correct et que les champs obligatoires sont remplis. diff --git a/apps/docs/content/docs/ja/execution/form.mdx b/apps/docs/content/docs/ja/execution/form.mdx deleted file mode 100644 index 837ab15ff47..00000000000 --- a/apps/docs/content/docs/ja/execution/form.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: フォームデプロイメント ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { Tab, Tabs } from 'fumadocs-ui/components/tabs' - -ワークフローを埋め込み可能なフォームとしてデプロイし、ユーザーがウェブサイト上で入力したり、リンク経由で共有したりできます。フォーム送信は、`form`トリガータイプでワークフローを起動します。 - -## 概要 - -フォームデプロイメントは、ワークフローの入力フォーマットをレスポンシブなフォームに変換します。このフォームは次のように利用できます: -- 直接リンクで共有(例: `https://sim.ai/form/my-survey`) -- iframeを使用して任意のウェブサイトに埋め込み - -ユーザーがフォームを送信すると、フォームデータを使用してワークフローが起動されます。 - - -フォームのフィールドは、ワークフローのStartブロックの入力フォーマットから派生します。各フィールドは、適切なタイプのフォーム入力になります。 - - -## フォームの作成 - -1. ワークフローを開き、**Deploy**をクリックします -2. **Form**タブを選択します -3. 設定: - - **URL**: 一意の識別子(例: `contact-form` → `sim.ai/form/contact-form`) - - **Title**: フォームの見出し - - **Description**: オプションのサブタイトル - - **Form Fields**: 各フィールドのラベルと説明をカスタマイズ - - **Authentication**: 公開、パスワード保護、またはメールホワイトリスト - - **Thank You Message**: 送信後に表示されるメッセージ -4. **Launch**をクリックします - -## フィールドタイプのマッピング - -| 入力フォーマットタイプ | フォームフィールド | -|------------------|------------| -| `string` | テキスト入力 | -| `number` | 数値入力 | -| `boolean` | トグルスイッチ | -| `object` | JSONエディタ | -| `array` | JSON配列エディタ | -| `files` | ファイルアップロード | - -## アクセス制御 - -| モード | 説明 | -|------|-------------| -| **Public** | リンクを持つ誰でも送信可能 | -| **Password** | ユーザーはパスワードを入力する必要があります | -| **Email Whitelist** | 指定されたメール/ドメインのみ送信可能 | - -メールホワイトリストの場合: -- 完全一致:`user@example.com` -- ドメイン:`@example.com`(ドメインからのすべてのメール) - -## 埋め込み - -### 直接リンク - -``` -https://sim.ai/form/your-identifier -``` - -### Iframe - -```html - -``` - -## API送信 - -プログラムでフォームを送信: - - - - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ - "formData": { - "name": "John Doe", - "email": "john@example.com" - } - }' -``` - - - - -```typescript -const response = await fetch('https://sim.ai/api/form/your-identifier', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - formData: { - name: 'John Doe', - email: 'john@example.com' - } - }) -}); - -const result = await response.json(); -// { success: true, data: { executionId: '...' } } -``` - - - - -### 保護されたフォーム - -パスワード保護されたフォームの場合: - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "password": "secret", "formData": { "name": "John" } }' -``` - -メール保護されたフォームの場合: - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "email": "allowed@example.com", "formData": { "name": "John" } }' -``` - -## トラブルシューティング - -**「入力フィールドが設定されていません」** - スタートブロックに入力フォーマットフィールドを追加してください。 - -**iframeでフォームが読み込まれない** - サイトのCSPが`sim.ai`からのiframeを許可しているか確認してください。 - -**送信が失敗する** - 識別子が正しく、必須フィールドが入力されているか確認してください。 diff --git a/apps/docs/content/docs/zh/execution/form.mdx b/apps/docs/content/docs/zh/execution/form.mdx deleted file mode 100644 index 3b5df28463c..00000000000 --- a/apps/docs/content/docs/zh/execution/form.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: 表单部署 ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { Tab, Tabs } from 'fumadocs-ui/components/tabs' - -将你的工作流部署为可嵌入的表单,用户可以在你的网站上填写,或通过链接分享。表单提交后会以 `form` 触发类型启动你的工作流。 - -## 概述 - -表单部署会将你的工作流输入格式转化为响应式表单,可用于: -- 通过直接链接分享(如:`https://sim.ai/form/my-survey`) -- 通过 iframe 嵌入到任意网站 - -当用户提交表单时,会携带表单数据触发你的工作流。 - - -表单字段来源于你工作流的 Start 块输入格式。每个字段都会变成对应类型的表单输入项。 - - -## 创建表单 - -1. 打开你的工作流并点击 **Deploy** -2. 选择 **Form** 标签页 -3. 配置: - - **URL**:唯一标识符(如:`contact-form` → `sim.ai/form/contact-form`) - - **Title**:表单标题 - - **Description**:可选副标题 - - **Form Fields**:自定义每个字段的标签和描述 - - **Authentication**:公开、密码保护或邮箱白名单 - - **Thank You Message**:提交后显示的感谢信息 -4. 点击 **Launch** - -## 字段类型映射 - -| 输入格式类型 | 表单字段 | -|------------------|------------| -| `string` | 文本输入 | -| `number` | 数字输入 | -| `boolean` | 开关切换 | -| `object` | JSON 编辑器 | -| `array` | JSON 数组编辑器 | -| `files` | 文件上传 | - -## 访问控制 - -| 模式 | 说明 | -|------|-------------| -| **Public** | 任何拥有链接的人都可提交 | -| **Password** | 用户需输入密码 | -| **Email Whitelist** | 仅指定邮箱/域名可提交 | - -对于邮箱白名单: -- 精确匹配:`user@example.com` -- 域名匹配:`@example.com`(该域名下所有邮箱) - -## 嵌入 - -### 直接链接 - -``` -https://sim.ai/form/your-identifier -``` - -### Iframe - -```html - -``` - -## API 提交 - -以编程方式提交表单: - - - - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ - "formData": { - "name": "John Doe", - "email": "john@example.com" - } - }' -``` - - - - -```typescript -const response = await fetch('https://sim.ai/api/form/your-identifier', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - formData: { - name: 'John Doe', - email: 'john@example.com' - } - }) -}); - -const result = await response.json(); -// { success: true, data: { executionId: '...' } } -``` - - - - -### 受保护的表单 - -对于密码保护的表单: - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "password": "secret", "formData": { "name": "John" } }' -``` - -对于邮箱保护的表单: - -```bash -curl -X POST https://sim.ai/api/form/your-identifier \ - -H "Content-Type: application/json" \ - -d '{ "email": "allowed@example.com", "formData": { "name": "John" } }' -``` - -## 故障排查 - -**“未配置输入字段”** - 请在 Start 块中添加 Input Format 字段。 - -**表单无法在 iframe 中加载** - 请检查你的网站 CSP 是否允许来自 `sim.ai` 的 iframe。 - -**提交失败** - 请确认标识符正确且所有必填项已填写。 diff --git a/apps/docs/public/icon.svg b/apps/docs/public/icon.svg new file mode 100644 index 00000000000..f96f875249b --- /dev/null +++ b/apps/docs/public/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-form.tsx index fb32e2decdc..49df93d00df 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-form.tsx @@ -7,14 +7,16 @@ import { Eye, EyeOff } from 'lucide-react' import Link from 'next/link' import { useRouter, useSearchParams } from 'next/navigation' import { + Chip, + ChipModal, + ChipModalBody, + ChipModalError, + ChipModalField, + ChipModalFooter, + ChipModalHeader, Input, Label, Loader, - Modal, - ModalBody, - ModalContent, - ModalDescription, - ModalHeader, } from '@/components/emcn' import { requestJson } from '@/lib/api/client/request' import { forgetPasswordContract } from '@/lib/api/contracts' @@ -379,11 +381,11 @@ export default function LoginPage({ className={cn( showEmailValidationError && emailErrors.length > 0 && - 'border-red-500 focus:border-red-500' + 'border-[var(--text-error)] focus:border-[var(--text-error)]' )} /> {showEmailValidationError && emailErrors.length > 0 && ( -
+
{emailErrors.map((error) => (

{error}

))} @@ -417,7 +419,7 @@ export default function LoginPage({ 'pr-10', showValidationError && passwordErrors.length > 0 && - 'border-red-500 focus:border-red-500' + 'border-[var(--text-error)] focus:border-[var(--text-error)]' )} />
{showValidationError && passwordErrors.length > 0 && ( -
+
{passwordErrors.map((error) => (

{error}

))} @@ -446,7 +448,7 @@ export default function LoginPage({ )} {formError && ( -
+

{formError}

)} @@ -527,60 +529,53 @@ export default function LoginPage({
- - - Reset Password - -
{ - e.preventDefault() - handleForgotPassword() - }} - > - - Enter your email address and we'll send you a link to reset your password if your - account exists. - -
-
- - setForgotPasswordEmail(e.target.value)} - placeholder='Enter your email' - required - type='email' - className={cn( - resetStatus.type === 'error' && 'border-red-500 focus:border-red-500' - )} - /> - {resetStatus.type === 'error' && ( -
-

{resetStatus.message}

-
- )} -
- {resetStatus.type === 'success' && ( -
-

{resetStatus.message}

-
- )} - -
-
-
-
-
+ + setForgotPasswordOpen(false)}> + Reset Password + + +

+ Enter your email address and we'll send you a link to reset your password if your + account exists. +

+ setForgotPasswordEmail(value)} + required + placeholder='you@example.com' + /> + {resetStatus.type === 'success' && ( +

{resetStatus.message}

+ )} + + {resetStatus.type === 'error' ? resetStatus.message : null} + +
+ + setForgotPasswordOpen(false)} + disabled={isSubmittingReset} + > + Cancel + + + {isSubmittingReset ? 'Sending…' : 'Send Reset Link'} + + +
) } diff --git a/apps/sim/app/(landing)/blog/[slug]/share-button.tsx b/apps/sim/app/(landing)/blog/[slug]/share-button.tsx index facde4b6c58..679c6f44c6e 100644 --- a/apps/sim/app/(landing)/blog/[slug]/share-button.tsx +++ b/apps/sim/app/(landing)/blog/[slug]/share-button.tsx @@ -8,7 +8,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/emcn' -import { Copy } from '@/components/emcn/icons' +import { Duplicate } from '@/components/emcn/icons' import { LinkedInIcon, xIcon as XIcon } from '@/components/icons' interface ShareButtonProps { @@ -46,21 +46,21 @@ export function ShareButton({ url, title }: ShareButtonProps) { className='flex items-center gap-1.5 text-[var(--landing-text-muted)] text-sm hover:text-[var(--landing-text)]' aria-label='Share this post' > - + Share - + {copied ? 'Copied!' : 'Copy link'} - + Share on X - + Share on LinkedIn diff --git a/apps/sim/app/(landing)/components/demo-request/demo-request-modal.tsx b/apps/sim/app/(landing)/components/demo-request/demo-request-modal.tsx index 8225d58cf68..bf1d4bc0449 100644 --- a/apps/sim/app/(landing)/components/demo-request/demo-request-modal.tsx +++ b/apps/sim/app/(landing)/components/demo-request/demo-request-modal.tsx @@ -3,7 +3,7 @@ import { useState } from 'react' import { useMutation } from '@tanstack/react-query' import { - Combobox, + ChipCombobox, Input, Modal, ModalBody, @@ -56,7 +56,7 @@ const INITIAL_FORM_STATE: DemoRequestFormState = { } const LANDING_INPUT = - 'h-[32px] rounded-[5px] border border-[var(--border-1)] bg-[var(--surface-5)] px-2.5 font-[430] font-season text-[13.5px] text-[var(--text-primary)] transition-colors placeholder:text-[var(--text-muted)] outline-none' + 'rounded-[5px] border border-[var(--border-1)] bg-[var(--surface-5)] px-2.5 font-[430] font-season text-[var(--text-primary)] transition-colors placeholder:text-[var(--text-muted)] outline-none' async function submitDemoRequest(payload: DemoRequestPayload) { return requestJson(submitDemoRequestContract, { body: payload }) @@ -161,6 +161,7 @@ export function DemoRequestModal({ children, theme = 'dark' }: DemoRequestModalP updateField('firstName', event.target.value)} placeholder='First' @@ -170,6 +171,7 @@ export function DemoRequestModal({ children, theme = 'dark' }: DemoRequestModalP updateField('lastName', event.target.value)} placeholder='Last' @@ -185,6 +187,7 @@ export function DemoRequestModal({ children, theme = 'dark' }: DemoRequestModalP > updateField('companyEmail', event.target.value)} @@ -201,6 +204,7 @@ export function DemoRequestModal({ children, theme = 'dark' }: DemoRequestModalP > updateField('phoneNumber', event.target.value)} @@ -210,7 +214,7 @@ export function DemoRequestModal({ children, theme = 'dark' }: DemoRequestModalP - diff --git a/apps/sim/app/(landing)/components/features/components/features-preview.tsx b/apps/sim/app/(landing)/components/features/components/features-preview.tsx index 2eab3ef253a..c3fae6f7baf 100644 --- a/apps/sim/app/(landing)/components/features/components/features-preview.tsx +++ b/apps/sim/app/(landing)/components/features/components/features-preview.tsx @@ -762,7 +762,7 @@ function MockFullLogs({ revealedRows }: { revealedRows: number }) { {['Workflow', 'Date', 'Status', 'Cost', 'Trigger', 'Duration'].map((col) => ( - {col} + {col} ))} diff --git a/apps/sim/app/(landing)/components/landing-preview/components/landing-preview-home/landing-preview-home.tsx b/apps/sim/app/(landing)/components/landing-preview/components/landing-preview-home/landing-preview-home.tsx index b6b8f7e1719..3f411f608c5 100644 --- a/apps/sim/app/(landing)/components/landing-preview/components/landing-preview-home/landing-preview-home.tsx +++ b/apps/sim/app/(landing)/components/landing-preview/components/landing-preview-home/landing-preview-home.tsx @@ -5,7 +5,6 @@ import { AnimatePresence, domAnimation, LazyMotion, m } from 'framer-motion' import { ArrowUp, Table } from 'lucide-react' import { Blimp, Checkbox, ChevronDown } from '@/components/emcn' import { TypeBoolean, TypeNumber, TypeText } from '@/components/emcn/icons' -import { handleKeyboardActivation } from '@/lib/core/utils/keyboard' import { captureClientEvent } from '@/lib/posthog/client' import { useLandingSubmit } from '@/app/(landing)/components/landing-preview/components/landing-preview-panel/landing-preview-panel' import { EASE_OUT } from '@/app/(landing)/components/landing-preview/components/landing-preview-workflow/workflow-data' @@ -215,10 +214,10 @@ export const LandingPreviewHome = memo(function LandingPreviewHome({ onClick={() => setToolsExpanded((p) => !p)} className='flex cursor-pointer items-center gap-2' > -
- +
+
- + Mothership + } title='Read Customer Leads' /> @@ -308,15 +310,9 @@ export const LandingPreviewHome = memo(function LandingPreviewHome({ transition={{ duration: 0.4, delay: 0.1, ease: EASE_OUT }} >
textareaRef.current?.focus()} - onKeyDown={(event) => { - if (event.target !== event.currentTarget) return - handleKeyboardActivation(event, () => textareaRef.current?.focus()) - }} >