mirror of
https://github.com/simstudioai/sim.git
synced 2026-10-28 02:41:36 +08:00
feat(workflows): sim trigger, logs v2 block, toolbar renaming (#4941)
* feat(workflows): sim trigger, logs v2 block, toolbar renaming * fix(review): bound rule queries, canonical logs params, watched-workflow SQL scoping Code-review fixes: read the canonical workflowIds param in logs_v2 (the serializer deletes the source pair ids), aggregate failure-rate in the DB and switch rule windows to the indexed startedAt column, clamp rule config to the legacy contract bounds, push no_activity watch scoping into SQL before the LIMIT, fix the generated sim icon-map key, normalize docs wording, and drop dead exports. Co-authored-by: Cursor <cursoragent@cursor.com> * address comments * fix(review): integer rule rounding, success-gated workflow labels, display module hygiene Second-pass review fixes: round integer rule fields so fractional input never reaches SQL LIMIT, gate workflow-name readiness on a successful non-placeholder load in both editor and preview (errored loads mislabeled valid workflows as deleted), lazily read the variables store in preview rows, move the filter-field JSON preview into the shared display module and unexport its single-consumer helpers, and align >= boundary copy (failure rate, error count, cooldown window) with implementation. Co-authored-by: Cursor <cursoragent@cursor.com> * chore: sync lockfile after staging merge Co-authored-by: Cursor <cursoragent@cursor.com> * fix(workspace-events): keyset-paginate the no_activity subscription scan A fixed LIMIT 500 with no ORDER BY silently starved subscriptions beyond the cap once the global count exceeded it. The poll now pages by webhook id so every subscription is visited each cycle; pagination bounds memory, not total work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(workspace-events): keyset-paginate the watched-workflow scan The 500-row LIMIT silently and deterministically excluded high-id workflows from no_activity coverage in watch-everything subscriptions on large workspaces. The scan now pages by workflow id, mirroring the subscription scan; per-workflow checks move into a helper so the pagination loop stays flat. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(workspace-events): skip no_activity subscriptions on the execution-completion path no_activity is poller-owned and can never fire from a completed execution, but it passed into the rule branch and cost a pointless cooldown point-read per subscription on the hottest path. Early-continue alongside the workflow_deployed guard. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(sim-trigger): note failure-based alert conditions evaluate on failed runs Co-authored-by: Cursor <cursoragent@cursor.com> * fix(blocks): recategorize Data Enrichment as a core block It's a Sim-native capability (registry enrichments over a managed provider cascade, like Search), not a third-party integration. Moves it to Core Blocks in the toolbar, out of the integrations catalog, and relocates its docs page to blocks/ with the icon-map allowlist keeping the docs card icon. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(blocks): recategorize MySQL, PostgreSQL, SFTP, SMTP, SSH as integrations External-system connectors with host/credential auth belong under Integrations, not Core Blocks — consistent with MongoDB, Redis, ClickHouse, and the other datastore integrations. They already carried integrationType and /tools docsLinks; the regenerated docs pages turn those previously-dangling links into real pages, and the blocks join the integrations catalog and icon maps. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
540e608e00
commit
6abcf82db2
@@ -6823,6 +6823,29 @@ export function SixtyfourIcon(props: SVGProps<SVGSVGElement>) {
|
||||
)
|
||||
}
|
||||
|
||||
export function SimTriggerIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
viewBox='0 0 222 222'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
aria-hidden='true'
|
||||
>
|
||||
<path
|
||||
fillRule='evenodd'
|
||||
clipRule='evenodd'
|
||||
d='M107.822 93.76C107.822 97.35 106.403 100.792 103.884 103.328L103.523 103.692C101.006 106.236 97.59 107.658 94.02 107.658H13.45C6.02 107.658 0 113.718 0 121.191V208.332C0 215.806 6.02 221.866 13.45 221.866H99.96C107.383 221.866 113.4 215.806 113.4 208.332V126.745C113.4 123.419 114.71 120.228 117.047 117.874C119.377 115.527 122.546 114.207 125.849 114.207H207.777C215.198 114.207 221.214 108.148 221.214 100.674V13.53C221.214 6.06 215.198 0 207.777 0H121.26C113.839 0 107.822 6.06 107.822 13.53V93.76ZM134.078 18.55H194.952C199.289 18.55 202.796 22.09 202.796 26.45V87.76C202.796 92.12 199.289 95.66 194.952 95.66H134.078C129.748 95.66 126.233 92.12 126.233 87.76V26.45C126.233 22.09 129.748 18.55 134.078 18.55Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M207.878 129.57H143.554C135.756 129.57 129.434 135.937 129.434 143.791V207.784C129.434 215.638 135.756 222.005 143.554 222.005H207.878C215.677 222.005 221.999 215.638 221.999 207.784V143.791C221.999 135.937 215.677 129.57 207.878 129.57Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function SimilarwebIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
|
||||
@@ -129,6 +129,7 @@ import {
|
||||
MistralIcon,
|
||||
MondayIcon,
|
||||
MongoDBIcon,
|
||||
MySQLIcon,
|
||||
Neo4jIcon,
|
||||
NeverBounceIcon,
|
||||
NewRelicIcon,
|
||||
@@ -146,6 +147,7 @@ import {
|
||||
PineconeIcon,
|
||||
PipedriveIcon,
|
||||
PolymarketIcon,
|
||||
PostgresIcon,
|
||||
PosthogIcon,
|
||||
ProfoundIcon,
|
||||
ProspeoIcon,
|
||||
@@ -173,11 +175,15 @@ import {
|
||||
SentryIcon,
|
||||
SerperIcon,
|
||||
ServiceNowIcon,
|
||||
SftpIcon,
|
||||
ShopifyIcon,
|
||||
SimilarwebIcon,
|
||||
SimTriggerIcon,
|
||||
SixtyfourIcon,
|
||||
SlackIcon,
|
||||
SmtpIcon,
|
||||
SQSIcon,
|
||||
SshIcon,
|
||||
STSIcon,
|
||||
STTIcon,
|
||||
StagehandIcon,
|
||||
@@ -355,6 +361,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
mistral_parse_v3: MistralIcon,
|
||||
monday: MondayIcon,
|
||||
mongodb: MongoDBIcon,
|
||||
mysql: MySQLIcon,
|
||||
neo4j: Neo4jIcon,
|
||||
neverbounce: NeverBounceIcon,
|
||||
new_relic: NewRelicIcon,
|
||||
@@ -373,6 +380,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
pinecone: PineconeIcon,
|
||||
pipedrive: PipedriveIcon,
|
||||
polymarket: PolymarketIcon,
|
||||
postgresql: PostgresIcon,
|
||||
posthog: PosthogIcon,
|
||||
profound: ProfoundIcon,
|
||||
prospeo: ProspeoIcon,
|
||||
@@ -402,13 +410,17 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
serper: SerperIcon,
|
||||
servicenow: ServiceNowIcon,
|
||||
ses: SESIcon,
|
||||
sftp: SftpIcon,
|
||||
sharepoint: MicrosoftSharepointIcon,
|
||||
sharepoint_v2: MicrosoftSharepointIcon,
|
||||
shopify: ShopifyIcon,
|
||||
sim_workspace_event: SimTriggerIcon,
|
||||
similarweb: SimilarwebIcon,
|
||||
sixtyfour: SixtyfourIcon,
|
||||
slack: SlackIcon,
|
||||
smtp: SmtpIcon,
|
||||
sqs: SQSIcon,
|
||||
ssh: SshIcon,
|
||||
stagehand: StagehandIcon,
|
||||
stripe: StripeIcon,
|
||||
sts: STSIcon,
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: Logs
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { FAQ } from '@/components/ui/faq'
|
||||
|
||||
The Logs block queries workflow run logs in the current workspace and fetches full details for individual runs — the same data you see on the Logs page, available to your workflows.
|
||||
|
||||
## Operations
|
||||
|
||||
<Tabs items={['Query Logs', 'Get Run Details']}>
|
||||
<Tab>
|
||||
<p>Find runs matching a set of filters. Returns only the matching <strong>run IDs</strong>, ordered newest-first by default.</p>
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li><strong>Workflows</strong>: select specific workflows, or leave empty for all (comma-separated IDs in advanced mode)</li>
|
||||
<li><strong>Status</strong>: info, error, running, pending, cancelled (empty for all)</li>
|
||||
<li><strong>Time Range</strong>: presets from the past 30 minutes to the past 30 days, or explicit ISO start/end dates in advanced mode</li>
|
||||
<li><strong>Cost</strong>: compare run cost against a credit threshold (e.g. ≥ 10 credits)</li>
|
||||
<li><strong>Duration</strong>: compare run duration against a millisecond threshold</li>
|
||||
<li><strong>Limit</strong>: maximum run IDs to return (default 100, max 200)</li>
|
||||
</ul>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<p>Fetch everything about a single run by its run ID:</p>
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li><strong>runId</strong>, <strong>workflowId</strong>, <strong>workflowName</strong></li>
|
||||
<li><strong>status</strong>, <strong>trigger</strong>, <strong>startedAt</strong>, <strong>durationMs</strong></li>
|
||||
<li><strong>cost</strong>: run cost in credits</li>
|
||||
<li><strong>traceSpans</strong>: the full trace — per-block inputs, outputs, timings, and tool calls</li>
|
||||
<li><strong>finalOutput</strong>: the run's final output</li>
|
||||
</ul>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Typical Pattern
|
||||
|
||||
Query for the runs you care about, then loop over the returned IDs and fetch details for each:
|
||||
|
||||
1. **Query Logs** with `Status: error` and `Time Range: Past 24 hours` → `<logs1.runIds>`
|
||||
2. Loop over the IDs and call **Get Run Details** → inspect `<logs2.traceSpans>` to find the failing block
|
||||
3. Act on it — post a summary to Slack, file a ticket, or feed the trace to an Agent block for diagnosis
|
||||
|
||||
This pairs naturally with the [Sim trigger](/triggers/sim): the trigger hands you the `runId` that fired the event, and Get Run Details gives you the full trace.
|
||||
|
||||
<Callout type="info">
|
||||
The block always operates on the current workspace. Costs are denominated in credits, both for
|
||||
the cost filter and the cost output.
|
||||
</Callout>
|
||||
|
||||
<FAQ items={[
|
||||
{ question: "Why does Query Logs only return run IDs?", answer: "To keep payloads small and predictable. Run summaries can be large — fetch only the runs you actually need with Get Run Details." },
|
||||
{ question: "Can I query logs from another workspace?", answer: "No. The block is scoped to the workspace the workflow lives in." },
|
||||
{ question: "What are trace spans?", answer: "The execution trace for a run: every block that ran, its inputs and outputs, timings, and any tool calls — the same data shown in the Logs page trace view." },
|
||||
{ question: "How far back can I query?", answer: "As far as your plan's log retention. Free plans retain logs for 7 days; paid plans retain them indefinitely." },
|
||||
]} />
|
||||
@@ -5,11 +5,13 @@
|
||||
"api",
|
||||
"condition",
|
||||
"credential",
|
||||
"enrichment",
|
||||
"evaluator",
|
||||
"function",
|
||||
"guardrails",
|
||||
"human-in-the-loop",
|
||||
"knowledge",
|
||||
"logs",
|
||||
"loop",
|
||||
"parallel",
|
||||
"response",
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
Sim provides a comprehensive external API for querying workflow run logs and setting up webhooks for real-time notifications when workflows complete.
|
||||
Sim provides a comprehensive external API for querying workflow run logs. To react to workflow runs in real time, use the Sim trigger block to run a workflow on workspace events like execution errors, successes, and deployments.
|
||||
|
||||
## Authentication
|
||||
|
||||
@@ -246,230 +246,13 @@ Retrieve run details including the workflow state snapshot.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Notifications
|
||||
|
||||
Get real-time notifications when workflow runs complete via webhook, email, or Slack. Notifications are configured at the workspace level from the Logs page.
|
||||
|
||||
### Configuration
|
||||
|
||||
Configure notifications from the Logs page by clicking the menu button and selecting "Configure Notifications".
|
||||
|
||||
**Notification Channels:**
|
||||
- **Webhook**: Send HTTP POST requests to your endpoint
|
||||
- **Email**: Receive email notifications with run details
|
||||
- **Slack**: Post messages to a Slack channel
|
||||
|
||||
**Workflow Selection:**
|
||||
- Select specific workflows to monitor
|
||||
- Or choose "All Workflows" to include current and future workflows
|
||||
|
||||
**Filtering Options:**
|
||||
- `levelFilter`: Log levels to receive (`info`, `error`)
|
||||
- `triggerFilter`: Trigger types to receive (`api`, `webhook`, `schedule`, `manual`, `chat`)
|
||||
|
||||
**Optional Data:**
|
||||
- `includeFinalOutput`: Include the workflow's final output
|
||||
- `includeTraceSpans`: Include detailed trace spans
|
||||
- `includeRateLimits`: Include rate limit information (sync/async limits and remaining)
|
||||
- `includeUsageData`: Include billing period usage and limits
|
||||
|
||||
### Alert Rules
|
||||
|
||||
Instead of receiving notifications for every run, configure alert rules to be notified only when issues are detected:
|
||||
|
||||
**Consecutive Failures**
|
||||
- Alert after X consecutive failed runs (e.g., 3 failures in a row)
|
||||
- Resets when a run succeeds
|
||||
|
||||
**Failure Rate**
|
||||
- Alert when failure rate exceeds X% over the last Y hours
|
||||
- Requires minimum 5 runs in the window
|
||||
- Only triggers after the full time window has elapsed
|
||||
|
||||
**Latency Threshold**
|
||||
- Alert when any run takes longer than X seconds
|
||||
- Useful for catching slow or hanging workflows
|
||||
|
||||
**Latency Spike**
|
||||
- Alert when a run is X% slower than the average
|
||||
- Compares against the average duration over the configured time window
|
||||
- Requires minimum 5 runs to establish baseline
|
||||
|
||||
**Cost Threshold**
|
||||
- Alert when a single run costs more than $X
|
||||
- Useful for catching expensive LLM calls
|
||||
|
||||
**No Activity**
|
||||
- Alert when no runs occur within X hours
|
||||
- Useful for monitoring scheduled workflows that should run regularly
|
||||
|
||||
**Error Count**
|
||||
- Alert when error count exceeds X within a time window
|
||||
- Tracks total errors, not consecutive
|
||||
|
||||
All alert types include a 1-hour cooldown to prevent notification spam.
|
||||
|
||||
### Webhook Configuration
|
||||
|
||||
For webhooks, additional options are available:
|
||||
- `url`: Your webhook endpoint URL
|
||||
- `secret`: Optional secret for HMAC signature verification
|
||||
|
||||
### Payload Structure
|
||||
|
||||
When a workflow run completes, Sim sends the following payload (via webhook POST, email, or Slack):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "evt_123",
|
||||
"type": "workflow.execution.completed",
|
||||
"timestamp": 1735925767890,
|
||||
"data": {
|
||||
"workflowId": "wf_xyz789",
|
||||
"executionId": "exec_def456",
|
||||
"status": "success",
|
||||
"level": "info",
|
||||
"trigger": "api",
|
||||
"startedAt": "2025-01-01T12:34:56.789Z",
|
||||
"endedAt": "2025-01-01T12:34:57.123Z",
|
||||
"totalDurationMs": 334,
|
||||
"cost": {
|
||||
"total": 0.00234,
|
||||
"tokens": {
|
||||
"prompt": 123,
|
||||
"completion": 456,
|
||||
"total": 579
|
||||
},
|
||||
"models": {
|
||||
"gpt-4o": {
|
||||
"input": 0.001,
|
||||
"output": 0.00134,
|
||||
"total": 0.00234,
|
||||
"tokens": {
|
||||
"prompt": 123,
|
||||
"completion": 456,
|
||||
"total": 579
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"files": null,
|
||||
"finalOutput": {...}, // Only if includeFinalOutput=true
|
||||
"traceSpans": [...], // Only if includeTraceSpans=true
|
||||
"rateLimits": {...}, // Only if includeRateLimits=true
|
||||
"usage": {...} // Only if includeUsageData=true
|
||||
},
|
||||
"links": {
|
||||
"log": "/v1/logs/log_abc123",
|
||||
"execution": "/v1/logs/executions/exec_def456"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Webhook Headers
|
||||
|
||||
Each webhook request includes these headers (webhook channel only):
|
||||
|
||||
- `sim-event`: Event type (always `workflow.execution.completed`)
|
||||
- `sim-timestamp`: Unix timestamp in milliseconds
|
||||
- `sim-delivery-id`: Unique delivery ID for idempotency
|
||||
- `sim-signature`: HMAC-SHA256 signature for verification (if secret configured)
|
||||
- `Idempotency-Key`: Same as delivery ID for duplicate detection
|
||||
|
||||
### Signature Verification
|
||||
|
||||
If you configure a webhook secret, verify the signature to ensure the webhook is from Sim:
|
||||
|
||||
<Tabs items={['Node.js', 'Python']}>
|
||||
<Tab value="Node.js">
|
||||
```javascript
|
||||
import crypto from 'crypto';
|
||||
|
||||
function verifyWebhookSignature(body, signature, secret) {
|
||||
const [timestampPart, signaturePart] = signature.split(',');
|
||||
const timestamp = timestampPart.replace('t=', '');
|
||||
const expectedSignature = signaturePart.replace('v1=', '');
|
||||
|
||||
const signatureBase = `${timestamp}.${body}`;
|
||||
const hmac = crypto.createHmac('sha256', secret);
|
||||
hmac.update(signatureBase);
|
||||
const computedSignature = hmac.digest('hex');
|
||||
|
||||
return computedSignature === expectedSignature;
|
||||
}
|
||||
|
||||
// In your webhook handler
|
||||
app.post('/webhook', (req, res) => {
|
||||
const signature = req.headers['sim-signature'];
|
||||
const body = JSON.stringify(req.body);
|
||||
|
||||
if (!verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET)) {
|
||||
return res.status(401).send('Invalid signature');
|
||||
}
|
||||
|
||||
// Process the webhook...
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="Python">
|
||||
```python
|
||||
import hmac
|
||||
import hashlib
|
||||
import json
|
||||
|
||||
def verify_webhook_signature(body: str, signature: str, secret: str) -> bool:
|
||||
timestamp_part, signature_part = signature.split(',')
|
||||
timestamp = timestamp_part.replace('t=', '')
|
||||
expected_signature = signature_part.replace('v1=', '')
|
||||
|
||||
signature_base = f"{timestamp}.{body}"
|
||||
computed_signature = hmac.new(
|
||||
secret.encode(),
|
||||
signature_base.encode(),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
return hmac.compare_digest(computed_signature, expected_signature)
|
||||
|
||||
# In your webhook handler
|
||||
@app.route('/webhook', methods=['POST'])
|
||||
def webhook():
|
||||
signature = request.headers.get('sim-signature')
|
||||
body = json.dumps(request.json)
|
||||
|
||||
if not verify_webhook_signature(body, signature, os.environ['WEBHOOK_SECRET']):
|
||||
return 'Invalid signature', 401
|
||||
|
||||
# Process the webhook...
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Retry Policy
|
||||
|
||||
Failed webhook deliveries are retried with exponential backoff and jitter:
|
||||
|
||||
- Maximum attempts: 5
|
||||
- Retry delays: 5 seconds, 15 seconds, 1 minute, 3 minutes, 10 minutes
|
||||
- Jitter: Up to 10% additional delay to prevent thundering herd
|
||||
- Only HTTP 5xx and 429 responses trigger retries
|
||||
- Deliveries timeout after 30 seconds
|
||||
|
||||
<Callout type="info">
|
||||
Webhook deliveries are processed asynchronously and don't affect workflow run performance.
|
||||
</Callout>
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Polling Strategy**: When polling for logs, use cursor-based pagination with `order=asc` and `startDate` to fetch new logs efficiently.
|
||||
|
||||
2. **Webhook Security**: Always configure a webhook secret and verify signatures to ensure requests are from Sim.
|
||||
2. **Privacy**: By default, `finalOutput` and `traceSpans` are excluded from responses. Only enable these if you need the data and understand the privacy implications.
|
||||
|
||||
3. **Idempotency**: Use the `Idempotency-Key` header to detect and handle duplicate webhook deliveries.
|
||||
|
||||
4. **Privacy**: By default, `finalOutput` and `traceSpans` are excluded from responses. Only enable these if you need the data and understand the privacy implications.
|
||||
|
||||
5. **Rate Limiting**: Implement exponential backoff when you receive 429 responses. Check the `Retry-After` header for the recommended wait time.
|
||||
3. **Rate Limiting**: Implement exponential backoff when you receive 429 responses. Check the `Retry-After` header for the recommended wait time.
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
@@ -540,67 +323,11 @@ async function pollLogs() {
|
||||
setInterval(pollLogs, 30000);
|
||||
```
|
||||
|
||||
## Example: Processing Webhooks
|
||||
|
||||
```javascript
|
||||
import express from 'express';
|
||||
import crypto from 'crypto';
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
app.post('/sim-webhook', (req, res) => {
|
||||
// Verify signature
|
||||
const signature = req.headers['sim-signature'];
|
||||
const body = JSON.stringify(req.body);
|
||||
|
||||
if (!verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET)) {
|
||||
return res.status(401).send('Invalid signature');
|
||||
}
|
||||
|
||||
// Check timestamp to prevent replay attacks
|
||||
const timestamp = parseInt(req.headers['sim-timestamp']);
|
||||
const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);
|
||||
|
||||
if (timestamp < fiveMinutesAgo) {
|
||||
return res.status(401).send('Timestamp too old');
|
||||
}
|
||||
|
||||
// Process the webhook
|
||||
const event = req.body;
|
||||
|
||||
switch (event.type) {
|
||||
case 'workflow.execution.completed':
|
||||
const { workflowId, executionId, status, cost } = event.data;
|
||||
|
||||
if (status === 'error') {
|
||||
console.error(`Workflow ${workflowId} failed: ${executionId}`);
|
||||
// Handle error...
|
||||
} else {
|
||||
console.log(`Workflow ${workflowId} completed: ${executionId}`);
|
||||
console.log(`Cost: $${cost.total}`);
|
||||
// Process successful execution...
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Return 200 to acknowledge receipt
|
||||
res.status(200).send('OK');
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log('Webhook server listening on port 3000');
|
||||
});
|
||||
```
|
||||
|
||||
import { FAQ } from '@/components/ui/faq'
|
||||
|
||||
<FAQ items={[
|
||||
{ question: "How do I trigger an async run via the API?", answer: "Set the X-Execution-Mode header to 'async' on your POST request to /api/workflows/{id}/execute. The API returns a 202 response with a jobId, executionId, and a statusUrl you can poll to check when the job completes. Async mode does not support draft state, workflow overrides, or selective output options." },
|
||||
{ question: "What authentication methods does the API support?", answer: "The API supports two authentication methods: API keys passed in the x-api-key header, and session-based authentication for logged-in users. API keys can be generated from Settings > Sim Keys in the platform. Workflows with public API access enabled can also be called without authentication." },
|
||||
{ question: "How does the webhook retry policy work?", answer: "Failed webhook deliveries are retried up to 5 times with exponential backoff: 5 seconds, 15 seconds, 1 minute, 3 minutes, and 10 minutes, plus up to 10% jitter. Only HTTP 5xx and 429 responses trigger retries. Each delivery times out after 30 seconds." },
|
||||
{ question: "What rate limits apply to the Logs API?", answer: "Rate limits use a token bucket algorithm. Free plans get 30 requests/minute with 60 burst capacity, Pro gets 100/200, Team gets 200/400, and Enterprise gets 500/1000. These are separate from workflow run rate limits, which are shown in the response body." },
|
||||
{ question: "How do I verify that a webhook is from Sim?", answer: "Configure a webhook secret when setting up notifications. Sim signs each delivery with HMAC-SHA256 using the format 't={timestamp},v1={signature}' in the sim-signature header. Compute the HMAC of '{timestamp}.{body}' with your secret and compare it to the signature value." },
|
||||
{ question: "What alert rules are available for notifications?", answer: "You can configure alerts for consecutive failures, failure rate thresholds, latency thresholds, latency spikes (percentage above average), cost thresholds, no-activity periods, and error counts within a time window. All alert types include a 1-hour cooldown to prevent notification spam." },
|
||||
{ question: "Can I filter which runs trigger notifications?", answer: "Yes. You can filter notifications by specific workflows (or select all), log level (info or error), and trigger type (api, webhook, schedule, manual, chat). You can also choose whether to include final output, trace spans, rate limits, and usage data in the notification payload." },
|
||||
{ question: "How do I get notified when a workflow run completes or fails?", answer: "Add the Sim trigger block to a workflow and deploy it. It runs on workspace events like execution successes, errors, deployments, and alert conditions such as latency spikes or cost thresholds — and you can compose any blocks downstream (Slack, email, webhooks, custom logic) to deliver the alert." },
|
||||
]} />
|
||||
|
||||
@@ -145,7 +145,7 @@ The snapshot provides:
|
||||
|
||||
- Learn about [Cost Calculation](/execution/costs) to understand workflow pricing
|
||||
- Explore the [External API](/execution/api) for programmatic log access
|
||||
- Set up [Notifications](/execution/api#notifications) for real-time alerts via webhook, email, or Slack
|
||||
- Add the Sim trigger block to a workflow to react to execution errors, successes, deployments, and alert conditions in real time
|
||||
|
||||
import { FAQ } from '@/components/ui/faq'
|
||||
|
||||
@@ -154,6 +154,6 @@ import { FAQ } from '@/components/ui/faq'
|
||||
{ question: "What data is captured in each run log?", answer: "Each log entry includes the run ID, workflow ID, trigger type, start and end timestamps, total duration in milliseconds, cost breakdown (total cost, token counts, and per-model breakdowns), run data with trace spans, final output, and any associated files. The log details sidebar lets you inspect block-level inputs and outputs." },
|
||||
{ question: "Are API keys visible in the logs?", answer: "No. API keys and credentials are automatically redacted in the log input tab for security. You can safely inspect block inputs without exposing sensitive values." },
|
||||
{ question: "What is a workflow snapshot?", answer: "A workflow snapshot is a frozen copy of the workflow's structure (blocks, connections, and configuration) captured at the time of a run. It lets you see the exact state of the workflow when a particular run happened, which is useful for debugging workflows that have been modified since." },
|
||||
{ question: "Can I access logs programmatically?", answer: "Yes. The External API provides endpoints to query logs with filtering by workflow, time range, trigger type, duration, cost, and model. You can also set up webhook, email, or Slack notifications for real-time alerts when runs complete." },
|
||||
{ question: "Can I access logs programmatically?", answer: "Yes. The External API provides endpoints to query logs with filtering by workflow, time range, trigger type, duration, cost, and model. To react to runs in real time, use the Sim trigger block to run a workflow on execution events." },
|
||||
{ question: "What does Live mode do on the Logs page?", answer: "Live mode automatically refreshes the Logs page in real-time so new log entries appear as they are recorded, without requiring manual page refreshes. This is useful during deployments or when monitoring active workflows." },
|
||||
]} />
|
||||
@@ -48,7 +48,6 @@
|
||||
"elevenlabs",
|
||||
"emailbison",
|
||||
"enrich",
|
||||
"enrichment",
|
||||
"evernote",
|
||||
"exa",
|
||||
"extend",
|
||||
@@ -120,6 +119,7 @@
|
||||
"mistral_parse",
|
||||
"monday",
|
||||
"mongodb",
|
||||
"mysql",
|
||||
"neo4j",
|
||||
"neverbounce",
|
||||
"new_relic",
|
||||
@@ -137,6 +137,7 @@
|
||||
"pinecone",
|
||||
"pipedrive",
|
||||
"polymarket",
|
||||
"postgresql",
|
||||
"posthog",
|
||||
"profound",
|
||||
"prospeo",
|
||||
@@ -164,12 +165,15 @@
|
||||
"serper",
|
||||
"servicenow",
|
||||
"ses",
|
||||
"sftp",
|
||||
"sharepoint",
|
||||
"shopify",
|
||||
"similarweb",
|
||||
"sixtyfour",
|
||||
"slack",
|
||||
"smtp",
|
||||
"sqs",
|
||||
"ssh",
|
||||
"stagehand",
|
||||
"stripe",
|
||||
"sts",
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
---
|
||||
title: MySQL
|
||||
description: Connect to MySQL database
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="mysql"
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
|
||||
## 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 |
|
||||
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
---
|
||||
title: PostgreSQL
|
||||
description: Connect to PostgreSQL database
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="postgresql"
|
||||
color="#336791"
|
||||
/>
|
||||
|
||||
## 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 |
|
||||
|
||||
|
||||
@@ -215,7 +215,6 @@ Attach a file to a ServiceNow record
|
||||
| `recordSysId` | string | Yes | sys_id of the record to attach the file to |
|
||||
| `fileName` | string | Yes | Name to give the uploaded file \(e.g., logs.txt\) |
|
||||
| `file` | file | No | File to upload \(UserFile object\) |
|
||||
| `fileContent` | string | No | Base64-encoded file content \(legacy\) |
|
||||
|
||||
#### Output
|
||||
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
---
|
||||
title: SFTP
|
||||
description: Transfer files via SFTP (SSH File Transfer Protocol)
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="sftp"
|
||||
color="#2D3748"
|
||||
/>
|
||||
|
||||
## 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 |
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: SMTP
|
||||
description: Send emails via any SMTP mail server
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="smtp"
|
||||
color="#2D3748"
|
||||
/>
|
||||
|
||||
## 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 |
|
||||
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
---
|
||||
title: SSH
|
||||
description: Connect to remote servers via SSH
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="ssh"
|
||||
color="#000000"
|
||||
/>
|
||||
|
||||
## 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 |
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"schedule",
|
||||
"webhook",
|
||||
"rss",
|
||||
"sim",
|
||||
"airtable",
|
||||
"ashby",
|
||||
"attio",
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
title: Sim
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { FAQ } from '@/components/ui/faq'
|
||||
|
||||
The Sim trigger runs a workflow when events happen in your workspace: another workflow's run fails or succeeds, a workflow is deployed, or an alert condition like a latency spike or cost threshold is met. Use it to build side-effect workflows — alerting, escalation, auto-remediation — composed from any blocks (Slack, email, webhooks, custom logic).
|
||||
|
||||
## Events
|
||||
|
||||
Pick one event per Sim trigger block:
|
||||
|
||||
**Plain events** — fire on every occurrence:
|
||||
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li><strong>Execution Error</strong>: a watched workflow's run failed</li>
|
||||
<li><strong>Execution Success</strong>: a watched workflow's run completed successfully</li>
|
||||
<li><strong>Workflow Deployed</strong>: a watched workflow was deployed (including redeploys and version rollbacks)</li>
|
||||
</ul>
|
||||
|
||||
**Alert conditions** — evaluated as runs complete (failure-based conditions evaluate on failed runs), with a cooldown so they fire at most once per cooldown window:
|
||||
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li><strong>Consecutive Failures</strong>: the last N runs all failed</li>
|
||||
<li><strong>Failure Rate</strong>: failure rate meets or exceeds a percentage over a time window (minimum 5 runs)</li>
|
||||
<li><strong>Latency Threshold</strong>: a run took longer than a fixed duration</li>
|
||||
<li><strong>Latency Spike</strong>: a run was a configurable percentage slower than the recent average (minimum 5 runs)</li>
|
||||
<li><strong>Cost Threshold</strong>: a run cost more than a credit threshold</li>
|
||||
<li><strong>Error Count</strong>: N or more errors occurred within a time window</li>
|
||||
<li><strong>No Activity</strong>: a watched workflow had no runs for a configurable number of hours</li>
|
||||
</ul>
|
||||
|
||||
## Workflow Scope
|
||||
|
||||
By default the trigger watches every workflow in the workspace. Select specific workflows to narrow it. The workflow containing the trigger is always excluded — it never receives events about itself.
|
||||
|
||||
## Outputs
|
||||
|
||||
All events include `event`, `timestamp`, `workflowId`, and `workflowName` (the source workflow). Additional fields depend on the event type:
|
||||
|
||||
<Tabs items={['Execution Events', 'Alert Conditions', 'Workflow Deployed']}>
|
||||
<Tab>
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li><strong>runId</strong>: the run that completed</li>
|
||||
<li><strong>durationMs</strong>: run duration in milliseconds</li>
|
||||
<li><strong>cost</strong>: run cost in credits</li>
|
||||
<li><strong>finalOutput</strong>: the run's final output (truncated when large)</li>
|
||||
</ul>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<p>Run-backed conditions nest the run that tripped them under <code>triggeringRun</code>:</p>
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li><strong>triggeringRun.runId</strong>, <strong>triggeringRun.durationMs</strong>, <strong>triggeringRun.cost</strong>, <strong>triggeringRun.finalOutput</strong></li>
|
||||
</ul>
|
||||
<p>No Activity has no triggering run, so it carries only the base fields.</p>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li><strong>version</strong>: the deployment version number that was activated</li>
|
||||
</ul>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Behavior
|
||||
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li>The workflow containing the Sim trigger must be <strong>deployed</strong> for events to fire.</li>
|
||||
<li>Runs started by a Sim trigger never emit workspace events, so side-effect workflows cannot chain or loop.</li>
|
||||
<li>Alert conditions fire at most once per cooldown window (one hour, or the inactivity window for No Activity).</li>
|
||||
<li>Event delivery is fire-and-forget: side-effect runs are billed like any other run and are subject to workspace rate limits.</li>
|
||||
</ul>
|
||||
|
||||
<Callout type="info">
|
||||
Trigger configuration is snapshotted at deploy time. After changing the event type, workflow
|
||||
scope, or thresholds, redeploy the workflow for the changes to take effect.
|
||||
</Callout>
|
||||
|
||||
<FAQ items={[
|
||||
{ question: "Why isn't my Sim trigger firing?", answer: "The workflow containing the trigger must be deployed — events only fire for deployed workflows. Also note the trigger never fires for the workflow it lives in, and runs started by another Sim trigger don't emit events." },
|
||||
{ question: "Can a Sim-triggered workflow trigger other Sim triggers?", answer: "No. Runs started by a Sim trigger never emit workspace events. This prevents chains and infinite loops — an alert workflow that fails can't re-trigger itself." },
|
||||
{ question: "How often do alert conditions fire?", answer: "At most once per cooldown window per trigger block. Most conditions use a one-hour cooldown; No Activity uses the configured inactivity window, evaluated per watched workflow." },
|
||||
{ question: "What unit is cost in?", answer: "Credits, both for the Cost Threshold configuration and the cost field in event payloads." },
|
||||
]} />
|
||||
Reference in New Issue
Block a user