Compare commits

..

34 Commits

Author SHA1 Message Date
aadamgough
92a08b0a33 removed success from microsoft tools 2025-12-15 19:37:45 -08:00
aadamgough
5d3b216922 fixed jira output 2025-12-14 21:06:28 -08:00
Waleed
431f206930 fix(tools): add validation for ids in tool routes (#2371) 2025-12-13 19:40:33 -08:00
Waleed
7443e28054 feat(i18n): update translations (#2370)
Co-authored-by: waleedlatif1 <waleedlatif1@users.noreply.github.com>
2025-12-13 19:26:31 -08:00
Waleed
c962e3b398 feat(webflow): added collection, item, & site selectors for webflow (#2368)
* feat(webflow): added collection, item, & site selectors for webflow

* ack PR comments

* ack PR comments
2025-12-13 19:14:33 -08:00
Waleed
d5b95cbd33 fix(organizations): move organization better-auth client to conditionally be included based on FF (#2367)
* fix(organizations): move organization better-auth client to conditionally be included based on FF

* ack PR comment
2025-12-13 19:06:12 -08:00
Waleed
0fb084b9e4 fix(subflows): prevent cross-boundary connections on autoconnect drop between subflow blocks and regular blocks (#2366) 2025-12-13 17:38:59 -08:00
Waleed
95b9ca4670 feat(registration): allow self-hosted users to disable registration altogether (#2365)
* feat(registration): allow self-hosted users to disable registration altogether

* updated tests

* fix build
2025-12-13 17:34:53 -08:00
Vikhyath Mondreti
746ff68a2e fix(sub-deletion): subscription deletion handling for pro vs team/enterprise (#2364)
* fix(subscription): deletion should sync pro limits back to free

* consolidate duplicate code
2025-12-13 16:10:47 -08:00
Waleed
75a5b43252 feat(og): update og image (#2362) 2025-12-13 15:52:13 -08:00
Vikhyath Mondreti
8d0e50fd0d improvement(admin-routes): cleanup code that could accidentally desync stripe and DB (#2363)
* remove non-functional admin route

* stripe updates cleanup
2025-12-13 15:11:14 -08:00
Waleed
f7d1b06d75 feat(docs): add opengraph to docs for dynamic link preview (#2360) 2025-12-13 13:51:43 -08:00
Vikhyath Mondreti
73940ab390 fix(deployed-chat): voice mode (#2358)
* fix(deployed-chat): voice mode

* remove redundant check

* consolidate query

* invalidate session on password change + race condition fix
2025-12-13 12:31:03 -08:00
Vikhyath Mondreti
f111dac020 improvement(autolayout): reduce horizontal spacing (#2357) 2025-12-13 11:06:42 -08:00
Waleed
690be530c8 chore(icons): update spotify icon (#2356) 2025-12-13 02:11:42 -08:00
Waleed
4edb3be52d fix(spotify): added missing human readable scopes to oauth required modal (#2355) 2025-12-12 21:09:12 -08:00
Waleed
9c8d845ba4 feat(ui): added component playground & fixed training modal (#2354) 2025-12-12 21:05:26 -08:00
Waleed
65ac64c2cf feat(i18n): update translations (#2351)
Co-authored-by: waleedlatif1 <waleedlatif1@users.noreply.github.com>
2025-12-12 20:15:06 -08:00
Waleed
9e3e18601c fix(next): externalize playwright and ws (#2352) 2025-12-12 20:14:53 -08:00
Waleed
821d127c00 fix(build): explicitly install shims module from anthropic and openai in stagehand route (#2350) 2025-12-12 19:24:47 -08:00
Siddharth Ganesan
ecf5209e6f feat(integration): add spotify (#2347)
* Add spotify

* Finish spotify integration

* Fix logo

* fix build

* Rename tools

* Fix docs

* Fix lint

* Fix imports

* ran lint

---------

Co-authored-by: waleed <walif6@gmail.com>
2025-12-12 19:22:17 -08:00
Vikhyath Mondreti
132f4bca38 fix(validation): don't validate disabled blocks (#2348) 2025-12-12 19:02:08 -08:00
Waleed
d27f7c232b fix(next): remove openai and anthropic sdk's from serverExternalPackages (#2349) 2025-12-12 18:09:17 -08:00
Siddharth Ganesan
d06d2b01e3 fix(copilot): fix incorrectly sanitizing json state (#2346)
* Fix

* Fix

* Remove dead code

* Fix lint
2025-12-12 17:55:29 -08:00
Waleed
92db054c53 feat(i18n): update translations (#2345)
Co-authored-by: waleedlatif1 <waleedlatif1@users.noreply.github.com>
2025-12-12 17:50:34 -08:00
Waleed
cd7fa688c9 fix(build): fix DB dockerfile (#2344) 2025-12-12 17:11:01 -08:00
Waleed
e359dc2946 fix(cron): reject CRON requests when CRON secret is not set (#2343) 2025-12-12 17:08:48 -08:00
Vikhyath Mondreti
0415eb47fe fix(minor-bugs): grafana, zep, video generation, templates fixes (#2336)
* make creator profile required

* fix grafana tag dropdown / outputs mismatch

* fix grafana annotations to make dashboard id required

* fix fal ai

* fix fal ai

* fix zep
2025-12-12 17:02:36 -08:00
Waleed
49d31c80f5 feat(i18n): update translations (#2339)
Co-authored-by: waleedlatif1 <waleedlatif1@users.noreply.github.com>
2025-12-12 16:59:04 -08:00
Waleed
0ea600d0e8 fix(browserbase): consoldiated stagehand agent and extract, updated wand UI to resize based on panel size (#2340) 2025-12-12 16:58:51 -08:00
Waleed
deb085881f chore(db): remove unused table and unused route (#2342) 2025-12-12 16:58:38 -08:00
Waleed
dda44f7382 fix(build): remove incompatible --frozen-lockfile and --omit dev from docker (#2341)
* fix(build): remove incompatible --frozen-lockfile and --omit dev from docker

* ack PR comments
2025-12-12 16:58:23 -08:00
Waleed
668118b19b fix(tools): remove pylon (#2338) 2025-12-12 16:00:52 -08:00
Waleed
323e03520d feat(releases): tag releases to main with version numbers, speed up docker builds (#2337)
* feat(releases): tag releases to main with version numbers, speed up docker builds

* resize runners
2025-12-12 15:57:10 -08:00
386 changed files with 29940 additions and 13541 deletions

View File

@@ -1,11 +1,67 @@
# Git
.git
.gitignore
# Documentation
LICENSE
NOTICE
README.md
*.md
docs/
# IDE and editor
.vscode
.idea
*.swp
*.swo
# Environment and config
.env*
!.env.example
.prettierrc
.prettierignore
README.md
.gitignore
.husky
.eslintrc*
.eslintignore
# CI/CD and DevOps
.github
.devcontainer
.env.example
node_modules
.husky
docker-compose*.yml
Dockerfile*
# Build artifacts and caches
.next
.turbo
.cache
dist
build
out
coverage
*.log
# Dependencies (will be installed fresh in container)
node_modules
.bun
# Test files
**/*.test.ts
**/*.test.tsx
**/*.spec.ts
**/*.spec.tsx
__tests__
__mocks__
jest.config.*
vitest.config.*
# TypeScript build info
*.tsbuildinfo
# OS files
.DS_Store
Thumbs.db
# Temporary files
tmp
temp
*.tmp

View File

@@ -16,10 +16,35 @@ jobs:
uses: ./.github/workflows/test-build.yml
secrets: inherit
# Detect if this is a version release commit (e.g., "v0.5.24: ...")
detect-version:
name: Detect Version
runs-on: blacksmith-4vcpu-ubuntu-2404
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging')
outputs:
version: ${{ steps.extract.outputs.version }}
is_release: ${{ steps.extract.outputs.is_release }}
steps:
- name: Extract version from commit message
id: extract
run: |
COMMIT_MSG="${{ github.event.head_commit.message }}"
# Only tag versions on main branch
if [ "${{ github.ref }}" = "refs/heads/main" ] && [[ "$COMMIT_MSG" =~ ^(v[0-9]+\.[0-9]+\.[0-9]+): ]]; then
VERSION="${BASH_REMATCH[1]}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "is_release=true" >> $GITHUB_OUTPUT
echo "✅ Detected release commit: ${VERSION}"
else
echo "version=" >> $GITHUB_OUTPUT
echo "is_release=false" >> $GITHUB_OUTPUT
echo " Not a release commit"
fi
# Build AMD64 images and push to ECR immediately (+ GHCR for main)
build-amd64:
name: Build AMD64
needs: test-build
needs: [test-build, detect-version]
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging')
runs-on: blacksmith-8vcpu-ubuntu-2404
permissions:
@@ -93,6 +118,14 @@ jobs:
GHCR_AMD64="${GHCR_IMAGE}:latest-amd64"
GHCR_SHA="${GHCR_IMAGE}:${{ github.sha }}-amd64"
TAGS="${TAGS},$GHCR_AMD64,$GHCR_SHA"
# Add version tag if this is a release commit
if [ "${{ needs.detect-version.outputs.is_release }}" = "true" ]; then
VERSION="${{ needs.detect-version.outputs.version }}"
GHCR_VERSION="${GHCR_IMAGE}:${VERSION}-amd64"
TAGS="${TAGS},$GHCR_VERSION"
echo "📦 Adding version tag: ${VERSION}-amd64"
fi
fi
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
@@ -111,7 +144,7 @@ jobs:
# Build ARM64 images for GHCR (main branch only, runs in parallel)
build-ghcr-arm64:
name: Build ARM64 (GHCR Only)
needs: test-build
needs: [test-build, detect-version]
runs-on: blacksmith-8vcpu-ubuntu-2404-arm
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
permissions:
@@ -146,7 +179,16 @@ jobs:
id: meta
run: |
IMAGE="${{ matrix.image }}"
echo "tags=${IMAGE}:latest-arm64,${IMAGE}:${{ github.sha }}-arm64" >> $GITHUB_OUTPUT
TAGS="${IMAGE}:latest-arm64,${IMAGE}:${{ github.sha }}-arm64"
# Add version tag if this is a release commit
if [ "${{ needs.detect-version.outputs.is_release }}" = "true" ]; then
VERSION="${{ needs.detect-version.outputs.version }}"
TAGS="${TAGS},${IMAGE}:${VERSION}-arm64"
echo "📦 Adding version tag: ${VERSION}-arm64"
fi
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
- name: Build and push ARM64 to GHCR
uses: useblacksmith/build-push-action@v2
@@ -162,8 +204,8 @@ jobs:
# Create GHCR multi-arch manifests (only for main, after both builds)
create-ghcr-manifests:
name: Create GHCR Manifests
runs-on: blacksmith-8vcpu-ubuntu-2404
needs: [build-amd64, build-ghcr-arm64]
runs-on: blacksmith-2vcpu-ubuntu-2404
needs: [build-amd64, build-ghcr-arm64, detect-version]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
permissions:
packages: write
@@ -198,6 +240,16 @@ jobs:
"${IMAGE_BASE}:${{ github.sha }}-arm64"
docker manifest push "${IMAGE_BASE}:${{ github.sha }}"
# Create version manifest if this is a release commit
if [ "${{ needs.detect-version.outputs.is_release }}" = "true" ]; then
VERSION="${{ needs.detect-version.outputs.version }}"
echo "📦 Creating version manifest: ${VERSION}"
docker manifest create "${IMAGE_BASE}:${VERSION}" \
"${IMAGE_BASE}:${VERSION}-amd64" \
"${IMAGE_BASE}:${VERSION}-arm64"
docker manifest push "${IMAGE_BASE}:${VERSION}"
fi
# Check if docs changed
check-docs-changes:
name: Check Docs Changes

View File

@@ -243,6 +243,9 @@ export async function generateMetadata(props: {
const baseUrl = 'https://docs.sim.ai'
const fullUrl = `${baseUrl}${page.url}`
const description = page.data.description || ''
const ogImageUrl = `${baseUrl}/api/og?title=${encodeURIComponent(page.data.title)}&category=DOCUMENTATION${description ? `&description=${encodeURIComponent(description)}` : ''}`
return {
title: page.data.title,
description:
@@ -272,12 +275,23 @@ export async function generateMetadata(props: {
alternateLocale: ['en', 'es', 'fr', 'de', 'ja', 'zh']
.filter((lang) => lang !== params.lang)
.map((lang) => (lang === 'en' ? 'en_US' : `${lang}_${lang.toUpperCase()}`)),
images: [
{
url: ogImageUrl,
width: 1200,
height: 630,
alt: page.data.title,
},
],
},
twitter: {
card: 'summary',
card: 'summary_large_image',
title: page.data.title,
description:
page.data.description || 'Sim visual workflow builder for AI applications documentation',
images: [ogImageUrl],
creator: '@simdotai',
site: '@simdotai',
},
robots: {
index: true,

View File

@@ -0,0 +1,173 @@
import { ImageResponse } from 'next/og'
import type { NextRequest } from 'next/server'
export const runtime = 'edge'
const TITLE_FONT_SIZE = {
large: 64,
medium: 56,
small: 48,
} as const
function getTitleFontSize(title: string): number {
if (title.length > 45) return TITLE_FONT_SIZE.small
if (title.length > 30) return TITLE_FONT_SIZE.medium
return TITLE_FONT_SIZE.large
}
/**
* Loads a Google Font dynamically by fetching the CSS and extracting the font URL.
*/
async function loadGoogleFont(font: string, weights: string, text: string): Promise<ArrayBuffer> {
const url = `https://fonts.googleapis.com/css2?family=${font}:wght@${weights}&text=${encodeURIComponent(text)}`
const css = await (await fetch(url)).text()
const resource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/)
if (resource) {
const response = await fetch(resource[1])
if (response.status === 200) {
return await response.arrayBuffer()
}
}
throw new Error('Failed to load font data')
}
/**
* Generates dynamic Open Graph images for documentation pages.
*/
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
const title = searchParams.get('title') || 'Documentation'
const category = searchParams.get('category') || 'DOCUMENTATION'
const description = searchParams.get('description') || ''
const baseUrl = new URL(request.url).origin
const backgroundImageUrl = `${baseUrl}/static/og-background.png`
const allText = `${title}${category}${description}docs.sim.ai`
const fontData = await loadGoogleFont('Geist', '400;500;600', allText)
return new ImageResponse(
<div
style={{
height: '100%',
width: '100%',
display: 'flex',
flexDirection: 'column',
background: 'linear-gradient(315deg, #1e1e3f 0%, #1a1a2e 40%, #0f0f0f 100%)',
position: 'relative',
fontFamily: 'Geist',
}}
>
{/* Background texture */}
<img
src={backgroundImageUrl}
alt=''
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
objectFit: 'cover',
opacity: 0.04,
}}
/>
{/* Subtle purple glow from bottom right */}
<div
style={{
position: 'absolute',
bottom: 0,
right: 0,
width: '50%',
height: '100%',
background:
'radial-gradient(ellipse at bottom right, rgba(112, 31, 252, 0.1) 0%, transparent 50%)',
display: 'flex',
}}
/>
{/* Content */}
<div
style={{
display: 'flex',
flexDirection: 'column',
padding: '56px 72px',
height: '100%',
justifyContent: 'space-between',
}}
>
{/* Logo */}
<img src={`${baseUrl}/static/logo.png`} alt='sim' height={32} />
{/* Category + Title + Description */}
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 12,
}}
>
<span
style={{
fontSize: 15,
fontWeight: 600,
color: '#802fff',
letterSpacing: '0.02em',
}}
>
{category}
</span>
<span
style={{
fontSize: getTitleFontSize(title),
fontWeight: 600,
color: '#ffffff',
lineHeight: 1.1,
letterSpacing: '-0.02em',
}}
>
{title}
</span>
{description && (
<span
style={{
fontSize: 18,
fontWeight: 400,
color: '#a1a1aa',
lineHeight: 1.4,
marginTop: 4,
}}
>
{description.length > 100 ? `${description.slice(0, 100)}...` : description}
</span>
)}
</div>
{/* Footer */}
<span
style={{
fontSize: 15,
fontWeight: 500,
color: '#52525b',
}}
>
docs.sim.ai
</span>
</div>
</div>,
{
width: 1200,
height: 630,
fonts: [
{
name: 'Geist',
data: fontData,
style: 'normal',
},
],
}
)
}

View File

@@ -56,6 +56,14 @@ export const metadata = {
title: 'Sim Documentation - Visual Workflow Builder for AI Applications',
description:
'Comprehensive documentation for Sim - the visual workflow builder for AI applications. Create powerful AI agents, automation workflows, and data processing pipelines.',
images: [
{
url: 'https://docs.sim.ai/api/og?title=Sim%20Documentation&category=DOCUMENTATION',
width: 1200,
height: 630,
alt: 'Sim Documentation',
},
],
},
twitter: {
card: 'summary_large_image',
@@ -64,7 +72,7 @@ export const metadata = {
'Comprehensive documentation for Sim - the visual workflow builder for AI applications.',
creator: '@simdotai',
site: '@simdotai',
images: ['/og-image.png'],
images: ['https://docs.sim.ai/api/og?title=Sim%20Documentation&category=DOCUMENTATION'],
},
robots: {
index: true,

File diff suppressed because one or more lines are too long

View File

@@ -75,7 +75,6 @@ import {
PolymarketIcon,
PostgresIcon,
PosthogIcon,
PylonIcon,
QdrantIcon,
RDSIcon,
RedditIcon,
@@ -90,6 +89,7 @@ import {
ShopifyIcon,
SlackIcon,
SmtpIcon,
SpotifyIcon,
SQSIcon,
SshIcon,
STTIcon,
@@ -143,10 +143,10 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
supabase: SupabaseIcon,
stt: STTIcon,
stripe: StripeIcon,
stagehand_agent: StagehandIcon,
stagehand: StagehandIcon,
ssh: SshIcon,
sqs: SQSIcon,
spotify: SpotifyIcon,
smtp: SmtpIcon,
slack: SlackIcon,
shopify: ShopifyIcon,
@@ -162,7 +162,6 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
reddit: RedditIcon,
rds: RDSIcon,
qdrant: QdrantIcon,
pylon: PylonIcon,
posthog: PosthogIcon,
postgresql: PostgresIcon,
polymarket: PolymarketIcon,

View File

@@ -321,7 +321,7 @@ Eine Anmerkung auf einem Dashboard oder als globale Anmerkung erstellen
| `organizationId` | string | Nein | Organisations-ID für Multi-Org-Grafana-Instanzen |
| `text` | string | Ja | Der Textinhalt der Anmerkung |
| `tags` | string | Nein | Kommagetrennte Liste von Tags |
| `dashboardUid` | string | Nein | UID des Dashboards, zu dem die Anmerkung hinzugefügt werden soll \(optional für globale Anmerkungen\) |
| `dashboardUid` | string | Ja | UID des Dashboards, zu dem die Anmerkung hinzugefügt werden soll |
| `panelId` | number | Nein | ID des Panels, zu dem die Anmerkung hinzugefügt werden soll |
| `time` | number | Nein | Startzeit in Epochenmillisekunden \(standardmäßig jetzt\) |
| `timeEnd` | number | Nein | Endzeit in Epochenmillisekunden \(für Bereichsanmerkungen\) |
@@ -346,11 +346,11 @@ Anmerkungen nach Zeitraum, Dashboard oder Tags abfragen
| `organizationId` | string | Nein | Organisations-ID für Multi-Org-Grafana-Instanzen |
| `from` | number | Nein | Startzeit in Epochenmillisekunden |
| `to` | number | Nein | Endzeit in Epochenmillisekunden |
| `dashboardUid` | string | Nein | Nach Dashboard-UID filtern |
| `dashboardUid` | string | Ja | Dashboard-UID, von der Anmerkungen abgefragt werden sollen |
| `panelId` | number | Nein | Nach Panel-ID filtern |
| `tags` | string | Nein | Kommagetrennte Liste von Tags, nach denen gefiltert werden soll |
| `tags` | string | Nein | Kommagetrennte Liste von Tags zum Filtern |
| `type` | string | Nein | Nach Typ filtern \(alert oder annotation\) |
| `limit` | number | Nein | Maximale Anzahl von zurückzugebenden Anmerkungen |
| `limit` | number | Nein | Maximale Anzahl der zurückzugebenden Anmerkungen |
#### Ausgabe
@@ -481,12 +481,22 @@ Einen neuen Ordner in Grafana erstellen
#### Ausgabe
| Parameter | Typ | Beschreibung |
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `id` | number | Die numerische ID des erstellten Ordners |
| `uid` | string | Die UID des erstellten Ordners |
| `title` | string | Der Titel des erstellten Ordners |
| `url` | string | Der URL-Pfad zum Ordner |
| `hasAcl` | boolean | Ob der Ordner benutzerdefinierte ACL-Berechtigungen hat |
| `canSave` | boolean | Ob der aktuelle Benutzer den Ordner speichern kann |
| `canEdit` | boolean | Ob der aktuelle Benutzer den Ordner bearbeiten kann |
| `canAdmin` | boolean | Ob der aktuelle Benutzer Administratorrechte für den Ordner hat |
| `canDelete` | boolean | Ob der aktuelle Benutzer den Ordner löschen kann |
| `createdBy` | string | Benutzername desjenigen, der den Ordner erstellt hat |
| `created` | string | Zeitstempel, wann der Ordner erstellt wurde |
| `updatedBy` | string | Benutzername desjenigen, der den Ordner zuletzt aktualisiert hat |
| `updated` | string | Zeitstempel, wann der Ordner zuletzt aktualisiert wurde |
| `version` | number | Versionsnummer des Ordners |
## Notizen

View File

@@ -1,807 +0,0 @@
---
title: Pylon
description: Verwalten Sie Kundensupport-Anfragen, Konten, Kontakte, Benutzer,
Teams und Tags in Pylon
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="pylon"
color="#E8F4FA"
/>
{/* MANUAL-CONTENT-START:intro */}
[Pylon](https://usepylon.com/) ist eine fortschrittliche Kundensupport- und Erfolgsplattform, die entwickelt wurde, um Ihnen bei der Verwaltung aller Aspekte Ihrer Kundenbeziehungen zu helfen von Support-Anfragen bis hin zu Konten, Kontakten, Benutzern, Teams und darüber hinaus. Pylon ermöglicht Support- und Erfolgsteams, effizient und programmatisch mit einer umfangreichen API und umfassenden Werkzeugen zu arbeiten.
Mit Pylon in Sim können Sie:
- **Support-Anfragen verwalten:**
- Support-Anfragen auflisten, erstellen, abrufen, aktualisieren und löschen für effizientes Falltracking.
- Anfragen durchsuchen und zurückstellen, um Agenten zu helfen, fokussiert und organisiert zu bleiben.
- Verwalten von Anfrage-Followern und externen Anfragen für nahtlose Zusammenarbeit mit internen und externen Stakeholdern.
- **Vollständige Kontoverwaltung:**
- Kundenkonten auflisten, erstellen, abrufen, aktualisieren und löschen.
- Massenaktualisierung von Konten programmatisch durchführen.
- Konten durchsuchen, um schnell kundenrelevante Informationen für Support oder Outreach zu finden.
- **Kontaktverwaltung:**
- Kontakte auflisten, erstellen, abrufen, aktualisieren, löschen und durchsuchen verwalten Sie alle Personen, die mit Ihren Konten verbunden sind.
- **Benutzer- und Team-Operationen:**
- Benutzer in Ihrem Pylon-Workspace auflisten, abrufen, aktualisieren und durchsuchen.
- Teams auflisten, erstellen, abrufen und aktualisieren, um Ihre Support-Organisation und Arbeitsabläufe zu strukturieren.
- **Tagging und Organisation:**
- Tags auflisten, abrufen, erstellen, aktualisieren und löschen zur Kategorisierung von Anfragen, Konten oder Kontakten.
- **Nachrichtenbearbeitung:**
- Sensible Nachrichteninhalte direkt aus Ihren Workflows redigieren für Datenschutz und Compliance.
Durch die Integration von Pylon-Tools in Sim können Ihre Agenten jeden Aspekt der Support-Operationen automatisieren:
- Automatisches Öffnen, Aktualisieren oder Priorisieren neuer Anfragen bei Kundenereignissen.
- Synchronisierte Konto- und Kontaktdaten über Ihren gesamten Tech-Stack hinweg pflegen.
- Gespräche weiterleiten, Eskalationen bearbeiten und Ihre Support-Daten mithilfe von Tags und Teams organisieren.
- Sicherstellen, dass sensible Daten ordnungsgemäß verwaltet werden, indem Nachrichten bei Bedarf redigiert werden.
Die Endpunkte von Pylon bieten granulare Kontrolle für das vollständige Lifecycle-Management von Kundenanliegen und -beziehungen. Ob beim Skalieren eines Support-Desks, bei der Unterstützung proaktiver Kundenbetreuung oder bei der Integration mit anderen Systemen Pylon in Sim ermöglicht erstklassige CRM-Automatisierung sicher, flexibel und skalierbar.
{/* MANUAL-CONTENT-END */}
## Nutzungsanleitung
Integrieren Sie Pylon in den Workflow. Verwalten Sie Anliegen (auflisten, erstellen, abrufen, aktualisieren, löschen, suchen, zurückstellen, Follower, externe Anliegen), Konten (auflisten, erstellen, abrufen, aktualisieren, löschen, Massenaktualisierung, suchen), Kontakte (auflisten, erstellen, abrufen, aktualisieren, löschen, suchen), Benutzer (auflisten, abrufen, aktualisieren, suchen), Teams (auflisten, abrufen, erstellen, aktualisieren), Tags (auflisten, abrufen, erstellen, aktualisieren, löschen) und Nachrichten (redigieren).
## Tools
### `pylon_list_issues`
Eine Liste von Anliegen innerhalb eines bestimmten Zeitraums abrufen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `startTime` | string | Ja | Startzeit im RFC3339-Format \(z.B. 2024-01-01T00:00:00Z\) |
| `endTime` | string | Ja | Endzeit im RFC3339-Format \(z.B. 2024-01-31T23:59:59Z\) |
| `cursor` | string | Nein | Paginierungscursor für die nächste Ergebnisseite |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Liste der Anliegen |
### `pylon_create_issue`
Ein neues Anliegen mit bestimmten Eigenschaften erstellen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `title` | string | Ja | Titel des Problems |
| `bodyHtml` | string | Ja | Inhalt des Problems im HTML-Format |
| `accountId` | string | Nein | Konto-ID, die mit dem Problem verknüpft werden soll |
| `assigneeId` | string | Nein | Benutzer-ID, der das Problem zugewiesen werden soll |
| `teamId` | string | Nein | Team-ID, dem das Problem zugewiesen werden soll |
| `requesterId` | string | Nein | Anforderer-Benutzer-ID \(Alternative zu requester_email\) |
| `requesterEmail` | string | Nein | E-Mail-Adresse des Anforderers \(Alternative zu requester_id\) |
| `priority` | string | Nein | Priorität des Problems |
| `tags` | string | Nein | Durch Komma getrennte Tag-IDs |
| `customFields` | string | Nein | Benutzerdefinierte Felder als JSON-Objekt |
| `attachmentUrls` | string | Nein | Durch Komma getrennte Anhang-URLs |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Daten des erstellten Issues |
### `pylon_get_issue`
Ruft ein bestimmtes Issue anhand der ID ab
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `issueId` | string | Ja | Die ID des abzurufenden Issues |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Issue-Daten |
### `pylon_update_issue`
Aktualisiert ein bestehendes Issue
#### Input
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `issueId` | string | Ja | Die ID des zu aktualisierenden Problems |
| `state` | string | Nein | Status des Problems |
| `assigneeId` | string | Nein | Benutzer-ID, der das Problem zugewiesen werden soll |
| `teamId` | string | Nein | Team-ID, dem das Problem zugewiesen werden soll |
| `tags` | string | Nein | Durch Komma getrennte Tag-IDs |
| `customFields` | string | Nein | Benutzerdefinierte Felder als JSON-Objekt |
| `customerPortalVisible` | boolean | Nein | Ob das Problem im Kundenportal sichtbar ist |
| `requesterId` | string | Nein | Anforderer-Benutzer-ID |
| `accountId` | string | Nein | Konto-ID, die mit dem Problem verknüpft werden soll |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Daten des aktualisierten Issues |
### `pylon_delete_issue`
Problem nach ID entfernen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `issueId` | string | Ja | Die ID des zu löschenden Problems |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Löschergebnis |
### `pylon_search_issues`
Probleme mit Filtern abfragen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `filter` | string | Ja | Filterkriterien als JSON-String |
| `cursor` | string | Nein | Paginierungscursor für die nächste Ergebnisseite |
| `limit` | number | Nein | Maximale Anzahl der zurückzugebenden Ergebnisse |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Suchergebnisse |
### `pylon_snooze_issue`
Problemsichtbarkeit bis zu einem bestimmten Zeitpunkt verschieben
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `issueId` | string | Ja | Die ID des zu schlummernden Problems |
| `snoozeUntil` | string | Ja | RFC3339-Zeitstempel, wann das Problem wieder erscheinen soll \(z.B. 2024-01-01T00:00:00Z\) |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Daten des zurückgestellten Problems |
### `pylon_list_issue_followers`
Liste der Follower für ein bestimmtes Problem abrufen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `issueId` | string | Ja | Die ID des Problems |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Liste der Follower |
### `pylon_manage_issue_followers`
Follower zu einem Problem hinzufügen oder entfernen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `issueId` | string | Ja | Die ID des Problems |
| `userIds` | string | Nein | Durch Komma getrennte Benutzer-IDs zum Hinzufügen/Entfernen |
| `contactIds` | string | Nein | Durch Komma getrennte Kontakt-IDs zum Hinzufügen/Entfernen |
| `operation` | string | Nein | Auszuführende Operation: "add" oder "remove" \(Standard: "add"\) |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Aktualisierte Liste der Follower |
### `pylon_link_external_issue`
Issue mit einem externen System-Issue verknüpfen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `issueId` | string | Ja | Die ID des Pylon-Issues |
| `externalIssueId` | string | Ja | Die ID des externen Issues |
| `source` | string | Ja | Das Quellsystem \(z.B. "jira", "linear", "github"\) |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Daten des verknüpften externen Issues |
### `pylon_list_accounts`
Eine paginierte Liste von Konten abrufen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `limit` | string | Nein | Anzahl der zurückzugebenden Konten \(1-1000, Standard 100\) |
| `cursor` | string | Nein | Paginierungscursor für die nächste Ergebnisseite |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Liste der Konten |
### `pylon_create_account`
Ein neues Konto mit bestimmten Eigenschaften erstellen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `name` | string | Ja | Kontoname |
| `domains` | string | Nein | Kommagetrennte Liste von Domains |
| `primaryDomain` | string | Nein | Primäre Domain für das Konto |
| `customFields` | string | Nein | Benutzerdefinierte Felder als JSON-Objekt |
| `tags` | string | Nein | Kommagetrennte Tag-IDs |
| `channels` | string | Nein | Kommagetrennte Kanal-IDs |
| `externalIds` | string | Nein | Kommagetrennte externe IDs |
| `ownerId` | string | Nein | Besitzer-Benutzer-ID |
| `logoUrl` | string | Nein | URL zum Konto-Logo |
| `subaccountIds` | string | Nein | Kommagetrennte Unterkonto-IDs |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Erstellte Kontodaten |
### `pylon_get_account`
Ein einzelnes Konto anhand der ID abrufen
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `accountId` | string | Ja | Konto-ID zum Abrufen |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Kontodaten |
### `pylon_update_account`
Ein bestehendes Konto mit neuen Eigenschaften aktualisieren
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `accountId` | string | Ja | Konto-ID zum Aktualisieren |
| `name` | string | Nein | Kontoname |
| `domains` | string | Nein | Kommagetrennte Liste von Domains |
| `primaryDomain` | string | Nein | Primäre Domain für das Konto |
| `customFields` | string | Nein | Benutzerdefinierte Felder als JSON-Objekt |
| `tags` | string | Nein | Kommagetrennte Tag-IDs |
| `channels` | string | Nein | Kommagetrennte Kanal-IDs |
| `externalIds` | string | Nein | Kommagetrennte externe IDs |
| `ownerId` | string | Nein | Besitzer-Benutzer-ID |
| `logoUrl` | string | Nein | URL zum Konto-Logo |
| `subaccountIds` | string | Nein | Kommagetrennte Unterkonto-IDs |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Aktualisierte Kontodaten |
### `pylon_delete_account`
Ein Konto anhand der ID entfernen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `accountId` | string | Ja | Konto-ID, die gelöscht werden soll |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Löschbestätigung |
### `pylon_bulk_update_accounts`
Mehrere Konten auf einmal aktualisieren
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `accountIds` | string | Ja | Durch Komma getrennte Konto-IDs, die aktualisiert werden sollen |
| `customFields` | string | Nein | Benutzerdefinierte Felder als JSON-Objekt |
| `tags` | string | Nein | Durch Komma getrennte Tag-IDs |
| `ownerId` | string | Nein | Besitzer-Benutzer-ID |
| `tagsApplyMode` | string | Nein | Tag-Anwendungsmodus: append_only, remove_only oder replace |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Massenhaft aktualisierte Kontodaten |
### `pylon_search_accounts`
Konten mit benutzerdefinierten Filtern durchsuchen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `filter` | string | Ja | Filter als JSON-String mit Feld/Operator/Wert-Struktur |
| `limit` | string | Nein | Anzahl der zurückzugebenden Konten \(1-1000, Standard 100\) |
| `cursor` | string | Nein | Paginierungscursor für die nächste Ergebnisseite |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Suchergebnisse |
### `pylon_list_contacts`
Eine Liste von Kontakten abrufen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `cursor` | string | Nein | Paginierungscursor für die nächste Ergebnisseite |
| `limit` | string | Nein | Maximale Anzahl der zurückzugebenden Kontakte |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Liste der Kontakte |
### `pylon_create_contact`
Einen neuen Kontakt mit bestimmten Eigenschaften erstellen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `name` | string | Ja | Kontaktname |
| `email` | string | Nein | E-Mail-Adresse des Kontakts |
| `accountId` | string | Nein | Konto-ID, die mit dem Kontakt verknüpft werden soll |
| `accountExternalId` | string | Nein | Externe Konto-ID, die mit dem Kontakt verknüpft werden soll |
| `avatarUrl` | string | Nein | URL für das Kontakt-Avatarbild |
| `customFields` | string | Nein | Benutzerdefinierte Felder als JSON-Objekt |
| `portalRole` | string | Nein | Portal-Rolle für den Kontakt |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Erstellte Kontaktdaten |
### `pylon_get_contact`
Einen bestimmten Kontakt anhand der ID abrufen
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `contactId` | string | Ja | Kontakt-ID zum Abrufen |
| `cursor` | string | Nein | Paginierungscursor für die nächste Ergebnisseite |
| `limit` | string | Nein | Maximale Anzahl der zurückzugebenden Elemente |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Kontaktdaten |
### `pylon_update_contact`
Einen vorhandenen Kontakt mit angegebenen Eigenschaften aktualisieren
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `contactId` | string | Ja | Kontakt-ID zum Aktualisieren |
| `name` | string | Nein | Kontaktname |
| `email` | string | Nein | E-Mail-Adresse des Kontakts |
| `accountId` | string | Nein | Konto-ID, die mit dem Kontakt verknüpft werden soll |
| `accountExternalId` | string | Nein | Externe Konto-ID, die mit dem Kontakt verknüpft werden soll |
| `avatarUrl` | string | Nein | URL für das Kontakt-Avatarbild |
| `customFields` | string | Nein | Benutzerdefinierte Felder als JSON-Objekt |
| `portalRole` | string | Nein | Portalrolle für den Kontakt |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Aktualisierte Kontaktdaten |
### `pylon_delete_contact`
Einen bestimmten Kontakt anhand der ID löschen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `contactId` | string | Ja | Zu löschende Kontakt-ID |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Ergebnis des Löschvorgangs |
### `pylon_search_contacts`
Nach Kontakten mit einem Filter suchen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `filter` | string | Ja | Filter als JSON-Objekt |
| `limit` | string | Nein | Maximale Anzahl der zurückzugebenden Kontakte |
| `cursor` | string | Nein | Paginierungscursor für die nächste Ergebnisseite |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Suchergebnisse |
### `pylon_list_users`
Eine Liste von Benutzern abrufen
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Liste der Benutzer |
### `pylon_get_user`
Einen bestimmten Benutzer anhand der ID abrufen
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `userId` | string | Ja | Benutzer-ID zum Abrufen |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Benutzerdaten |
### `pylon_update_user`
Einen vorhandenen Benutzer mit angegebenen Eigenschaften aktualisieren
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `userId` | string | Ja | Benutzer-ID zum Aktualisieren |
| `roleId` | string | Nein | Rollen-ID, die dem Benutzer zugewiesen werden soll |
| `status` | string | Nein | Benutzerstatus |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Aktualisierte Benutzerdaten |
### `pylon_search_users`
Nach Benutzern mit einem Filter für das E-Mail-Feld suchen
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `filter` | string | Ja | Filter als JSON-Objekt mit E-Mail-Feld |
| `cursor` | string | Nein | Paginierungscursor für die nächste Ergebnisseite |
| `limit` | string | Nein | Maximale Anzahl der zurückzugebenden Benutzer |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Suchergebnisse |
### `pylon_list_teams`
Eine Liste von Teams abrufen
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Liste der Teams |
### `pylon_get_team`
Ein bestimmtes Team anhand der ID abrufen
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `teamId` | string | Ja | Team-ID zum Abrufen |
#### Output
| Parameter | Type | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Team-Daten |
### `pylon_create_team`
Ein neues Team mit bestimmten Eigenschaften erstellen
#### Input
| Parameter | Type | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `name` | string | Nein | Team-Name |
| `userIds` | string | Nein | Durch Kommas getrennte Benutzer-IDs, die als Teammitglieder hinzugefügt werden sollen |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Erstellte Team-Daten |
### `pylon_update_team`
Aktualisieren eines vorhandenen Teams mit angegebenen Eigenschaften (userIds ersetzt die gesamte Mitgliedschaft)
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `teamId` | string | Ja | Team-ID zum Aktualisieren |
| `name` | string | Nein | Team-Name |
| `userIds` | string | Nein | Kommagetrennte Benutzer-IDs \(ersetzt die gesamte Team-Mitgliedschaft\) |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Aktualisierte Team-Daten |
### `pylon_list_tags`
Abrufen einer Liste von Tags
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Status des Operationserfolgs |
| `output` | object | Liste der Tags |
### `pylon_get_tag`
Abrufen eines bestimmten Tags anhand der ID
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `tagId` | string | Ja | Tag-ID zum Abrufen |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Tag-Daten |
### `pylon_create_tag`
Erstellt einen neuen Tag mit angegebenen Eigenschaften (objectType: account/issue/contact)
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `objectType` | string | Ja | Objekttyp für Tag \(account, issue oder contact\) |
| `value` | string | Ja | Tag-Wert/Name |
| `hexColor` | string | Nein | Hex-Farbcode für Tag \(z.B. #FF5733\) |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Daten des erstellten Tags |
### `pylon_update_tag`
Aktualisiert einen vorhandenen Tag mit angegebenen Eigenschaften
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `tagId` | string | Ja | Zu aktualisierende Tag-ID |
| `hexColor` | string | Nein | Hex-Farbcode für Tag \(z.B. #FF5733\) |
| `value` | string | Nein | Tag-Wert/Name |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Daten des aktualisierten Tags |
### `pylon_delete_tag`
Löschen eines bestimmten Tags anhand der ID
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `tagId` | string | Ja | Tag-ID zum Löschen |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Ergebnis der Löschoperation |
### `pylon_redact_message`
Redigieren einer bestimmten Nachricht innerhalb eines Issues
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Ja | Pylon API-Token |
| `issueId` | string | Ja | Issue-ID, die die Nachricht enthält |
| `messageId` | string | Ja | Nachrichten-ID zum Redigieren |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Erfolgsstatus der Operation |
| `output` | object | Ergebnis der Redigieroperation |
## Hinweise
- Kategorie: `tools`
- Typ: `pylon`

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
---
title: Stagehand Extract
description: Extract data from websites
title: Stagehand
description: Web-Automatisierung und Datenextraktion
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
@@ -11,43 +11,73 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://stagehand.com) is a tool that allows you to extract structured data from webpages using Browserbase and OpenAI.
[Stagehand](https://stagehand.com) ist ein Tool, das sowohl die Extraktion strukturierter Daten aus Webseiten als auch autonome Web-Automatisierung mittels Browserbase und modernen LLMs (OpenAI oder Anthropic) ermöglicht.
With Stagehand, you can:
Stagehand bietet zwei Hauptfunktionen in Sim:
- **Extract structured data**: Extract structured data from webpages using Browserbase and OpenAI
- **Save data to a database**: Save the extracted data to a database
- **Automate workflows**: Automate workflows to extract data from webpages
- **stagehand_extract**: Extrahiert strukturierte Daten von einer einzelnen Webseite. Sie geben an, was Sie möchten (ein Schema), und die KI ruft die Daten in dieser Form von der Seite ab und analysiert sie. Dies eignet sich am besten zum Extrahieren von Listen, Feldern oder Objekten, wenn Sie genau wissen, welche Informationen Sie benötigen und woher Sie diese bekommen.
In Sim, the Stagehand integration enables your agents to extract structured data from webpages using Browserbase and OpenAI. This allows for powerful automation scenarios such as data extraction, data analysis, and data integration. Your agents can extract structured data from webpages, save the extracted data to a database, and automate workflows to extract data from webpages. This integration bridges the gap between your AI workflows and your data management system, enabling seamless data extraction and integration. By connecting Sim with Stagehand, you can automate data extraction processes, maintain up-to-date information repositories, generate reports, and organize information intelligently - all through your intelligent agents.
- **stagehand_agent**: Führt einen autonomen Web-Agenten aus, der in der Lage ist, mehrstufige Aufgaben zu erledigen, mit Elementen zu interagieren, zwischen Seiten zu navigieren und strukturierte Ergebnisse zurückzugeben. Dies ist viel flexibler: der Agent kann Dinge wie Anmeldungen, Suchen, Ausfüllen von Formularen, Sammeln von Daten aus verschiedenen Quellen durchführen und ein Endergebnis gemäß einem angeforderten Schema ausgeben.
**Wesentliche Unterschiede:**
- *stagehand_extract* ist ein schneller “extrahiere diese Daten von dieser Seite” Vorgang. Es funktioniert am besten für direkte, einstufige Extraktionsaufgaben.
- *stagehand_agent* führt komplexe, mehrstufige autonome Aufgaben im Web aus — wie Navigation, Suche oder sogar Transaktionen — und kann Daten dynamisch gemäß Ihren Anweisungen und einem optionalen Schema extrahieren.
In der Praxis verwenden Sie **stagehand_extract**, wenn Sie wissen, was Sie wollen und woher, und **stagehand_agent**, wenn Sie einen Bot benötigen, der interaktive Arbeitsabläufe durchdenkt und ausführt.
Durch die Integration von Stagehand können Sim-Agenten die Datenerfassung, -analyse und Workflow-Ausführung im Web automatisieren: Datenbanken aktualisieren, Informationen organisieren und benutzerdefinierte Berichte erstellen — nahtlos und autonom.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
## Gebrauchsanweisung
Integrate Stagehand into the workflow. Can extract structured data from webpages.
Integrieren Sie Stagehand in den Workflow. Kann strukturierte Daten aus Webseiten extrahieren oder einen autonomen Agenten ausführen, um Aufgaben zu erledigen.
## Tools
### `stagehand_extract`
Extract structured data from a webpage using Stagehand
Extrahieren Sie strukturierte Daten von einer Webseite mit Stagehand
#### Input
#### Eingabe
| Parameter | Type | Required | Description |
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `url` | string | Yes | URL of the webpage to extract data from |
| `instruction` | string | Yes | Instructions for extraction |
| `apiKey` | string | Yes | OpenAI API key for extraction \(required by Stagehand\) |
| `schema` | json | Yes | JSON schema defining the structure of the data to extract |
| `url` | string | Ja | URL der Webseite, aus der Daten extrahiert werden sollen |
| `instruction` | string | Ja | Anweisungen für die Extraktion |
| `provider` | string | Nein | Zu verwendender KI-Anbieter: openai oder anthropic |
| `apiKey` | string | Ja | API-Schlüssel für den ausgewählten Anbieter |
| `schema` | json | Ja | JSON-Schema, das die Struktur der zu extrahierenden Daten definiert |
#### Ausgabe
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `data` | object | Extrahierte strukturierte Daten, die dem bereitgestellten Schema entsprechen |
### `stagehand_agent`
Führen Sie einen autonomen Web-Agenten aus, um Aufgaben zu erledigen und strukturierte Daten zu extrahieren
#### Eingabe
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | Ja | URL der Webseite, auf der der Agent starten soll |
| `task` | string | Ja | Die zu erledigende Aufgabe oder das zu erreichende Ziel auf der Website |
| `variables` | json | Nein | Optionale Variablen, die in der Aufgabe ersetzt werden sollen (Format: \{key: value\}). Referenzierung in der Aufgabe mit %key% |
| `format` | string | Nein | Keine Beschreibung |
| `provider` | string | Nein | Zu verwendender KI-Anbieter: openai oder anthropic |
| `apiKey` | string | Ja | API-Schlüssel für den ausgewählten Anbieter |
| `outputSchema` | json | Nein | Optionales JSON-Schema, das die Struktur der Daten definiert, die der Agent zurückgeben soll |
#### Output
| Parameter | Type | Description |
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `data` | object | Extracted structured data matching the provided schema |
| `agentResult` | object | Ergebnis der Stagehand-Agent-Ausführung |
## Notes
## Hinweise
- Category: `tools`
- Type: `stagehand`
- Kategorie: `tools`
- Typ: `stagehand`

View File

@@ -1,59 +0,0 @@
---
title: Stagehand Agent
description: Autonomous web browsing agent
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="stagehand_agent"
color="#FFC83C"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://www.stagehand.dev/) is an autonomous web agent platform that enables AI systems to navigate and interact with websites just like a human would. It provides a powerful solution for automating complex web tasks without requiring custom code or browser automation scripts.
With Stagehand, you can:
- **Automate web navigation**: Enable AI to browse websites, click links, fill forms, and interact with web elements
- **Extract structured data**: Collect specific information from websites in a structured, usable format
- **Complete complex workflows**: Perform multi-step tasks across different websites and web applications
- **Handle authentication**: Navigate login processes and maintain sessions across websites
- **Process dynamic content**: Interact with JavaScript-heavy sites and single-page applications
- **Maintain context awareness**: Keep track of the current state and history while navigating
- **Generate detailed reports**: Receive comprehensive logs of actions taken and data collected
In Sim, the Stagehand integration enables your agents to seamlessly interact with web-based systems as part of their workflows. This allows for sophisticated automation scenarios that bridge the gap between your AI agents and the vast information and functionality available on the web. Your agents can search for information, interact with web applications, extract data from websites, and incorporate these capabilities into their decision-making processes. By connecting Sim with Stagehand, you can create agents that extend beyond API-based integrations to navigate the web just as a human would - filling forms, clicking buttons, reading content, and extracting valuable information to complete their tasks more effectively.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
Integrate Stagehand Agent into the workflow. Can navigate the web and perform tasks.
## Tools
### `stagehand_agent`
Run an autonomous web agent to complete tasks and extract structured data
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | Yes | URL of the webpage to start the agent on |
| `task` | string | Yes | The task to complete or goal to achieve on the website |
| `variables` | json | No | Optional variables to substitute in the task \(format: \{key: value\}\). Reference in task using %key% |
| `format` | string | No | No description |
| `apiKey` | string | Yes | OpenAI API key for agent execution \(required by Stagehand\) |
| `outputSchema` | json | No | Optional JSON schema defining the structure of data the agent should return |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `agentResult` | object | Result from the Stagehand agent execution |
## Notes
- Category: `tools`
- Type: `stagehand_agent`

View File

@@ -45,10 +45,8 @@ Alle Listen auf einem Trello-Board auflisten
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Ob der Vorgang erfolgreich war |
| `lists` | array | Array von Listenobjekten mit id, name, closed, pos und idBoard |
| `count` | number | Anzahl der zurückgegebenen Listen |
| `error` | string | Fehlermeldung, wenn der Vorgang fehlgeschlagen ist |
### `trello_list_cards`
@@ -65,10 +63,8 @@ Alle Listen eines Trello-Boards auflisten
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Ob der Vorgang erfolgreich war |
| `cards` | array | Array von Kartenobjekten mit id, name, desc, url, Board/Listen-IDs, Labels und Fälligkeitsdatum |
| `count` | number | Anzahl der zurückgegebenen Karten |
| `error` | string | Fehlermeldung, wenn der Vorgang fehlgeschlagen ist |
### `trello_create_card`
@@ -90,9 +86,7 @@ Eine neue Karte auf einem Trello-Board erstellen
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Ob die Karte erfolgreich erstellt wurde |
| `card` | object | Das erstellte Kartenobjekt mit ID, Name, Beschreibung, URL und anderen Eigenschaften |
| `error` | string | Fehlermeldung, falls der Vorgang fehlgeschlagen ist |
| `card` | object | Das erstellte Kartenobjekt mit id, name, desc, url und anderen Eigenschaften |
### `trello_update_card`
@@ -114,9 +108,7 @@ Eine bestehende Karte in Trello aktualisieren
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Ob die Karte erfolgreich aktualisiert wurde |
| `card` | object | Das aktualisierte Kartenobjekt mit ID, Name, Beschreibung, URL und anderen Eigenschaften |
| `error` | string | Fehlermeldung, falls der Vorgang fehlgeschlagen ist |
| `card` | object | Das aktualisierte Kartenobjekt mit id, name, desc, url und anderen Eigenschaften |
### `trello_get_actions`
@@ -135,10 +127,8 @@ Aktivitäten/Aktionen von einem Board oder einer Karte abrufen
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Ob der Vorgang erfolgreich war |
| `actions` | array | Array von Aktionsobjekten mit Typ, Datum, Mitglied und Daten |
| `actions` | array | Array von Aktionsobjekten mit type, date, member und data |
| `count` | number | Anzahl der zurückgegebenen Aktionen |
| `error` | string | Fehlermeldung, falls der Vorgang fehlgeschlagen ist |
### `trello_add_comment`
@@ -155,9 +145,7 @@ Einen Kommentar zu einer Trello-Karte hinzufügen
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Ob der Kommentar erfolgreich hinzugefügt wurde |
| `comment` | object | Das erstellte Kommentarobjekt mit ID, Text, Datum und Mitglied-Ersteller |
| `error` | string | Fehlermeldung, falls der Vorgang fehlgeschlagen ist |
| `comment` | object | Das erstellte Kommentarobjekt mit id, text, date und member creator |
## Hinweise

View File

@@ -39,9 +39,10 @@ Alle Elemente aus einer Webflow CMS-Sammlung auflisten
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Ja | ID der Webflow-Website |
| `collectionId` | string | Ja | ID der Sammlung |
| `offset` | number | Nein | Offset für Paginierung \(optional\) |
| `limit` | number | Nein | Maximale Anzahl der zurückzugebenden Elemente \(optional, Standard: 100\) |
| `offset` | number | Nein | Offset für Paginierung (optional) |
| `limit` | number | Nein | Maximale Anzahl der zurückzugebenden Elemente (optional, Standard: 100) |
#### Ausgabe
@@ -58,6 +59,7 @@ Ein einzelnes Element aus einer Webflow CMS-Sammlung abrufen
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Ja | ID der Webflow-Website |
| `collectionId` | string | Ja | ID der Sammlung |
| `itemId` | string | Ja | ID des abzurufenden Elements |
@@ -76,8 +78,9 @@ Ein neues Element in einer Webflow CMS-Sammlung erstellen
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Ja | ID der Webflow-Website |
| `collectionId` | string | Ja | ID der Sammlung |
| `fieldData` | json | Ja | Felddaten für das neue Element als JSON-Objekt. Die Schlüssel sollten mit den Feldnamen der Sammlung übereinstimmen. |
| `fieldData` | json | Ja | Felddaten für das neue Element als JSON-Objekt. Schlüssel sollten mit den Sammlungsfeldnamen übereinstimmen. |
#### Ausgabe
@@ -94,6 +97,7 @@ Ein vorhandenes Element in einer Webflow CMS-Sammlung aktualisieren
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Ja | ID der Webflow-Website |
| `collectionId` | string | Ja | ID der Sammlung |
| `itemId` | string | Ja | ID des zu aktualisierenden Elements |
| `fieldData` | json | Ja | Zu aktualisierende Felddaten als JSON-Objekt. Nur Felder einschließen, die geändert werden sollen. |
@@ -113,6 +117,7 @@ Ein Element aus einer Webflow CMS-Sammlung löschen
| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Ja | ID der Webflow-Website |
| `collectionId` | string | Ja | ID der Sammlung |
| `itemId` | string | Ja | ID des zu löschenden Elements |

View File

@@ -94,10 +94,7 @@ Benutzerkontext aus einem Thread mit Zusammenfassungs- oder Basismodus abrufen
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `context` | string | Der Kontextstring \(Zusammenfassung oder Basis\) |
| `facts` | array | Extrahierte Fakten |
| `entities` | array | Extrahierte Entitäten |
| `summary` | string | Konversationszusammenfassung |
| `context` | string | Die Kontext-Zeichenfolge \(Zusammenfassung oder Basismodus\) |
### `zep_get_messages`
@@ -137,9 +134,9 @@ Nachrichten zu einem bestehenden Thread hinzufügen
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `context` | string | Aktualisierter Kontext nach dem Hinzufügen von Nachrichten |
| `messageIds` | array | Array der hinzugefügten Nachrichten-UUIDs |
| `threadId` | string | Die Thread-ID |
| `added` | boolean | Ob Nachrichten erfolgreich hinzugefügt wurden |
| `messageIds` | array | Array der hinzugefügten Nachrichten-UUIDs |
### `zep_add_user`
@@ -209,7 +206,7 @@ Alle Konversations-Threads für einen bestimmten Benutzer auflisten
| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `threads` | array | Array von Thread-Objekten für diesen Benutzer |
| `userId` | string | Die Benutzer-ID |
| `totalCount` | number | Gesamtanzahl der zurückgegebenen Threads |
## Hinweise

View File

@@ -324,7 +324,7 @@ Create an annotation on a dashboard or as a global annotation
| `organizationId` | string | No | Organization ID for multi-org Grafana instances |
| `text` | string | Yes | The text content of the annotation |
| `tags` | string | No | Comma-separated list of tags |
| `dashboardUid` | string | No | UID of the dashboard to add the annotation to \(optional for global annotations\) |
| `dashboardUid` | string | Yes | UID of the dashboard to add the annotation to |
| `panelId` | number | No | ID of the panel to add the annotation to |
| `time` | number | No | Start time in epoch milliseconds \(defaults to now\) |
| `timeEnd` | number | No | End time in epoch milliseconds \(for range annotations\) |
@@ -349,7 +349,7 @@ Query annotations by time range, dashboard, or tags
| `organizationId` | string | No | Organization ID for multi-org Grafana instances |
| `from` | number | No | Start time in epoch milliseconds |
| `to` | number | No | End time in epoch milliseconds |
| `dashboardUid` | string | No | Filter by dashboard UID |
| `dashboardUid` | string | Yes | Dashboard UID to query annotations from |
| `panelId` | number | No | Filter by panel ID |
| `tags` | string | No | Comma-separated list of tags to filter by |
| `type` | string | No | Filter by type \(alert or annotation\) |
@@ -490,6 +490,16 @@ Create a new folder in Grafana
| `uid` | string | The UID of the created folder |
| `title` | string | The title of the created folder |
| `url` | string | The URL path to the folder |
| `hasAcl` | boolean | Whether the folder has custom ACL permissions |
| `canSave` | boolean | Whether the current user can save the folder |
| `canEdit` | boolean | Whether the current user can edit the folder |
| `canAdmin` | boolean | Whether the current user has admin rights on the folder |
| `canDelete` | boolean | Whether the current user can delete the folder |
| `createdBy` | string | Username of who created the folder |
| `created` | string | Timestamp when the folder was created |
| `updatedBy` | string | Username of who last updated the folder |
| `updated` | string | Timestamp when the folder was last updated |
| `version` | number | Version number of the folder |

View File

@@ -70,7 +70,6 @@
"polymarket",
"postgresql",
"posthog",
"pylon",
"qdrant",
"rds",
"reddit",
@@ -86,10 +85,10 @@
"shopify",
"slack",
"smtp",
"spotify",
"sqs",
"ssh",
"stagehand",
"stagehand_agent",
"stripe",
"stt",
"supabase",

View File

@@ -1,811 +0,0 @@
---
title: Pylon
description: Manage customer support issues, accounts, contacts, users, teams, and tags in Pylon
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="pylon"
color="#E8F4FA"
/>
{/* MANUAL-CONTENT-START:intro */}
[Pylon](https://usepylon.com/) is an advanced customer support and success platform designed to help you manage every aspect of your customer relationships—from support issues to accounts, contacts, users, teams, and beyond. Pylon empowers support and success teams to operate efficiently and programmatically with a rich API and comprehensive toolset.
With Pylon in Sim, you can:
- **Manage Support Issues:**
- List, create, get, update, and delete support issues for efficient case tracking.
- Search and snooze issues to help agents stay focused and organized.
- Handle issue followers and external issues for seamless collaboration with internal and external stakeholders.
- **Full Account Management:**
- List, create, get, update, and delete customer accounts.
- Bulk update accounts programmatically.
- Search accounts to quickly find customer information relevant for support or outreach.
- **Contact Management:**
- List, create, get, update, delete, and search contacts—manage everyone connected to your accounts.
- **User and Team Operations:**
- List, get, update, and search users in your Pylon workspace.
- List, create, get, and update teams to structure your support organization and workflows.
- **Tagging and Organization:**
- List, get, create, update, and delete tags for categorizing issues, accounts, or contacts.
- **Message Handling:**
- Redact sensitive message content directly from your workflows for privacy and compliance.
By integrating Pylon tools into Sim, your agents can automate every aspect of support operations:
- Automatically open, update, or triage new issues when customer events occur.
- Maintain synchronized account and contact data across your tech stack.
- Route conversations, handle escalations, and organize your support data using tags and teams.
- Ensure sensitive data is properly managed by redacting messages as needed.
Pylon's endpoints provide granular control for full-lifecycle management of customer issues and relationships. Whether scaling a support desk, powering proactive customer success, or integrating with other systems, Pylon in Sim enables best-in-class CRM automation—securely, flexibly, and at scale.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
Integrate Pylon into the workflow. Manage issues (list, create, get, update, delete, search, snooze, followers, external issues), accounts (list, create, get, update, delete, bulk update, search), contacts (list, create, get, update, delete, search), users (list, get, update, search), teams (list, get, create, update), tags (list, get, create, update, delete), and messages (redact).
## Tools
### `pylon_list_issues`
Retrieve a list of issues within a specified time range
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `startTime` | string | Yes | Start time in RFC3339 format \(e.g., 2024-01-01T00:00:00Z\) |
| `endTime` | string | Yes | End time in RFC3339 format \(e.g., 2024-01-31T23:59:59Z\) |
| `cursor` | string | No | Pagination cursor for next page of results |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | List of issues |
### `pylon_create_issue`
Create a new issue with specified properties
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `title` | string | Yes | Issue title |
| `bodyHtml` | string | Yes | Issue body in HTML format |
| `accountId` | string | No | Account ID to associate with issue |
| `assigneeId` | string | No | User ID to assign issue to |
| `teamId` | string | No | Team ID to assign issue to |
| `requesterId` | string | No | Requester user ID \(alternative to requester_email\) |
| `requesterEmail` | string | No | Requester email address \(alternative to requester_id\) |
| `priority` | string | No | Issue priority |
| `tags` | string | No | Comma-separated tag IDs |
| `customFields` | string | No | Custom fields as JSON object |
| `attachmentUrls` | string | No | Comma-separated attachment URLs |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Created issue data |
### `pylon_get_issue`
Fetch a specific issue by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `issueId` | string | Yes | The ID of the issue to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Issue data |
### `pylon_update_issue`
Update an existing issue
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `issueId` | string | Yes | The ID of the issue to update |
| `state` | string | No | Issue state |
| `assigneeId` | string | No | User ID to assign issue to |
| `teamId` | string | No | Team ID to assign issue to |
| `tags` | string | No | Comma-separated tag IDs |
| `customFields` | string | No | Custom fields as JSON object |
| `customerPortalVisible` | boolean | No | Whether issue is visible in customer portal |
| `requesterId` | string | No | Requester user ID |
| `accountId` | string | No | Account ID to associate with issue |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Updated issue data |
### `pylon_delete_issue`
Remove an issue by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `issueId` | string | Yes | The ID of the issue to delete |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Deletion result |
### `pylon_search_issues`
Query issues using filters
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `filter` | string | Yes | Filter criteria as JSON string |
| `cursor` | string | No | Pagination cursor for next page of results |
| `limit` | number | No | Maximum number of results to return |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Search results |
### `pylon_snooze_issue`
Postpone issue visibility until specified time
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `issueId` | string | Yes | The ID of the issue to snooze |
| `snoozeUntil` | string | Yes | RFC3339 timestamp when issue should reappear \(e.g., 2024-01-01T00:00:00Z\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Snoozed issue data |
### `pylon_list_issue_followers`
Get list of followers for a specific issue
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `issueId` | string | Yes | The ID of the issue |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Followers list |
### `pylon_manage_issue_followers`
Add or remove followers from an issue
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `issueId` | string | Yes | The ID of the issue |
| `userIds` | string | No | Comma-separated user IDs to add/remove |
| `contactIds` | string | No | Comma-separated contact IDs to add/remove |
| `operation` | string | No | Operation to perform: "add" or "remove" \(default: "add"\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Updated followers list |
### `pylon_link_external_issue`
Link an issue to an external system issue
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `issueId` | string | Yes | The ID of the Pylon issue |
| `externalIssueId` | string | Yes | The ID of the external issue |
| `source` | string | Yes | The source system \(e.g., "jira", "linear", "github"\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Linked external issue data |
### `pylon_list_accounts`
Retrieve a paginated list of accounts
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `limit` | string | No | Number of accounts to return \(1-1000, default 100\) |
| `cursor` | string | No | Pagination cursor for next page of results |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | List of accounts |
### `pylon_create_account`
Create a new account with specified properties
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `name` | string | Yes | Account name |
| `domains` | string | No | Comma-separated list of domains |
| `primaryDomain` | string | No | Primary domain for the account |
| `customFields` | string | No | Custom fields as JSON object |
| `tags` | string | No | Comma-separated tag IDs |
| `channels` | string | No | Comma-separated channel IDs |
| `externalIds` | string | No | Comma-separated external IDs |
| `ownerId` | string | No | Owner user ID |
| `logoUrl` | string | No | URL to account logo |
| `subaccountIds` | string | No | Comma-separated subaccount IDs |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Created account data |
### `pylon_get_account`
Retrieve a single account by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `accountId` | string | Yes | Account ID to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Account data |
### `pylon_update_account`
Update an existing account with new properties
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `accountId` | string | Yes | Account ID to update |
| `name` | string | No | Account name |
| `domains` | string | No | Comma-separated list of domains |
| `primaryDomain` | string | No | Primary domain for the account |
| `customFields` | string | No | Custom fields as JSON object |
| `tags` | string | No | Comma-separated tag IDs |
| `channels` | string | No | Comma-separated channel IDs |
| `externalIds` | string | No | Comma-separated external IDs |
| `ownerId` | string | No | Owner user ID |
| `logoUrl` | string | No | URL to account logo |
| `subaccountIds` | string | No | Comma-separated subaccount IDs |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Updated account data |
### `pylon_delete_account`
Remove an account by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `accountId` | string | Yes | Account ID to delete |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Deletion confirmation |
### `pylon_bulk_update_accounts`
Update multiple accounts at once
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `accountIds` | string | Yes | Comma-separated account IDs to update |
| `customFields` | string | No | Custom fields as JSON object |
| `tags` | string | No | Comma-separated tag IDs |
| `ownerId` | string | No | Owner user ID |
| `tagsApplyMode` | string | No | Tag application mode: append_only, remove_only, or replace |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Bulk updated accounts data |
### `pylon_search_accounts`
Search accounts with custom filters
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `filter` | string | Yes | Filter as JSON string with field/operator/value structure |
| `limit` | string | No | Number of accounts to return \(1-1000, default 100\) |
| `cursor` | string | No | Pagination cursor for next page of results |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Search results |
### `pylon_list_contacts`
Retrieve a list of contacts
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `cursor` | string | No | Pagination cursor for next page of results |
| `limit` | string | No | Maximum number of contacts to return |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | List of contacts |
### `pylon_create_contact`
Create a new contact with specified properties
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `name` | string | Yes | Contact name |
| `email` | string | No | Contact email address |
| `accountId` | string | No | Account ID to associate with contact |
| `accountExternalId` | string | No | External account ID to associate with contact |
| `avatarUrl` | string | No | URL for contact avatar image |
| `customFields` | string | No | Custom fields as JSON object |
| `portalRole` | string | No | Portal role for the contact |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Created contact data |
### `pylon_get_contact`
Retrieve a specific contact by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `contactId` | string | Yes | Contact ID to retrieve |
| `cursor` | string | No | Pagination cursor for next page of results |
| `limit` | string | No | Maximum number of items to return |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Contact data |
### `pylon_update_contact`
Update an existing contact with specified properties
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `contactId` | string | Yes | Contact ID to update |
| `name` | string | No | Contact name |
| `email` | string | No | Contact email address |
| `accountId` | string | No | Account ID to associate with contact |
| `accountExternalId` | string | No | External account ID to associate with contact |
| `avatarUrl` | string | No | URL for contact avatar image |
| `customFields` | string | No | Custom fields as JSON object |
| `portalRole` | string | No | Portal role for the contact |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Updated contact data |
### `pylon_delete_contact`
Delete a specific contact by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `contactId` | string | Yes | Contact ID to delete |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Delete operation result |
### `pylon_search_contacts`
Search for contacts using a filter
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `filter` | string | Yes | Filter as JSON object |
| `limit` | string | No | Maximum number of contacts to return |
| `cursor` | string | No | Pagination cursor for next page of results |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Search results |
### `pylon_list_users`
Retrieve a list of users
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | List of users |
### `pylon_get_user`
Retrieve a specific user by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `userId` | string | Yes | User ID to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | User data |
### `pylon_update_user`
Update an existing user with specified properties
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `userId` | string | Yes | User ID to update |
| `roleId` | string | No | Role ID to assign to user |
| `status` | string | No | User status |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Updated user data |
### `pylon_search_users`
Search for users using a filter with email field
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `filter` | string | Yes | Filter as JSON object with email field |
| `cursor` | string | No | Pagination cursor for next page of results |
| `limit` | string | No | Maximum number of users to return |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Search results |
### `pylon_list_teams`
Retrieve a list of teams
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | List of teams |
### `pylon_get_team`
Retrieve a specific team by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `teamId` | string | Yes | Team ID to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Team data |
### `pylon_create_team`
Create a new team with specified properties
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `name` | string | No | Team name |
| `userIds` | string | No | Comma-separated user IDs to add as team members |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Created team data |
### `pylon_update_team`
Update an existing team with specified properties (userIds replaces entire membership)
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `teamId` | string | Yes | Team ID to update |
| `name` | string | No | Team name |
| `userIds` | string | No | Comma-separated user IDs \(replaces entire team membership\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Updated team data |
### `pylon_list_tags`
Retrieve a list of tags
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | List of tags |
### `pylon_get_tag`
Retrieve a specific tag by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `tagId` | string | Yes | Tag ID to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Tag data |
### `pylon_create_tag`
Create a new tag with specified properties (objectType: account/issue/contact)
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `objectType` | string | Yes | Object type for tag \(account, issue, or contact\) |
| `value` | string | Yes | Tag value/name |
| `hexColor` | string | No | Hex color code for tag \(e.g., #FF5733\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Created tag data |
### `pylon_update_tag`
Update an existing tag with specified properties
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `tagId` | string | Yes | Tag ID to update |
| `hexColor` | string | No | Hex color code for tag \(e.g., #FF5733\) |
| `value` | string | No | Tag value/name |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Updated tag data |
### `pylon_delete_tag`
Delete a specific tag by ID
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `tagId` | string | Yes | Tag ID to delete |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Delete operation result |
### `pylon_redact_message`
Redact a specific message within an issue
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Yes | Pylon API token |
| `issueId` | string | Yes | Issue ID containing the message |
| `messageId` | string | Yes | Message ID to redact |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Operation success status |
| `output` | object | Redact operation result |
## Notes
- Category: `tools`
- Type: `pylon`

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
---
title: Stagehand Extract
description: Extract data from websites
title: Stagehand
description: Web automation and data extraction
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
@@ -11,21 +11,28 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://stagehand.com) is a tool that allows you to extract structured data from webpages using Browserbase and OpenAI.
[Stagehand](https://stagehand.com) is a tool that enables both extraction of structured data from webpages and autonomous web automation using Browserbase and modern LLMs (OpenAI or Anthropic).
With Stagehand, you can:
Stagehand offers two main capabilities in Sim:
- **Extract structured data**: Extract structured data from webpages using Browserbase and OpenAI
- **Save data to a database**: Save the extracted data to a database
- **Automate workflows**: Automate workflows to extract data from webpages
- **stagehand_extract**: Extract structured data from a single webpage. You specify what you want (a schema), and the AI retrieves and parses the data in that shape from the page. This is best for extracting lists, fields, or objects when you know exactly what information you need and where to get it.
In Sim, the Stagehand integration enables your agents to extract structured data from webpages using Browserbase and OpenAI. This allows for powerful automation scenarios such as data extraction, data analysis, and data integration. Your agents can extract structured data from webpages, save the extracted data to a database, and automate workflows to extract data from webpages. This integration bridges the gap between your AI workflows and your data management system, enabling seamless data extraction and integration. By connecting Sim with Stagehand, you can automate data extraction processes, maintain up-to-date information repositories, generate reports, and organize information intelligently - all through your intelligent agents.
- **stagehand_agent**: Run an autonomous web agent capable of completing multi-step tasks, interacting with elements, navigating between pages, and returning structured results. This is much more flexible: the agent can do things like log in, search, fill forms, gather data from multiple places, and output a final result according to a requested schema.
**Key Differences:**
- *stagehand_extract* is a rapid “extract this data from this page” operation. It works best for direct, one-step extraction tasks.
- *stagehand_agent* performs complex, multi-step autonomous tasks on the web — such as navigation, searching, or even transactions — and can dynamically extract data according to your instructions and an optional schema.
In practice, use **stagehand_extract** when you know what you want and where, and use **stagehand_agent** when you need a bot to think through and execute interactive workflows.
By integrating Stagehand, Sim agents can automate data gathering, analysis, and workflow execution on the web: updating databases, organizing information, and generating custom reports—seamlessly and autonomously.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
Integrate Stagehand into the workflow. Can extract structured data from webpages.
Integrate Stagehand into the workflow. Can extract structured data from webpages or run an autonomous agent to perform tasks.
@@ -41,7 +48,8 @@ Extract structured data from a webpage using Stagehand
| --------- | ---- | -------- | ----------- |
| `url` | string | Yes | URL of the webpage to extract data from |
| `instruction` | string | Yes | Instructions for extraction |
| `apiKey` | string | Yes | OpenAI API key for extraction \(required by Stagehand\) |
| `provider` | string | No | AI provider to use: openai or anthropic |
| `apiKey` | string | Yes | API key for the selected provider |
| `schema` | json | Yes | JSON schema defining the structure of the data to extract |
#### Output
@@ -50,6 +58,28 @@ Extract structured data from a webpage using Stagehand
| --------- | ---- | ----------- |
| `data` | object | Extracted structured data matching the provided schema |
### `stagehand_agent`
Run an autonomous web agent to complete tasks and extract structured data
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | Yes | URL of the webpage to start the agent on |
| `task` | string | Yes | The task to complete or goal to achieve on the website |
| `variables` | json | No | Optional variables to substitute in the task \(format: \{key: value\}\). Reference in task using %key% |
| `format` | string | No | No description |
| `provider` | string | No | AI provider to use: openai or anthropic |
| `apiKey` | string | Yes | API key for the selected provider |
| `outputSchema` | json | No | Optional JSON schema defining the structure of data the agent should return |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `agentResult` | object | Result from the Stagehand agent execution |
## Notes

View File

@@ -1,64 +0,0 @@
---
title: Stagehand Agent
description: Autonomous web browsing agent
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="stagehand_agent"
color="#FFC83C"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://www.stagehand.dev/) is an autonomous web agent platform that enables AI systems to navigate and interact with websites just like a human would. It provides a powerful solution for automating complex web tasks without requiring custom code or browser automation scripts.
With Stagehand, you can:
- **Automate web navigation**: Enable AI to browse websites, click links, fill forms, and interact with web elements
- **Extract structured data**: Collect specific information from websites in a structured, usable format
- **Complete complex workflows**: Perform multi-step tasks across different websites and web applications
- **Handle authentication**: Navigate login processes and maintain sessions across websites
- **Process dynamic content**: Interact with JavaScript-heavy sites and single-page applications
- **Maintain context awareness**: Keep track of the current state and history while navigating
- **Generate detailed reports**: Receive comprehensive logs of actions taken and data collected
In Sim, the Stagehand integration enables your agents to seamlessly interact with web-based systems as part of their workflows. This allows for sophisticated automation scenarios that bridge the gap between your AI agents and the vast information and functionality available on the web. Your agents can search for information, interact with web applications, extract data from websites, and incorporate these capabilities into their decision-making processes. By connecting Sim with Stagehand, you can create agents that extend beyond API-based integrations to navigate the web just as a human would - filling forms, clicking buttons, reading content, and extracting valuable information to complete their tasks more effectively.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
Integrate Stagehand Agent into the workflow. Can navigate the web and perform tasks.
## Tools
### `stagehand_agent`
Run an autonomous web agent to complete tasks and extract structured data
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | Yes | URL of the webpage to start the agent on |
| `task` | string | Yes | The task to complete or goal to achieve on the website |
| `variables` | json | No | Optional variables to substitute in the task \(format: \{key: value\}\). Reference in task using %key% |
| `format` | string | No | No description |
| `apiKey` | string | Yes | OpenAI API key for agent execution \(required by Stagehand\) |
| `outputSchema` | json | No | Optional JSON schema defining the structure of data the agent should return |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `agentResult` | object | Result from the Stagehand agent execution |
## Notes
- Category: `tools`
- Type: `stagehand_agent`

View File

@@ -48,10 +48,8 @@ List all lists on a Trello board
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Whether the operation was successful |
| `lists` | array | Array of list objects with id, name, closed, pos, and idBoard |
| `count` | number | Number of lists returned |
| `error` | string | Error message if operation failed |
### `trello_list_cards`
@@ -68,10 +66,8 @@ List all cards on a Trello board
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Whether the operation was successful |
| `cards` | array | Array of card objects with id, name, desc, url, board/list IDs, labels, and due date |
| `count` | number | Number of cards returned |
| `error` | string | Error message if operation failed |
### `trello_create_card`
@@ -93,9 +89,7 @@ Create a new card on a Trello board
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Whether the card was created successfully |
| `card` | object | The created card object with id, name, desc, url, and other properties |
| `error` | string | Error message if operation failed |
### `trello_update_card`
@@ -117,9 +111,7 @@ Update an existing card on Trello
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Whether the card was updated successfully |
| `card` | object | The updated card object with id, name, desc, url, and other properties |
| `error` | string | Error message if operation failed |
### `trello_get_actions`
@@ -138,10 +130,8 @@ Get activity/actions from a board or card
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Whether the operation was successful |
| `actions` | array | Array of action objects with type, date, member, and data |
| `count` | number | Number of actions returned |
| `error` | string | Error message if operation failed |
### `trello_add_comment`
@@ -158,9 +148,7 @@ Add a comment to a Trello card
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Whether the comment was added successfully |
| `comment` | object | The created comment object with id, text, date, and member creator |
| `error` | string | Error message if operation failed |

View File

@@ -42,6 +42,7 @@ List all items from a Webflow CMS collection
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Yes | ID of the Webflow site |
| `collectionId` | string | Yes | ID of the collection |
| `offset` | number | No | Offset for pagination \(optional\) |
| `limit` | number | No | Maximum number of items to return \(optional, default: 100\) |
@@ -61,6 +62,7 @@ Get a single item from a Webflow CMS collection
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Yes | ID of the Webflow site |
| `collectionId` | string | Yes | ID of the collection |
| `itemId` | string | Yes | ID of the item to retrieve |
@@ -79,6 +81,7 @@ Create a new item in a Webflow CMS collection
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Yes | ID of the Webflow site |
| `collectionId` | string | Yes | ID of the collection |
| `fieldData` | json | Yes | Field data for the new item as a JSON object. Keys should match collection field names. |
@@ -97,6 +100,7 @@ Update an existing item in a Webflow CMS collection
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Yes | ID of the Webflow site |
| `collectionId` | string | Yes | ID of the collection |
| `itemId` | string | Yes | ID of the item to update |
| `fieldData` | json | Yes | Field data to update as a JSON object. Only include fields you want to change. |
@@ -116,6 +120,7 @@ Delete an item from a Webflow CMS collection
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Yes | ID of the Webflow site |
| `collectionId` | string | Yes | ID of the collection |
| `itemId` | string | Yes | ID of the item to delete |

View File

@@ -96,10 +96,7 @@ Retrieve user context from a thread with summary or basic mode
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `context` | string | The context string \(summary or basic\) |
| `facts` | array | Extracted facts |
| `entities` | array | Extracted entities |
| `summary` | string | Conversation summary |
| `context` | string | The context string \(summary or basic mode\) |
### `zep_get_messages`
@@ -139,9 +136,9 @@ Add messages to an existing thread
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `context` | string | Updated context after adding messages |
| `messageIds` | array | Array of added message UUIDs |
| `threadId` | string | The thread ID |
| `added` | boolean | Whether messages were added successfully |
| `messageIds` | array | Array of added message UUIDs |
### `zep_add_user`
@@ -211,7 +208,7 @@ List all conversation threads for a specific user
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `threads` | array | Array of thread objects for this user |
| `userId` | string | The user ID |
| `totalCount` | number | Total number of threads returned |

View File

@@ -318,10 +318,10 @@ Crear una anotación en un panel o como una anotación global
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Sí | Token de cuenta de servicio de Grafana |
| `baseUrl` | string | Sí | URL de la instancia de Grafana \(p. ej., https://your-grafana.com\) |
| `organizationId` | string | No | ID de la organización para instancias de Grafana multi-organización |
| `organizationId` | string | No | ID de organización para instancias Grafana multi-organización |
| `text` | string | Sí | El contenido de texto de la anotación |
| `tags` | string | No | Lista de etiquetas separadas por comas |
| `dashboardUid` | string | No | UID del panel donde añadir la anotación \(opcional para anotaciones globales\) |
| `dashboardUid` | string | | UID del panel de control donde añadir la anotación |
| `panelId` | number | No | ID del panel donde añadir la anotación |
| `time` | number | No | Hora de inicio en milisegundos de época \(por defecto es ahora\) |
| `timeEnd` | number | No | Hora de finalización en milisegundos de época \(para anotaciones de rango\) |
@@ -343,11 +343,11 @@ Consultar anotaciones por rango de tiempo, panel o etiquetas
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Sí | Token de cuenta de servicio de Grafana |
| `baseUrl` | string | Sí | URL de la instancia de Grafana \(p. ej., https://your-grafana.com\) |
| `organizationId` | string | No | ID de la organización para instancias de Grafana multi-organización |
| `organizationId` | string | No | ID de organización para instancias Grafana multi-organización |
| `from` | number | No | Hora de inicio en milisegundos de época |
| `to` | number | No | Hora de finalización en milisegundos de época |
| `dashboardUid` | string | No | Filtrar por UID del panel |
| `panelId` | number | No | Filtrar por ID del panel |
| `dashboardUid` | string | | UID del panel de control para consultar anotaciones |
| `panelId` | number | No | Filtrar por ID de panel |
| `tags` | string | No | Lista de etiquetas separadas por comas para filtrar |
| `type` | string | No | Filtrar por tipo \(alerta o anotación\) |
| `limit` | number | No | Número máximo de anotaciones a devolver |
@@ -487,6 +487,16 @@ Crear una nueva carpeta en Grafana
| `uid` | string | El UID de la carpeta creada |
| `title` | string | El título de la carpeta creada |
| `url` | string | La ruta URL a la carpeta |
| `hasAcl` | boolean | Si la carpeta tiene permisos ACL personalizados |
| `canSave` | boolean | Si el usuario actual puede guardar la carpeta |
| `canEdit` | boolean | Si el usuario actual puede editar la carpeta |
| `canAdmin` | boolean | Si el usuario actual tiene derechos de administrador en la carpeta |
| `canDelete` | boolean | Si el usuario actual puede eliminar la carpeta |
| `createdBy` | string | Nombre de usuario de quien creó la carpeta |
| `created` | string | Marca de tiempo cuando se creó la carpeta |
| `updatedBy` | string | Nombre de usuario de quien actualizó por última vez la carpeta |
| `updated` | string | Marca de tiempo cuando se actualizó por última vez la carpeta |
| `version` | number | Número de versión de la carpeta |
## Notas

View File

@@ -1,807 +0,0 @@
---
title: Pylon
description: Gestiona problemas de atención al cliente, cuentas, contactos,
usuarios, equipos y etiquetas en Pylon
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="pylon"
color="#E8F4FA"
/>
{/* MANUAL-CONTENT-START:intro */}
[Pylon](https://usepylon.com/) es una plataforma avanzada de soporte y éxito del cliente diseñada para ayudarte a gestionar todos los aspectos de tus relaciones con los clientes—desde problemas de soporte hasta cuentas, contactos, usuarios, equipos y más. Pylon permite a los equipos de soporte y éxito operar de manera eficiente y programática con una API rica y un conjunto completo de herramientas.
Con Pylon en Sim, puedes:
- **Gestionar problemas de soporte:**
- Listar, crear, obtener, actualizar y eliminar problemas de soporte para un seguimiento eficiente de casos.
- Buscar y posponer problemas para ayudar a los agentes a mantenerse enfocados y organizados.
- Manejar seguidores de problemas y problemas externos para una colaboración fluida con partes interesadas internas y externas.
- **Gestión completa de cuentas:**
- Listar, crear, obtener, actualizar y eliminar cuentas de clientes.
- Actualizar cuentas en masa de forma programática.
- Buscar cuentas para encontrar rápidamente información de clientes relevante para soporte o contacto.
- **Gestión de contactos:**
- Listar, crear, obtener, actualizar, eliminar y buscar contactos—gestiona a todas las personas conectadas a tus cuentas.
- **Operaciones de usuarios y equipos:**
- Listar, obtener, actualizar y buscar usuarios en tu espacio de trabajo de Pylon.
- Listar, crear, obtener y actualizar equipos para estructurar tu organización de soporte y flujos de trabajo.
- **Etiquetado y organización:**
- Listar, obtener, crear, actualizar y eliminar etiquetas para categorizar problemas, cuentas o contactos.
- **Gestión de mensajes:**
- Redactar contenido sensible de mensajes directamente desde tus flujos de trabajo para privacidad y cumplimiento.
Al integrar las herramientas de Pylon en Sim, tus agentes pueden automatizar todos los aspectos de las operaciones de soporte:
- Abrir, actualizar o clasificar automáticamente nuevos problemas cuando ocurren eventos de clientes.
- Mantener datos de cuentas y contactos sincronizados en toda tu infraestructura tecnológica.
- Dirigir conversaciones, manejar escalaciones y organizar tus datos de soporte usando etiquetas y equipos.
- Asegurar que los datos sensibles se gestionen adecuadamente redactando mensajes según sea necesario.
Los endpoints de Pylon proporcionan un control granular para la gestión completa del ciclo de vida de los problemas y relaciones con los clientes. Ya sea escalando un servicio de soporte, impulsando el éxito proactivo del cliente o integrándose con otros sistemas, Pylon en Sim permite la mejor automatización de CRM de su clase, de manera segura, flexible y a escala.
{/* MANUAL-CONTENT-END */}
## Instrucciones de uso
Integra Pylon en el flujo de trabajo. Gestiona problemas (listar, crear, obtener, actualizar, eliminar, buscar, posponer, seguidores, problemas externos), cuentas (listar, crear, obtener, actualizar, eliminar, actualización masiva, buscar), contactos (listar, crear, obtener, actualizar, eliminar, buscar), usuarios (listar, obtener, actualizar, buscar), equipos (listar, obtener, crear, actualizar), etiquetas (listar, obtener, crear, actualizar, eliminar) y mensajes (redactar).
## Herramientas
### `pylon_list_issues`
Recuperar una lista de problemas dentro de un rango de tiempo específico
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `startTime` | string | Sí | Hora de inicio en formato RFC3339 \(p. ej., 2024-01-01T00:00:00Z\) |
| `endTime` | string | Sí | Hora de fin en formato RFC3339 \(p. ej., 2024-01-31T23:59:59Z\) |
| `cursor` | string | No | Cursor de paginación para la siguiente página de resultados |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Lista de problemas |
### `pylon_create_issue`
Crear un nuevo problema con propiedades específicas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `title` | string | Sí | Título del problema |
| `bodyHtml` | string | Sí | Cuerpo del problema en formato HTML |
| `accountId` | string | No | ID de la cuenta a asociar con el problema |
| `assigneeId` | string | No | ID del usuario al que asignar el problema |
| `teamId` | string | No | ID del equipo al que asignar el problema |
| `requesterId` | string | No | ID del usuario solicitante \(alternativa a requester_email\) |
| `requesterEmail` | string | No | Dirección de correo electrónico del solicitante \(alternativa a requester_id\) |
| `priority` | string | No | Prioridad del problema |
| `tags` | string | No | IDs de etiquetas separados por comas |
| `customFields` | string | No | Campos personalizados como objeto JSON |
| `attachmentUrls` | string | No | URLs de archivos adjuntos separados por comas |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del problema creado |
### `pylon_get_issue`
Obtener un problema específico por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `issueId` | string | Sí | El ID del problema a recuperar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del problema |
### `pylon_update_issue`
Actualizar un problema existente
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `issueId` | string | Sí | El ID del problema a actualizar |
| `state` | string | No | Estado del problema |
| `assigneeId` | string | No | ID del usuario al que asignar el problema |
| `teamId` | string | No | ID del equipo al que asignar el problema |
| `tags` | string | No | IDs de etiquetas separados por comas |
| `customFields` | string | No | Campos personalizados como objeto JSON |
| `customerPortalVisible` | boolean | No | Si el problema es visible en el portal del cliente |
| `requesterId` | string | No | ID del usuario solicitante |
| `accountId` | string | No | ID de la cuenta a asociar con el problema |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del problema actualizado |
### `pylon_delete_issue`
Eliminar un problema por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `issueId` | string | Sí | El ID del problema a eliminar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Resultado de la eliminación |
### `pylon_search_issues`
Consultar problemas usando filtros
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `filter` | string | Sí | Criterios de filtro como cadena JSON |
| `cursor` | string | No | Cursor de paginación para la siguiente página de resultados |
| `limit` | number | No | Número máximo de resultados a devolver |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Resultados de la búsqueda |
### `pylon_snooze_issue`
Posponer la visibilidad del problema hasta un momento específico
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `issueId` | string | Sí | El ID del problema a posponer |
| `snoozeUntil` | string | Sí | Marca de tiempo RFC3339 cuando el problema debe reaparecer \(p. ej., 2024-01-01T00:00:00Z\) |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del problema pospuesto |
### `pylon_list_issue_followers`
Obtener lista de seguidores para un problema específico
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `issueId` | string | Sí | El ID del problema |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Lista de seguidores |
### `pylon_manage_issue_followers`
Añadir o eliminar seguidores de un problema
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `issueId` | string | Sí | El ID del problema |
| `userIds` | string | No | IDs de usuarios separados por comas para añadir/eliminar |
| `contactIds` | string | No | IDs de contactos separados por comas para añadir/eliminar |
| `operation` | string | No | Operación a realizar: "add" o "remove" \(predeterminado: "add"\) |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Lista actualizada de seguidores |
### `pylon_link_external_issue`
Vincular un problema a un problema de sistema externo
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `issueId` | string | Sí | El ID del problema de Pylon |
| `externalIssueId` | string | Sí | El ID del problema externo |
| `source` | string | Sí | El sistema de origen \(p. ej., "jira", "linear", "github"\) |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del problema externo vinculado |
### `pylon_list_accounts`
Obtener una lista paginada de cuentas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `limit` | string | No | Número de cuentas a devolver \(1-1000, predeterminado 100\) |
| `cursor` | string | No | Cursor de paginación para la siguiente página de resultados |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Lista de cuentas |
### `pylon_create_account`
Crear una nueva cuenta con propiedades específicas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `name` | string | Sí | Nombre de la cuenta |
| `domains` | string | No | Lista de dominios separados por comas |
| `primaryDomain` | string | No | Dominio principal para la cuenta |
| `customFields` | string | No | Campos personalizados como objeto JSON |
| `tags` | string | No | IDs de etiquetas separados por comas |
| `channels` | string | No | IDs de canales separados por comas |
| `externalIds` | string | No | IDs externos separados por comas |
| `ownerId` | string | No | ID de usuario propietario |
| `logoUrl` | string | No | URL del logotipo de la cuenta |
| `subaccountIds` | string | No | IDs de subcuentas separados por comas |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos de la cuenta creada |
### `pylon_get_account`
Recuperar una sola cuenta por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `accountId` | string | Sí | ID de la cuenta a recuperar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos de la cuenta |
### `pylon_update_account`
Actualizar una cuenta existente con nuevas propiedades
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `accountId` | string | Sí | ID de la cuenta a actualizar |
| `name` | string | No | Nombre de la cuenta |
| `domains` | string | No | Lista de dominios separados por comas |
| `primaryDomain` | string | No | Dominio principal para la cuenta |
| `customFields` | string | No | Campos personalizados como objeto JSON |
| `tags` | string | No | IDs de etiquetas separados por comas |
| `channels` | string | No | IDs de canales separados por comas |
| `externalIds` | string | No | IDs externos separados por comas |
| `ownerId` | string | No | ID de usuario propietario |
| `logoUrl` | string | No | URL del logotipo de la cuenta |
| `subaccountIds` | string | No | IDs de subcuentas separados por comas |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos de la cuenta actualizados |
### `pylon_delete_account`
Eliminar una cuenta por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `accountId` | string | Sí | ID de la cuenta a eliminar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Confirmación de eliminación |
### `pylon_bulk_update_accounts`
Actualizar múltiples cuentas a la vez
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `accountIds` | string | Sí | IDs de cuentas separados por comas para actualizar |
| `customFields` | string | No | Campos personalizados como objeto JSON |
| `tags` | string | No | IDs de etiquetas separados por comas |
| `ownerId` | string | No | ID de usuario propietario |
| `tagsApplyMode` | string | No | Modo de aplicación de etiquetas: append_only, remove_only, o replace |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos de las cuentas actualizadas en masa |
### `pylon_search_accounts`
Buscar cuentas con filtros personalizados
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `filter` | string | Sí | Filtro como cadena JSON con estructura de campo/operador/valor |
| `limit` | string | No | Número de cuentas a devolver \(1-1000, predeterminado 100\) |
| `cursor` | string | No | Cursor de paginación para la siguiente página de resultados |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Resultados de la búsqueda |
### `pylon_list_contacts`
Obtener una lista de contactos
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `cursor` | string | No | Cursor de paginación para la siguiente página de resultados |
| `limit` | string | No | Número máximo de contactos a devolver |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Lista de contactos |
### `pylon_create_contact`
Crear un nuevo contacto con propiedades específicas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `name` | string | Sí | Nombre del contacto |
| `email` | string | No | Dirección de correo electrónico del contacto |
| `accountId` | string | No | ID de cuenta para asociar con el contacto |
| `accountExternalId` | string | No | ID de cuenta externa para asociar con el contacto |
| `avatarUrl` | string | No | URL para la imagen de avatar del contacto |
| `customFields` | string | No | Campos personalizados como objeto JSON |
| `portalRole` | string | No | Rol del portal para el contacto |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del contacto creado |
### `pylon_get_contact`
Recuperar un contacto específico por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `contactId` | string | Sí | ID del contacto a recuperar |
| `cursor` | string | No | Cursor de paginación para la siguiente página de resultados |
| `limit` | string | No | Número máximo de elementos a devolver |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del contacto |
### `pylon_update_contact`
Actualizar un contacto existente con propiedades específicas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `contactId` | string | Sí | ID del contacto a actualizar |
| `name` | string | No | Nombre del contacto |
| `email` | string | No | Dirección de correo electrónico del contacto |
| `accountId` | string | No | ID de cuenta para asociar con el contacto |
| `accountExternalId` | string | No | ID de cuenta externa para asociar con el contacto |
| `avatarUrl` | string | No | URL para la imagen de avatar del contacto |
| `customFields` | string | No | Campos personalizados como objeto JSON |
| `portalRole` | string | No | Rol del portal para el contacto |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos de contacto actualizados |
### `pylon_delete_contact`
Eliminar un contacto específico por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `contactId` | string | Sí | ID del contacto a eliminar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Resultado de la operación de eliminación |
### `pylon_search_contacts`
Buscar contactos utilizando un filtro
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `filter` | string | Sí | Filtro como objeto JSON |
| `limit` | string | No | Número máximo de contactos a devolver |
| `cursor` | string | No | Cursor de paginación para la siguiente página de resultados |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Resultados de la búsqueda |
### `pylon_list_users`
Obtener una lista de usuarios
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Lista de usuarios |
### `pylon_get_user`
Recuperar un usuario específico por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `userId` | string | Sí | ID del usuario a recuperar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del usuario |
### `pylon_update_user`
Actualizar un usuario existente con propiedades específicas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `userId` | string | Sí | ID del usuario a actualizar |
| `roleId` | string | No | ID del rol a asignar al usuario |
| `status` | string | No | Estado del usuario |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos actualizados del usuario |
### `pylon_search_users`
Buscar usuarios utilizando un filtro con campo de correo electrónico
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `filter` | string | Sí | Filtro como objeto JSON con campo de correo electrónico |
| `cursor` | string | No | Cursor de paginación para la siguiente página de resultados |
| `limit` | string | No | Número máximo de usuarios a devolver |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Resultados de búsqueda |
### `pylon_list_teams`
Obtener una lista de equipos
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Lista de equipos |
### `pylon_get_team`
Obtener un equipo específico por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `teamId` | string | Sí | ID del equipo a recuperar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del equipo |
### `pylon_create_team`
Crear un nuevo equipo con propiedades específicas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `name` | string | No | Nombre del equipo |
| `userIds` | string | No | IDs de usuarios separados por comas para añadir como miembros del equipo |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del equipo creado |
### `pylon_update_team`
Actualizar un equipo existente con propiedades específicas (userIds reemplaza toda la membresía)
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `teamId` | string | Sí | ID del equipo a actualizar |
| `name` | string | No | Nombre del equipo |
| `userIds` | string | No | IDs de usuario separados por comas \(reemplaza toda la membresía del equipo\) |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos del equipo actualizado |
### `pylon_list_tags`
Obtener una lista de etiquetas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Lista de etiquetas |
### `pylon_get_tag`
Obtener una etiqueta específica por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `tagId` | string | Sí | ID de la etiqueta a obtener |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos de la etiqueta |
### `pylon_create_tag`
Crear una nueva etiqueta con propiedades específicas (objectType: account/issue/contact)
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `objectType` | string | Sí | Tipo de objeto para la etiqueta \(account, issue, o contact\) |
| `value` | string | Sí | Valor/nombre de la etiqueta |
| `hexColor` | string | No | Código de color hexadecimal para la etiqueta \(p. ej., #FF5733\) |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos de la etiqueta creada |
### `pylon_update_tag`
Actualizar una etiqueta existente con propiedades específicas
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `tagId` | string | Sí | ID de la etiqueta a actualizar |
| `hexColor` | string | No | Código de color hexadecimal para la etiqueta \(p. ej., #FF5733\) |
| `value` | string | No | Valor/nombre de la etiqueta |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Datos de la etiqueta actualizada |
### `pylon_delete_tag`
Eliminar una etiqueta específica por ID
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `tagId` | string | Sí | ID de la etiqueta a eliminar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Resultado de la operación de eliminación |
### `pylon_redact_message`
Redactar un mensaje específico dentro de un problema
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Sí | Token de API de Pylon |
| `issueId` | string | Sí | ID del problema que contiene el mensaje |
| `messageId` | string | Sí | ID del mensaje a redactar |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Estado de éxito de la operación |
| `output` | object | Resultado de la operación de redacción |
## Notas
- Categoría: `tools`
- Tipo: `pylon`

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
---
title: Stagehand Extract
description: Extrae datos de sitios web
title: Stagehand
description: Automatización web y extracción de datos
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
@@ -11,34 +11,42 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://stagehand.com) es una herramienta que te permite extraer datos estructurados de páginas web utilizando Browserbase y OpenAI.
[Stagehand](https://stagehand.com) es una herramienta que permite tanto la extracción de datos estructurados de páginas web como la automatización web autónoma utilizando Browserbase y LLMs modernos (OpenAI o Anthropic).
Con Stagehand, puedes:
Stagehand ofrece dos capacidades principales en Sim:
- **Extraer datos estructurados**: Extraer datos estructurados de páginas web utilizando Browserbase y OpenAI
- **Guardar datos en una base de datos**: Guardar los datos extraídos en una base de datos
- **Automatizar flujos de trabajo**: Automatizar flujos de trabajo para extraer datos de páginas web
- **stagehand_extract**: Extrae datos estructurados de una sola página web. Especificas lo que quieres (un esquema), y la IA recupera y analiza los datos en esa forma desde la página. Esto es mejor para extraer listas, campos u objetos cuando sabes exactamente qué información necesitas y dónde obtenerla.
En Sim, la integración de Stagehand permite a tus agentes extraer datos estructurados de páginas web utilizando Browserbase y OpenAI. Esto permite escenarios de automatización potentes como extracción de datos, análisis de datos e integración de datos. Tus agentes pueden extraer datos estructurados de páginas web, guardar los datos extraídos en una base de datos y automatizar flujos de trabajo para extraer datos de páginas web. Esta integración cierra la brecha entre tus flujos de trabajo de IA y tu sistema de gestión de datos, permitiendo una extracción e integración de datos sin problemas. Al conectar Sim con Stagehand, puedes automatizar procesos de extracción de datos, mantener repositorios de información actualizados, generar informes y organizar información de manera inteligente, todo a través de tus agentes inteligentes.
- **stagehand_agent**: Ejecuta un agente web autónomo capaz de completar tareas de múltiples pasos, interactuar con elementos, navegar entre páginas y devolver resultados estructurados. Esto es mucho más flexible: el agente puede hacer cosas como iniciar sesión, buscar, completar formularios, recopilar datos de múltiples lugares y generar un resultado final según un esquema solicitado.
**Diferencias clave:**
- *stagehand_extract* es una operación rápida de “extraer estos datos de esta página”. Funciona mejor para tareas de extracción directas, de un solo paso.
- *stagehand_agent* realiza tareas autónomas complejas de múltiples pasos en la web — como navegación, búsqueda o incluso transacciones — y puede extraer datos dinámicamente según tus instrucciones y un esquema opcional.
En la práctica, usa **stagehand_extract** cuando sabes qué quieres y dónde, y usa **stagehand_agent** cuando necesitas que un bot piense y ejecute flujos de trabajo interactivos.
Al integrar Stagehand, los agentes de Sim pueden automatizar la recopilación de datos, el análisis y la ejecución de flujos de trabajo en la web: actualizando bases de datos, organizando información y generando informes personalizados, de manera fluida y autónoma.
{/* MANUAL-CONTENT-END */}
## Instrucciones de uso
Integra Stagehand en el flujo de trabajo. Puede extraer datos estructurados de páginas web. Requiere clave API.
Integra Stagehand en el flujo de trabajo. Puede extraer datos estructurados de páginas web o ejecutar un agente autónomo para realizar tareas.
## Herramientas
### `stagehand_extract`
Extrae datos estructurados de una página web utilizando Stagehand
Extraer datos estructurados de una página web usando Stagehand
#### Entrada
| Parámetro | Tipo | Requerido | Descripción |
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `url` | string | Sí | URL de la página web de la que extraer datos |
| `instruction` | string | Sí | Instrucciones para la extracción |
| `apiKey` | string | | Clave API de OpenAI para la extracción \(requerida por Stagehand\) |
| `provider` | string | No | Proveedor de IA a utilizar: openai o anthropic |
| `apiKey` | string | Sí | Clave API para el proveedor seleccionado |
| `schema` | json | Sí | Esquema JSON que define la estructura de los datos a extraer |
#### Salida
@@ -47,6 +55,28 @@ Extrae datos estructurados de una página web utilizando Stagehand
| --------- | ---- | ----------- |
| `data` | object | Datos estructurados extraídos que coinciden con el esquema proporcionado |
### `stagehand_agent`
Ejecutar un agente web autónomo para completar tareas y extraer datos estructurados
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | Sí | URL de la página web donde iniciar el agente |
| `task` | string | Sí | La tarea a completar o el objetivo a lograr en el sitio web |
| `variables` | json | No | Variables opcionales para sustituir en la tarea \(formato: \{key: value\}\). Referencia en la tarea usando %key% |
| `format` | string | No | Sin descripción |
| `provider` | string | No | Proveedor de IA a utilizar: openai o anthropic |
| `apiKey` | string | Sí | Clave API para el proveedor seleccionado |
| `outputSchema` | json | No | Esquema JSON opcional que define la estructura de los datos que el agente debe devolver |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `agentResult` | objeto | Resultado de la ejecución del agente Stagehand |
## Notas
- Categoría: `tools`

View File

@@ -1,59 +0,0 @@
---
title: Stagehand Agent
description: Agente autónomo de navegación web
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="stagehand_agent"
color="#FFC83C"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://www.stagehand.dev/) es una plataforma de agentes web autónomos que permite a los sistemas de IA navegar e interactuar con sitios web tal como lo haría un humano. Proporciona una solución potente para automatizar tareas web complejas sin necesidad de código personalizado o scripts de automatización de navegador.
Con Stagehand, puedes:
- **Automatizar la navegación web**: Permitir que la IA navegue por sitios web, haga clic en enlaces, complete formularios e interactúe con elementos web
- **Extraer datos estructurados**: Recopilar información específica de sitios web en un formato estructurado y utilizable
- **Completar flujos de trabajo complejos**: Realizar tareas de múltiples pasos en diferentes sitios web y aplicaciones web
- **Gestionar la autenticación**: Navegar por procesos de inicio de sesión y mantener sesiones en sitios web
- **Procesar contenido dinámico**: Interactuar con sitios con uso intensivo de JavaScript y aplicaciones de una sola página
- **Mantener la conciencia del contexto**: Realizar un seguimiento del estado actual y del historial durante la navegación
- **Generar informes detallados**: Recibir registros completos de las acciones realizadas y los datos recopilados
En Sim, la integración de Stagehand permite que tus agentes interactúen sin problemas con sistemas basados en web como parte de sus flujos de trabajo. Esto permite escenarios de automatización sofisticados que conectan a tus agentes de IA con la amplia información y funcionalidad disponible en la web. Tus agentes pueden buscar información, interactuar con aplicaciones web, extraer datos de sitios web e incorporar estas capacidades en sus procesos de toma de decisiones. Al conectar Sim con Stagehand, puedes crear agentes que van más allá de las integraciones basadas en API para navegar por la web tal como lo haría un humano: completando formularios, haciendo clic en botones, leyendo contenido y extrayendo información valiosa para completar sus tareas de manera más efectiva.
{/* MANUAL-CONTENT-END */}
## Instrucciones de uso
Integra el Agente Stagehand en el flujo de trabajo. Puede navegar por la web y realizar tareas. Requiere clave API.
## Herramientas
### `stagehand_agent`
Ejecuta un agente web autónomo para completar tareas y extraer datos estructurados
#### Entrada
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | ----------- | ----------- |
| `startUrl` | string | Sí | URL de la página web donde iniciará el agente |
| `task` | string | Sí | La tarea a completar o el objetivo a lograr en el sitio web |
| `variables` | json | No | Variables opcionales para sustituir en la tarea \(formato: \{key: value\}\). Referencia en la tarea usando %key% |
| `format` | string | No | Sin descripción |
| `apiKey` | string | Sí | Clave API de OpenAI para la ejecución del agente \(requerida por Stagehand\) |
| `outputSchema` | json | No | Esquema JSON opcional que define la estructura de los datos que el agente debe devolver |
#### Salida
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `agentResult` | object | Resultado de la ejecución del agente Stagehand |
## Notas
- Categoría: `tools`
- Tipo: `stagehand_agent`

View File

@@ -45,10 +45,8 @@ Listar todas las listas en un tablero de Trello
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Si la operación fue exitosa |
| `lists` | array | Array de objetos de lista con id, nombre, cerrado, posición e idTablero |
| `lists` | array | Array de objetos de lista con id, nombre, closed, pos e idBoard |
| `count` | number | Número de listas devueltas |
| `error` | string | Mensaje de error si la operación falló |
### `trello_list_cards`
@@ -64,10 +62,8 @@ Listar todas las listas en un tablero de Trello
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Si la operación fue exitosa |
| `cards` | array | Array de objetos de tarjeta con id, nombre, desc, url, IDs de tablero/lista, etiquetas y fecha de vencimiento |
| `count` | number | Número de tarjetas devueltas |
| `error` | string | Mensaje de error si la operación falló |
### `trello_create_card`
@@ -89,9 +85,7 @@ Crear una nueva tarjeta en un tablero de Trello
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Si la tarjeta se creó correctamente |
| `card` | object | El objeto de la tarjeta creada con id, nombre, descripción, url y otras propiedades |
| `error` | string | Mensaje de error si la operación falló |
| `card` | object | El objeto de tarjeta creada con id, nombre, desc, url y otras propiedades |
### `trello_update_card`
@@ -113,9 +107,7 @@ Actualizar una tarjeta existente en Trello
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Si la tarjeta se actualizó correctamente |
| `card` | object | El objeto de la tarjeta actualizada con id, nombre, descripción, url y otras propiedades |
| `error` | string | Mensaje de error si la operación falló |
| `card` | object | El objeto de tarjeta actualizada con id, nombre, desc, url y otras propiedades |
### `trello_get_actions`
@@ -134,10 +126,8 @@ Obtener actividad/acciones de un tablero o tarjeta
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Si la operación fue exitosa |
| `actions` | array | Array de objetos de acción con tipo, fecha, miembro y datos |
| `count` | number | Número de acciones devueltas |
| `error` | string | Mensaje de error si la operación falló |
### `trello_add_comment`
@@ -154,9 +144,7 @@ Añadir un comentario a una tarjeta de Trello
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `success` | boolean | Si el comentario se añadió correctamente |
| `comment` | object | El objeto de comentario creado con id, texto, fecha y miembro creador |
| `error` | string | Mensaje de error si la operación falló |
## Notas

View File

@@ -39,6 +39,7 @@ Listar todos los elementos de una colección del CMS de Webflow
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Sí | ID del sitio de Webflow |
| `collectionId` | string | Sí | ID de la colección |
| `offset` | number | No | Desplazamiento para paginación \(opcional\) |
| `limit` | number | No | Número máximo de elementos a devolver \(opcional, predeterminado: 100\) |
@@ -58,6 +59,7 @@ Obtener un solo elemento de una colección del CMS de Webflow
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Sí | ID del sitio de Webflow |
| `collectionId` | string | Sí | ID de la colección |
| `itemId` | string | Sí | ID del elemento a recuperar |
@@ -76,6 +78,7 @@ Crear un nuevo elemento en una colección del CMS de Webflow
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Sí | ID del sitio de Webflow |
| `collectionId` | string | Sí | ID de la colección |
| `fieldData` | json | Sí | Datos de campo para el nuevo elemento como objeto JSON. Las claves deben coincidir con los nombres de campo de la colección. |
@@ -94,6 +97,7 @@ Actualizar un elemento existente en una colección CMS de Webflow
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Sí | ID del sitio de Webflow |
| `collectionId` | string | Sí | ID de la colección |
| `itemId` | string | Sí | ID del elemento a actualizar |
| `fieldData` | json | Sí | Datos de campo para actualizar como objeto JSON. Solo incluye los campos que quieres cambiar. |
@@ -113,6 +117,7 @@ Eliminar un elemento de una colección CMS de Webflow
| Parámetro | Tipo | Obligatorio | Descripción |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | Sí | ID del sitio de Webflow |
| `collectionId` | string | Sí | ID de la colección |
| `itemId` | string | Sí | ID del elemento a eliminar |

View File

@@ -94,10 +94,7 @@ Recuperar el contexto del usuario de un hilo con modo resumen o básico
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `context` | string | La cadena de contexto \(resumen o básico\) |
| `facts` | array | Hechos extraídos |
| `entities` | array | Entidades extraídas |
| `summary` | string | Resumen de la conversación |
| `context` | string | La cadena de contexto \(modo resumen o básico\) |
### `zep_get_messages`
@@ -137,9 +134,9 @@ Añadir mensajes a un hilo existente
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `context` | string | Contexto actualizado después de añadir mensajes |
| `messageIds` | array | Array de UUIDs de mensajes añadidos |
| `threadId` | string | El ID del hilo |
| `added` | boolean | Si los mensajes se agregaron correctamente |
| `messageIds` | array | Array de UUIDs de mensajes agregados |
### `zep_add_user`
@@ -209,7 +206,7 @@ Listar todos los hilos de conversación para un usuario específico
| Parámetro | Tipo | Descripción |
| --------- | ---- | ----------- |
| `threads` | array | Array de objetos de hilo para este usuario |
| `userId` | string | El ID del usuario |
| `totalCount` | number | Número total de hilos devueltos |
## Notas

View File

@@ -315,13 +315,13 @@ Créer une annotation sur un tableau de bord ou comme annotation globale
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ---------- | ----------- |
| --------- | ---- | -------- | ----------- |
| `apiKey` | chaîne | Oui | Jeton de compte de service Grafana |
| `baseUrl` | chaîne | Oui | URL de l'instance Grafana \(ex., https://your-grafana.com\) |
| `organizationId` | chaîne | Non | ID d'organisation pour les instances Grafana multi-organisations |
| `organizationId` | chaîne | Non | ID de l'organisation pour les instances Grafana multi-organisations |
| `text` | chaîne | Oui | Le contenu textuel de l'annotation |
| `tags` | chaîne | Non | Liste de tags séparés par des virgules |
| `dashboardUid` | chaîne | Non | UID du tableau de bord auquel ajouter l'annotation \(facultatif pour les annotations globales\) |
| `tags` | chaîne | Non | Liste d'étiquettes séparées par des virgules |
| `dashboardUid` | chaîne | Oui | UID du tableau de bord auquel ajouter l'annotation |
| `panelId` | nombre | Non | ID du panneau auquel ajouter l'annotation |
| `time` | nombre | Non | Heure de début en millisecondes d'époque \(par défaut : maintenant\) |
| `timeEnd` | nombre | Non | Heure de fin en millisecondes d'époque \(pour les annotations de plage\) |
@@ -340,15 +340,15 @@ Interroger les annotations par plage de temps, tableau de bord ou tags
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ---------- | ----------- |
| --------- | ---- | -------- | ----------- |
| `apiKey` | chaîne | Oui | Jeton de compte de service Grafana |
| `baseUrl` | chaîne | Oui | URL de l'instance Grafana \(ex., https://your-grafana.com\) |
| `organizationId` | chaîne | Non | ID d'organisation pour les instances Grafana multi-organisations |
| `organizationId` | chaîne | Non | ID de l'organisation pour les instances Grafana multi-organisations |
| `from` | nombre | Non | Heure de début en millisecondes d'époque |
| `to` | nombre | Non | Heure de fin en millisecondes d'époque |
| `dashboardUid` | chaîne | Non | Filtrer par UID de tableau de bord |
| `dashboardUid` | chaîne | Oui | UID du tableau de bord pour interroger les annotations |
| `panelId` | nombre | Non | Filtrer par ID de panneau |
| `tags` | chaîne | Non | Liste de tags séparés par des virgules pour filtrer |
| `tags` | chaîne | Non | Liste d'étiquettes séparées par des virgules pour filtrer |
| `type` | chaîne | Non | Filtrer par type \(alerte ou annotation\) |
| `limit` | nombre | Non | Nombre maximum d'annotations à retourner |
@@ -483,10 +483,20 @@ Créer un nouveau dossier dans Grafana
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `id` | nombre | L'ID numérique du dossier créé |
| `uid` | chaîne | L'UID du dossier créé |
| `title` | chaîne | Le titre du dossier créé |
| `url` | chaîne | Le chemin URL vers le dossier |
| `id` | number | L'identifiant numérique du dossier créé |
| `uid` | string | L'UID du dossier créé |
| `title` | string | Le titre du dossier créé |
| `url` | string | Le chemin URL vers le dossier |
| `hasAcl` | boolean | Si le dossier possède des permissions ACL personnalisées |
| `canSave` | boolean | Si l'utilisateur actuel peut enregistrer le dossier |
| `canEdit` | boolean | Si l'utilisateur actuel peut modifier le dossier |
| `canAdmin` | boolean | Si l'utilisateur actuel a des droits d'administrateur sur le dossier |
| `canDelete` | boolean | Si l'utilisateur actuel peut supprimer le dossier |
| `createdBy` | string | Nom d'utilisateur de la personne qui a créé le dossier |
| `created` | string | Horodatage de la création du dossier |
| `updatedBy` | string | Nom d'utilisateur de la personne qui a dernièrement mis à jour le dossier |
| `updated` | string | Horodatage de la dernière mise à jour du dossier |
| `version` | number | Numéro de version du dossier |
## Notes

View File

@@ -1,807 +0,0 @@
---
title: Pylon
description: Gérez les problèmes de support client, les comptes, les contacts,
les utilisateurs, les équipes et les tags dans Pylon
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="pylon"
color="#E8F4FA"
/>
{/* MANUAL-CONTENT-START:intro */}
[Pylon](https://usepylon.com/) est une plateforme avancée de support et de réussite client conçue pour vous aider à gérer tous les aspects de vos relations client—des problèmes de support aux comptes, contacts, utilisateurs, équipes et au-delà. Pylon permet aux équipes de support et de réussite d'opérer efficacement et de manière programmatique avec une API riche et un ensemble d'outils complet.
Avec Pylon dans Sim, vous pouvez :
- **Gérer les problèmes de support :**
- Lister, créer, obtenir, mettre à jour et supprimer des problèmes de support pour un suivi efficace des cas.
- Rechercher et mettre en veille des problèmes pour aider les agents à rester concentrés et organisés.
- Gérer les abonnés aux problèmes et les problèmes externes pour une collaboration fluide avec les parties prenantes internes et externes.
- **Gestion complète des comptes :**
- Lister, créer, obtenir, mettre à jour et supprimer des comptes clients.
- Mettre à jour en masse des comptes de manière programmatique.
- Rechercher des comptes pour trouver rapidement les informations clients pertinentes pour le support ou la prospection.
- **Gestion des contacts :**
- Lister, créer, obtenir, mettre à jour, supprimer et rechercher des contacts—gérez toutes les personnes liées à vos comptes.
- **Opérations utilisateurs et équipes :**
- Lister, obtenir, mettre à jour et rechercher des utilisateurs dans votre espace de travail Pylon.
- Lister, créer, obtenir et mettre à jour des équipes pour structurer votre organisation de support et vos flux de travail.
- **Étiquetage et organisation :**
- Lister, obtenir, créer, mettre à jour et supprimer des tags pour catégoriser les problèmes, les comptes ou les contacts.
- **Gestion des messages :**
- Expurger le contenu sensible des messages directement depuis vos flux de travail pour la confidentialité et la conformité.
En intégrant les outils Pylon dans Sim, vos agents peuvent automatiser tous les aspects des opérations de support :
- Ouvrir, mettre à jour ou trier automatiquement de nouveaux problèmes lorsque des événements clients se produisent.
- Maintenir des données de compte et de contact synchronisées dans l'ensemble de votre stack technologique.
- Acheminer les conversations, gérer les escalades et organiser vos données de support à l'aide de tags et d'équipes.
- Garantir que les données sensibles sont correctement gérées en expurgeant les messages selon les besoins.
Les points de terminaison de Pylon offrent un contrôle granulaire pour la gestion complète du cycle de vie des problèmes et des relations clients. Que ce soit pour développer un service d'assistance, alimenter un service client proactif ou s'intégrer à d'autres systèmes, Pylon dans Sim permet une automatisation CRM de premier ordre — de manière sécurisée, flexible et à grande échelle.
{/* MANUAL-CONTENT-END */}
## Instructions d'utilisation
Intégrez Pylon dans le flux de travail. Gérez les problèmes (lister, créer, obtenir, mettre à jour, supprimer, rechercher, mettre en veille, suiveurs, problèmes externes), les comptes (lister, créer, obtenir, mettre à jour, supprimer, mise à jour en masse, rechercher), les contacts (lister, créer, obtenir, mettre à jour, supprimer, rechercher), les utilisateurs (lister, obtenir, mettre à jour, rechercher), les équipes (lister, obtenir, créer, mettre à jour), les tags (lister, obtenir, créer, mettre à jour, supprimer) et les messages (expurger).
## Outils
### `pylon_list_issues`
Récupérer une liste de problèmes dans une plage de temps spécifiée
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | chaîne | Oui | Jeton API Pylon |
| `startTime` | chaîne | Oui | Heure de début au format RFC3339 \(ex., 2024-01-01T00:00:00Z\) |
| `endTime` | chaîne | Oui | Heure de fin au format RFC3339 \(ex., 2024-01-31T23:59:59Z\) |
| `cursor` | chaîne | Non | Curseur de pagination pour la page suivante de résultats |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | booléen | Statut de réussite de l'opération |
| `output` | objet | Liste des problèmes |
### `pylon_create_issue`
Créer un nouveau problème avec les propriétés spécifiées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `title` | string | Oui | Titre du problème |
| `bodyHtml` | string | Oui | Corps du problème au format HTML |
| `accountId` | string | Non | ID du compte à associer au problème |
| `assigneeId` | string | Non | ID de l'utilisateur à qui assigner le problème |
| `teamId` | string | Non | ID de l'équipe à qui assigner le problème |
| `requesterId` | string | Non | ID de l'utilisateur demandeur \(alternative à requester_email\) |
| `requesterEmail` | string | Non | Adresse e-mail du demandeur \(alternative à requester_id\) |
| `priority` | string | Non | Priorité du problème |
| `tags` | string | Non | IDs de tags séparés par des virgules |
| `customFields` | string | Non | Champs personnalisés sous forme d'objet JSON |
| `attachmentUrls` | string | Non | URLs des pièces jointes séparées par des virgules |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du problème créé |
### `pylon_get_issue`
Récupérer un problème spécifique par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `issueId` | string | Oui | L'ID du problème à récupérer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du problème |
### `pylon_update_issue`
Mettre à jour un problème existant
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `issueId` | string | Oui | L'ID du problème à mettre à jour |
| `state` | string | Non | État du problème |
| `assigneeId` | string | Non | ID de l'utilisateur à qui assigner le problème |
| `teamId` | string | Non | ID de l'équipe à qui assigner le problème |
| `tags` | string | Non | IDs de tags séparés par des virgules |
| `customFields` | string | Non | Champs personnalisés sous forme d'objet JSON |
| `customerPortalVisible` | boolean | Non | Indique si le problème est visible dans le portail client |
| `requesterId` | string | Non | ID de l'utilisateur demandeur |
| `accountId` | string | Non | ID du compte à associer au problème |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du problème mis à jour |
### `pylon_delete_issue`
Supprimer un problème par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | chaîne | Oui | Jeton API Pylon |
| `issueId` | chaîne | Oui | L'ID du problème à supprimer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | booléen | Statut de réussite de l'opération |
| `output` | objet | Résultat de la suppression |
### `pylon_search_issues`
Interroger les problèmes à l'aide de filtres
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | chaîne | Oui | Jeton API Pylon |
| `filter` | chaîne | Oui | Critères de filtre sous forme de chaîne JSON |
| `cursor` | chaîne | Non | Curseur de pagination pour la page suivante de résultats |
| `limit` | nombre | Non | Nombre maximum de résultats à retourner |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | booléen | Statut de réussite de l'opération |
| `output` | objet | Résultats de la recherche |
### `pylon_snooze_issue`
Reporter la visibilité du problème jusqu'à l'heure spécifiée
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | chaîne | Oui | Jeton API Pylon |
| `issueId` | chaîne | Oui | L'ID du problème à mettre en veille |
| `snoozeUntil` | chaîne | Oui | Horodatage RFC3339 indiquant quand le problème doit réapparaître \(par exemple, 2024-01-01T00:00:00Z\) |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du problème mis en veille |
### `pylon_list_issue_followers`
Obtenir la liste des abonnés pour un problème spécifique
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `issueId` | string | Oui | L'ID du problème |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Liste des abonnés |
### `pylon_manage_issue_followers`
Ajouter ou supprimer des abonnés d'un problème
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `issueId` | string | Oui | L'ID du problème |
| `userIds` | string | Non | IDs d'utilisateurs séparés par des virgules à ajouter/supprimer |
| `contactIds` | string | Non | IDs de contacts séparés par des virgules à ajouter/supprimer |
| `operation` | string | Non | Opération à effectuer : "add" ou "remove" \(par défaut : "add"\) |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Liste mise à jour des abonnés |
### `pylon_link_external_issue`
Lier un problème à un problème de système externe
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `issueId` | string | Oui | L'ID du problème Pylon |
| `externalIssueId` | string | Oui | L'ID du problème externe |
| `source` | string | Oui | Le système source \(par ex., "jira", "linear", "github"\) |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du problème externe lié |
### `pylon_list_accounts`
Récupérer une liste paginée de comptes
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `limit` | string | Non | Nombre de comptes à retourner \(1-1000, par défaut 100\) |
| `cursor` | string | Non | Curseur de pagination pour la page suivante de résultats |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Liste des comptes |
### `pylon_create_account`
Créer un nouveau compte avec les propriétés spécifiées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `name` | string | Oui | Nom du compte |
| `domains` | string | Non | Liste de domaines séparés par des virgules |
| `primaryDomain` | string | Non | Domaine principal pour le compte |
| `customFields` | string | Non | Champs personnalisés sous forme d'objet JSON |
| `tags` | string | Non | IDs de tags séparés par des virgules |
| `channels` | string | Non | IDs de canaux séparés par des virgules |
| `externalIds` | string | Non | IDs externes séparés par des virgules |
| `ownerId` | string | Non | ID de l'utilisateur propriétaire |
| `logoUrl` | string | Non | URL vers le logo du compte |
| `subaccountIds` | string | Non | IDs de sous-comptes séparés par des virgules |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du compte créé |
### `pylon_get_account`
Récupérer un seul compte par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `accountId` | string | Oui | ID du compte à récupérer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du compte |
### `pylon_update_account`
Mettre à jour un compte existant avec de nouvelles propriétés
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `accountId` | string | Oui | ID du compte à mettre à jour |
| `name` | string | Non | Nom du compte |
| `domains` | string | Non | Liste de domaines séparés par des virgules |
| `primaryDomain` | string | Non | Domaine principal du compte |
| `customFields` | string | Non | Champs personnalisés sous forme d'objet JSON |
| `tags` | string | Non | IDs de tags séparés par des virgules |
| `channels` | string | Non | IDs de canaux séparés par des virgules |
| `externalIds` | string | Non | IDs externes séparés par des virgules |
| `ownerId` | string | Non | ID de l'utilisateur propriétaire |
| `logoUrl` | string | Non | URL du logo du compte |
| `subaccountIds` | string | Non | IDs de sous-comptes séparés par des virgules |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du compte mises à jour |
### `pylon_delete_account`
Supprimer un compte par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `accountId` | string | Oui | ID du compte à supprimer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Confirmation de suppression |
### `pylon_bulk_update_accounts`
Mettre à jour plusieurs comptes à la fois
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `accountIds` | string | Oui | IDs de comptes séparés par des virgules à mettre à jour |
| `customFields` | string | Non | Champs personnalisés sous forme d'objet JSON |
| `tags` | string | Non | IDs de tags séparés par des virgules |
| `ownerId` | string | Non | ID de l'utilisateur propriétaire |
| `tagsApplyMode` | string | Non | Mode d'application des tags : append_only, remove_only, ou replace |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données des comptes mis à jour en masse |
### `pylon_search_accounts`
Rechercher des comptes avec des filtres personnalisés
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `filter` | string | Oui | Filtre sous forme de chaîne JSON avec structure champ/opérateur/valeur |
| `limit` | string | Non | Nombre de comptes à retourner \(1-1000, par défaut 100\) |
| `cursor` | string | Non | Curseur de pagination pour la page suivante de résultats |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Résultats de recherche |
### `pylon_list_contacts`
Récupérer une liste de contacts
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `cursor` | string | Non | Curseur de pagination pour la page suivante de résultats |
| `limit` | string | Non | Nombre maximum de contacts à retourner |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Liste des contacts |
### `pylon_create_contact`
Créer un nouveau contact avec des propriétés spécifiées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `name` | string | Oui | Nom du contact |
| `email` | string | Non | Adresse e-mail du contact |
| `accountId` | string | Non | ID du compte à associer au contact |
| `accountExternalId` | string | Non | ID de compte externe à associer au contact |
| `avatarUrl` | string | Non | URL pour l'image d'avatar du contact |
| `customFields` | string | Non | Champs personnalisés sous forme d'objet JSON |
| `portalRole` | string | Non | Rôle du portail pour le contact |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du contact créé |
### `pylon_get_contact`
Récupérer un contact spécifique par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Oui | Token API Pylon |
| `contactId` | string | Oui | ID du contact à récupérer |
| `cursor` | string | Non | Curseur de pagination pour la page suivante de résultats |
| `limit` | string | Non | Nombre maximum d'éléments à retourner |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du contact |
### `pylon_update_contact`
Mettre à jour un contact existant avec les propriétés spécifiées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | string | Oui | Token API Pylon |
| `contactId` | string | Oui | ID du contact à mettre à jour |
| `name` | string | Non | Nom du contact |
| `email` | string | Non | Adresse e-mail du contact |
| `accountId` | string | Non | ID du compte à associer au contact |
| `accountExternalId` | string | Non | ID de compte externe à associer au contact |
| `avatarUrl` | string | Non | URL pour l'image d'avatar du contact |
| `customFields` | string | Non | Champs personnalisés sous forme d'objet JSON |
| `portalRole` | string | Non | Rôle du portail pour le contact |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du contact mises à jour |
### `pylon_delete_contact`
Supprimer un contact spécifique par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `contactId` | string | Oui | ID du contact à supprimer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Résultat de l'opération de suppression |
### `pylon_search_contacts`
Rechercher des contacts à l'aide d'un filtre
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `filter` | string | Oui | Filtre sous forme d'objet JSON |
| `limit` | string | Non | Nombre maximum de contacts à renvoyer |
| `cursor` | string | Non | Curseur de pagination pour la page suivante de résultats |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Résultats de la recherche |
### `pylon_list_users`
Récupérer une liste d'utilisateurs
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Liste des utilisateurs |
### `pylon_get_user`
Récupérer un utilisateur spécifique par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `userId` | string | Oui | ID de l'utilisateur à récupérer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données de l'utilisateur |
### `pylon_update_user`
Mettre à jour un utilisateur existant avec les propriétés spécifiées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `userId` | string | Oui | ID de l'utilisateur à mettre à jour |
| `roleId` | string | Non | ID du rôle à attribuer à l'utilisateur |
| `status` | string | Non | Statut de l'utilisateur |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données de l'utilisateur mises à jour |
### `pylon_search_users`
Rechercher des utilisateurs à l'aide d'un filtre avec le champ email
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `filter` | string | Oui | Filtre sous forme d'objet JSON avec champ email |
| `cursor` | string | Non | Curseur de pagination pour la page suivante de résultats |
| `limit` | string | Non | Nombre maximum d'utilisateurs à retourner |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Résultats de recherche |
### `pylon_list_teams`
Récupérer une liste d'équipes
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Liste des équipes |
### `pylon_get_team`
Récupérer une équipe spécifique par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `teamId` | string | Oui | ID de l'équipe à récupérer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données de l'équipe |
### `pylon_create_team`
Créer une nouvelle équipe avec les propriétés spécifiées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `name` | string | Non | Nom de l'équipe |
| `userIds` | string | Non | IDs d'utilisateurs séparés par des virgules à ajouter comme membres de l'équipe |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données de l'équipe créée |
### `pylon_update_team`
Mettre à jour une équipe existante avec les propriétés spécifiées (userIds remplace l'ensemble des membres)
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `teamId` | string | Oui | ID de l'équipe à mettre à jour |
| `name` | string | Non | Nom de l'équipe |
| `userIds` | string | Non | IDs d'utilisateurs séparés par des virgules \(remplace tous les membres de l'équipe\) |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données de l'équipe mise à jour |
### `pylon_list_tags`
Récupérer une liste de tags
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Liste des tags |
### `pylon_get_tag`
Récupérer un tag spécifique par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Jeton API Pylon |
| `tagId` | string | Oui | ID du tag à récupérer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du tag |
### `pylon_create_tag`
Créer un nouveau tag avec les propriétés spécifiées (objectType : account/issue/contact)
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Token API Pylon |
| `objectType` | string | Oui | Type d'objet pour le tag \(account, issue, ou contact\) |
| `value` | string | Oui | Valeur/nom du tag |
| `hexColor` | string | Non | Code couleur hexadécimal pour le tag \(ex., #FF5733\) |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du tag créé |
### `pylon_update_tag`
Mettre à jour un tag existant avec les propriétés spécifiées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | Oui | Token API Pylon |
| `tagId` | string | Oui | ID du tag à mettre à jour |
| `hexColor` | string | Non | Code couleur hexadécimal pour le tag \(ex., #FF5733\) |
| `value` | string | Non | Valeur/nom du tag |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Statut de réussite de l'opération |
| `output` | object | Données du tag mis à jour |
### `pylon_delete_tag`
Supprimer un tag spécifique par ID
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | chaîne | Oui | Token API Pylon |
| `tagId` | chaîne | Oui | ID du tag à supprimer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | booléen | Statut de réussite de l'opération |
| `output` | objet | Résultat de l'opération de suppression |
### `pylon_redact_message`
Expurger un message spécifique dans un problème
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `apiToken` | chaîne | Oui | Token API Pylon |
| `issueId` | chaîne | Oui | ID du problème contenant le message |
| `messageId` | chaîne | Oui | ID du message à expurger |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | booléen | Statut de réussite de l'opération |
| `output` | objet | Résultat de l'opération d'expurgation |
## Notes
- Catégorie : `tools`
- Type : `pylon`

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
---
title: Stagehand Extract
description: Extraire des données de sites web
title: Stagehand
description: Automatisation web et extraction de données
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
@@ -11,20 +11,27 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://stagehand.com) est un outil qui vous permet d'extraire des données structurées de pages web en utilisant Browserbase et OpenAI.
[Stagehand](https://stagehand.com) est un outil qui permet à la fois l'extraction de données structurées à partir de pages web et l'automatisation web autonome en utilisant Browserbase et les LLM modernes (OpenAI ou Anthropic).
Avec Stagehand, vous pouvez :
Stagehand offre deux capacités principales dans Sim :
- **Extraire des données structurées** : Extraire des données structurées de pages web en utilisant Browserbase et OpenAI
- **Enregistrer des données dans une base de données** : Sauvegarder les données extraites dans une base de données
- **Automatiser des flux de travail** : Automatiser des flux de travail pour extraire des données de pages web
- **stagehand_extract** : Extrait des données structurées d'une seule page web. Vous spécifiez ce que vous voulez (un schéma), et l'IA récupère et analyse les données dans cette forme à partir de la page. C'est idéal pour extraire des listes, des champs ou des objets lorsque vous savez exactement quelles informations vous avez besoin et où les obtenir.
Dans Sim, l'intégration Stagehand permet à vos agents d'extraire des données structurées de pages web en utilisant Browserbase et OpenAI. Cela permet des scénarios d'automatisation puissants tels que l'extraction de données, l'analyse de données et l'intégration de données. Vos agents peuvent extraire des données structurées de pages web, sauvegarder les données extraites dans une base de données et automatiser des flux de travail pour extraire des données de pages web. Cette intégration comble le fossé entre vos flux de travail IA et votre système de gestion de données, permettant une extraction et une intégration de données transparentes. En connectant Sim avec Stagehand, vous pouvez automatiser les processus d'extraction de données, maintenir des référentiels d'informations à jour, générer des rapports et organiser intelligemment les informations - le tout grâce à vos agents intelligents.
- **stagehand_agent** : Exécute un agent web autonome capable d'accomplir des tâches en plusieurs étapes, d'interagir avec des éléments, de naviguer entre les pages et de renvoyer des résultats structurés. C'est beaucoup plus flexible : l'agent peut faire des choses comme se connecter, rechercher, remplir des formulaires, recueillir des données de plusieurs endroits et produire un résultat final selon un schéma demandé.
**Différences clés :**
- *stagehand_extract* est une opération rapide “extraire ces données de cette page”. Il fonctionne mieux pour les tâches d'extraction directes en une seule étape.
- *stagehand_agent* effectue des tâches autonomes complexes en plusieurs étapes sur le web — comme la navigation, la recherche, ou même des transactions — et peut extraire dynamiquement des données selon vos instructions et un schéma optionnel.
En pratique, utilisez **stagehand_extract** lorsque vous savez ce que vous voulez et où, et utilisez **stagehand_agent** lorsque vous avez besoin d'un bot pour réfléchir et exécuter des flux de travail interactifs.
En intégrant Stagehand, les agents Sim peuvent automatiser la collecte de données, l'analyse et l'exécution de flux de travail sur le web : mise à jour de bases de données, organisation d'informations et génération de rapports personnalisés — de manière transparente et autonome.
{/* MANUAL-CONTENT-END */}
## Instructions d'utilisation
Intégrez Stagehand dans le flux de travail. Peut extraire des données structurées à partir de pages web. Nécessite une clé API.
Intégrez Stagehand dans le flux de travail. Peut extraire des données structurées à partir de pages web ou exécuter un agent autonome pour effectuer des tâches.
## Outils
@@ -35,17 +42,40 @@ Extraire des données structurées d'une page web en utilisant Stagehand
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ---------- | ----------- |
| `url` | string | Oui | URL de la page web à partir de laquelle extraire des données |
| `instruction` | string | Oui | Instructions pour l'extraction |
| `apiKey` | string | Oui | Clé API OpenAI pour l'extraction \(requise par Stagehand\) |
| --------- | ---- | -------- | ----------- |
| `url` | chaîne | Oui | URL de la page web à partir de laquelle extraire les données |
| `instruction` | chaîne | Oui | Instructions pour l'extraction |
| `provider` | chaîne | Non | Fournisseur d'IA à utiliser : openai ou anthropic |
| `apiKey` | chaîne | Oui | Clé API pour le fournisseur sélectionné |
| `schema` | json | Oui | Schéma JSON définissant la structure des données à extraire |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `data` | object | Données structurées extraites correspondant au schéma fourni |
| `data` | objet | Données structurées extraites correspondant au schéma fourni |
### `stagehand_agent`
Exécuter un agent web autonome pour accomplir des tâches et extraire des données structurées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| `startUrl` | chaîne | Oui | URL de la page web sur laquelle démarrer l'agent |
| `task` | chaîne | Oui | La tâche à accomplir ou l'objectif à atteindre sur le site web |
| `variables` | json | Non | Variables optionnelles à substituer dans la tâche (format : \{key: value\}). Référence dans la tâche en utilisant %key% |
| `format` | chaîne | Non | Pas de description |
| `provider` | chaîne | Non | Fournisseur d'IA à utiliser : openai ou anthropic |
| `apiKey` | chaîne | Oui | Clé API pour le fournisseur sélectionné |
| `outputSchema` | json | Non | Schéma JSON optionnel définissant la structure des données que l'agent doit renvoyer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `agentResult` | object | Résultat de l'exécution de l'agent Stagehand |
## Notes

View File

@@ -1,59 +0,0 @@
---
title: Agent Stagehand
description: Agent de navigation web autonome
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="stagehand_agent"
color="#FFC83C"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://www.stagehand.dev/) est une plateforme d'agent web autonome qui permet aux systèmes d'IA de naviguer et d'interagir avec des sites web comme le ferait un humain. Elle offre une solution puissante pour automatiser des tâches web complexes sans nécessiter de code personnalisé ou de scripts d'automatisation de navigateur.
Avec Stagehand, vous pouvez :
- **Automatiser la navigation web** : permettre à l'IA de parcourir des sites web, cliquer sur des liens, remplir des formulaires et interagir avec des éléments web
- **Extraire des données structurées** : collecter des informations spécifiques à partir de sites web dans un format structuré et utilisable
- **Réaliser des flux de travail complexes** : effectuer des tâches en plusieurs étapes sur différents sites web et applications web
- **Gérer l'authentification** : naviguer dans les processus de connexion et maintenir les sessions sur les sites web
- **Traiter du contenu dynamique** : interagir avec des sites à forte composante JavaScript et des applications à page unique
- **Maintenir une conscience contextuelle** : suivre l'état actuel et l'historique pendant la navigation
- **Générer des rapports détaillés** : recevoir des journaux complets des actions entreprises et des données collectées
Dans Sim, l'intégration de Stagehand permet à vos agents d'interagir de manière transparente avec des systèmes basés sur le web dans le cadre de leurs flux de travail. Cela permet des scénarios d'automatisation sophistiqués qui comblent le fossé entre vos agents d'IA et la vaste quantité d'informations et de fonctionnalités disponibles sur le web. Vos agents peuvent rechercher des informations, interagir avec des applications web, extraire des données de sites web et intégrer ces capacités dans leurs processus de prise de décision. En connectant Sim avec Stagehand, vous pouvez créer des agents qui vont au-delà des intégrations basées sur API pour naviguer sur le web comme le ferait un humain - remplir des formulaires, cliquer sur des boutons, lire du contenu et extraire des informations précieuses pour accomplir leurs tâches plus efficacement.
{/* MANUAL-CONTENT-END */}
## Instructions d'utilisation
Intégrez l'agent Stagehand dans le flux de travail. Peut naviguer sur le web et effectuer des tâches. Nécessite une clé API.
## Outils
### `stagehand_agent`
Exécuter un agent web autonome pour accomplir des tâches et extraire des données structurées
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ----------- | ----------- |
| `startUrl` | string | Oui | URL de la page web sur laquelle démarrer l'agent |
| `task` | string | Oui | La tâche à accomplir ou l'objectif à atteindre sur le site web |
| `variables` | json | Non | Variables optionnelles à substituer dans la tâche \(format : \{key: value\}\). Référencez dans la tâche en utilisant %key% |
| `format` | string | Non | Pas de description |
| `apiKey` | string | Oui | Clé API OpenAI pour l'exécution de l'agent \(requise par Stagehand\) |
| `outputSchema` | json | Non | Schéma JSON optionnel définissant la structure des données que l'agent doit renvoyer |
#### Sortie
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `agentResult` | object | Résultat de l'exécution de l'agent Stagehand |
## Remarques
- Catégorie : `tools`
- Type : `stagehand_agent`

View File

@@ -45,10 +45,8 @@ Lister toutes les listes d'un tableau Trello
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Si l'opération a réussi |
| `lists` | array | Tableau d'objets liste avec id, nom, fermé, position et idTableau |
| `lists` | array | Tableau d'objets liste avec id, name, closed, pos et idBoard |
| `count` | number | Nombre de listes retournées |
| `error` | string | Message d'erreur si l'opération a échoué |
### `trello_list_cards`
@@ -65,10 +63,8 @@ Lister toutes les cartes d'un tableau Trello
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Si l'opération a réussi |
| `cards` | array | Tableau d'objets carte avec id, nom, description, url, IDs du tableau/liste, étiquettes et date d'échéance |
| `cards` | array | Tableau d'objets carte avec id, name, desc, url, IDs de tableau/liste, étiquettes et date d'échéance |
| `count` | number | Nombre de cartes retournées |
| `error` | string | Message d'erreur si l'opération a échoué |
### `trello_create_card`
@@ -90,9 +86,7 @@ Créer une nouvelle carte sur un tableau Trello
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | booléen | Indique si la carte a été créée avec succès |
| `card` | objet | L'objet carte créé avec id, nom, description, url et autres propriétés |
| `error` | chaîne | Message d'erreur si l'opération a échoué |
| `card` | object | L'objet carte créé avec id, name, desc, url et autres propriétés |
### `trello_update_card`
@@ -114,9 +108,7 @@ Mettre à jour une carte existante sur Trello
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | booléen | Indique si la carte a été mise à jour avec succès |
| `card` | objet | L'objet carte mis à jour avec id, nom, description, url et autres propriétés |
| `error` | chaîne | Message d'erreur si l'opération a échoué |
| `card` | object | L'objet carte mis à jour avec id, name, desc, url et autres propriétés |
### `trello_get_actions`
@@ -135,10 +127,8 @@ Obtenir l'activité/les actions d'un tableau ou d'une carte
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Indique si l'opération a réussi |
| `actions` | array | Tableau d'objets d'action avec type, date, membre et données |
| `actions` | array | Tableau d'objets action avec type, date, member et data |
| `count` | number | Nombre d'actions retournées |
| `error` | string | Message d'erreur si l'opération a échoué |
### `trello_add_comment`
@@ -155,9 +145,7 @@ Ajouter un commentaire à une carte Trello
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Indique si le commentaire a été ajouté avec succès |
| `comment` | object | L'objet commentaire créé avec id, texte, date et membre créateur |
| `error` | string | Message d'erreur si l'opération a échoué |
| `comment` | object | L'objet commentaire créé avec id, text, date et member creator |
## Notes

View File

@@ -38,7 +38,8 @@ Lister tous les éléments d'une collection CMS Webflow
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| --------- | ---- | ---------- | ----------- |
| `siteId` | string | Oui | ID du site Webflow |
| `collectionId` | string | Oui | ID de la collection |
| `offset` | number | Non | Décalage pour la pagination \(facultatif\) |
| `limit` | number | Non | Nombre maximum d'éléments à retourner \(facultatif, par défaut : 100\) |
@@ -57,7 +58,8 @@ Obtenir un seul élément d'une collection CMS Webflow
#### Entrée
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | -------- | ----------- |
| --------- | ---- | ---------- | ----------- |
| `siteId` | string | Oui | ID du site Webflow |
| `collectionId` | string | Oui | ID de la collection |
| `itemId` | string | Oui | ID de l'élément à récupérer |
@@ -76,8 +78,9 @@ Créer un nouvel élément dans une collection CMS Webflow
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ---------- | ----------- |
| `siteId` | string | Oui | ID du site Webflow |
| `collectionId` | string | Oui | ID de la collection |
| `fieldData` | json | Oui | Données de champ pour le nouvel élément sous forme d'objet JSON. Les clés doivent correspondre aux noms des champs de la collection. |
| `fieldData` | json | Oui | Données des champs pour le nouvel élément sous forme d'objet JSON. Les clés doivent correspondre aux noms des champs de la collection. |
#### Sortie
@@ -94,9 +97,10 @@ Mettre à jour un élément existant dans une collection CMS Webflow
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ---------- | ----------- |
| `siteId` | string | Oui | ID du site Webflow |
| `collectionId` | string | Oui | ID de la collection |
| `itemId` | string | Oui | ID de l'élément à mettre à jour |
| `fieldData` | json | Oui | Données de champ à mettre à jour sous forme d'objet JSON. N'incluez que les champs que vous souhaitez modifier. |
| `fieldData` | json | Oui | Données des champs à mettre à jour sous forme d'objet JSON. N'incluez que les champs que vous souhaitez modifier. |
#### Sortie
@@ -113,6 +117,7 @@ Supprimer un élément d'une collection CMS Webflow
| Paramètre | Type | Obligatoire | Description |
| --------- | ---- | ---------- | ----------- |
| `siteId` | string | Oui | ID du site Webflow |
| `collectionId` | string | Oui | ID de la collection |
| `itemId` | string | Oui | ID de l'élément à supprimer |

View File

@@ -94,10 +94,7 @@ Récupérer le contexte utilisateur d'un fil de discussion en mode résumé ou b
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `context` | string | La chaîne de contexte \(résumé ou basique\) |
| `facts` | array | Faits extraits |
| `entities` | array | Entités extraites |
| `summary` | string | Résumé de la conversation |
| `context` | string | La chaîne de contexte \(mode résumé ou basique\) |
### `zep_get_messages`
@@ -137,9 +134,9 @@ Ajouter des messages à un fil de discussion existant
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `context` | chaîne | Contexte mis à jour après l'ajout des messages |
| `messageIds` | tableau | Tableau des UUID des messages ajoutés |
| `threadId` | chaîne | L'ID du fil de discussion |
| `threadId` | string | L'ID du fil de discussion |
| `added` | boolean | Si les messages ont été ajoutés avec succès |
| `messageIds` | array | Tableau des UUID des messages ajoutés |
### `zep_add_user`
@@ -208,8 +205,8 @@ Lister tous les fils de conversation pour un utilisateur spécifique
| Paramètre | Type | Description |
| --------- | ---- | ----------- |
| `threads` | tableau | Tableau d'objets de fils pour cet utilisateur |
| `userId` | chaîne | L'ID de l'utilisateur |
| `threads` | array | Tableau d'objets de fil de discussion pour cet utilisateur |
| `totalCount` | number | Nombre total de fils de discussion retournés |
## Notes

View File

@@ -321,9 +321,9 @@ UIDによるアラートルールの削除
| `organizationId` | string | いいえ | マルチ組織Grafanaインスタンス用の組織ID |
| `text` | string | はい | アノテーションのテキスト内容 |
| `tags` | string | いいえ | カンマ区切りのタグリスト |
| `dashboardUid` | string | いいえ | アテーションを追加するダッシュボードのUID(全体的なアノテーションの場合はオプション) |
| `dashboardUid` | string | い | アテーションを追加するダッシュボードのUID |
| `panelId` | number | いいえ | アテーションを追加するパネルのID |
| `time` | number | いいえ | エポックミリ秒での開始時間(デフォルトは現在) |
| `time` | number | いいえ | エポックミリ秒での開始時間(デフォルトは現在時刻 |
| `timeEnd` | number | いいえ | エポックミリ秒での終了時間(範囲アノテーション用) |
#### 出力
@@ -346,10 +346,10 @@ UIDによるアラートルールの削除
| `organizationId` | string | いいえ | マルチ組織Grafanaインスタンス用の組織ID |
| `from` | number | いいえ | エポックミリ秒での開始時間 |
| `to` | number | いいえ | エポックミリ秒での終了時間 |
| `dashboardUid` | string | いいえ | ダッシュボードUIDでフィルタリング |
| `dashboardUid` | string | はい | アノテーションを取得するダッシュボードUID |
| `panelId` | number | いいえ | パネルIDでフィルタリング |
| `tags` | string | いいえ | フィルタリングするタグのカンマ区切りリスト |
| `type` | string | いいえ | タイプでフィルタリング(アラートまたはアノテーション |
| `type` | string | いいえ | タイプでフィルタリング(alertまたはannotation |
| `limit` | number | いいえ | 返すアノテーションの最大数 |
#### 出力
@@ -487,6 +487,16 @@ Grafanaに新しいフォルダを作成
| `uid` | string | 作成されたフォルダのUID |
| `title` | string | 作成されたフォルダのタイトル |
| `url` | string | フォルダへのURLパス |
| `hasAcl` | boolean | フォルダがカスタムACL権限を持っているかどうか |
| `canSave` | boolean | 現在のユーザーがフォルダを保存できるかどうか |
| `canEdit` | boolean | 現在のユーザーがフォルダを編集できるかどうか |
| `canAdmin` | boolean | 現在のユーザーがフォルダに対して管理者権限を持っているかどうか |
| `canDelete` | boolean | 現在のユーザーがフォルダを削除できるかどうか |
| `createdBy` | string | フォルダを作成したユーザーのユーザー名 |
| `created` | string | フォルダが作成されたときのタイムスタンプ |
| `updatedBy` | string | フォルダを最後に更新したユーザーのユーザー名 |
| `updated` | string | フォルダが最後に更新されたときのタイムスタンプ |
| `version` | number | フォルダのバージョン番号 |
## メモ

View File

@@ -1,806 +0,0 @@
---
title: Pylon
description: Pylonでカスタマーサポートの問題、アカウント、連絡先、ユーザー、チーム、タグを管理する
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="pylon"
color="#E8F4FA"
/>
{/* MANUAL-CONTENT-START:intro */}
[Pylon](https://usepylon.com/)は、カスタマーサポートの問題からアカウント、連絡先、ユーザー、チームなど、顧客関係のあらゆる側面を管理するために設計された高度なカスタマーサポートおよび成功プラットフォームです。Pylonは豊富なAPIと包括的なツールセットを備え、サポートおよび成功チームが効率的かつプログラム的に運営できるよう支援します。
SimでPylonを使用すると、以下のことが可能です
- **サポート問題の管理:**
- 効率的なケース追跡のために、サポート問題の一覧表示、作成、取得、更新、削除ができます。
- エージェントが集中して整理できるよう、問題の検索やスヌーズ機能を利用できます。
- 内部および外部の関係者とのシームレスな連携のために、問題のフォロワーや外部問題を処理できます。
- **完全なアカウント管理:**
- 顧客アカウントの一覧表示、作成、取得、更新、削除ができます。
- プログラムによるアカウントの一括更新が可能です。
- サポートやアウトリーチに関連する顧客情報をすばやく見つけるためのアカウント検索ができます。
- **連絡先管理:**
- アカウントに関連するすべての人を管理するための連絡先の一覧表示、作成、取得、更新、削除、検索ができます。
- **ユーザーとチームの操作:**
- Pylonワークスペース内のユーザーの一覧表示、取得、更新、検索ができます。
- サポート組織とワークフローを構築するためのチームの一覧表示、作成、取得、更新ができます。
- **タグ付けと整理:**
- 問題、アカウント、または連絡先を分類するためのタグの一覧表示、取得、作成、更新、削除ができます。
- **メッセージ処理:**
- プライバシーとコンプライアンスのために、ワークフローから直接機密メッセージ内容を編集できます。
PylonツールをSimに統合することで、エージェントはサポート業務のあらゆる側面を自動化できます
- 顧客イベントが発生した際に、新しい問題を自動的に開いたり、更新したり、トリアージしたりできます。
- テクノロジースタック全体でアカウントと連絡先データを同期させて維持できます。
- タグとチームを使用して会話のルーティング、エスカレーションの処理、サポートデータの整理ができます。
- 必要に応じてメッセージを編集することで、機密データが適切に管理されるようにします。
Pylonのエンドポイントは、顧客の問題と関係の全ライフサイクル管理のための詳細な制御を提供します。サポートデスクの拡張、積極的な顧客成功の推進、または他のシステムとの統合など、Sim内のPylonは、安全に、柔軟に、そして大規模に、最高クラスのCRM自動化を実現します。
{/* MANUAL-CONTENT-END */}
## 使用方法
Pylonをワークフローに統合します。問題一覧表示、作成、取得、更新、削除、検索、スヌーズ、フォロワー、外部問題、アカウント一覧表示、作成、取得、更新、削除、一括更新、検索、連絡先一覧表示、作成、取得、更新、削除、検索、ユーザー一覧表示、取得、更新、検索、チーム一覧表示、取得、作成、更新、タグ一覧表示、取得、作成、更新、削除、およびメッセージ編集を管理します。
## ツール
### `pylon_list_issues`
指定された時間範囲内の問題のリストを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `startTime` | string | はい | RFC3339形式の開始時間2024-01-01T00:00:00Z |
| `endTime` | string | はい | RFC3339形式の終了時間2024-01-31T23:59:59Z |
| `cursor` | string | いいえ | 結果の次のページのページネーションカーソル |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 問題のリスト |
### `pylon_create_issue`
指定されたプロパティで新しい問題を作成する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `title` | string | はい | 課題のタイトル |
| `bodyHtml` | string | はい | HTML形式の課題本文 |
| `accountId` | string | いいえ | 課題に関連付けるアカウントID |
| `assigneeId` | string | いいえ | 課題を割り当てるユーザーID |
| `teamId` | string | いいえ | 課題を割り当てるチームID |
| `requesterId` | string | いいえ | 要求者ユーザーIDrequester_emailの代替 |
| `requesterEmail` | string | いいえ | 要求者のメールアドレスrequester_idの代替 |
| `priority` | string | いいえ | 課題の優先度 |
| `tags` | string | いいえ | カンマ区切りのタグID |
| `customFields` | string | いいえ | JSONオブジェクトとしてのカスタムフィールド |
| `attachmentUrls` | string | いいえ | カンマ区切りの添付ファイルURL |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 作成された課題データ |
### `pylon_get_issue`
IDで特定の課題を取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `issueId` | string | はい | 取得する課題のID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 課題データ |
### `pylon_update_issue`
既存の課題を更新する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `issueId` | string | はい | 更新する課題のID |
| `state` | string | いいえ | 課題の状態 |
| `assigneeId` | string | いいえ | 課題を割り当てるユーザーID |
| `teamId` | string | いいえ | 課題を割り当てるチームID |
| `tags` | string | いいえ | カンマ区切りのタグID |
| `customFields` | string | いいえ | JSONオブジェクトとしてのカスタムフィールド |
| `customerPortalVisible` | boolean | いいえ | 課題がカスタマーポータルで表示されるかどうか |
| `requesterId` | string | いいえ | 要求者ユーザーID |
| `accountId` | string | いいえ | 課題に関連付けるアカウントID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 更新された課題データ |
### `pylon_delete_issue`
IDで課題を削除する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `issueId` | string | はい | 削除する課題のID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 削除結果 |
### `pylon_search_issues`
フィルターを使用して課題を検索する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `filter` | string | はい | JSON文字列としてのフィルター条件 |
| `cursor` | string | いいえ | 次のページの結果のためのページネーションカーソル |
| `limit` | number | いいえ | 返す結果の最大数 |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 検索結果 |
### `pylon_snooze_issue`
指定した時間まで課題の表示を延期する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `issueId` | string | はい | スヌーズする課題のID |
| `snoozeUntil` | string | はい | 課題が再表示されるべきRFC3339タイムスタンプ2024-01-01T00:00:00Z |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | スヌーズされた課題データ |
### `pylon_list_issue_followers`
特定の課題のフォロワーリストを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `issueId` | string | はい | 課題のID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | フォロワーリスト |
### `pylon_manage_issue_followers`
課題にフォロワーを追加または削除する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `issueId` | string | はい | 課題のID |
| `userIds` | string | いいえ | 追加/削除するユーザーIDのカンマ区切りリスト |
| `contactIds` | string | いいえ | 追加/削除する連絡先IDのカンマ区切りリスト |
| `operation` | string | いいえ | 実行する操作:"add"(追加)または"remove"(削除)(デフォルト:"add" |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 更新されたフォロワーリスト |
### `pylon_link_external_issue`
課題を外部システムの課題にリンクする
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `issueId` | string | はい | Pylon課題のID |
| `externalIssueId` | string | はい | 外部課題のID |
| `source` | string | はい | ソースシステム(例:"jira"、"linear"、"github" |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | リンクされた外部課題データ |
### `pylon_list_accounts`
アカウントのページ分割リストを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `limit` | string | いいえ | 返すアカウント数1-1000、デフォルト100 |
| `cursor` | string | いいえ | 次のページの結果のためのページネーションカーソル |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | アカウントのリスト |
### `pylon_create_account`
指定されたプロパティで新しいアカウントを作成する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `name` | string | はい | アカウント名 |
| `domains` | string | いいえ | カンマ区切りのドメインリスト |
| `primaryDomain` | string | いいえ | アカウントのプライマリドメイン |
| `customFields` | string | いいえ | JSONオブジェクトとしてのカスタムフィールド |
| `tags` | string | いいえ | カンマ区切りのタグID |
| `channels` | string | いいえ | カンマ区切りのチャネルID |
| `externalIds` | string | いいえ | カンマ区切りの外部ID |
| `ownerId` | string | いいえ | オーナーユーザーID |
| `logoUrl` | string | いいえ | アカウントロゴのURL |
| `subaccountIds` | string | いいえ | カンマ区切りのサブアカウントID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 作成されたアカウントデータ |
### `pylon_get_account`
IDで単一のアカウントを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `accountId` | string | はい | 取得するアカウントID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | アカウントデータ |
### `pylon_update_account`
既存のアカウントを新しいプロパティで更新する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `accountId` | string | はい | 更新するアカウントID |
| `name` | string | いいえ | アカウント名 |
| `domains` | string | いいえ | カンマ区切りのドメインリスト |
| `primaryDomain` | string | いいえ | アカウントのプライマリドメイン |
| `customFields` | string | いいえ | JSONオブジェクトとしてのカスタムフィールド |
| `tags` | string | いいえ | カンマ区切りのタグID |
| `channels` | string | いいえ | カンマ区切りのチャネルID |
| `externalIds` | string | いいえ | カンマ区切りの外部ID |
| `ownerId` | string | いいえ | オーナーユーザーID |
| `logoUrl` | string | いいえ | アカウントロゴのURL |
| `subaccountIds` | string | いいえ | カンマ区切りのサブアカウントID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 更新されたアカウントデータ |
### `pylon_delete_account`
IDによるアカウントの削除
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `accountId` | string | はい | 削除するアカウントID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 削除確認 |
### `pylon_bulk_update_accounts`
複数のアカウントを一度に更新
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `accountIds` | string | はい | 更新するアカウントIDのカンマ区切りリスト |
| `customFields` | string | いいえ | JSONオブジェクトとしてのカスタムフィールド |
| `tags` | string | いいえ | カンマ区切りのタグID |
| `ownerId` | string | いいえ | オーナーユーザーID |
| `tagsApplyMode` | string | いいえ | タグ適用モード: append_only、remove_only、またはreplace |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 一括更新されたアカウントデータ |
### `pylon_search_accounts`
カスタムフィルターでアカウントを検索
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `filter` | string | はい | フィールド/演算子/値構造を持つJSONフィルター文字列 |
| `limit` | string | いいえ | 返すアカウント数1-1000、デフォルト100 |
| `cursor` | string | いいえ | 次のページの結果用のページネーションカーソル |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 検索結果 |
### `pylon_list_contacts`
連絡先リストの取得
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `cursor` | string | いいえ | 次のページの結果用のページネーションカーソル |
| `limit` | string | いいえ | 返す連絡先の最大数 |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 連絡先リスト |
### `pylon_create_contact`
指定されたプロパティで新しい連絡先を作成
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `name` | string | はい | 連絡先名 |
| `email` | string | いいえ | 連絡先のメールアドレス |
| `accountId` | string | いいえ | 連絡先に関連付けるアカウントID |
| `accountExternalId` | string | いいえ | 連絡先に関連付ける外部アカウントID |
| `avatarUrl` | string | いいえ | 連絡先のアバター画像のURL |
| `customFields` | string | いいえ | JSONオブジェクトとしてのカスタムフィールド |
| `portalRole` | string | いいえ | 連絡先のポータルロール |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 作成された連絡先データ |
### `pylon_get_contact`
IDで特定の連絡先を取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `contactId` | string | はい | 取得する連絡先ID |
| `cursor` | string | いいえ | 次のページの結果のためのページネーションカーソル |
| `limit` | string | いいえ | 返す項目の最大数 |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 連絡先データ |
### `pylon_update_contact`
指定されたプロパティで既存の連絡先を更新する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `contactId` | string | はい | 更新する連絡先ID |
| `name` | string | いいえ | 連絡先名 |
| `email` | string | いいえ | 連絡先のメールアドレス |
| `accountId` | string | いいえ | 連絡先に関連付けるアカウントID |
| `accountExternalId` | string | いいえ | 連絡先に関連付ける外部アカウントID |
| `avatarUrl` | string | いいえ | 連絡先のアバター画像のURL |
| `customFields` | string | いいえ | JSONオブジェクトとしてのカスタムフィールド |
| `portalRole` | string | いいえ | 連絡先のポータルロール |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 更新された連絡先データ |
### `pylon_delete_contact`
IDで特定の連絡先を削除する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `contactId` | string | はい | 削除する連絡先ID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 削除操作の結果 |
### `pylon_search_contacts`
フィルターを使用して連絡先を検索する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `filter` | string | はい | JSONオブジェクトとしてのフィルター |
| `limit` | string | いいえ | 返す連絡先の最大数 |
| `cursor` | string | いいえ | 次のページの結果のためのページネーションカーソル |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 検索結果 |
### `pylon_list_users`
ユーザーリストを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | ユーザーリスト |
### `pylon_get_user`
IDで特定のユーザーを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `userId` | string | はい | 取得するユーザーID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | ユーザーデータ |
### `pylon_update_user`
指定されたプロパティで既存のユーザーを更新する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `userId` | string | はい | 更新するユーザーID |
| `roleId` | string | いいえ | ユーザーに割り当てるロールID |
| `status` | string | いいえ | ユーザーステータス |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 更新されたユーザーデータ |
### `pylon_search_users`
メールフィールドを使用したフィルターでユーザーを検索する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `filter` | string | はい | メールフィールドを含むJSONオブジェクトとしてのフィルター |
| `cursor` | string | いいえ | 次のページの結果のためのページネーションカーソル |
| `limit` | string | いいえ | 返すユーザーの最大数 |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 検索結果 |
### `pylon_list_teams`
チームのリストを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | チームのリスト |
### `pylon_get_team`
IDで特定のチームを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `teamId` | string | はい | 取得するチームID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | チームデータ |
### `pylon_create_team`
指定されたプロパティで新しいチームを作成する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `name` | string | いいえ | チーム名 |
| `userIds` | string | いいえ | チームメンバーとして追加するユーザーIDのカンマ区切りリスト |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 作成されたチームデータ |
### `pylon_update_team`
指定されたプロパティで既存のチームを更新しますuserIdsはメンバーシップ全体を置き換えます
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `teamId` | string | はい | 更新するチームID |
| `name` | string | いいえ | チーム名 |
| `userIds` | string | いいえ | カンマ区切りのユーザーIDチームメンバーシップ全体を置き換えます |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 更新されたチームデータ |
### `pylon_list_tags`
タグのリストを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | タグのリスト |
### `pylon_get_tag`
IDで特定のタグを取得する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `tagId` | string | はい | 取得するタグID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | タグデータ |
### `pylon_create_tag`
指定されたプロパティで新しいタグを作成しますobjectType: account/issue/contact
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `objectType` | string | はい | タグのオブジェクトタイプaccount、issue、またはcontact |
| `value` | string | はい | タグの値/名前 |
| `hexColor` | string | いいえ | タグの16進カラーコード#FF5733 |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 作成されたタグデータ |
### `pylon_update_tag`
指定されたプロパティで既存のタグを更新します
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `tagId` | string | はい | 更新するタグID |
| `hexColor` | string | いいえ | タグの16進カラーコード#FF5733 |
| `value` | string | いいえ | タグの値/名前 |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 更新されたタグデータ |
### `pylon_delete_tag`
IDで特定のタグを削除する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `tagId` | string | はい | 削除するタグID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 削除操作の結果 |
### `pylon_redact_message`
問題内の特定のメッセージを編集する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | はい | Pylon APIトークン |
| `issueId` | string | はい | メッセージを含む問題ID |
| `messageId` | string | はい | 編集するメッセージID |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功ステータス |
| `output` | object | 編集操作の結果 |
## 注意事項
- カテゴリー: `tools`
- タイプ: `pylon`

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
---
title: Stagehand Extract
description: Extract data from websites
title: Stagehand
description: Webの自動化とデータ抽出
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
@@ -11,43 +11,73 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://stagehand.com) is a tool that allows you to extract structured data from webpages using Browserbase and OpenAI.
[Stagehand](https://stagehand.com)は、BrowserbaseとモダンなLLMOpenAIまたはAnthropicを使用して、Webページからの構造化データの抽出と自律的なWeb自動化の両方を可能にするツールです。
With Stagehand, you can:
StagehandはSimで2つの主要な機能を提供します
- **Extract structured data**: Extract structured data from webpages using Browserbase and OpenAI
- **Save data to a database**: Save the extracted data to a database
- **Automate workflows**: Automate workflows to extract data from webpages
- **stagehand_extract**: 単一のWebページから構造化データを抽出します。必要なものスキーマを指定すると、AIがページからその形式でデータを取得して解析します。これは、必要な情報とその取得場所を正確に把握している場合に、リスト、フィールド、またはオブジェクトを抽出するのに最適です。
In Sim, the Stagehand integration enables your agents to extract structured data from webpages using Browserbase and OpenAI. This allows for powerful automation scenarios such as data extraction, data analysis, and data integration. Your agents can extract structured data from webpages, save the extracted data to a database, and automate workflows to extract data from webpages. This integration bridges the gap between your AI workflows and your data management system, enabling seamless data extraction and integration. By connecting Sim with Stagehand, you can automate data extraction processes, maintain up-to-date information repositories, generate reports, and organize information intelligently - all through your intelligent agents.
- **stagehand_agent**: 複数ステップのタスクを完了し、要素と対話し、ページ間を移動し、構造化された結果を返すことができる自律型Webエージェントを実行します。これははるかに柔軟で、エージェントはログイン、検索、フォーム入力、複数の場所からのデータ収集、要求されたスキーマに従った最終結果の出力などを行うことができます。
**主な違い:**
- *stagehand_extract*は迅速な“このページからこのデータを抽出する”操作です。直接的な一段階の抽出タスクに最適です。
- *stagehand_agent*はWeb上で複雑な複数ステップの自律的なタスクナビゲーション、検索、さらには取引などを実行し、指示とオプションのスキーマに従って動的にデータを抽出できます。
実際には、何が欲しいのかとその場所を知っている場合は**stagehand_extract**を使用し、インタラクティブなワークフローを考え実行するボットが必要な場合は**stagehand_agent**を使用します。
Stagehandを統合することで、Simエージェントはデータ収集、分析、Web上でのワークフロー実行を自動化できますデータベースの更新、情報の整理、カスタムレポートの生成を、シームレスかつ自律的に行います。
{/* MANUAL-CONTENT-END */}
## Usage Instructions
## 使用方法
Integrate Stagehand into the workflow. Can extract structured data from webpages.
Stagehandをワークフローに統合します。ウェブページから構造化データを抽出したり、タスクを実行する自律型エージェントを実行したりできます。
## Tools
## ツール
### `stagehand_extract`
Extract structured data from a webpage using Stagehand
Stagehandを使用してウェブページから構造化データを抽出する
#### Input
#### 入力
| Parameter | Type | Required | Description |
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `url` | string | Yes | URL of the webpage to extract data from |
| `instruction` | string | Yes | Instructions for extraction |
| `apiKey` | string | Yes | OpenAI API key for extraction \(required by Stagehand\) |
| `schema` | json | Yes | JSON schema defining the structure of the data to extract |
| `url` | string | はい | データを抽出するウェブページのURL |
| `instruction` | string | はい | 抽出のための指示 |
| `provider` | string | いいえ | 使用するAIプロバイダーopenaiまたはanthropic |
| `apiKey` | string | はい | 選択したプロバイダーのAPIキー |
| `schema` | json | はい | 抽出するデータの構造を定義するJSONスキーマ |
#### Output
#### 出力
| Parameter | Type | Description |
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `data` | object | Extracted structured data matching the provided schema |
| `data` | object | 提供されたスキーマに一致する抽出された構造化データ |
## Notes
### `stagehand_agent`
- Category: `tools`
- Type: `stagehand`
タスクを完了し構造化データを抽出するための自律型ウェブエージェントを実行する
#### 入力
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | はい | エージェントを開始するウェブページのURL |
| `task` | string | はい | ウェブサイトで完了するタスクまたは達成する目標 |
| `variables` | json | いいえ | タスクで置き換えるオプションの変数(形式:\{key: value\})。タスク内で%key%を使用して参照 |
| `format` | string | いいえ | 説明なし |
| `provider` | string | いいえ | 使用するAIプロバイダーopenaiまたはanthropic |
| `apiKey` | string | はい | 選択したプロバイダーのAPIキー |
| `outputSchema` | json | いいえ | エージェントが返すべきデータの構造を定義するオプションのJSONスキーマ |
#### 出力
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `agentResult` | object | Stagehandエージェント実行からの結果 |
## 注意事項
- カテゴリー: `tools`
- タイプ: `stagehand`

View File

@@ -1,59 +0,0 @@
---
title: Stagehand Agent
description: Autonomous web browsing agent
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="stagehand_agent"
color="#FFC83C"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://www.stagehand.dev/) is an autonomous web agent platform that enables AI systems to navigate and interact with websites just like a human would. It provides a powerful solution for automating complex web tasks without requiring custom code or browser automation scripts.
With Stagehand, you can:
- **Automate web navigation**: Enable AI to browse websites, click links, fill forms, and interact with web elements
- **Extract structured data**: Collect specific information from websites in a structured, usable format
- **Complete complex workflows**: Perform multi-step tasks across different websites and web applications
- **Handle authentication**: Navigate login processes and maintain sessions across websites
- **Process dynamic content**: Interact with JavaScript-heavy sites and single-page applications
- **Maintain context awareness**: Keep track of the current state and history while navigating
- **Generate detailed reports**: Receive comprehensive logs of actions taken and data collected
In Sim, the Stagehand integration enables your agents to seamlessly interact with web-based systems as part of their workflows. This allows for sophisticated automation scenarios that bridge the gap between your AI agents and the vast information and functionality available on the web. Your agents can search for information, interact with web applications, extract data from websites, and incorporate these capabilities into their decision-making processes. By connecting Sim with Stagehand, you can create agents that extend beyond API-based integrations to navigate the web just as a human would - filling forms, clicking buttons, reading content, and extracting valuable information to complete their tasks more effectively.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
Integrate Stagehand Agent into the workflow. Can navigate the web and perform tasks.
## Tools
### `stagehand_agent`
Run an autonomous web agent to complete tasks and extract structured data
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | Yes | URL of the webpage to start the agent on |
| `task` | string | Yes | The task to complete or goal to achieve on the website |
| `variables` | json | No | Optional variables to substitute in the task \(format: \{key: value\}\). Reference in task using %key% |
| `format` | string | No | No description |
| `apiKey` | string | Yes | OpenAI API key for agent execution \(required by Stagehand\) |
| `outputSchema` | json | No | Optional JSON schema defining the structure of data the agent should return |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `agentResult` | object | Result from the Stagehand agent execution |
## Notes
- Category: `tools`
- Type: `stagehand_agent`

View File

@@ -45,10 +45,8 @@ Trelloボード上のすべてのリストを表示する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作が成功したかどうか |
| `lists` | array | id、name、closed、pos、idBoardを含むリストオブジェクトの配列 |
| `count` | number | 返されたリストの数 |
| `error` | string | 操作が失敗した場合のエラーメッセージ |
### `trello_list_cards`
@@ -65,10 +63,8 @@ Trelloボード上のすべてのカードを表示する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作が成功したかどうか |
| `cards` | array | id、name、desc、url、ボード/リストID、ラベル、期限日を含むカードオブジェクトの配列 |
| `count` | number | 返されたカードの数 |
| `error` | string | 操作が失敗した場合のエラーメッセージ |
### `trello_create_card`
@@ -90,9 +86,7 @@ Trelloボードに新しいカードを作成する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | カードが正常に作成されたかどうか |
| `card` | object | 作成されたカードオブジェクトid、name、desc、url、その他のプロパティを含む |
| `error` | string | 操作が失敗した場合のエラーメッセージ |
| `card` | object | id、name、desc、urlなどのプロパティを含む作成されたカードオブジェクト |
### `trello_update_card`
@@ -114,9 +108,7 @@ Trelloの既存のカードを更新する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | カードが正常に更新されたかどうか |
| `card` | object | 更新されたカードオブジェクトid、name、desc、url、その他のプロパティを含む |
| `error` | string | 操作が失敗した場合のエラーメッセージ |
| `card` | object | id、name、desc、urlなどのプロパティを含む更新されたカードオブジェクト |
### `trello_get_actions`
@@ -135,10 +127,8 @@ Trelloの既存のカードを更新する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作が成功したかどうか |
| `actions` | array | タイプ、日付、メンバー、データを含むアクションオブジェクトの配列 |
| `actions` | array | type、date、member、dataを含むアクションオブジェクトの配列 |
| `count` | number | 返されたアクションの数 |
| `error` | string | 操作が失敗した場合のエラーメッセージ |
### `trello_add_comment`
@@ -155,9 +145,7 @@ Trelloカードにコメントを追加する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `success` | boolean | コメントが正常に追加されたかどうか |
| `comment` | object | ID、テキスト、日付、作成者メンバーを含む作成されたコメントオブジェクト |
| `error` | string | 操作が失敗した場合のエラーメッセージ |
| `comment` | object | id、text、date、member creatorを含む作成されたコメントオブジェクト |
## 注意事項

View File

@@ -39,9 +39,10 @@ Webflow CMSコレクションからすべてのアイテムを一覧表示する
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | はい | WebflowサイトのID |
| `collectionId` | string | はい | コレクションのID |
| `offset` | number | いいえ | ページネーション用のオフセット(オプション) |
| `limit` | number | いいえ | 返すアイテムの最大オプション、デフォルト100 |
| `limit` | number | いいえ | 返す最大アイテム数オプション、デフォルト100 |
#### 出力
@@ -58,6 +59,7 @@ Webflow CMSコレクションから単一のアイテムを取得する
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | はい | WebflowサイトのID |
| `collectionId` | string | はい | コレクションのID |
| `itemId` | string | はい | 取得するアイテムのID |
@@ -76,8 +78,9 @@ Webflow CMSコレクションに新しいアイテムを作成する
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | はい | WebflowサイトのID |
| `collectionId` | string | はい | コレクションのID |
| `fieldData` | json | はい | 新しいアイテムのフィールドデータJSONオブジェクト形式)。キーはコレクションフィールド名と一致する必要があります。 |
| `fieldData` | json | はい | 新しいアイテムのフィールドデータJSONオブジェクト。キーはコレクションフィールド名と一致する必要があります。 |
#### 出力
@@ -94,9 +97,10 @@ Webflow CMSコレクション内の既存アイテムを更新する
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | はい | WebflowサイトのID |
| `collectionId` | string | はい | コレクションのID |
| `itemId` | string | はい | 更新するアイテムのID |
| `fieldData` | json | はい | 更新するフィールドデータJSONオブジェクト形式)。変更したいフィールドのみを含めてください。 |
| `fieldData` | json | はい | 更新するフィールドデータJSONオブジェクト。変更したいフィールドのみを含めてください。 |
#### 出力
@@ -113,6 +117,7 @@ Webflow CMSコレクションからアイテムを削除する
| パラメータ | 型 | 必須 | 説明 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | はい | WebflowサイトのID |
| `collectionId` | string | はい | コレクションのID |
| `itemId` | string | はい | 削除するアイテムのID |

View File

@@ -94,10 +94,7 @@ Zepから会話スレッドを削除する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `context` | string | コンテキスト文字列(サマリーまたは基本) |
| `facts` | array | 抽出されたファクト |
| `entities` | array | 抽出されたエンティティ |
| `summary` | string | 会話のサマリー |
| `context` | string | コンテキスト文字列(要約または基本モード |
### `zep_get_messages`
@@ -137,9 +134,9 @@ Zepから会話スレッドを削除する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `context` | string | メッセージ追加後の更新されたコンテキスト |
| `messageIds` | array | 追加されたメッセージUUIDの配列 |
| `threadId` | string | スレッドID |
| `added` | boolean | メッセージが正常に追加されたかどうか |
| `messageIds` | array | 追加されたメッセージUUIDの配列 |
### `zep_add_user`
@@ -209,7 +206,7 @@ Zepからユーザー情報を取得する
| パラメータ | 型 | 説明 |
| --------- | ---- | ----------- |
| `threads` | array | このユーザーのスレッドオブジェクトの配列 |
| `userId` | string | ユーザーID |
| `totalCount` | number | 返されたスレッドの総数 |
## 注意事項

View File

@@ -320,11 +320,11 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| `baseUrl` | string | 是 | Grafana 实例 URL \(例如https://your-grafana.com\) |
| `organizationId` | string | 否 | 多组织 Grafana 实例的组织 ID |
| `text` | string | 是 | 注释的文本内容 |
| `tags` | string | 否 | 逗号分隔的标签列表 |
| `dashboardUid` | string | | 要添加注释的仪表板 UID \(全局注释可选\) |
| `tags` | string | 否 | 逗号分隔的标签列表 |
| `dashboardUid` | string | | 要添加注释的仪表板 UID |
| `panelId` | number | 否 | 要添加注释的面板 ID |
| `time` | number | 否 | 始时间(以 epoch 毫秒为单位,默认为当前时间) |
| `timeEnd` | number | 否 | 结束时间(以 epoch 毫秒为单位,用于范围注释) |
| `time` | number | 否 | 始时间(以纪元毫秒为单位,默认为当前时间) |
| `timeEnd` | number | 否 | 结束时间(以纪元毫秒为单位,用于范围注释) |
#### 输出
@@ -342,15 +342,15 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | 是 | Grafana 服务账户令牌 |
| ---INLINE-CODE-PLACEHOLDER-42355e89d407292dbef683bcc5a4fc3e--- | string | 是 | Grafana 实例 URL \(例如https://your-grafana.com\) |
| `baseUrl` | string | 是 | Grafana 实例 URL \(例如https://your-grafana.com\) |
| `organizationId` | string | 否 | 多组织 Grafana 实例的组织 ID |
| `from` | number | 否 | 始时间(以 epoch 毫秒为单位) |
| `to` | number | 否 | 结束时间(以 epoch 毫秒为单位) |
| `dashboardUid` | string | | 仪表板 UID 过滤 |
| `from` | number | 否 | 始时间(以纪元毫秒为单位) |
| `to` | number | 否 | 结束时间(以纪元毫秒为单位) |
| `dashboardUid` | string | | 要查询注释的仪表板 UID |
| `panelId` | number | 否 | 按面板 ID 过滤 |
| `tags` | string | 否 | 按逗号分隔的标签列表过滤 |
| `type` | string | 否 | 按类型过滤 \(警报或注释\) |
| `limit` | number | 否 | 返回的最大注释数 |
| `tags` | string | 否 | 按标签过滤(逗号分隔) |
| `type` | string | 否 | 按类型过滤 \(alert 或 annotation\) |
| `limit` | number | 否 | 返回的注释最大数量 |
#### 输出
@@ -483,10 +483,20 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `id` | number | 创建文件夹的数字 ID |
| `uid` | string | 创建文件夹的 UID |
| `title` | string | 创建文件夹的标题 |
| `id` | number | 创建文件夹的数字 ID |
| `uid` | string | 创建文件夹的 UID |
| `title` | string | 创建文件夹的标题 |
| `url` | string | 文件夹的 URL 路径 |
| `hasAcl` | boolean | 文件夹是否具有自定义 ACL 权限 |
| `canSave` | boolean | 当前用户是否可以保存文件夹 |
| `canEdit` | boolean | 当前用户是否可以编辑文件夹 |
| `canAdmin` | boolean | 当前用户是否对文件夹具有管理员权限 |
| `canDelete` | boolean | 当前用户是否可以删除文件夹 |
| `createdBy` | string | 创建文件夹的用户名 |
| `created` | string | 文件夹创建的时间戳 |
| `updatedBy` | string | 最后更新文件夹的用户名 |
| `updated` | string | 文件夹最后更新的时间戳 |
| `version` | number | 文件夹的版本号 |
## 注意事项

View File

@@ -1,806 +0,0 @@
---
title: Pylon
description: 在 Pylon 中管理客户支持问题、账户、联系人、用户、团队和标签
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="pylon"
color="#E8F4FA"
/>
{/* MANUAL-CONTENT-START:intro */}
[Pylon](https://usepylon.com/) 是一个先进的客户支持和成功平台旨在帮助您管理客户关系的各个方面——从支持问题到账户、联系人、用户、团队等。Pylon 通过丰富的 API 和全面的工具集,使支持和成功团队能够高效且程序化地运作。
在 Sim 中使用 Pylon您可以
- **管理支持问题:**
- 列出、创建、获取、更新和删除支持问题,以实现高效的案例跟踪。
- 搜索和延后问题,帮助代理专注并保持有序。
- 处理问题关注者和外部问题,与内部和外部利益相关者无缝协作。
- **全面的账户管理:**
- 列出、创建、获取、更新和删除客户账户。
- 以编程方式批量更新账户。
- 搜索账户,快速找到与支持或外联相关的客户信息。
- **联系人管理:**
- 列出、创建、获取、更新、删除和搜索联系人——管理与您的账户相关的所有人。
- **用户和团队操作:**
- 列出、获取、更新和搜索 Pylon 工作区中的用户。
- 列出、创建、获取和更新团队,以构建您的支持组织和工作流程。
- **标签和组织:**
- 列出、获取、创建、更新和删除标签,用于对问题、账户或联系人进行分类。
- **消息处理:**
- 直接从您的工作流程中编辑敏感消息内容,以确保隐私和合规性。
通过将 Pylon 工具集成到 Sim 中,您的代理可以自动化支持操作的各个方面:
- 在客户事件发生时自动打开、更新或分类新问题。
- 在您的技术堆栈中保持账户和联系人数据的同步。
- 使用标签和团队路由对话、处理升级并组织您的支持数据。
- 确保敏感数据得到妥善管理,根据需要编辑消息。
Pylon 的端点提供了对客户问题和关系全生命周期管理的精细控制。无论是扩展支持服务台、推动主动客户成功还是与其他系统集成Sim 中的 Pylon 都能实现一流的 CRM 自动化——安全、灵活且可扩展。
{/* MANUAL-CONTENT-END */}
## 使用说明
将 Pylon 集成到工作流程中。管理问题(列表、创建、获取、更新、删除、搜索、延迟、关注者、外部问题)、账户(列表、创建、获取、更新、删除、批量更新、搜索)、联系人(列表、创建、获取、更新、删除、搜索)、用户(列表、获取、更新、搜索)、团队(列表、获取、创建、更新)、标签(列表、获取、创建、更新、删除)和消息(编辑)。
## 工具
### `pylon_list_issues`
检索指定时间范围内的问题列表
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `startTime` | string | 是 | RFC3339 格式的开始时间 \(例如2024-01-01T00:00:00Z\) |
| `endTime` | string | 是 | RFC3339 格式的结束时间 \(例如2024-01-31T23:59:59Z\) |
| `cursor` | string | 否 | 下一页结果的分页游标 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 问题列表 |
### `pylon_create_issue`
创建具有指定属性的新问题
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `title` | string | 是 | 问题标题 |
| `bodyHtml` | string | 是 | HTML 格式的问题正文 |
| `accountId` | string | 否 | 与问题关联的账户 ID |
| `assigneeId` | string | 否 | 分配问题的用户 ID |
| `teamId` | string | 否 | 分配问题的团队 ID |
| `requesterId` | string | 否 | 请求者用户 ID请求者邮箱的替代选项 |
| `requesterEmail` | string | 否 | 请求者邮箱地址(请求者 ID 的替代选项) |
| `priority` | string | 否 | 问题优先级 |
| `tags` | string | 否 | 逗号分隔的标签 ID |
| `customFields` | string | 否 | 作为 JSON 对象的自定义字段 |
| `attachmentUrls` | string | 否 | 逗号分隔的附件 URL |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 创建的问题数据 |
### `pylon_get_issue`
通过 ID 获取特定问题
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `issueId` | string | 是 | 要检索的问题 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 问题数据 |
### `pylon_update_issue`
更新现有问题
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `issueId` | string | 是 | 要更新的问题 ID |
| `state` | string | 否 | 问题状态 |
| `assigneeId` | string | 否 | 分配问题的用户 ID |
| `teamId` | string | 否 | 分配问题的团队 ID |
| `tags` | string | 否 | 逗号分隔的标签 ID |
| `customFields` | string | 否 | 作为 JSON 对象的自定义字段 |
| `customerPortalVisible` | boolean | 否 | 问题是否在客户门户中可见 |
| `requesterId` | string | 否 | 请求者用户 ID |
| `accountId` | string | 否 | 与问题关联的账户 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 更新的问题数据 |
### `pylon_delete_issue`
通过 ID 删除问题
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `issueId` | string | 是 | 要删除的问题 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 删除结果 |
### `pylon_search_issues`
使用筛选器查询问题
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `filter` | string | 是 | 作为 JSON 字符串的筛选条件 |
| `cursor` | string | 否 | 下一页结果的分页游标 |
| `limit` | number | 否 | 要返回的最大结果数 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 搜索结果 |
### `pylon_snooze_issue`
推迟问题的可见性直到指定时间
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `issueId` | string | 是 | 要推迟的问题 ID |
| `snoozeUntil` | string | 是 | 问题应重新出现的 RFC3339 时间戳 \(例如2024-01-01T00:00:00Z\) |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 延期问题数据 |
### `pylon_list_issue_followers`
获取特定问题的关注者列表
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `issueId` | string | 是 | 问题的 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 关注者列表 |
### `pylon_manage_issue_followers`
添加或移除问题的关注者
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `issueId` | string | 是 | 问题的 ID |
| `userIds` | string | 否 | 逗号分隔的用户 ID 列表,用于添加/移除 |
| `contactIds` | string | 否 | 逗号分隔的联系人 ID 列表,用于添加/移除 |
| `operation` | string | 否 | 要执行的操作:"add" 或 "remove" \(默认值:"add"\) |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 更新后的关注者列表 |
### `pylon_link_external_issue`
将问题链接到外部系统问题
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `issueId` | string | 是 | Pylon 问题的 ID |
| `externalIssueId` | string | 是 | 外部问题的 ID |
| `source` | string | 是 | 来源系统(例如:"jira", "linear", "github" |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 已链接的外部问题数据 |
### `pylon_list_accounts`
检索账户的分页列表
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `limit` | string | 否 | 要返回的账户数量1-1000默认 100 |
| `cursor` | string | 否 | 下一页结果的分页游标 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 账户列表 |
### `pylon_create_account`
使用指定属性创建新账户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `name` | string | 是 | 账户名称 |
| `domains` | string | 否 | 逗号分隔的域名列表 |
| `primaryDomain` | string | 否 | 账户的主域名 |
| `customFields` | string | 否 | 作为 JSON 对象的自定义字段 |
| `tags` | string | 否 | 逗号分隔的标签 ID |
| `channels` | string | 否 | 逗号分隔的频道 ID |
| `externalIds` | string | 否 | 逗号分隔的外部 ID |
| `ownerId` | string | 否 | 所有者用户 ID |
| `logoUrl` | string | 否 | 账户徽标的 URL |
| `subaccountIds` | string | 否 | 逗号分隔的子账户 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 创建的账户数据 |
### `pylon_get_account`
通过 ID 检索单个账户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `accountId` | string | 是 | 要检索的账户 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 账户数据 |
### `pylon_update_account`
使用新属性更新现有账户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `accountId` | string | 是 | 要更新的账户 ID |
| `name` | string | 否 | 账户名称 |
| `domains` | string | 否 | 逗号分隔的域名列表 |
| `primaryDomain` | string | 否 | 账户的主域名 |
| `customFields` | string | 否 | 作为 JSON 对象的自定义字段 |
| `tags` | string | 否 | 逗号分隔的标签 ID |
| `channels` | string | 否 | 逗号分隔的频道 ID |
| `externalIds` | string | 否 | 逗号分隔的外部 ID |
| `ownerId` | string | 否 | 所有者用户 ID |
| `logoUrl` | string | 否 | 账户标志的 URL |
| `subaccountIds` | string | 否 | 逗号分隔的子账户 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 更新的账户数据 |
### `pylon_delete_account`
通过 ID 删除账户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `accountId` | string | 是 | 要删除的账户 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 删除确认 |
### `pylon_bulk_update_accounts`
一次更新多个账户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `accountIds` | string | 是 | 逗号分隔的账户 ID 列表 |
| `customFields` | string | 否 | 自定义字段JSON 对象) |
| `tags` | string | 否 | 逗号分隔的标签 ID |
| `ownerId` | string | 否 | 所有者用户 ID |
| `tagsApplyMode` | string | 否 | 标签应用模式append_only、remove_only 或 replace |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 批量更新的账户数据 |
### `pylon_search_accounts`
使用自定义筛选器搜索账户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `filter` | string | 是 | 以 JSON 字符串形式表示的筛选器,包含字段/操作符/值结构 |
| `limit` | string | 否 | 要返回的账户数量 \(1-1000默认 100\) |
| `cursor` | string | 否 | 用于下一页结果的分页游标 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 搜索结果 |
### `pylon_list_contacts`
检索联系人列表
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `cursor` | string | 否 | 用于下一页结果的分页游标 |
| `limit` | string | 否 | 要返回的最大联系人数量 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 联系人列表 |
### `pylon_create_contact`
创建具有指定属性的新联系人
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `name` | string | 是 | 联系人姓名 |
| `email` | string | 否 | 联系人电子邮件地址 |
| `accountId` | string | 否 | 要与联系人关联的账户 ID |
| `accountExternalId` | string | 否 | 要与联系人关联的外部账户 ID |
| `avatarUrl` | string | 否 | 联系人头像图片的 URL |
| `customFields` | string | 否 | 以 JSON 对象形式表示的自定义字段 |
| `portalRole` | string | 否 | 联系人的门户角色 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 创建的联系人数据 |
### `pylon_get_contact`
通过 ID 检索特定联系人
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `contactId` | string | 是 | 要检索的联系人 ID |
| `cursor` | string | 否 | 下一页结果的分页游标 |
| `limit` | string | 否 | 要返回的最大项目数 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 联系人数据 |
### `pylon_update_contact`
使用指定属性更新现有联系人
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `contactId` | string | 是 | 要更新的联系人 ID |
| `name` | string | 否 | 联系人姓名 |
| `email` | string | 否 | 联系人电子邮件地址 |
| `accountId` | string | 否 | 要与联系人关联的账户 ID |
| `accountExternalId` | string | 否 | 要与联系人关联的外部账户 ID |
| `avatarUrl` | string | 否 | 联系人头像图片的 URL |
| `customFields` | string | 否 | 作为 JSON 对象的自定义字段 |
| `portalRole` | string | 否 | 联系人的门户角色 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 更新的联系人数据 |
### `pylon_delete_contact`
通过 ID 删除特定联系人
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `contactId` | string | 是 | 要删除的联系人 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 删除操作结果 |
### `pylon_search_contacts`
使用筛选器搜索联系人
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `filter` | string | 是 | 作为 JSON 对象的筛选器 |
| `limit` | string | 否 | 要返回的最大联系人数量 |
| `cursor` | string | 否 | 下一页结果的分页游标 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 搜索结果 |
### `pylon_list_users`
检索用户列表
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 用户列表 |
### `pylon_get_user`
通过 ID 检索特定用户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `userId` | string | 是 | 要检索的用户 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 用户数据 |
### `pylon_update_user`
使用指定属性更新现有用户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `userId` | string | 是 | 要更新的用户 ID |
| `roleId` | string | 否 | 要分配给用户的角色 ID |
| `status` | string | 否 | 用户状态 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 更新的用户数据 |
### `pylon_search_users`
使用电子邮件字段的过滤器搜索用户
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `filter` | string | 是 | 包含电子邮件字段的 JSON 对象过滤器 |
| `cursor` | string | 否 | 下一页结果的分页游标 |
| `limit` | string | 否 | 要返回的最大用户数 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 搜索结果 |
### `pylon_list_teams`
检索团队列表
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 团队列表 |
### `pylon_get_team`
通过 ID 检索特定团队
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `teamId` | string | 是 | 要检索的团队 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 团队数据 |
### `pylon_create_team`
使用指定属性创建新团队
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `name` | string | 否 | 团队名称 |
| `userIds` | string | 否 | 以逗号分隔的用户 ID用于添加为团队成员 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 创建的团队数据 |
### `pylon_update_team`
使用指定属性更新现有团队userIds 将替换整个成员列表)
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `teamId` | string | 是 | 要更新的团队 ID |
| `name` | string | 否 | 团队名称 |
| `userIds` | string | 否 | 逗号分隔的用户 ID替换整个团队成员列表 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 更新的团队数据 |
### `pylon_list_tags`
检索标签列表
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 标签列表 |
### `pylon_get_tag`
通过 ID 检索特定标签
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `tagId` | string | 是 | 要检索的标签 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 标签数据 |
### `pylon_create_tag`
使用指定属性创建一个新标签objectType: account/issue/contact
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `objectType` | string | 是 | 标签的对象类型 \(account, issue, 或 contact\) |
| `value` | string | 是 | 标签值/名称 |
| `hexColor` | string | 否 | 标签的十六进制颜色代码 \(例如:#FF5733\) |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 创建的标签数据 |
### `pylon_update_tag`
使用指定属性更新现有标签
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `tagId` | string | 是 | 要更新的标签 ID |
| `hexColor` | string | 否 | 标签的十六进制颜色代码 \(例如:#FF5733\) |
| `value` | string | 否 | 标签值/名称 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 更新的标签数据 |
### `pylon_delete_tag`
通过 ID 删除特定标签
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `tagId` | string | 是 | 要删除的标签 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 删除操作结果 |
### `pylon_redact_message`
编辑问题中的特定消息
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `apiToken` | string | 是 | Pylon API 令牌 |
| `issueId` | string | 是 | 包含消息的问题 ID |
| `messageId` | string | 是 | 要编辑的消息 ID |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作成功状态 |
| `output` | object | 编辑操作结果 |
## 注意事项
- 类别:`tools`
- 类型:`pylon`

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
---
title: Stagehand Extract
description: 从网站提取数据
title: Stagehand
description: 网页自动化和数据提取
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
@@ -11,20 +11,27 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://stagehand.com) 是一款工具,可通过 Browserbase 和 OpenAI 从网页中提取结构化数据。
[Stagehand](https://stagehand.com) 是一款工具,可通过 Browserbase 和现代 LLMs如 OpenAI 或 Anthropic实现从网页中提取结构化数据以及自主网页自动化
使用 Stagehand,您可以
Stagehand 在 Sim 中提供了两项主要功能
- **提取结构化数据**:通过 Browserbase 和 OpenAI 从网页中提取结构化数据
- **将数据保存到数据库**:将提取的数据保存到数据库中
- **自动化工作流程**:自动化工作流程以从网页中提取数据
- **stagehand_extract**从单个网页中提取结构化数据。您可以指定所需内容一个模式AI 会从页面中以该格式检索并解析数据。这非常适合在您明确知道需要什么信息以及从哪里获取时,用于提取列表、字段或对象。
在 Sim 中Stagehand 集成使您的代理能够通过 Browserbase 和 OpenAI 从网页中提取结构化数据。这为数据提取、数据分析和数据集成等强大的自动化场景提供了可能。您的代理可以从网页中提取结构化数据,将提取的数据保存到数据库中,并自动化工作流程以提取数据。此集成弥合了 AI 工作流程与数据管理系统之间的差距,实现了无缝的数据提取和集成。通过将 Sim 与 Stagehand 连接,您可以自动化数据提取流程,维护最新的信息库,生成报告,并智能地组织信息——这一切都通过您的智能代理完成
- **stagehand_agent**:运行一个自主的网页代理能够完成多步骤任务,与元素交互,在页面之间导航,并返回结构化结果。这更加灵活:代理可以执行登录、搜索、填写表单、从多个地方收集数据,并根据请求的模式输出最终结果
**关键区别:**
- *stagehand_extract* 是一个快速的“从这个页面提取这些数据”的操作。它最适合直接的、一步完成的提取任务。
- *stagehand_agent* 执行复杂的、多步骤的自主网页任务,例如导航、搜索,甚至交易,并可以根据您的指示和可选的模式动态提取数据。
在实际应用中,当您知道需要什么以及在哪里时,请使用 **stagehand_extract**;当您需要一个机器人思考并执行交互式工作流程时,请使用 **stagehand_agent**。
通过集成 StagehandSim 代理可以在网页上自动化数据收集、分析和工作流程执行:更新数据库、组织信息以及生成自定义报告——无缝且自主地完成。
{/* MANUAL-CONTENT-END */}
## 使用说明
将 Stagehand 集成到工作流程中。可以从网页中提取结构化数据。需要 API 密钥
将 Stagehand 集成到工作流程中。可以从网页中提取结构化数据,或运行自主代理执行任务
## 工具
@@ -38,14 +45,37 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| --------- | ---- | -------- | ----------- |
| `url` | string | 是 | 要提取数据的网页 URL |
| `instruction` | string | 是 | 提取的指令 |
| `apiKey` | string | | 用于提取的 OpenAI API 密钥 \(Stagehand 所需\) |
| `provider` | string | | 要使用的 AI 提供商openai 或 anthropic |
| `apiKey` | string | 是 | 所选提供商的 API 密钥 |
| `schema` | json | 是 | 定义要提取数据结构的 JSON 架构 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `data` | object | 提取的与提供的模式匹配的结构化数据 |
| `data` | object | 符合提供架构的提取结构化数据 |
### `stagehand_agent`
运行自主网页代理以完成任务并提取结构化数据
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | 是 | 启动代理的网页 URL |
| `task` | string | 是 | 在网站上完成的任务或目标 |
| `variables` | json | 否 | 任务中可替换的可选变量(格式:\{key: value\})。在任务中使用 %key% 引用 |
| `format` | string | 否 | 无描述 |
| `provider` | string | 否 | 要使用的 AI 提供商openai 或 anthropic |
| `apiKey` | string | 是 | 所选提供商的 API 密钥 |
| `outputSchema` | json | 否 | 定义代理应返回数据结构的可选 JSON 架构 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `agentResult` | object | Stagehand 代理执行的结果 |
## 注意事项

View File

@@ -1,59 +0,0 @@
---
title: Stagehand Agent
description: 自主网页浏览代理
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="stagehand_agent"
color="#FFC83C"
/>
{/* MANUAL-CONTENT-START:intro */}
[Stagehand](https://www.stagehand.dev/) 是一个自主的网页代理平台,使 AI 系统能够像人类一样浏览和与网站交互。它为自动化复杂的网页任务提供了强大的解决方案,无需定制代码或浏览器自动化脚本。
使用 Stagehand您可以
- **自动化网页导航**:使 AI 能够浏览网站、点击链接、填写表单并与网页元素交互
- **提取结构化数据**:从网站收集特定信息并以结构化、可用的格式呈现
- **完成复杂工作流程**:在不同网站和网页应用程序之间执行多步骤任务
- **处理身份验证**:导航登录流程并维护跨网站的会话
- **处理动态内容**:与 JavaScript 密集型网站和单页应用程序交互
- **保持上下文感知**:在导航时跟踪当前状态和历史记录
- **生成详细报告**:接收所采取操作和收集数据的全面日志
在 Sim 中Stagehand 集成使您的代理能够无缝地与基于网页的系统交互,作为其工作流程的一部分。这允许复杂的自动化场景,将您的 AI 代理与网络上广泛的信息和功能连接起来。您的代理可以搜索信息、与网页应用程序交互、从网站提取数据,并将这些能力融入其决策过程中。通过将 Sim 与 Stagehand 连接,您可以创建超越基于 API 集成的代理,使其能够像人类一样浏览网页——填写表单、点击按钮、阅读内容并提取有价值的信息,从而更高效地完成任务。
{/* MANUAL-CONTENT-END */}
## 使用说明
将 Stagehand Agent 集成到工作流程中。可以浏览网页并执行任务。需要 API 密钥。
## 工具
### `stagehand_agent`
运行一个自主的网页代理来完成任务并提取结构化数据
#### 输入
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `startUrl` | string | 是 | 启动代理的网页 URL |
| `task` | string | 是 | 在网站上完成的任务或实现的目标 |
| `variables` | json | 否 | 替代任务中的可选变量(格式:\{key: value\})。在任务中使用 %key% 引用 |
| `format` | string | 否 | 无描述 |
| `apiKey` | string | 是 | 用于代理执行的 OpenAI API 密钥Stagehand 必需) |
| `outputSchema` | json | 否 | 定义代理应返回的数据结构的可选 JSON 架构 |
#### 输出
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `agentResult` | object | Stagehand 代理执行的结果 |
## 注意
- 类别:`tools`
- 类型:`stagehand_agent`

View File

@@ -45,10 +45,8 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作是否成功 |
| `lists` | array | 包含 id、name、closed、pos 和 idBoard 的列表对象数组 |
| `count` | number | 返回的列表数量 |
| `error` | string | 如果操作失败的错误信息 |
### `trello_list_cards`
@@ -65,10 +63,8 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作是否成功 |
| `cards` | array | 包含 id、name、desc、url、board/list IDs、labels 和到期日期的卡片对象数组 |
| `cards` | array | 包含 id、name、desc、url、看板/列表 ID、标签和到期日期的卡片对象数组 |
| `count` | number | 返回的卡片数量 |
| `error` | string | 如果操作失败的错误信息 |
### `trello_create_card`
@@ -90,9 +86,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 卡片是否创建成功 |
| `card` | object | 创建的卡片对象,包含 id、name、desc、url 和其他属性 |
| `error` | string | 如果操作失败,返回错误信息 |
### `trello_update_card`
@@ -114,9 +108,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 卡片是否更新成功 |
| `card` | object | 更新的卡片对象,包含 id、name、desc、url 和其他属性 |
| `error` | string | 如果操作失败,返回错误信息 |
### `trello_get_actions`
@@ -135,10 +127,8 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 操作是否成功 |
| `actions` | array | 包含类型、日期、成员和数据的操作对象数组 |
| `actions` | array | 包含 type、date、member 和 data 的操作对象数组 |
| `count` | number | 返回的操作数量 |
| `error` | string | 如果操作失败,返回的错误信息 |
### `trello_add_comment`
@@ -155,9 +145,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `success` | boolean | 评论是否成功添加 |
| `comment` | object | 创建的评论对象,包含 id、text、date 和 member creator |
| `error` | string | 如果操作失败,返回的错误信息 |
| `comment` | object | 创建的评论对象,包含 id、text、date 和创建者信息 |
## 注意事项

View File

@@ -38,9 +38,10 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | 是 | Webflow 网站的 ID |
| `collectionId` | string | 是 | 集合的 ID |
| `offset` | number | 否 | 分页偏移量(可选) |
| `limit` | number | 否 | 返回的最大项目数可选默认值100 |
| `offset` | number | 否 | 分页偏移量(可选) |
| `limit` | number | 否 | 返回的最大项目数可选默认值100 |
#### 输出
@@ -57,8 +58,9 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | 是 | Webflow 网站的 ID |
| `collectionId` | string | 是 | 集合的 ID |
| `itemId` | string | 是 | 要检索项目 ID |
| `itemId` | string | 是 | 要检索项目 ID |
#### 输出
@@ -75,8 +77,9 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | 是 | Webflow 网站的 ID |
| `collectionId` | string | 是 | 集合的 ID |
| `fieldData` | json | 是 | 新项目的字段数据,格式为 JSON 对象。键名应与集合字段名匹配。 |
| `fieldData` | json | 是 | 新项目的字段数据,格式为 JSON 对象。键名应与集合字段名匹配。 |
#### 输出
@@ -93,9 +96,10 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | 是 | Webflow 网站的 ID |
| `collectionId` | string | 是 | 集合的 ID |
| `itemId` | string | 是 | 要更新项目的 ID |
| `fieldData` | json | 是 | 要更新的字段数据,格式为 JSON 对象。仅包含您想更改的字段。 |
| `fieldData` | json | 是 | 要更新的字段数据,格式为 JSON 对象。仅包含需要更改的字段。 |
#### 输出
@@ -112,6 +116,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 必需 | 描述 |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | 是 | Webflow 网站的 ID |
| `collectionId` | string | 是 | 集合的 ID |
| `itemId` | string | 是 | 要删除项目的 ID |

View File

@@ -94,10 +94,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `context` | 字符串 | 上下文字符串(摘要或基本) |
| `facts` | 数组 | 提取的事实 |
| `entities` | 数组 | 提取的实体 |
| `summary` | 字符串 | 会话摘要 |
| `context` | string | 上下文字符串(摘要或基本模式 |
### `zep_get_messages`
@@ -137,9 +134,9 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `context` | string | 添加消息后的更新上下文 |
| `messageIds` | array | 添加的消息 UUID 数组 |
| `threadId` | string | 线程 ID |
| `added` | boolean | 消息是否成功添加 |
| `messageIds` | array | 添加的消息 UUID 数组 |
### `zep_add_user`
@@ -209,7 +206,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
| 参数 | 类型 | 描述 |
| --------- | ---- | ----------- |
| `threads` | array | 此用户的线程对象数组 |
| `userId` | string | 用户 ID |
| `totalCount` | number | 返回的线程总数 |
## 注意

View File

@@ -844,25 +844,35 @@ checksums:
content/15: b3f310d5ef115bea5a8b75bf25d7ea9a
content/16: a367df5277edf27ed08ff11b03279fdd
abf533c0ff218cfc4166a55a9bd3a01f:
meta/title: fa81baef9ba5e794e519b71ad8a0bcf2
meta/description: a6150e728da734390689627af1a2fd34
meta/title: 01271b85ff001bf1a4a8d1730f570331
meta/description: 78b809fd1f5ecde25dab06776f6090d6
content/0: 1b031fb0c62c46b177aeed5c3d3f8f80
content/1: fdd8ecb5e550d9ed729ea0445c3c3ad1
content/2: a0e89f4efd3f7a0474568bceef251e05
content/3: c96320b1e7271f8b46b18556cf10f680
content/4: 0cf4d7d650aec185fb41b3e92f507057
content/5: 3816dfaf26ed3afd7aff9090710024f1
content/6: 821e6394b0a953e2b0842b04ae8f3105
content/7: e47a99fb84a6ba46b2f6bf91c26f842b
content/8: 9c8aa3f09c9b2bd50ea4cdff3598ea4e
content/9: 0f2701a070121f0abbbf8cc289652330
content/10: 18e01e99857573a423da69c5b4127487
content/11: 371d0e46b4bd2c23f559b8bc112f6955
content/12: d9f2aa90cdfac53f9a3b09225bb67700
content/13: bcadfc362b69078beee0088e5936c98b
content/14: cca5bb45df434d1dd843d94eb9ac3f76
content/15: b3f310d5ef115bea5a8b75bf25d7ea9a
content/16: c5ce52e3a765ca8ed0be639afb2eee7b
content/2: 6f77421e48f3fc5d9d226461657d5955
content/3: 992b3abebfb89a1ba9ca3498b86079ff
content/4: 80d3d3ff22a583a17280020155880f42
content/5: 7e97694717a88e22ca342219173d8007
content/6: 2c10a97e08ea83f66da35433bba4b161
content/7: cd0d728e5ece860818fd28cb492b7d51
content/8: a2f4a9e48c0a82a5cf4776abac56f135
content/9: d8c8b2d9dfb5aac795de26be43a7d9b9
content/10: 821e6394b0a953e2b0842b04ae8f3105
content/11: dfc1ee41d6b3e799ee65271d45fbe2a8
content/12: 9c8aa3f09c9b2bd50ea4cdff3598ea4e
content/13: 0f2701a070121f0abbbf8cc289652330
content/14: 18e01e99857573a423da69c5b4127487
content/15: 371d0e46b4bd2c23f559b8bc112f6955
content/16: b7d7d051b6003de92f09eff59955c4e7
content/17: bcadfc362b69078beee0088e5936c98b
content/18: cca5bb45df434d1dd843d94eb9ac3f76
content/19: b09ace13f48c17268148d1602d105999
content/20: 553d5f0825e9d426b9753e64dd596872
content/21: 371d0e46b4bd2c23f559b8bc112f6955
content/22: ea958419fd22c3fbd2f647aae2ddb32a
content/23: bcadfc362b69078beee0088e5936c98b
content/24: 08992483aceab1862eedadd4e0e374d5
content/25: b3f310d5ef115bea5a8b75bf25d7ea9a
content/26: c5ce52e3a765ca8ed0be639afb2eee7b
14b4bb962f102a4a42dd93498f0cf40c:
meta/title: 7b7b808a136ce10b6199c504e81fb902
meta/description: 9b77a5b1561b43c9f30bb06febc6ff6c
@@ -5915,7 +5925,7 @@ checksums:
content/25: 371d0e46b4bd2c23f559b8bc112f6955
content/26: 1c1914a63d880607fa1f0ccaa47d6bdc
content/27: bcadfc362b69078beee0088e5936c98b
content/28: dfba53a44a72ddb05d937ac850642c32
content/28: 92c61c22136d02896171fccc6ade1f69
content/29: 25c0139e6dbae0caf7045db76d678057
content/30: c11a5d76541d3111055068edb43d26af
content/31: 371d0e46b4bd2c23f559b8bc112f6955
@@ -5927,7 +5937,7 @@ checksums:
content/37: 371d0e46b4bd2c23f559b8bc112f6955
content/38: 722e870ff0fd01d4bf8abf17bfc56110
content/39: bcadfc362b69078beee0088e5936c98b
content/40: edf9a72a6b185e4dc921c84774bef409
content/40: 4e89b91d0a20c2e0ab0de5f93cfb4382
content/41: ffae7ab7fc862449bf8c47818726e36d
content/42: 31375eb7944dce78bcba23c2e754f9e6
content/43: 371d0e46b4bd2c23f559b8bc112f6955
@@ -5945,7 +5955,7 @@ checksums:
content/55: 371d0e46b4bd2c23f559b8bc112f6955
content/56: 094163dad0578662e2a3197dbf665a4e
content/57: bcadfc362b69078beee0088e5936c98b
content/58: 74af50eceb2a5f514301c497a8e64030
content/58: f2e1fb3bce0b54b10e312b5421f61707
content/59: b3f310d5ef115bea5a8b75bf25d7ea9a
content/60: 549a9bd7ff92264fbd18c9d6e616594b
65891ef7e29a3ad2464222a998549ff5:
@@ -5963,31 +5973,31 @@ checksums:
content/9: 5914baadfaf2ca26d54130a36dd5ed29
content/10: 25507380ac7d9c7f8cf9f5256c6a0dbb
content/11: 371d0e46b4bd2c23f559b8bc112f6955
content/12: e7fb612c3323c1e6b05eacfcea360d34
content/12: e034523b05e8c7bd1723ef0ba96c5332
content/13: bcadfc362b69078beee0088e5936c98b
content/14: e5f830d6049ff79a318110098e5e0130
content/15: 711e90714806b91f93923018e82ad2e9
content/16: 0f3f7d9699d7397cb3a094c3229329ee
content/17: 371d0e46b4bd2c23f559b8bc112f6955
content/18: c53b5b8f901066e63fe159ad2fa5e6e0
content/18: 4b0c581b30f4449b0bfa3cdd4af69e02
content/19: bcadfc362b69078beee0088e5936c98b
content/20: 5f2afdd49c3ac13381401c69d1eca22a
content/21: cc4baa9096fafa4c6276f6136412ba66
content/22: 676f76e8a7154a576d7fa20b245cef70
content/23: 371d0e46b4bd2c23f559b8bc112f6955
content/24: c67c387eb7e274ee7c07b7e1748afce1
content/24: d26dd24c5398fd036d1f464ba3789002
content/25: bcadfc362b69078beee0088e5936c98b
content/26: a6ffebda549ad5b903a66c7d9ac03a20
content/27: 0dadd51cde48d6ea75b29ec3ee4ade56
content/28: cdc74f6483a0b4e9933ecdd92ed7480f
content/29: 371d0e46b4bd2c23f559b8bc112f6955
content/30: 4cda10aa374e1a46d60ad14eeaa79100
content/30: cec3953ee52d1d3c8b1a495f9684d35b
content/31: bcadfc362b69078beee0088e5936c98b
content/32: 5f221421953a0e760ead7388cbf66561
content/33: a3c0372590cef72d5d983dbc8dbbc2cb
content/34: 1402e53c08bdd8a741f44b2d66fcd003
content/35: 371d0e46b4bd2c23f559b8bc112f6955
content/36: 028e579a28e55def4fbc59f39f4610b7
content/36: db921b05a9e5ddceb28a4f3f1af2a377
content/37: bcadfc362b69078beee0088e5936c98b
content/38: 4fe4260da2f137679ce2fa42cffcf56a
content/39: b3f310d5ef115bea5a8b75bf25d7ea9a
@@ -6429,37 +6439,37 @@ checksums:
content/11: 371d0e46b4bd2c23f559b8bc112f6955
content/12: 6602fca05cac2890ce1e6c2bfb4c3edc
content/13: bcadfc362b69078beee0088e5936c98b
content/14: 30597d02be39403d58878009bf9ad180
content/14: 30a5638b5aabcb47356cee8feefe35df
content/15: 0f74280b9f76b77c5ff3d7adf579567f
content/16: c49e0c8c6a6e30001076b52666b65513
content/17: 371d0e46b4bd2c23f559b8bc112f6955
content/18: 44177bd68134b05e5d857fd4d961faec
content/19: bcadfc362b69078beee0088e5936c98b
content/20: 7114399c57ea4b939fb2ceec1c1c73d4
content/20: 151e3c55629a36e872d2a16e3e8aa02b
content/21: 5380b52a75a54072ce4c80ef02c1d9f9
content/22: f81573284f81699b8ccd4c9a32134b76
content/23: 371d0e46b4bd2c23f559b8bc112f6955
content/24: e1d1f3f81bc90ef9dc2d9a7000584517
content/25: bcadfc362b69078beee0088e5936c98b
content/26: 5703816c9993cad8f724477c7d3baba1
content/26: a2ee2f96a49b3c6804562e2b0603c663
content/27: a989ad3de44846f0494357c17a41ee9a
content/28: 97cb66519a9ab1bf445fb1cb9c94122e
content/29: 371d0e46b4bd2c23f559b8bc112f6955
content/30: e67b226b18e41f76c4891c7899446a7c
content/31: bcadfc362b69078beee0088e5936c98b
content/32: 7cb731c92a2952d96be745a4dc813317
content/32: 6ef3798dfeac016bcd19a8be2547f6d0
content/33: a887a78b115ab7ddd3ddd817c4bd2021
content/34: 27141f5a3f85214f3ef64decfa914b6c
content/35: 371d0e46b4bd2c23f559b8bc112f6955
content/36: efe5483771b85548be6a18808d8f8190
content/37: bcadfc362b69078beee0088e5936c98b
content/38: 9564cc04cb9372fa8e24c84c82e347b2
content/38: 70afce01643c577069971ff10da90acb
content/39: b35883a517799e6b6dae2fab1582086e
content/40: 42f88110bd2976790ec32981c33833ec
content/41: 371d0e46b4bd2c23f559b8bc112f6955
content/42: 85e2b5b0b03f537b0513c041a6b8eb50
content/43: bcadfc362b69078beee0088e5936c98b
content/44: 2a9520f488643a0aefc6985c64353ab6
content/44: fc1fba3d0fb8497db9326b741efbc4bc
content/45: b3f310d5ef115bea5a8b75bf25d7ea9a
content/46: 3a03da5c351afd4029f7e7b099f9d47a
4708d770626bc09eea209330925801e6:
@@ -48401,13 +48411,13 @@ checksums:
content/77: 1168e89ec2162f8b1c0f4437e79d683b
content/78: 1175fa4d6a946de24b5fb57d016f68c1
content/79: 371d0e46b4bd2c23f559b8bc112f6955
content/80: 502dd72a174138e7888c41a31a445bc9
content/80: b3d399422a0cc360275321cbf348c3fe
content/81: bcadfc362b69078beee0088e5936c98b
content/82: f194ced69b293f9f8d49d752f44caadb
content/83: 90a2342ab1d3182265f81c9c7b94e800
content/84: a44f8a4284da46f9e6eea1418e4053d5
content/85: 371d0e46b4bd2c23f559b8bc112f6955
content/86: f0be34514306abc1a6f2d43bba7c4743
content/86: 6c0bde07d783bdd9c4dbc9295a9aad23
content/87: bcadfc362b69078beee0088e5936c98b
content/88: 907a7c72c1cb1bbaa476500208058e61
content/89: 77b4c49ac2abbf3177723a26027f4b20
@@ -48445,7 +48455,7 @@ checksums:
content/121: 371d0e46b4bd2c23f559b8bc112f6955
content/122: de3c6dc828985e7145637e03d3749170
content/123: bcadfc362b69078beee0088e5936c98b
content/124: f5157d6ea024ed45c55f8bed7516220a
content/124: fc1646564753a62ca90f9dc1dedd8dd8
content/125: b3f310d5ef115bea5a8b75bf25d7ea9a
content/126: a7a0477ca54d01f3c0d815d727c47143
6bf4a002144862f19cec5ad8c2151fa3:
@@ -49333,3 +49343,481 @@ checksums:
content/16: a064887f5c777b54e029ba6ba1b56848
content/17: b3f310d5ef115bea5a8b75bf25d7ea9a
content/18: a4748f8ce0a4667675ca03e4d9fef87b
69ea9d99d8ef0b139c482d74509ab07b:
meta/title: 423cacfcc17c571c411a211fd0229cd4
meta/description: 8c462ba6272aef51b1a0ffa7aac37fb5
content/0: 1b031fb0c62c46b177aeed5c3d3f8f80
content/1: b171b09b3f47764cf7aa827625194864
content/2: 821e6394b0a953e2b0842b04ae8f3105
content/3: 1670b89782aa1b50d232766d4ddc6ccd
content/4: 9c8aa3f09c9b2bd50ea4cdff3598ea4e
content/5: f70cf85dcd2c3cf7d46b01dc32aa10d6
content/6: cc27d8fa96a722609186b19333d85814
content/7: 371d0e46b4bd2c23f559b8bc112f6955
content/8: 8bf8c43d7d7ae7278da7ebe6ecd356ac
content/9: bcadfc362b69078beee0088e5936c98b
content/10: 879f16545eaf9c61e35185b4129b64d4
content/11: 8b880d3439aa74c33b9902d27c8a870d
content/12: 1467c26def4fe4ecc55fa200b40384b7
content/13: 371d0e46b4bd2c23f559b8bc112f6955
content/14: cf9b2ad21e039311bca96387146eeb87
content/15: bcadfc362b69078beee0088e5936c98b
content/16: f61f5faf356f1a6b891cadbed34c84d2
content/17: e29d2b102b3f58bd37638ea9210894bf
content/18: 378a38c76c0106c7209934794597d5d9
content/19: 371d0e46b4bd2c23f559b8bc112f6955
content/20: 83824e68c76b4a6e5c4fe62d58ea1c82
content/21: bcadfc362b69078beee0088e5936c98b
content/22: 966cf37490e58a583d3958368df796fa
content/23: 8c81c45fda92e753c0dac4367973eac6
content/24: ce0c05074a2bddbd40f5e26485ee5f06
content/25: 371d0e46b4bd2c23f559b8bc112f6955
content/26: e7c5338c8271763746e8ff8b6369183d
content/27: bcadfc362b69078beee0088e5936c98b
content/28: 227953269e44083ef3bc39218711cb05
content/29: dc170a7f70ce32d5908cb1757103f8f8
content/30: f2e6726730cf2f8612e10d0fdd03eaf8
content/31: 371d0e46b4bd2c23f559b8bc112f6955
content/32: 7ceeaac2d12299cae6e3892d6369ed9f
content/33: bcadfc362b69078beee0088e5936c98b
content/34: 8d2aeec4a01cda0a03816d9624b117c2
content/35: ba00e04a0ff2e1a6a12d7aee62fa33f8
content/36: 6d3896e9abe0f44805fecde59e52dfb4
content/37: 371d0e46b4bd2c23f559b8bc112f6955
content/38: 3310c3cd1e7ad3538d876973c5d4cd74
content/39: bcadfc362b69078beee0088e5936c98b
content/40: aa4677bf16eb43aae63a4ae9ac57c5e5
content/41: 08f5cdb1f569ac004040dbc0a0dfbce7
content/42: 543a7893133239c24998013b6383a2ec
content/43: 371d0e46b4bd2c23f559b8bc112f6955
content/44: f3505fc99976c10189a8bdd06281289a
content/45: bcadfc362b69078beee0088e5936c98b
content/46: b944979ca1b96c44154db7b38480f47a
content/47: ec85158684a17f7075c55ca5ba178c40
content/48: 0508c2f54b25f8f31ed432805e094b0b
content/49: 371d0e46b4bd2c23f559b8bc112f6955
content/50: 6e91b64186a5b220e8539b190991eca2
content/51: bcadfc362b69078beee0088e5936c98b
content/52: ae001f604fd5ff92aef5797aa0094c2a
content/53: 47f7b5486bee09d1d0f2e5c976099ced
content/54: c096bcae5c582e9e060d3922549d3eb5
content/55: 371d0e46b4bd2c23f559b8bc112f6955
content/56: 6e91b64186a5b220e8539b190991eca2
content/57: bcadfc362b69078beee0088e5936c98b
content/58: 68dc862efbc97d4bd6a12ea5e0bb768a
content/59: 3a43a63dc6dc7080da15db3e9cc3b7d9
content/60: 507990b312b03294b9a70bf617a4f6f7
content/61: 371d0e46b4bd2c23f559b8bc112f6955
content/62: 6e91b64186a5b220e8539b190991eca2
content/63: bcadfc362b69078beee0088e5936c98b
content/64: e4738365d87b2951f7284d2ed3a499ea
content/65: a5ff73112631e5d1f07812c7bafa8e1b
content/66: 8d56ee136021f3324dacf867b853038e
content/67: 371d0e46b4bd2c23f559b8bc112f6955
content/68: 48338466c2390dc956c8d7e29dbe54e5
content/69: bcadfc362b69078beee0088e5936c98b
content/70: 5939fda569e9e2470d0ec33c9e9f65c7
content/71: 070ed023774d1aa1e25488372b52307e
content/72: a18e5c2a4cd9cf33e6ce14254b22ceba
content/73: 371d0e46b4bd2c23f559b8bc112f6955
content/74: 4641cc3e4a6b63ce0e14c724b34017b8
content/75: bcadfc362b69078beee0088e5936c98b
content/76: 976e478e3f2972d8ee3a245dfbe7b62e
content/77: 0e87446547d645d6a9d3bf4cdf1578e7
content/78: 3211cb4fe3bc83c7c2b54399f0f9137c
content/79: 371d0e46b4bd2c23f559b8bc112f6955
content/80: 84b2621db57916bbc9e1ff0533cb38e8
content/81: bcadfc362b69078beee0088e5936c98b
content/82: 824ba104f268f10f2cc115913f6029ad
content/83: 64cc7298d2de7ceb78788d58d87898d9
content/84: 74cd415dadcb38afdca3f733866a1aa7
content/85: 371d0e46b4bd2c23f559b8bc112f6955
content/86: 32660308667470b041bb2ad58ea661c1
content/87: bcadfc362b69078beee0088e5936c98b
content/88: b029d32a6beabaca93723811cb26cd81
content/89: 7115d89068cd7857095940eaf8e1bddd
content/90: 61d17e01d34a752b71157b8a005ba057
content/91: 371d0e46b4bd2c23f559b8bc112f6955
content/92: 1ab0a1bc823fcf2de657524ceea291af
content/93: bcadfc362b69078beee0088e5936c98b
content/94: a7c67f06628744551a9ae8179f2de2f1
content/95: f309abdedd929f33810fffa5be8367c2
content/96: 37feff6bad59c085b76fade5530b3cef
content/97: 371d0e46b4bd2c23f559b8bc112f6955
content/98: f9b550860e44f6246a4f40c58c259b92
content/99: bcadfc362b69078beee0088e5936c98b
content/100: f88ef41a0cd5601c4ce748b36f256253
content/101: 675999bd8732f157f00284487dd610c7
content/102: 543a7893133239c24998013b6383a2ec
content/103: 371d0e46b4bd2c23f559b8bc112f6955
content/104: f6b0d1db4665a2bb31dfc8868b633e83
content/105: bcadfc362b69078beee0088e5936c98b
content/106: db8f7f803591cdb0d53aa6f6aeeadac9
content/107: 272d4f8e911da506722e66ea7fc06069
content/108: 3ab139411b417c30e7473cad1ed374a1
content/109: 371d0e46b4bd2c23f559b8bc112f6955
content/110: 4735e0cc24471b2d1083dfde44bcccd5
content/111: bcadfc362b69078beee0088e5936c98b
content/112: a205342d961d329a951066d1aeb9d344
content/113: 325a0443a09a80a7795a3e53d790a608
content/114: 907503eb014a7f0781237be119ed936c
content/115: 371d0e46b4bd2c23f559b8bc112f6955
content/116: b3f1358de153b9dab2ef4c04d992965d
content/117: bcadfc362b69078beee0088e5936c98b
content/118: 0e244093c7c68d2993dba96d32d78814
content/119: 1aa7fb20b2b2da0057d50edee1ee4804
content/120: b413d3cb6cc735740d52686d859141ce
content/121: 371d0e46b4bd2c23f559b8bc112f6955
content/122: 6c042d17fa1610528e0dda13884fd75d
content/123: bcadfc362b69078beee0088e5936c98b
content/124: c9febd022d469475d126e799d2ee3ddd
content/125: ad73b5cc613e18385c5b2b4d501d38cc
content/126: df462f7a572ad3994994f0ca76a68e76
content/127: 371d0e46b4bd2c23f559b8bc112f6955
content/128: 09899077a6a6b195512df6caf6c8fa01
content/129: bcadfc362b69078beee0088e5936c98b
content/130: 12f0d6903559cb1120d4a3148dd381e7
content/131: 9491f7740180102c9d049090daf5102a
content/132: 543a7893133239c24998013b6383a2ec
content/133: 371d0e46b4bd2c23f559b8bc112f6955
content/134: ecc05074290b48ca06325410279a51dc
content/135: bcadfc362b69078beee0088e5936c98b
content/136: 106cc40304bb3b99875a664945d20653
content/137: e903e245433fa0f0050609d0672c0cb5
content/138: 9791cc374db8ab132621a0ae7ec50964
content/139: 371d0e46b4bd2c23f559b8bc112f6955
content/140: 77522579656cf07dd8643eb54962a3e6
content/141: bcadfc362b69078beee0088e5936c98b
content/142: 97f12ce3c5e54f2b54792bf4eaeaa959
content/143: 5420a194a8d33ad00076e768c1a299f6
content/144: 2ef88df8b8a3684d125e9355a0dc57ce
content/145: 371d0e46b4bd2c23f559b8bc112f6955
content/146: 77522579656cf07dd8643eb54962a3e6
content/147: bcadfc362b69078beee0088e5936c98b
content/148: 25c2070b192a0c432f9c406fd3e68811
content/149: 7e57012ba94aa52f9b0a10c121414454
content/150: 7d384443444ff0f66076340b465adf8c
content/151: 371d0e46b4bd2c23f559b8bc112f6955
content/152: 77522579656cf07dd8643eb54962a3e6
content/153: bcadfc362b69078beee0088e5936c98b
content/154: 68f0fb5fb1c482871629a7ef6f68f401
content/155: 5fcce1f516514f07d19ada48a67e64b9
content/156: d0f8733556af6080f14f961a970d3ed2
content/157: 371d0e46b4bd2c23f559b8bc112f6955
content/158: 603d40532b35027d1070a1d511279dd7
content/159: bcadfc362b69078beee0088e5936c98b
content/160: 8854a695814f9c3e5408024a6de4b874
content/161: 38824704803684b47120f90d72c4d1f3
content/162: fae2b8c0813d8c4a16cfc1a939557b12
content/163: 371d0e46b4bd2c23f559b8bc112f6955
content/164: 3e87387b13c5a32cf60e79e288081d2a
content/165: bcadfc362b69078beee0088e5936c98b
content/166: e611f1b9fcd2ec209f7e8c541da0d334
content/167: e23262668801f4e01b1705bf2e06dbb9
content/168: 543a7893133239c24998013b6383a2ec
content/169: 371d0e46b4bd2c23f559b8bc112f6955
content/170: ea6bfafd502021032c8461583d575003
content/171: bcadfc362b69078beee0088e5936c98b
content/172: fc2291a33dbe5fb5a8e6e9fba4a962e5
content/173: 465f3cda4842dcbd91914420c94e7e2c
content/174: 0827bafb8fd84e5d2c941a5ba49180f9
content/175: 371d0e46b4bd2c23f559b8bc112f6955
content/176: 80d9e59852604254bbea9b5b429a56a9
content/177: bcadfc362b69078beee0088e5936c98b
content/178: e48a4a4332a93d669ae9d6734faf52ed
content/179: f4b3dc25c15cd089a940c3f87e1682cb
content/180: 29fcda568d59b51927e5032fea029bbb
content/181: 371d0e46b4bd2c23f559b8bc112f6955
content/182: 80d9e59852604254bbea9b5b429a56a9
content/183: bcadfc362b69078beee0088e5936c98b
content/184: d5fc19166d3a3cea8b8d2d50f0d563bb
content/185: d094dd11ce2f71593989b9f08ef50d1c
content/186: ecc367223a7d500e39174238f904c96b
content/187: 371d0e46b4bd2c23f559b8bc112f6955
content/188: 80d9e59852604254bbea9b5b429a56a9
content/189: bcadfc362b69078beee0088e5936c98b
content/190: 965bce63781360c2d25225ef73ab2be6
content/191: 91d09906a52576aca688686d68fe98c3
content/192: 0ef50aac80634edc58281abaf4c172de
content/193: 371d0e46b4bd2c23f559b8bc112f6955
content/194: 52d31c23ea85ff2429d9ffa3304764f7
content/195: bcadfc362b69078beee0088e5936c98b
content/196: e6f6c7f9ebe48b0904f00e22dc7fa6a5
content/197: 22e79701e2b405b16f3ec3eb1c45ab6e
content/198: 6c49f8ce476f21412e4d9ab21dd99a35
content/199: 371d0e46b4bd2c23f559b8bc112f6955
content/200: ef7d5b6b00dec889debfa44a73912f00
content/201: bcadfc362b69078beee0088e5936c98b
content/202: d0c41bb0907153104dbdc410f9f8bdb2
content/203: 33429e717ec12c6c21aaf8c08cebf59d
content/204: 0e8ff53af4c52be00d5dd6f6089e9eb6
content/205: 371d0e46b4bd2c23f559b8bc112f6955
content/206: 5fd8c99db5befe8b23fd5a689ce113a7
content/207: bcadfc362b69078beee0088e5936c98b
content/208: 6e076a87026c2bd5cec3f1e3f41f03e5
content/209: d0563ce6c297585d9c9597190d55dca4
content/210: 543a7893133239c24998013b6383a2ec
content/211: 371d0e46b4bd2c23f559b8bc112f6955
content/212: ce48d31c56d3bf55875623e232e3a4f7
content/213: bcadfc362b69078beee0088e5936c98b
content/214: f05f834e80d44f4b261ed70444986784
content/215: cc504b22e453c680bd5af9b7346a9b16
content/216: c09610268eeccf0bfd34ebd5dd35c007
content/217: 371d0e46b4bd2c23f559b8bc112f6955
content/218: b367871da0561ad3c5d7dacf2cb9a176
content/219: bcadfc362b69078beee0088e5936c98b
content/220: 85e1990e4f26720de4b40a1bc42a3e32
content/221: f630cb95b06d7aad74eb3ee3061ea255
content/222: ff11171170fa01ddfe1b54a6a9b7bf7e
content/223: 371d0e46b4bd2c23f559b8bc112f6955
content/224: b367871da0561ad3c5d7dacf2cb9a176
content/225: bcadfc362b69078beee0088e5936c98b
content/226: 2b9e1aad4a556211a265a182cbe25a05
content/227: 40965cc40257c6bd2be2cac20c5dfccb
content/228: 257fbd87a9b8b1c20190b5b91b304c37
content/229: 371d0e46b4bd2c23f559b8bc112f6955
content/230: b367871da0561ad3c5d7dacf2cb9a176
content/231: bcadfc362b69078beee0088e5936c98b
content/232: 55cb78c8d67ffcf7ada95dcc00bde23c
content/233: 6cef845ded645616c419d28bad1d6f9e
content/234: ba43c5aeb8f25faf46f26bf55b19bff1
content/235: 371d0e46b4bd2c23f559b8bc112f6955
content/236: 44115089ae4f362d5b4039b17ade418c
content/237: bcadfc362b69078beee0088e5936c98b
content/238: c3d9c66aa878494de5e962966252bcd4
content/239: ed22ba9ba05d9a98ddf5c52c37df20bd
content/240: 2cf208e195bb91c07ad9e53e948f6ddf
content/241: 371d0e46b4bd2c23f559b8bc112f6955
content/242: e6ef31303aa260ffd54368f310718c60
content/243: bcadfc362b69078beee0088e5936c98b
content/244: e8f550ccf6f5146969dc94e230896468
content/245: 4fb261f05c50668d4dbf59cb5b33187c
content/246: ca25da475b2c19ca9365eb40a3e883ef
content/247: 371d0e46b4bd2c23f559b8bc112f6955
content/248: 014b7067c2080c6778a1c5af5786de1f
content/249: bcadfc362b69078beee0088e5936c98b
content/250: 420275dbc42f605397d2e5d792dd0ec6
content/251: e3ae93e2557ade9f9101c7d7002ebae2
content/252: 41be55e87cb49923a825c78943f87cda
content/253: 371d0e46b4bd2c23f559b8bc112f6955
content/254: c86d375921bcc75708fbdcee104151e3
content/255: bcadfc362b69078beee0088e5936c98b
content/256: 49208ed01fcf6816c16f9be9c609bc3f
content/257: d786589994cd61d6822c95ef9bade462
content/258: e2a3bd59ba9f74919e79722d01b2cd08
content/259: 371d0e46b4bd2c23f559b8bc112f6955
content/260: fe4f450f29f2ab131ab01c1e3418050f
content/261: bcadfc362b69078beee0088e5936c98b
content/262: f0acbbe591b2053cfb0ff4592ada342d
content/263: 1e55ca66a9625b7e5d1d402a7b8ad866
content/264: 6191ceb51b5788eab069f6f9445ac7d9
content/265: 371d0e46b4bd2c23f559b8bc112f6955
content/266: ad4f64f06c612d941d8caf1241539721
content/267: bcadfc362b69078beee0088e5936c98b
content/268: f48fcfa0a3ed81e1a5090d7023745106
content/269: 02c6f039913ad3d9aeb4d64940b144a7
content/270: 3adfe68791a044e51a37c630a1164083
content/271: 371d0e46b4bd2c23f559b8bc112f6955
content/272: 4c6876bac6fc6e63bdfa336ed8287e82
content/273: bcadfc362b69078beee0088e5936c98b
content/274: 267cca917156e53a0a7191ea3b654dd2
content/275: 7f59ca32e2e37a892ec0fa0106980689
content/276: 837fe390f427bf342fdb347f660b8e24
content/277: 371d0e46b4bd2c23f559b8bc112f6955
content/278: 1e0346d0d1a808956842f5834a9a4ca7
content/279: bcadfc362b69078beee0088e5936c98b
content/280: 41138a38aa9cc6bf8d202404de595669
content/281: bfe437d8120b3bfdcb3d32f8baaa08cc
content/282: a45b4af8c2f1ce76300a770abfdb4586
content/283: 371d0e46b4bd2c23f559b8bc112f6955
content/284: b13666816ba70de0836700f0baa6a3cd
content/285: bcadfc362b69078beee0088e5936c98b
content/286: 41138a38aa9cc6bf8d202404de595669
content/287: 4d891a03094ba52d969bde716a26ef79
content/288: f00b571a9ab7a024a1b7256850110465
content/289: 371d0e46b4bd2c23f559b8bc112f6955
content/290: 285d1aaab77d5d2c1c6e3414c498458b
content/291: bcadfc362b69078beee0088e5936c98b
content/292: f3bb7d23cf26b0729d5c2bd050ee2f3d
content/293: cc51bfd76f006cb46a1f0971bf6725b3
content/294: 0740301dc6622444bf888739959cd064
content/295: 371d0e46b4bd2c23f559b8bc112f6955
content/296: dbaa8157daa175b74bf24a7a344d9b50
content/297: bcadfc362b69078beee0088e5936c98b
content/298: f3bb7d23cf26b0729d5c2bd050ee2f3d
content/299: 99c6883c74ac9ff2029bf9a993d108b2
content/300: 8888ecab4b3b39f2359344b27297b9fc
content/301: 371d0e46b4bd2c23f559b8bc112f6955
content/302: 725e1460c8d7e77af73130661211832b
content/303: bcadfc362b69078beee0088e5936c98b
content/304: 8d16e692f351c8018a19ebe10b42e600
content/305: 4c657061119501c3e92e44e2e1d34872
content/306: 47e2cc0eeec5f2cb91d830348d233911
content/307: 371d0e46b4bd2c23f559b8bc112f6955
content/308: 014b7067c2080c6778a1c5af5786de1f
content/309: bcadfc362b69078beee0088e5936c98b
content/310: 0a27f1dece5205a1fdad782471983af0
content/311: 208d2fe38550193159f17e05de690d3a
content/312: 3d1d49231eeb2920ffb765feb9099fd7
content/313: 371d0e46b4bd2c23f559b8bc112f6955
content/314: ac5aa666db2990b8e5c9328d435e6f2f
content/315: bcadfc362b69078beee0088e5936c98b
content/316: 63c2bbaa67c1f21c8394137da481c35c
content/317: d3fc31382a8b93b5798b0a8204200e9a
content/318: 41be55e87cb49923a825c78943f87cda
content/319: 371d0e46b4bd2c23f559b8bc112f6955
content/320: d71b6bb8e2dd6ce98101aec6a1dd77f2
content/321: bcadfc362b69078beee0088e5936c98b
content/322: 04a5b82cf37aba4a903f9fd607bf4321
content/323: a981995f0ce1ff26f910fa3f14084258
content/324: bb1385dbf0bd4ca26e69ee7259049758
content/325: 371d0e46b4bd2c23f559b8bc112f6955
content/326: b2cea0326a67f273c57fa21d72669c2d
content/327: bcadfc362b69078beee0088e5936c98b
content/328: 5f48c7eab78092422ecf5b876f38f5d6
content/329: 5465f9813e73a2b2434f093ae9f9e4fe
content/330: 41be55e87cb49923a825c78943f87cda
content/331: 371d0e46b4bd2c23f559b8bc112f6955
content/332: 5043d4e44428c5608442876f605f8fbf
content/333: bcadfc362b69078beee0088e5936c98b
content/334: 87050e58efe03557a55e784813899b25
content/335: 7daa967e284f004f64c8fbcac1dabd6d
content/336: 41be55e87cb49923a825c78943f87cda
content/337: 371d0e46b4bd2c23f559b8bc112f6955
content/338: 245d9a70b38a1b43467510b43b1dfd0b
content/339: bcadfc362b69078beee0088e5936c98b
content/340: b8b046b580b425b46ee97042b007cb5c
content/341: c516d20b10d7d47f9250156fdc05b51b
content/342: 41be55e87cb49923a825c78943f87cda
content/343: 371d0e46b4bd2c23f559b8bc112f6955
content/344: d3f7cf28e23f03c6ccd3c322a0dfcf7a
content/345: bcadfc362b69078beee0088e5936c98b
content/346: 87050e58efe03557a55e784813899b25
content/347: 93e76f13a0b2468f443b0addf2f5b426
content/348: fd835a0491ef404f10f95a64a8d799d7
content/349: 371d0e46b4bd2c23f559b8bc112f6955
content/350: 9330190b54228f4946546d6c918d362a
content/351: bcadfc362b69078beee0088e5936c98b
content/352: ef38c832c7c3e8a7912326a82e8e152d
content/353: cdbda4d943cce1c1e6cee284cd9499ba
content/354: afcdfbbd50590cddc8f328231183ffc7
content/355: 371d0e46b4bd2c23f559b8bc112f6955
content/356: 08b384a0452ac039fcd5a10c700887ef
content/357: bcadfc362b69078beee0088e5936c98b
content/358: 29bf3a3adb2e03579ce3067c31000cfe
content/359: ba0f72f52c6c1b69eb4b7ed77ace3eed
content/360: a0f850e27892642967e8387d236c7d3d
content/361: 371d0e46b4bd2c23f559b8bc112f6955
content/362: b1085b1b1b2cacf24e21dab7e53275ef
content/363: bcadfc362b69078beee0088e5936c98b
content/364: 3224246af0e256d3b1cebc4f5d4af7b8
content/365: 2b7033832f71a1afea2ad0de1a4eb0f6
content/366: 543a7893133239c24998013b6383a2ec
content/367: 371d0e46b4bd2c23f559b8bc112f6955
content/368: dacda77a1a1e6eb1fb09681a03b16b39
content/369: bcadfc362b69078beee0088e5936c98b
content/370: f92ddf910a76ccfba44526b5fc9e18eb
content/371: e5df0bf9989c8fb4bb8cc84bbc2893aa
content/372: 8d8179708a474294e5c18aa0f4c8e211
content/373: 371d0e46b4bd2c23f559b8bc112f6955
content/374: 13d49b60016c99dab88b976bc726dff2
content/375: bcadfc362b69078beee0088e5936c98b
content/376: 540cebf1a23579cbff89a8471080e513
content/377: 2316cd35c407ec12007f9791d7addc5d
content/378: 6a8a257b30c96326fb03188c00a8b89f
content/379: 371d0e46b4bd2c23f559b8bc112f6955
content/380: e9732d548f74b7cc7d045c755255d14b
content/381: bcadfc362b69078beee0088e5936c98b
content/382: d01baf6d3458f3e6ac1e1b93adbedc85
content/383: f04f7c69567c6d4641432928dd8fbbe0
content/384: 186964792066e564d16712d000144cfc
content/385: 371d0e46b4bd2c23f559b8bc112f6955
content/386: d71b6bb8e2dd6ce98101aec6a1dd77f2
content/387: bcadfc362b69078beee0088e5936c98b
content/388: 23531b030992d6af95a46fedf7ebba2d
content/389: 99e642e2d7e14f2de122fd31c8cc05a2
content/390: 67cb0568fb3a1ec30492380da7a07d76
content/391: 371d0e46b4bd2c23f559b8bc112f6955
content/392: 9dfe50ce64c70b434d17598a4ac8234b
content/393: bcadfc362b69078beee0088e5936c98b
content/394: ed2143e277e57380a95890c21950efa6
content/395: 0c6c2544d0bacb6f0f6fd613d858789a
content/396: 543a7893133239c24998013b6383a2ec
content/397: 371d0e46b4bd2c23f559b8bc112f6955
content/398: 6600803515bc80ef0b1a567c49794a6f
content/399: bcadfc362b69078beee0088e5936c98b
content/400: 36e4192fe30f586d12f1617efd6ef404
content/401: 6e7203406297c99cb022bb5c6afe0835
content/402: 543a7893133239c24998013b6383a2ec
content/403: 371d0e46b4bd2c23f559b8bc112f6955
content/404: d71b6bb8e2dd6ce98101aec6a1dd77f2
content/405: bcadfc362b69078beee0088e5936c98b
content/406: e30243efbaf6344a2588df16b7b03284
content/407: 16310c021653f143fa83827a9e4f3a34
content/408: 543a7893133239c24998013b6383a2ec
content/409: 371d0e46b4bd2c23f559b8bc112f6955
content/410: d71b6bb8e2dd6ce98101aec6a1dd77f2
content/411: bcadfc362b69078beee0088e5936c98b
content/412: 967acf2732882d79bbfbbb09157f5754
content/413: 80faf4b7ad34e672124993b741af2632
content/414: 513b1bd1010130caba927d7cb4ad317d
content/415: 371d0e46b4bd2c23f559b8bc112f6955
content/416: 683cb2f65472983ba73b76bd7b6e2d13
content/417: bcadfc362b69078beee0088e5936c98b
content/418: a6bb59aed6ec6c5cbc6380c07e5d875d
content/419: 020bf7263ea4bfdd38b730a5d97a1d27
content/420: c5a66ae6dd3d38e0955ddc199b241f94
content/421: 371d0e46b4bd2c23f559b8bc112f6955
content/422: e670ca8583015c3bbeaa9f0e04dc07e7
content/423: bcadfc362b69078beee0088e5936c98b
content/424: e35f604c54faeba3ab9cc9222b008e13
content/425: fcf4b372290efddeafde18f874cb9056
content/426: af6ffdf3979d631c1c0f3ce41aabcf56
content/427: 371d0e46b4bd2c23f559b8bc112f6955
content/428: f4d2b9c6ac152adb8676d09177e356bb
content/429: bcadfc362b69078beee0088e5936c98b
content/430: 49bc6ae2d6952bc9ff409d41bb0d21be
content/431: 4d6e4bbe907d379c3fbf703ab58b3022
content/432: 5536b11f94c6e96cc8ecb198bcf53ca7
content/433: 371d0e46b4bd2c23f559b8bc112f6955
content/434: f4d2b9c6ac152adb8676d09177e356bb
content/435: bcadfc362b69078beee0088e5936c98b
content/436: 49bc6ae2d6952bc9ff409d41bb0d21be
content/437: fd10df2f8761ee35226d0093777bdf6d
content/438: 95260d57dd53c9c3b7fe9429257e767e
content/439: 371d0e46b4bd2c23f559b8bc112f6955
content/440: 826b5d8ecc169a1e377687ac028040f5
content/441: bcadfc362b69078beee0088e5936c98b
content/442: 840756181376b103737fda44d21a98f6
content/443: 70fe3481a60a82c17db681eced11eada
content/444: e974d6f1cc3444d6f44495180e69b05e
content/445: 371d0e46b4bd2c23f559b8bc112f6955
content/446: 9921ba4d4de84198b763bc0bde6b03b3
content/447: bcadfc362b69078beee0088e5936c98b
content/448: d5f105ab1237fca610d09608b3b4e88d
content/449: 5b3b40dab522c857510f51a63237293c
content/450: 030bf2ff87d6c11732b684f306b4d2f5
content/451: 371d0e46b4bd2c23f559b8bc112f6955
content/452: 9ed3acd5390461eeb6414faf0a1a512e
content/453: bcadfc362b69078beee0088e5936c98b
content/454: eaca3ee3a7d41ebd10e3ede6127bf459
content/455: bf893edcd95310e98a3af9e73cdaae60
content/456: c0b33fa82175a4cc6ad90b02c67713b9
content/457: 371d0e46b4bd2c23f559b8bc112f6955
content/458: f82a23358be57576d645fa76c0955391
content/459: bcadfc362b69078beee0088e5936c98b
content/460: 834d3f74c39b74e6aa4c99ccd13a46e8
content/461: 67c97a416e8abeb8d61893c3f5ac17fd
content/462: c2f07afc0743347406fb9c9b98690997
content/463: 371d0e46b4bd2c23f559b8bc112f6955
content/464: 44d040b1598cbd8043043cb270da5bbb
content/465: bcadfc362b69078beee0088e5936c98b
content/466: c1a8cbf38b2a8480ea70243b38d509bc
content/467: dc3a650eefb9d65f582bfee6517ac2f9
content/468: 883277a3e47c7476d6356dc48df6c257
content/469: 371d0e46b4bd2c23f559b8bc112f6955
content/470: 96d428e4bb2231882653c845b590469b
content/471: bcadfc362b69078beee0088e5936c98b
content/472: dbc5fceeefb3ab5fa505394becafef4e
content/473: b3f310d5ef115bea5a8b75bf25d7ea9a
content/474: 27c398e669b297cea076e4ce4cc0c5eb

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 KiB

View File

@@ -4,10 +4,13 @@ DATABASE_URL="postgresql://postgres:password@localhost:5432/postgres"
# PostgreSQL Port (Optional) - defaults to 5432 if not specified
# POSTGRES_PORT=5432
# Authentication (Required)
# Authentication (Required unless DISABLE_AUTH=true)
BETTER_AUTH_SECRET=your_secret_key # Use `openssl rand -hex 32` to generate, or visit https://www.better-auth.com/docs/installation
BETTER_AUTH_URL=http://localhost:3000
# Authentication Bypass (Optional - for self-hosted deployments behind private networks)
# DISABLE_AUTH=true # Uncomment to bypass authentication entirely. Creates an anonymous session for all requests.
# NextJS (Required)
NEXT_PUBLIC_APP_URL=http://localhost:3000

View File

@@ -1,7 +1,7 @@
'use server'
import { env } from '@/lib/core/config/env'
import { isProd } from '@/lib/core/config/environment'
import { isProd } from '@/lib/core/config/feature-flags'
export async function getOAuthProviderStatus() {
const githubAvailable = !!(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET)

View File

@@ -1,7 +1,6 @@
import { getOAuthProviderStatus } from '@/app/(auth)/components/oauth-provider-checker'
import LoginForm from '@/app/(auth)/login/login-form'
// Force dynamic rendering to avoid prerender errors with search params
export const dynamic = 'force-dynamic'
export default async function LoginPage() {

View File

@@ -1,16 +1,16 @@
import { env, isTruthy } from '@/lib/core/config/env'
import { isRegistrationDisabled } from '@/lib/core/config/feature-flags'
import { getOAuthProviderStatus } from '@/app/(auth)/components/oauth-provider-checker'
import SignupForm from '@/app/(auth)/signup/signup-form'
export const dynamic = 'force-dynamic'
export default async function SignupPage() {
const { githubAvailable, googleAvailable, isProduction } = await getOAuthProviderStatus()
if (isTruthy(env.DISABLE_REGISTRATION)) {
if (isRegistrationDisabled) {
return <div>Registration is disabled, please contact your admin.</div>
}
const { githubAvailable, googleAvailable, isProduction } = await getOAuthProviderStatus()
return (
<SignupForm
githubAvailable={githubAvailable}

View File

@@ -1,4 +1,4 @@
import { isEmailVerificationEnabled, isProd } from '@/lib/core/config/environment'
import { isEmailVerificationEnabled, isProd } from '@/lib/core/config/feature-flags'
import { hasEmailService } from '@/lib/messaging/email/mailer'
import { VerifyContent } from '@/app/(auth)/verify/verify-content'

View File

@@ -1,6 +1,6 @@
import { createLogger } from '@/lib/logs/console/logger'
const DEFAULT_STARS = '18.6k'
const DEFAULT_STARS = '19.4k'
const logger = createLogger('GitHubStars')

View File

@@ -13,7 +13,7 @@ import {
SelectValue,
} from '@/components/ui/select'
import { Textarea } from '@/components/ui/textarea'
import { isHosted } from '@/lib/core/config/environment'
import { isHosted } from '@/lib/core/config/feature-flags'
import { cn } from '@/lib/core/utils/cn'
import { createLogger } from '@/lib/logs/console/logger'
import { quickValidateEmail } from '@/lib/messaging/email/validation'

View File

@@ -63,7 +63,6 @@ export const FOOTER_TOOLS = [
'Pipedrive',
'PostHog',
'PostgreSQL',
'Pylon',
'Qdrant',
'Reddit',
'Resend',

View File

@@ -1,6 +1,6 @@
'use client'
import { isHosted } from '@/lib/core/config/environment'
import { isHosted } from '@/lib/core/config/feature-flags'
import { soehne } from '@/app/_styles/fonts/soehne/soehne'
import Footer from '@/app/(landing)/components/footer/footer'
import Nav from '@/app/(landing)/components/nav/nav'

View File

@@ -7,7 +7,7 @@ import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { GithubIcon } from '@/components/icons'
import { useBrandConfig } from '@/lib/branding/branding'
import { isHosted } from '@/lib/core/config/environment'
import { isHosted } from '@/lib/core/config/feature-flags'
import { createLogger } from '@/lib/logs/console/logger'
import { soehne } from '@/app/_styles/fonts/soehne/soehne'
import { getFormattedGitHubStars } from '@/app/(landing)/actions/github'

View File

@@ -1,6 +1,23 @@
import { toNextJsHandler } from 'better-auth/next-js'
import { type NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { createAnonymousSession, ensureAnonymousUserExists } from '@/lib/auth/anonymous'
import { isAuthDisabled } from '@/lib/core/config/feature-flags'
export const dynamic = 'force-dynamic'
export const { GET, POST } = toNextJsHandler(auth.handler)
const { GET: betterAuthGET, POST: betterAuthPOST } = toNextJsHandler(auth.handler)
export async function GET(request: NextRequest) {
const url = new URL(request.url)
const path = url.pathname.replace('/api/auth/', '')
if (path === 'get-session' && isAuthDisabled) {
await ensureAnonymousUserExists()
return NextResponse.json(createAnonymousSession())
}
return betterAuthGET(request)
}
export const POST = betterAuthPOST

View File

@@ -1,9 +1,14 @@
import { headers } from 'next/headers'
import { NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { isAuthDisabled } from '@/lib/core/config/feature-flags'
export async function POST() {
try {
if (isAuthDisabled) {
return NextResponse.json({ token: 'anonymous-socket-token' })
}
const hdrs = await headers()
const response = await auth.api.generateOneTimeToken({
headers: hdrs,

View File

@@ -1,14 +1,14 @@
import { db, ssoProvider } from '@sim/db'
import { eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('SSO-Providers')
export async function GET(req: NextRequest) {
export async function GET() {
try {
const session = await auth.api.getSession({ headers: req.headers })
const session = await getSession()
let providers
if (session?.user?.id) {
@@ -38,8 +38,6 @@ export async function GET(req: NextRequest) {
: ('oidc' as 'oidc' | 'saml'),
}))
} else {
// Unauthenticated users can only see basic info (domain only)
// This is needed for SSO login flow to check if a domain has SSO enabled
const results = await db
.select({
domain: ssoProvider.domain,

View File

@@ -5,7 +5,7 @@ import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { checkAndBillOverageThreshold } from '@/lib/billing/threshold-billing'
import { checkInternalApiKey } from '@/lib/copilot/utils'
import { isBillingEnabled } from '@/lib/core/config/environment'
import { isBillingEnabled } from '@/lib/core/config/feature-flags'
import { generateRequestId } from '@/lib/core/utils/request'
import { createLogger } from '@/lib/logs/console/logger'

View File

@@ -132,7 +132,7 @@ export async function POST(
if ((password || email) && !input) {
const response = addCorsHeaders(createSuccessResponse({ authenticated: true }), request)
setChatAuthCookie(response, deployment.id, deployment.authType)
setChatAuthCookie(response, deployment.id, deployment.authType, deployment.password)
return response
}
@@ -315,7 +315,7 @@ export async function GET(
if (
deployment.authType !== 'public' &&
authCookie &&
validateAuthToken(authCookie.value, deployment.id)
validateAuthToken(authCookie.value, deployment.id, deployment.password)
) {
return addCorsHeaders(
createSuccessResponse({

View File

@@ -6,6 +6,12 @@ import { NextRequest } from 'next/server'
*/
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
vi.mock('@/lib/core/config/feature-flags', () => ({
isDev: true,
isHosted: false,
isProd: false,
}))
describe('Chat Edit API Route', () => {
const mockSelect = vi.fn()
const mockFrom = vi.fn()
@@ -24,7 +30,6 @@ describe('Chat Edit API Route', () => {
beforeEach(() => {
vi.resetModules()
// Set default return values
mockLimit.mockResolvedValue([])
mockSelect.mockReturnValue({ from: mockFrom })
mockFrom.mockReturnValue({ where: mockWhere })
@@ -77,10 +82,6 @@ describe('Chat Edit API Route', () => {
getEmailDomain: vi.fn().mockReturnValue('localhost:3000'),
}))
vi.doMock('@/lib/core/config/environment', () => ({
isDev: true,
}))
vi.doMock('@/app/api/chat/utils', () => ({
checkChatAccess: mockCheckChatAccess,
}))
@@ -254,7 +255,6 @@ describe('Chat Edit API Route', () => {
mockCheckChatAccess.mockResolvedValue({ hasAccess: true, chat: mockChat })
// Reset and reconfigure mockLimit to return the conflict
mockLimit.mockReset()
mockLimit.mockResolvedValue([{ id: 'other-chat-id', identifier: 'new-identifier' }])
mockWhere.mockReturnValue({ limit: mockLimit })
@@ -291,7 +291,7 @@ describe('Chat Edit API Route', () => {
const req = new NextRequest('http://localhost:3000/api/chat/manage/chat-123', {
method: 'PATCH',
body: JSON.stringify({ authType: 'password' }), // No password provided
body: JSON.stringify({ authType: 'password' }),
})
const { PATCH } = await import('@/app/api/chat/manage/[id]/route')
const response = await PATCH(req, { params: Promise.resolve({ id: 'chat-123' }) })
@@ -316,9 +316,8 @@ describe('Chat Edit API Route', () => {
workflowId: 'workflow-123',
}
// User doesn't own chat but has workspace admin access
mockCheckChatAccess.mockResolvedValue({ hasAccess: true, chat: mockChat })
mockLimit.mockResolvedValueOnce([]) // No identifier conflict
mockLimit.mockResolvedValueOnce([])
const req = new NextRequest('http://localhost:3000/api/chat/manage/chat-123', {
method: 'PATCH',
@@ -399,7 +398,6 @@ describe('Chat Edit API Route', () => {
}),
}))
// User doesn't own chat but has workspace admin access
mockCheckChatAccess.mockResolvedValue({ hasAccess: true })
mockWhere.mockResolvedValue(undefined)

View File

@@ -4,7 +4,7 @@ import { eq } from 'drizzle-orm'
import type { NextRequest } from 'next/server'
import { z } from 'zod'
import { getSession } from '@/lib/auth'
import { isDev } from '@/lib/core/config/environment'
import { isDev } from '@/lib/core/config/feature-flags'
import { encryptSecret } from '@/lib/core/security/encryption'
import { getEmailDomain } from '@/lib/core/utils/urls'
import { createLogger } from '@/lib/logs/console/logger'

View File

@@ -5,7 +5,7 @@ import type { NextRequest } from 'next/server'
import { v4 as uuidv4 } from 'uuid'
import { z } from 'zod'
import { getSession } from '@/lib/auth'
import { isDev } from '@/lib/core/config/environment'
import { isDev } from '@/lib/core/config/feature-flags'
import { encryptSecret } from '@/lib/core/security/encryption'
import { getBaseUrl } from '@/lib/core/utils/urls'
import { createLogger } from '@/lib/logs/console/logger'

View File

@@ -44,6 +44,12 @@ vi.mock('@/lib/core/utils/request', () => ({
generateRequestId: vi.fn(),
}))
vi.mock('@/lib/core/config/feature-flags', () => ({
isDev: true,
isHosted: false,
isProd: false,
}))
describe('Chat API Utils', () => {
beforeEach(() => {
vi.doMock('@/lib/logs/console/logger', () => ({
@@ -62,11 +68,6 @@ describe('Chat API Utils', () => {
NODE_ENV: 'development',
},
})
vi.doMock('@/lib/core/config/environment', () => ({
isDev: true,
isHosted: false,
}))
})
afterEach(() => {

View File

@@ -1,14 +1,19 @@
import { createHash } from 'crypto'
import { db } from '@sim/db'
import { chat, workflow } from '@sim/db/schema'
import { eq } from 'drizzle-orm'
import type { NextRequest, NextResponse } from 'next/server'
import { isDev } from '@/lib/core/config/environment'
import { isDev } from '@/lib/core/config/feature-flags'
import { decryptSecret } from '@/lib/core/security/encryption'
import { createLogger } from '@/lib/logs/console/logger'
import { hasAdminPermission } from '@/lib/workspaces/permissions/utils'
const logger = createLogger('ChatAuthUtils')
function hashPassword(encryptedPassword: string): string {
return createHash('sha256').update(encryptedPassword).digest('hex').substring(0, 8)
}
/**
* Check if user has permission to create a chat for a specific workflow
* Either the user owns the workflow directly OR has admin permission for the workflow's workspace
@@ -77,14 +82,20 @@ export async function checkChatAccess(
return { hasAccess: false }
}
const encryptAuthToken = (chatId: string, type: string): string => {
return Buffer.from(`${chatId}:${type}:${Date.now()}`).toString('base64')
function encryptAuthToken(chatId: string, type: string, encryptedPassword?: string | null): string {
const pwHash = encryptedPassword ? hashPassword(encryptedPassword) : ''
return Buffer.from(`${chatId}:${type}:${Date.now()}:${pwHash}`).toString('base64')
}
export const validateAuthToken = (token: string, chatId: string): boolean => {
export function validateAuthToken(
token: string,
chatId: string,
encryptedPassword?: string | null
): boolean {
try {
const decoded = Buffer.from(token, 'base64').toString()
const [storedId, _type, timestamp] = decoded.split(':')
const parts = decoded.split(':')
const [storedId, _type, timestamp, storedPwHash] = parts
if (storedId !== chatId) {
return false
@@ -92,20 +103,32 @@ export const validateAuthToken = (token: string, chatId: string): boolean => {
const createdAt = Number.parseInt(timestamp)
const now = Date.now()
const expireTime = 24 * 60 * 60 * 1000 // 24 hours
const expireTime = 24 * 60 * 60 * 1000
if (now - createdAt > expireTime) {
return false
}
if (encryptedPassword) {
const currentPwHash = hashPassword(encryptedPassword)
if (storedPwHash !== currentPwHash) {
return false
}
}
return true
} catch (_e) {
return false
}
}
export const setChatAuthCookie = (response: NextResponse, chatId: string, type: string): void => {
const token = encryptAuthToken(chatId, type)
export function setChatAuthCookie(
response: NextResponse,
chatId: string,
type: string,
encryptedPassword?: string | null
): void {
const token = encryptAuthToken(chatId, type, encryptedPassword)
response.cookies.set({
name: `chat_auth_${chatId}`,
value: token,
@@ -113,7 +136,7 @@ export const setChatAuthCookie = (response: NextResponse, chatId: string, type:
secure: !isDev,
sameSite: 'lax',
path: '/',
maxAge: 60 * 60 * 24, // 24 hours
maxAge: 60 * 60 * 24,
})
}
@@ -145,7 +168,7 @@ export async function validateChatAuth(
const cookieName = `chat_auth_${deployment.id}`
const authCookie = request.cookies.get(cookieName)
if (authCookie && validateAuthToken(authCookie.value, deployment.id)) {
if (authCookie && validateAuthToken(authCookie.value, deployment.id, deployment.password)) {
return { authorized: true }
}
@@ -259,8 +282,8 @@ export async function validateChatAuth(
return { authorized: false, error: 'Email not authorized for SSO access' }
}
const { auth } = await import('@/lib/auth')
const session = await auth.api.getSession({ headers: request.headers })
const { getSession } = await import('@/lib/auth')
const session = await getSession()
if (!session || !session.user) {
return { authorized: false, error: 'auth_required_sso' }

View File

@@ -2,7 +2,7 @@ import { db } from '@sim/db'
import { settings } from '@sim/db/schema'
import { eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('CopilotAutoAllowedToolsAPI')
@@ -10,9 +10,9 @@ const logger = createLogger('CopilotAutoAllowedToolsAPI')
/**
* GET - Fetch user's auto-allowed integration tools
*/
export async function GET(request: NextRequest) {
export async function GET() {
try {
const session = await auth.api.getSession({ headers: request.headers })
const session = await getSession()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
@@ -31,7 +31,6 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ autoAllowedTools })
}
// If no settings record exists, create one with empty array
await db.insert(settings).values({
id: userId,
userId,
@@ -50,7 +49,7 @@ export async function GET(request: NextRequest) {
*/
export async function POST(request: NextRequest) {
try {
const session = await auth.api.getSession({ headers: request.headers })
const session = await getSession()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
@@ -65,13 +64,11 @@ export async function POST(request: NextRequest) {
const toolId = body.toolId
// Get existing settings
const [existing] = await db.select().from(settings).where(eq(settings.userId, userId)).limit(1)
if (existing) {
const currentTools = (existing.copilotAutoAllowedTools as string[]) || []
// Add tool if not already present
if (!currentTools.includes(toolId)) {
const updatedTools = [...currentTools, toolId]
await db
@@ -89,7 +86,6 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, autoAllowedTools: currentTools })
}
// Create new settings record with the tool
await db.insert(settings).values({
id: userId,
userId,
@@ -109,7 +105,7 @@ export async function POST(request: NextRequest) {
*/
export async function DELETE(request: NextRequest) {
try {
const session = await auth.api.getSession({ headers: request.headers })
const session = await getSession()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
@@ -123,7 +119,6 @@ export async function DELETE(request: NextRequest) {
return NextResponse.json({ error: 'toolId query parameter is required' }, { status: 400 })
}
// Get existing settings
const [existing] = await db.select().from(settings).where(eq(settings.userId, userId)).limit(1)
if (existing) {

View File

@@ -1,6 +1,6 @@
import { eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console/logger'
import { db } from '@/../../packages/db'
import { settings } from '@/../../packages/db/schema'
@@ -32,7 +32,7 @@ const DEFAULT_ENABLED_MODELS: Record<string, boolean> = {
// GET - Fetch user's enabled models
export async function GET(request: NextRequest) {
try {
const session = await auth.api.getSession({ headers: request.headers })
const session = await getSession()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
@@ -40,7 +40,6 @@ export async function GET(request: NextRequest) {
const userId = session.user.id
// Try to fetch existing settings record
const [userSettings] = await db
.select()
.from(settings)
@@ -50,13 +49,11 @@ export async function GET(request: NextRequest) {
if (userSettings) {
const userModelsMap = (userSettings.copilotEnabledModels as Record<string, boolean>) || {}
// Merge: start with defaults, then override with user's existing preferences
const mergedModels = { ...DEFAULT_ENABLED_MODELS }
for (const [modelId, enabled] of Object.entries(userModelsMap)) {
mergedModels[modelId] = enabled
}
// If we added any new models, update the database
const hasNewModels = Object.keys(DEFAULT_ENABLED_MODELS).some(
(key) => !(key in userModelsMap)
)
@@ -76,7 +73,6 @@ export async function GET(request: NextRequest) {
})
}
// If no settings record exists, create one with defaults
await db.insert(settings).values({
id: userId,
userId,
@@ -97,7 +93,7 @@ export async function GET(request: NextRequest) {
// PUT - Update user's enabled models
export async function PUT(request: NextRequest) {
try {
const session = await auth.api.getSession({ headers: request.headers })
const session = await getSession()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
@@ -110,11 +106,9 @@ export async function PUT(request: NextRequest) {
return NextResponse.json({ error: 'enabledModels must be an object' }, { status: 400 })
}
// Check if settings record exists
const [existing] = await db.select().from(settings).where(eq(settings.userId, userId)).limit(1)
if (existing) {
// Update existing record
await db
.update(settings)
.set({
@@ -123,7 +117,6 @@ export async function PUT(request: NextRequest) {
})
.where(eq(settings.userId, userId))
} else {
// Create new settings record
await db.insert(settings).values({
id: userId,
userId,

View File

@@ -1,6 +1,6 @@
import { createContext, Script } from 'vm'
import { type NextRequest, NextResponse } from 'next/server'
import { env, isTruthy } from '@/lib/core/config/env'
import { isE2bEnabled } from '@/lib/core/config/feature-flags'
import { validateProxyUrl } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request'
import { executeInE2B } from '@/lib/execution/e2b'
@@ -701,7 +701,6 @@ export async function POST(req: NextRequest) {
resolvedCode = codeResolution.resolvedCode
const contextVariables = codeResolution.contextVariables
const e2bEnabled = isTruthy(env.E2B_ENABLED)
const lang = isValidCodeLanguage(language) ? language : DEFAULT_CODE_LANGUAGE
// Extract imports once for JavaScript code (reuse later to avoid double extraction)
@@ -722,14 +721,14 @@ export async function POST(req: NextRequest) {
}
// Python always requires E2B
if (lang === CodeLanguage.Python && !e2bEnabled) {
if (lang === CodeLanguage.Python && !isE2bEnabled) {
throw new Error(
'Python execution requires E2B to be enabled. Please contact your administrator to enable E2B, or use JavaScript instead.'
)
}
// JavaScript with imports requires E2B
if (lang === CodeLanguage.JavaScript && hasImports && !e2bEnabled) {
if (lang === CodeLanguage.JavaScript && hasImports && !isE2bEnabled) {
throw new Error(
'JavaScript code with import statements requires E2B to be enabled. Please remove the import statements, or contact your administrator to enable E2B.'
)
@@ -740,13 +739,13 @@ export async function POST(req: NextRequest) {
// - Not a custom tool AND
// - (Python OR JavaScript with imports)
const useE2B =
e2bEnabled &&
isE2bEnabled &&
!isCustomTool &&
(lang === CodeLanguage.Python || (lang === CodeLanguage.JavaScript && hasImports))
if (useE2B) {
logger.info(`[${requestId}] E2B status`, {
enabled: e2bEnabled,
enabled: isE2bEnabled,
hasApiKey: Boolean(process.env.E2B_API_KEY),
language: lang,
})

View File

@@ -6,7 +6,7 @@ import { z } from 'zod'
import { getSession } from '@/lib/auth'
import { getPlanPricing } from '@/lib/billing/core/billing'
import { requireStripeClient } from '@/lib/billing/stripe-client'
import { isBillingEnabled } from '@/lib/core/config/environment'
import { isBillingEnabled } from '@/lib/core/config/feature-flags'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('OrganizationSeatsAPI')

View File

@@ -3,7 +3,7 @@ import { NextResponse } from 'next/server'
import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid'
import { generateInternalToken } from '@/lib/auth/internal'
import { isDev } from '@/lib/core/config/environment'
import { isDev } from '@/lib/core/config/feature-flags'
import { createPinnedUrl, validateUrlWithDNS } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request'
import { getBaseUrl } from '@/lib/core/utils/urls'

View File

@@ -1,26 +1,81 @@
import { db } from '@sim/db'
import { chat } from '@sim/db/schema'
import { eq } from 'drizzle-orm'
import type { NextRequest } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid'
import { env } from '@/lib/core/config/env'
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import { createLogger } from '@/lib/logs/console/logger'
import { validateAuthToken } from '@/app/api/chat/utils'
const logger = createLogger('ProxyTTSStreamAPI')
export async function POST(request: NextRequest) {
/**
* Validates chat-based authentication for deployed chat voice mode
* Checks if the user has a valid chat auth cookie for the given chatId
*/
async function validateChatAuth(request: NextRequest, chatId: string): Promise<boolean> {
try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
if (!authResult.success) {
logger.error('Authentication failed for TTS stream proxy:', authResult.error)
return new Response('Unauthorized', { status: 401 })
const chatResult = await db
.select({
id: chat.id,
isActive: chat.isActive,
authType: chat.authType,
password: chat.password,
})
.from(chat)
.where(eq(chat.id, chatId))
.limit(1)
if (chatResult.length === 0 || !chatResult[0].isActive) {
logger.warn('Chat not found or inactive for TTS auth:', chatId)
return false
}
const body = await request.json()
const { text, voiceId, modelId = 'eleven_turbo_v2_5' } = body
const chatData = chatResult[0]
if (chatData.authType === 'public') {
return true
}
const cookieName = `chat_auth_${chatId}`
const authCookie = request.cookies.get(cookieName)
if (authCookie && validateAuthToken(authCookie.value, chatId, chatData.password)) {
return true
}
return false
} catch (error) {
logger.error('Error validating chat auth for TTS:', error)
return false
}
}
export async function POST(request: NextRequest) {
try {
let body: any
try {
body = await request.json()
} catch {
return new Response('Invalid request body', { status: 400 })
}
const { text, voiceId, modelId = 'eleven_turbo_v2_5', chatId } = body
if (!chatId) {
return new Response('chatId is required', { status: 400 })
}
if (!text || !voiceId) {
return new Response('Missing required parameters', { status: 400 })
}
const isChatAuthed = await validateChatAuth(request, chatId)
if (!isChatAuthed) {
logger.warn('Chat authentication failed for TTS, chatId:', chatId)
return new Response('Unauthorized', { status: 401 })
}
const voiceIdValidation = validateAlphanumericId(voiceId, 'voiceId', 255)
if (!voiceIdValidation.isValid) {
logger.error(`Invalid voice ID: ${voiceIdValidation.error}`)

View File

@@ -1,6 +1,7 @@
import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid'
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import { getBaseUrl } from '@/lib/core/utils/urls'
import { createLogger } from '@/lib/logs/console/logger'
import { StorageService } from '@/lib/uploads'
@@ -147,6 +148,10 @@ export async function POST(request: NextRequest) {
{ status: 400 }
)
}
const voiceIdValidation = validateAlphanumericId(body.voiceId, 'voiceId')
if (!voiceIdValidation.isValid) {
return NextResponse.json({ error: voiceIdValidation.error }, { status: 400 })
}
const result = await synthesizeWithElevenLabs({
text,
apiKey,

View File

@@ -807,18 +807,31 @@ async function generateWithFalAI(
// Build request body based on model requirements
const requestBody: any = { prompt }
// Format duration based on model requirements
const formattedDuration = formatDuration(model, duration)
if (formattedDuration !== undefined) {
requestBody.duration = formattedDuration
}
// Models that support duration and aspect_ratio parameters
const supportsStandardParams = [
'kling-2.5-turbo-pro',
'kling-2.1-pro',
'minimax-hailuo-2.3-pro',
'minimax-hailuo-2.3-standard',
]
if (aspectRatio) {
requestBody.aspect_ratio = aspectRatio
}
// Models that only need prompt (minimal params)
const minimalParamModels = ['ltxv-0.9.8', 'wan-2.1', 'veo-3.1', 'sora-2']
if (resolution) {
requestBody.resolution = resolution
if (supportsStandardParams.includes(model)) {
// Kling and MiniMax models support duration and aspect_ratio
const formattedDuration = formatDuration(model, duration)
if (formattedDuration !== undefined) {
requestBody.duration = formattedDuration
}
if (aspectRatio) {
requestBody.aspect_ratio = aspectRatio
}
if (resolution) {
requestBody.resolution = resolution
}
}
// MiniMax models support prompt optimizer

View File

@@ -42,11 +42,11 @@ describe('Scheduled Workflow Execution API Route', () => {
executeScheduleJob: mockExecuteScheduleJob,
}))
vi.doMock('@/lib/core/config/env', () => ({
env: {
TRIGGER_DEV_ENABLED: false,
},
isTruthy: vi.fn(() => false),
vi.doMock('@/lib/core/config/feature-flags', () => ({
isTriggerDevEnabled: false,
isHosted: false,
isProd: false,
isDev: true,
}))
vi.doMock('drizzle-orm', () => ({
@@ -119,11 +119,11 @@ describe('Scheduled Workflow Execution API Route', () => {
},
}))
vi.doMock('@/lib/core/config/env', () => ({
env: {
TRIGGER_DEV_ENABLED: true,
},
isTruthy: vi.fn(() => true),
vi.doMock('@/lib/core/config/feature-flags', () => ({
isTriggerDevEnabled: true,
isHosted: false,
isProd: false,
isDev: true,
}))
vi.doMock('drizzle-orm', () => ({
@@ -191,11 +191,11 @@ describe('Scheduled Workflow Execution API Route', () => {
executeScheduleJob: vi.fn().mockResolvedValue(undefined),
}))
vi.doMock('@/lib/core/config/env', () => ({
env: {
TRIGGER_DEV_ENABLED: false,
},
isTruthy: vi.fn(() => false),
vi.doMock('@/lib/core/config/feature-flags', () => ({
isTriggerDevEnabled: false,
isHosted: false,
isProd: false,
isDev: true,
}))
vi.doMock('drizzle-orm', () => ({
@@ -250,11 +250,11 @@ describe('Scheduled Workflow Execution API Route', () => {
executeScheduleJob: vi.fn().mockResolvedValue(undefined),
}))
vi.doMock('@/lib/core/config/env', () => ({
env: {
TRIGGER_DEV_ENABLED: false,
},
isTruthy: vi.fn(() => false),
vi.doMock('@/lib/core/config/feature-flags', () => ({
isTriggerDevEnabled: false,
isHosted: false,
isProd: false,
isDev: true,
}))
vi.doMock('drizzle-orm', () => ({

View File

@@ -3,7 +3,7 @@ import { tasks } from '@trigger.dev/sdk'
import { and, eq, isNull, lt, lte, not, or } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { verifyCronAuth } from '@/lib/auth/internal'
import { env, isTruthy } from '@/lib/core/config/env'
import { isTriggerDevEnabled } from '@/lib/core/config/feature-flags'
import { generateRequestId } from '@/lib/core/utils/request'
import { createLogger } from '@/lib/logs/console/logger'
import { executeScheduleJob } from '@/background/schedule-execution'
@@ -54,9 +54,7 @@ export async function GET(request: NextRequest) {
logger.debug(`[${requestId}] Successfully queried schedules: ${dueSchedules.length} found`)
logger.info(`[${requestId}] Processing ${dueSchedules.length} due scheduled workflows`)
const useTrigger = isTruthy(env.TRIGGER_DEV_ENABLED)
if (useTrigger) {
if (isTriggerDevEnabled) {
const triggerPromises = dueSchedules.map(async (schedule) => {
const queueTime = schedule.lastQueuedAt ?? queuedAt

View File

@@ -23,13 +23,13 @@ export async function GET() {
if (!response.ok) {
console.warn('GitHub API request failed:', response.status)
return NextResponse.json({ stars: formatStarCount(14500) })
return NextResponse.json({ stars: formatStarCount(19400) })
}
const data = await response.json()
return NextResponse.json({ stars: formatStarCount(Number(data?.stargazers_count ?? 14500)) })
return NextResponse.json({ stars: formatStarCount(Number(data?.stargazers_count ?? 19400)) })
} catch (error) {
console.warn('Error fetching GitHub stars:', error)
return NextResponse.json({ stars: formatStarCount(14500) })
return NextResponse.json({ stars: formatStarCount(19400) })
}
}

View File

@@ -1,6 +1,6 @@
import { type NextRequest, NextResponse } from 'next/server'
import { env } from '@/lib/core/config/env'
import { isProd } from '@/lib/core/config/environment'
import { isProd } from '@/lib/core/config/feature-flags'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('TelemetryAPI')

View File

@@ -40,7 +40,7 @@ const CreateTemplateSchema = z.object({
about: z.string().optional(), // Markdown long description
})
.optional(),
creatorId: z.string().optional(), // Creator profile ID
creatorId: z.string().min(1, 'Creator profile is required'),
tags: z.array(z.string()).max(10, 'Maximum 10 tags allowed').optional().default([]),
})
@@ -204,50 +204,47 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ error: 'Workflow not found' }, { status: 404 })
}
// Validate creator profile if provided
if (data.creatorId) {
// Verify the creator profile exists and user has access
const creatorProfile = await db
// Validate creator profile - required for all templates
const creatorProfile = await db
.select()
.from(templateCreators)
.where(eq(templateCreators.id, data.creatorId))
.limit(1)
if (creatorProfile.length === 0) {
logger.warn(`[${requestId}] Creator profile not found: ${data.creatorId}`)
return NextResponse.json({ error: 'Creator profile not found' }, { status: 404 })
}
const creator = creatorProfile[0]
// Verify user has permission to use this creator profile
if (creator.referenceType === 'user') {
if (creator.referenceId !== session.user.id) {
logger.warn(`[${requestId}] User cannot use creator profile: ${data.creatorId}`)
return NextResponse.json(
{ error: 'You do not have permission to use this creator profile' },
{ status: 403 }
)
}
} else if (creator.referenceType === 'organization') {
// Verify user is a member of the organization
const membership = await db
.select()
.from(templateCreators)
.where(eq(templateCreators.id, data.creatorId))
.from(member)
.where(
and(eq(member.userId, session.user.id), eq(member.organizationId, creator.referenceId))
)
.limit(1)
if (creatorProfile.length === 0) {
logger.warn(`[${requestId}] Creator profile not found: ${data.creatorId}`)
return NextResponse.json({ error: 'Creator profile not found' }, { status: 404 })
}
const creator = creatorProfile[0]
// Verify user has permission to use this creator profile
if (creator.referenceType === 'user') {
if (creator.referenceId !== session.user.id) {
logger.warn(`[${requestId}] User cannot use creator profile: ${data.creatorId}`)
return NextResponse.json(
{ error: 'You do not have permission to use this creator profile' },
{ status: 403 }
)
}
} else if (creator.referenceType === 'organization') {
// Verify user is a member of the organization
const membership = await db
.select()
.from(member)
.where(
and(eq(member.userId, session.user.id), eq(member.organizationId, creator.referenceId))
)
.limit(1)
if (membership.length === 0) {
logger.warn(
`[${requestId}] User not a member of organization for creator: ${data.creatorId}`
)
return NextResponse.json(
{ error: 'You must be a member of the organization to use its creator profile' },
{ status: 403 }
)
}
if (membership.length === 0) {
logger.warn(
`[${requestId}] User not a member of organization for creator: ${data.creatorId}`
)
return NextResponse.json(
{ error: 'You must be a member of the organization to use its creator profile' },
{ status: 403 }
)
}
}
@@ -307,7 +304,7 @@ export async function POST(request: NextRequest) {
workflowId: data.workflowId,
name: data.name,
details: data.details || null,
creatorId: data.creatorId || null,
creatorId: data.creatorId,
views: 0,
stars: 0,
status: 'pending' as const, // All new templates start as pending

View File

@@ -1,6 +1,7 @@
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid'
import { validateNumericId } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request'
import { createLogger } from '@/lib/logs/console/logger'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
@@ -41,6 +42,17 @@ export async function POST(request: NextRequest) {
const body = await request.json()
const validatedData = DiscordSendMessageSchema.parse(body)
const channelIdValidation = validateNumericId(validatedData.channelId, 'channelId')
if (!channelIdValidation.isValid) {
logger.warn(`[${requestId}] Invalid channelId format`, {
error: channelIdValidation.error,
})
return NextResponse.json(
{ success: false, error: channelIdValidation.error },
{ status: 400 }
)
}
logger.info(`[${requestId}] Sending Discord message`, {
channelId: validatedData.channelId,
hasFiles: !!(validatedData.files && validatedData.files.length > 0),

View File

@@ -1,4 +1,3 @@
import { Stagehand } from '@browserbasehq/stagehand'
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { env } from '@/lib/core/config/env'
@@ -7,6 +6,8 @@ import { ensureZodObject, normalizeUrl } from '@/app/api/tools/stagehand/utils'
const logger = createLogger('StagehandAgentAPI')
type StagehandType = import('@browserbasehq/stagehand').Stagehand
const BROWSERBASE_API_KEY = env.BROWSERBASE_API_KEY
const BROWSERBASE_PROJECT_ID = env.BROWSERBASE_PROJECT_ID
@@ -15,9 +16,13 @@ const requestSchema = z.object({
startUrl: z.string().url(),
outputSchema: z.any(),
variables: z.any(),
provider: z.enum(['openai', 'anthropic']).optional().default('openai'),
apiKey: z.string(),
})
/**
* Extracts the inner schema object from a potentially nested schema structure
*/
function getSchemaObject(outputSchema: Record<string, any>): Record<string, any> {
if (outputSchema.schema && typeof outputSchema.schema === 'object') {
return outputSchema.schema
@@ -25,6 +30,9 @@ function getSchemaObject(outputSchema: Record<string, any>): Record<string, any>
return outputSchema
}
/**
* Formats a schema object as a string for inclusion in agent instructions
*/
function formatSchemaForInstructions(schema: Record<string, any>): string {
try {
return JSON.stringify(schema, null, 2)
@@ -34,359 +42,55 @@ function formatSchemaForInstructions(schema: Record<string, any>): string {
}
}
function extractActionDirectives(task: string): {
processedTask: string
actionDirectives: Array<{ index: number; action: string }>
} {
const actionRegex = /\[\[ACTION:(.*?)\]\]/g
const actionDirectives: Array<{ index: number; action: string }> = []
let match
let processedTask = task
/**
* Processes variables from various input formats into a standardized key-value object
*/
function processVariables(variables: any): Record<string, string> | undefined {
if (!variables) return undefined
while ((match = actionRegex.exec(task)) !== null) {
const actionText = match[1].trim()
const index = match.index
let variablesObject: Record<string, string> = {}
actionDirectives.push({
index,
action: actionText,
if (Array.isArray(variables)) {
variables.forEach((item: any) => {
if (item?.cells?.Key && typeof item.cells.Key === 'string') {
variablesObject[item.cells.Key] = item.cells.Value || ''
}
})
}
if (actionDirectives.length > 0) {
let offset = 0
for (let i = 0; i < actionDirectives.length; i++) {
const directive = actionDirectives[i]
const originalIndex = directive.index
const placeholder = `[SECURE ACTION ${i + 1}]`
const adjustedIndex = originalIndex - offset
const fullMatch = task.substring(
originalIndex,
originalIndex + task.substring(originalIndex).indexOf(']]') + 2
)
processedTask =
processedTask.substring(0, adjustedIndex) +
placeholder +
processedTask.substring(adjustedIndex + fullMatch.length)
offset += fullMatch.length - placeholder.length
} else if (typeof variables === 'object' && variables !== null) {
variablesObject = { ...variables }
} else if (typeof variables === 'string') {
try {
variablesObject = JSON.parse(variables)
} catch (_e) {
logger.warn('Failed to parse variables string as JSON', { variables })
return undefined
}
}
return { processedTask, actionDirectives }
if (Object.keys(variablesObject).length === 0) {
return undefined
}
return variablesObject
}
async function processSecureActions(
message: string,
stagehand: Stagehand,
actionDirectives: Array<{ index: number; action: string }>,
variables: Record<string, string> | undefined
): Promise<{
modifiedMessage: string
executedActions: Array<{ action: string; result: { success: boolean; message: string } }>
}> {
const executedActions: Array<{ action: string; result: { success: boolean; message: string } }> =
[]
let modifiedMessage = message
/**
* Substitutes variable placeholders in text with their actual values
* Variables are referenced using %key% syntax
*/
function substituteVariables(text: string, variables: Record<string, string> | undefined): string {
if (!variables) return text
const secureActionMatches = [...message.matchAll(/EXECUTE SECURE ACTION (\d+)/gi)]
for (const match of secureActionMatches) {
const fullMatch = match[0]
const actionIndex = Number.parseInt(match[1], 10) - 1
if (actionDirectives[actionIndex]) {
const actionDirective = actionDirectives[actionIndex]
let resultMessage = ''
try {
logger.info(`Executing secure action ${actionIndex + 1}`, {
action: actionDirective.action,
})
const result = await stagehand.act(actionDirective.action, {
variables: variables || {},
})
executedActions.push({
action: actionDirective.action,
result: {
success: result.success,
message: result.message,
},
})
resultMessage = `\nSecure action ${actionIndex + 1} executed successfully.\n`
} catch (error) {
logger.error(`Error executing secure action ${actionIndex + 1}`, {
error,
action: actionDirective.action,
})
executedActions.push({
action: actionDirective.action,
result: {
success: false,
message: error instanceof Error ? error.message : 'Unknown error',
},
})
resultMessage = `\nError executing secure action ${actionIndex + 1}: ${error instanceof Error ? error.message : 'Unknown error'}\n`
}
modifiedMessage = modifiedMessage.replace(fullMatch, resultMessage)
} else {
const errorMessage = `\nError: Secure action ${actionIndex + 1} does not exist.\n`
modifiedMessage = modifiedMessage.replace(fullMatch, errorMessage)
}
}
return { modifiedMessage, executedActions }
}
async function attemptDirectLogin(
stagehand: Stagehand,
variables: Record<string, string> | undefined
): Promise<{
attempted: boolean
success: boolean
message: string
}> {
if (!stagehand || !variables) {
return {
attempted: false,
success: false,
message: 'Login not attempted: missing stagehand or variables',
}
}
const usernameKeys = ['username', 'email', 'user']
const passwordKeys = ['password', 'pass', 'secret']
const usernameKey = usernameKeys.find((key) => variables[key] !== undefined)
const passwordKey = passwordKeys.find((key) => variables[key] !== undefined)
if (!usernameKey || !passwordKey) {
logger.info('Direct login skipped: Missing username or password variable.')
return {
attempted: false,
success: false,
message: 'Login not attempted: Missing username or password variable.',
}
}
const usernameValue = variables[usernameKey]
const passwordValue = variables[passwordKey]
logger.info('Attempting direct login with provided variables.')
try {
const page = stagehand.context.pages()[0]
const usernameSelectors = [
'input[type="text"][name*="user"]',
'input[type="email"]',
'input[name*="email"]',
'input[id*="user"]',
'input[id*="email"]',
'input[placeholder*="user" i]',
'input[placeholder*="email" i]',
'input[aria-label*="user" i]',
'input[aria-label*="email" i]',
]
const passwordSelectors = [
'input[type="password"]',
'input[name*="pass"]',
'input[id*="pass"]',
'input[placeholder*="pass" i]',
'input[aria-label*="pass" i]',
]
const submitSelectors = [
'button[type="submit"]',
'input[type="submit"]',
'button:has-text("Login")',
'button:has-text("Sign in")',
'button[id*="login"]',
'button[id*="submit"]',
'button[name*="login"]',
'button[name*="submit"]',
]
let usernameFilled = false
for (const selector of usernameSelectors) {
const input = page.locator(selector).first()
if ((await input.count()) > 0 && (await input.isVisible())) {
logger.info(`Found username field: ${selector}`)
await input.fill(usernameValue)
usernameFilled = true
break
}
}
if (!usernameFilled) {
logger.warn('Could not find a visible username/email field for direct login.')
return {
attempted: false,
success: false,
message: 'Login not attempted: Could not find a username field.',
}
}
let passwordFilled = false
for (const selector of passwordSelectors) {
const input = page.locator(selector).first()
if ((await input.count()) > 0 && (await input.isVisible())) {
logger.info(`Found password field: ${selector}`)
await input.fill(passwordValue)
passwordFilled = true
break
}
}
if (!passwordFilled) {
logger.warn('Could not find a visible password field for direct login.')
return {
attempted: true,
success: false,
message:
'Login attempt incomplete: Found and filled username but could not find password field.',
}
}
let submitClicked = false
for (const selector of submitSelectors) {
const button = page.locator(selector).first()
if ((await button.count()) > 0 && (await button.isVisible())) {
logger.info(`Found submit button: ${selector}`)
await button.click()
await new Promise((resolve) => setTimeout(resolve, 3000))
submitClicked = true
break
}
}
if (!submitClicked) {
logger.warn('Could not find a visible/enabled submit button for direct login.')
return {
attempted: true,
success: false,
message:
'Login attempt incomplete: Found and filled form fields but could not find submit button.',
}
}
logger.info(
'Direct login attempt completed (fields filled, submit clicked). Verifying result...'
)
const currentUrl = page.url()
const isStillOnLoginPage =
currentUrl.includes('login') ||
currentUrl.includes('signin') ||
currentUrl.includes('auth') ||
currentUrl.includes('signup') ||
currentUrl.includes('register')
const hasLoginError = await page.evaluate(() => {
const errorSelectors = [
'[class*="error" i]',
'[id*="error" i]',
'[role="alert"]',
'.alert-danger',
'.text-danger',
'.text-error',
'.notification-error',
]
for (const selector of errorSelectors) {
const elements = document.querySelectorAll(selector)
for (const element of elements) {
const text = element.textContent || ''
if (
text.toLowerCase().includes('password') ||
text.toLowerCase().includes('login failed') ||
text.toLowerCase().includes('incorrect') ||
text.toLowerCase().includes('invalid') ||
text.toLowerCase().includes("doesn't match") ||
text.toLowerCase().includes('does not match')
) {
return true
}
}
}
return false
})
const hasSuccessIndicators = await page.evaluate(() => {
const userMenuSelectors = [
'[class*="avatar" i]',
'[class*="profile" i]',
'[class*="user-menu" i]',
'[class*="account" i]',
'[aria-label*="account" i]',
'[aria-label*="profile" i]',
]
for (const selector of userMenuSelectors) {
if (document.querySelector(selector)) {
return true
}
}
return false
})
if (!isStillOnLoginPage && !hasLoginError && hasSuccessIndicators) {
logger.info('Login verification successful: Detected successful login.')
return {
attempted: true,
success: true,
message: 'Login successful. User is now authenticated.',
}
}
if (hasLoginError) {
logger.warn('Login verification failed: Detected login error message.')
return {
attempted: true,
success: false,
message:
'Login attempted but failed: Detected error message on page. Likely invalid credentials.',
}
}
if (isStillOnLoginPage) {
logger.warn('Login verification inconclusive: Still on login page.')
return {
attempted: true,
success: false,
message: 'Login attempted but failed: Still on login/authentication page.',
}
}
logger.info('Login verification inconclusive. Proceeding as if login was successful.')
return {
attempted: true,
success: true,
message: 'Login likely successful, but could not verify with certainty.',
}
} catch (error) {
logger.error('Error during direct login attempt', {
error: error instanceof Error ? error.message : String(error),
})
return {
attempted: true,
success: false,
message: `Login attempt encountered an error: ${error instanceof Error ? error.message : String(error)}`,
}
let result = text
for (const [key, value] of Object.entries(variables)) {
const placeholder = `%${key}%`
result = result.split(placeholder).join(value)
}
return result
}
export async function POST(request: NextRequest) {
let stagehand: Stagehand | null = null
let stagehand: StagehandType | null = null
try {
const body = await request.json()
@@ -408,70 +112,17 @@ export async function POST(request: NextRequest) {
}
const params = validationResult.data
let variablesObject: Record<string, string> | undefined
const { task, startUrl: rawStartUrl, outputSchema, provider, apiKey } = params
const variablesObject = processVariables(params.variables)
if (params.variables) {
if (Array.isArray(params.variables)) {
variablesObject = {}
params.variables.forEach((item: any) => {
if (item?.cells?.Key && typeof item.cells.Key === 'string') {
variablesObject![item.cells.Key] = item.cells.Value || ''
}
})
} else if (typeof params.variables === 'object' && params.variables !== null) {
variablesObject = { ...params.variables }
} else if (typeof params.variables === 'string') {
try {
variablesObject = JSON.parse(params.variables)
} catch (_e) {
logger.warn('Failed to parse variables string as JSON', { variables: params.variables })
}
}
if (!variablesObject || Object.keys(variablesObject).length === 0) {
logger.warn('Variables object is empty after processing', {
originalVariables: params.variables,
variablesType: typeof params.variables,
})
if (typeof params.variables === 'object' && params.variables !== null) {
variablesObject = {}
for (const key in params.variables) {
if (typeof params.variables[key] === 'string') {
variablesObject[key] = params.variables[key]
}
}
logger.info('Recovered variables from raw object', {
recoveredCount: Object.keys(variablesObject).length,
})
}
}
if (variablesObject) {
const safeVarKeys = Object.keys(variablesObject).map((key) => {
return key.toLowerCase().includes('password')
? `${key}: [REDACTED]`
: `${key}: ${variablesObject?.[key]}`
})
logger.info('Collected variables for substitution', {
variableCount: Object.keys(variablesObject).length,
safeVariables: safeVarKeys,
})
}
}
const { task, startUrl: rawStartUrl, outputSchema, apiKey } = params
let startUrl = rawStartUrl
startUrl = normalizeUrl(startUrl)
const startUrl = normalizeUrl(rawStartUrl)
logger.info('Starting Stagehand agent process', {
rawStartUrl,
startUrl,
hasTask: !!task,
hasVariables: !!variablesObject && Object.keys(variablesObject).length > 0,
hasVariables: !!variablesObject,
provider,
})
if (!BROWSERBASE_API_KEY || !BROWSERBASE_PROJECT_ID) {
@@ -486,17 +137,38 @@ export async function POST(request: NextRequest) {
)
}
if (!apiKey || typeof apiKey !== 'string') {
logger.error('API key is required')
return NextResponse.json({ error: 'API key is required' }, { status: 400 })
}
if (provider === 'openai' && !apiKey.startsWith('sk-')) {
logger.error('Invalid OpenAI API key format')
return NextResponse.json({ error: 'Invalid OpenAI API key format' }, { status: 400 })
}
if (provider === 'anthropic' && !apiKey.startsWith('sk-ant-')) {
logger.error('Invalid Anthropic API key format')
return NextResponse.json({ error: 'Invalid Anthropic API key format' }, { status: 400 })
}
const modelName =
provider === 'anthropic' ? 'anthropic/claude-3-7-sonnet-latest' : 'openai/gpt-4.1'
try {
logger.info('Initializing Stagehand with Browserbase (v3)')
logger.info('Initializing Stagehand with Browserbase (v3)', { provider, modelName })
const { Stagehand } = await import('@browserbasehq/stagehand')
stagehand = new Stagehand({
env: 'BROWSERBASE',
apiKey: BROWSERBASE_API_KEY,
projectId: BROWSERBASE_PROJECT_ID,
verbose: 1,
disableAPI: true, // Use local agent handler instead of Browserbase API
logger: (msg) => logger.info(typeof msg === 'string' ? msg : JSON.stringify(msg)),
model: {
modelName: 'anthropic/claude-3-7-sonnet-latest',
modelName,
apiKey: apiKey,
},
})
@@ -506,288 +178,47 @@ export async function POST(request: NextRequest) {
logger.info('Stagehand initialized successfully')
const page = stagehand.context.pages()[0]
logger.info(`Navigating to ${startUrl}`)
await page.goto(startUrl, { waitUntil: 'networkidle' })
logger.info('Navigation complete')
const ensureLoginPage = async (): Promise<boolean> => {
if (!stagehand) {
logger.error('Stagehand instance is null')
return false
}
const taskWithVariables = substituteVariables(task, variablesObject)
const currentPage = stagehand.context.pages()[0]
logger.info('Checking if we need to navigate to login page')
let agentInstructions = `You are a helpful web browsing assistant. Complete the following task: ${taskWithVariables}`
try {
const loginFormExists = await currentPage.evaluate(() => {
const usernameInput = document.querySelector(
'input[type="text"], input[type="email"], input[name="username"], input[id="username"]'
)
const passwordInput = document.querySelector('input[type="password"]')
return !!(usernameInput && passwordInput)
})
if (loginFormExists) {
logger.info('Already on login page with username/password fields')
return true
}
const loginElements = await stagehand.observe('Find login buttons or links on this page')
if (loginElements && loginElements.length > 0) {
for (const element of loginElements) {
if (
element.description.toLowerCase().includes('login') ||
element.description.toLowerCase().includes('sign in')
) {
logger.info(`Found login element: ${element.description}`)
if (element.selector) {
logger.info(`Clicking login element: ${element.selector}`)
await stagehand.act(`Click on the ${element.description}`)
await new Promise((resolve) => setTimeout(resolve, 2000))
const loginPageAfterClick = await currentPage.evaluate(() => {
const usernameInput = document.querySelector(
'input[type="text"], input[type="email"], input[name="username"], input[id="username"]'
)
const passwordInput = document.querySelector('input[type="password"]')
return !!(usernameInput && passwordInput)
})
if (loginPageAfterClick) {
logger.info('Successfully navigated to login page')
return true
}
}
}
}
}
logger.info('Trying direct navigation to /login path')
const currentUrl = currentPage.url()
const loginUrl = new URL('/login', currentUrl).toString()
await currentPage.goto(loginUrl, { waitUntil: 'networkidle' })
const loginPageAfterDirectNav = await currentPage.evaluate(() => {
const usernameInput = document.querySelector(
'input[type="text"], input[type="email"], input[name="username"], input[id="username"]'
)
const passwordInput = document.querySelector('input[type="password"]')
return !!(usernameInput && passwordInput)
})
if (loginPageAfterDirectNav) {
logger.info('Successfully navigated to login page via direct URL')
return true
}
logger.warn('Could not navigate to login page')
return false
} catch (error) {
logger.error('Error finding login page', { error })
return false
}
if (variablesObject && Object.keys(variablesObject).length > 0) {
const safeVarKeys = Object.keys(variablesObject).map((key) => {
return key.toLowerCase().includes('password') ? `${key}: [REDACTED]` : key
})
logger.info('Variables available for task', { variables: safeVarKeys })
}
let directLoginAttempted = false
let directLoginSuccess = false
let loginMessage = ''
let taskForAgent = task
let agentInstructions = ''
const hasLoginVars =
variablesObject &&
Object.keys(variablesObject).some((k) =>
['username', 'email', 'user'].includes(k.toLowerCase())
) &&
Object.keys(variablesObject).some((k) =>
['password', 'pass', 'secret'].includes(k.toLowerCase())
)
if (hasLoginVars) {
logger.info('Login variables detected, checking if login page navigation is needed.')
const isOnLoginPage = await ensureLoginPage()
if (isOnLoginPage && stagehand) {
logger.info('Attempting direct login before involving the agent.')
const loginResult = await attemptDirectLogin(stagehand, variablesObject)
directLoginAttempted = loginResult.attempted
directLoginSuccess = loginResult.success
loginMessage = loginResult.message
logger.info('Direct login attempt result', {
attempted: directLoginAttempted,
success: directLoginSuccess,
message: loginMessage,
})
if (directLoginAttempted) {
if (directLoginSuccess) {
taskForAgent = `Login has been completed programmatically and was successful. Please verify that you are logged in and then proceed with the original task: ${task}`
} else {
taskForAgent = `Login was attempted programmatically but failed (${loginMessage}). You will need to check the current state and either:
1. Try to login again if you see a login form
2. Or proceed with the task if login actually succeeded: ${task}`
}
logger.info('Task modified for agent after direct login attempt.')
}
} else {
logger.info('Skipping direct login attempt: Not on login page or stagehand unavailable.')
}
} else {
logger.info('Skipping direct login: No relevant username/password variables found.')
if (outputSchema && typeof outputSchema === 'object' && outputSchema !== null) {
const schemaObj = getSchemaObject(outputSchema)
agentInstructions += `\n\nIMPORTANT: You MUST return your final result in the following JSON format exactly:\n${formatSchemaForInstructions(schemaObj)}\n\nYour response should consist of valid JSON only, with no additional text.`
}
const { processedTask, actionDirectives } = extractActionDirectives(task)
logger.info('Extracted action directives', {
actionCount: actionDirectives.length,
hasActionDirectives: actionDirectives.length > 0,
})
if (directLoginAttempted) {
const loginInstructions = directLoginSuccess
? 'Login was completed programmatically and appears successful. Please VERIFY if the login was successful by checking for elements that only appear when logged in.'
: `Login was attempted programmatically but appears to have FAILED (${loginMessage}).
IMPORTANT: Check if you see a login form, and if so:
1. Username and password fields may already be filled (but may contain placeholder text if the login failed)
2. If you need to attempt login again, make sure you use the actual variable placeholders (%username%, %password%) so they are properly substituted.
3. Check for any error messages to understand why the login failed.`
agentInstructions = `You are a helpful web browsing assistant. ${loginInstructions}
Once you've verified the login state, proceed with the following task: ${task}
${actionDirectives.length > 0 ? `\n\nNote on Secure Actions: You might see [SECURE ACTION X] placeholders. Handle these by outputting "EXECUTE SECURE ACTION X" when appropriate.` : ''}
${outputSchema && typeof outputSchema === 'object' && outputSchema !== null ? `\n\nIMPORTANT: You MUST return your final result in the following JSON format exactly:\n${formatSchemaForInstructions(getSchemaObject(outputSchema))}\n\nYour response should consist of valid JSON only, with no additional text.` : ''}`
} else {
agentInstructions = `You are a helpful web browsing assistant that will complete tasks on websites. Your goal is to accomplish the following task: ${processedTask}\n
${actionDirectives.length > 0 ? `\n\nYou'll see [SECURE ACTION X] placeholders in the task. These represent secure actions that will be handled automatically when you navigate to the appropriate page. When you reach a point where a secure action should be performed, output a line with exactly: "EXECUTE SECURE ACTION X" (where X is the action number). Then wait for confirmation before proceeding.` : ''}\n
IMPORTANT: For any form fields that require sensitive information like usernames or passwords:
1. If you see placeholders like %username% or %password% in the task, DO NOT ask for the actual values.
2. If you need to type in login forms, use the EXACT placeholder text (e.g., "%username%" or "%password%") UNLESS instructed otherwise.
3. The system will automatically substitute the real values when you use these placeholders IF direct login was not attempted.
4. Example correct approach: "type %username% in the username field".${
variablesObject && Object.keys(variablesObject).length > 0
? `\n5. Available variables: ${Object.keys(variablesObject)
.map((k) => `%${k}%`)
.join(', ')}`
: ''
}\n
WEBSITE NAVIGATION GUIDANCE:
1. If you need to log in but don't see a login form, LOOK for login buttons or links (they might say "Login" or "Sign in").
2. If you're on a login page but don't see a username/password form, try scrolling or looking for "Continue with email" or similar options.
3. Always TYPE carefully in form fields - use accurate coordinates for clicking if necessary.
4. Use specific actions like "type %username% in the username field".
5. After logging in, verify you've successfully authenticated before proceeding.\n
${outputSchema && typeof outputSchema === 'object' && outputSchema !== null ? `\n\nIMPORTANT: You MUST return your final result in the following JSON format exactly:\n${formatSchemaForInstructions(getSchemaObject(outputSchema))}\n\nYour response should consist of valid JSON only, with no additional text. Ensure the data in your response adheres strictly to the schema provided.` : ''}`
}
logger.info('Creating Stagehand agent', {
directLoginAttempted,
directLoginSuccess,
loginMessage,
})
const additionalContext = directLoginAttempted
? `Login was ${directLoginSuccess ? 'successfully completed' : 'attempted but failed'}.
${loginMessage}
First check the current state of the page.
If login failed, you may need to click the login button again after ensuring fields are properly filled.`
: `
This task may contain placeholder variables like %username% and %password%.
When you need to fill form fields, use these placeholders directly (e.g., type "%username%").
The system will substitute actual values when these placeholders are used, keeping sensitive data secure.
`.trim()
logger.info('Creating Stagehand agent')
const agent = stagehand.agent({
model: {
modelName: 'anthropic/claude-3-7-sonnet-latest',
modelName,
apiKey: apiKey,
},
executionModel: {
modelName: 'anthropic/claude-3-7-sonnet-latest',
modelName,
apiKey: apiKey,
},
systemPrompt: `${agentInstructions}\n\n${additionalContext}`,
systemPrompt: agentInstructions,
})
const runAgentWithSecureActions = async (): Promise<any> => {
let currentResult = await agent.execute({ instruction: taskForAgent })
let allExecutedActions: Array<{
action: string
result: { success: boolean; message: string }
}> = []
let iterationCount = 0
const maxIterations = 10 // Safety limit for iterations
logger.info('Executing agent task', { task: taskWithVariables })
while (iterationCount < maxIterations && stagehand !== null) {
if (!currentResult.message) {
break
}
if (!/EXECUTE SECURE ACTION \d+/i.test(currentResult.message)) {
break
}
const { modifiedMessage, executedActions } = await processSecureActions(
currentResult.message,
stagehand,
actionDirectives,
variablesObject
)
allExecutedActions = [...allExecutedActions, ...executedActions]
if (executedActions.length === 0) {
break
}
iterationCount++
const hasStructuredOutput = /```json|^\s*{/.test(modifiedMessage)
if (hasStructuredOutput) {
currentResult.message = modifiedMessage
break
}
logger.info(
`Continuing agent execution with processed actions, iteration ${iterationCount}`
)
try {
const continuationPrompt = `${modifiedMessage}\n\nPlease continue with the task.`
const nextResult = await agent.execute({ instruction: continuationPrompt })
currentResult = {
...nextResult,
actions: [...currentResult.actions, ...nextResult.actions],
}
} catch (error) {
logger.error('Error continuing agent execution', { error })
break
}
}
return {
...currentResult,
secureActions: allExecutedActions,
}
}
logger.info('Executing agent task', {
task: taskForAgent,
actionDirectiveCount: actionDirectives.length,
directLoginAttempted,
directLoginSuccess,
loginMessage,
const agentExecutionResult = await agent.execute({
instruction: taskWithVariables,
maxSteps: 20,
})
const agentExecutionResult = await runAgentWithSecureActions()
const agentResult = {
success: agentExecutionResult.success,
completed: agentExecutionResult.completed,
@@ -798,7 +229,7 @@ The system will substitute actual values when these placeholders are used, keepi
logger.info('Agent execution complete', {
success: agentResult.success,
completed: agentResult.completed,
executedActionCount: agentExecutionResult.secureActions?.length || 0,
actionCount: agentResult.actions?.length || 0,
})
let structuredOutput = null
@@ -849,7 +280,6 @@ The system will substitute actual values when these placeholders are used, keepi
return NextResponse.json({
agentResult,
structuredOutput,
secureActions: agentExecutionResult.secureActions || [],
})
} catch (error) {
logger.error('Stagehand agent execution error', {

View File

@@ -1,4 +1,3 @@
import { Stagehand } from '@browserbasehq/stagehand'
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { env } from '@/lib/core/config/env'
@@ -7,6 +6,8 @@ import { ensureZodObject, normalizeUrl } from '@/app/api/tools/stagehand/utils'
const logger = createLogger('StagehandExtractAPI')
type StagehandType = import('@browserbasehq/stagehand').Stagehand
const BROWSERBASE_API_KEY = env.BROWSERBASE_API_KEY
const BROWSERBASE_PROJECT_ID = env.BROWSERBASE_PROJECT_ID
@@ -15,12 +16,13 @@ const requestSchema = z.object({
schema: z.record(z.any()),
useTextExtract: z.boolean().optional().default(false),
selector: z.string().nullable().optional(),
provider: z.enum(['openai', 'anthropic']).optional().default('openai'),
apiKey: z.string(),
url: z.string().url(),
})
export async function POST(request: NextRequest) {
let stagehand: Stagehand | null = null
let stagehand: StagehandType | null = null
try {
const body = await request.json()
@@ -41,7 +43,7 @@ export async function POST(request: NextRequest) {
}
const params = validationResult.data
const { url: rawUrl, instruction, selector, apiKey, schema } = params
const { url: rawUrl, instruction, selector, provider, apiKey, schema } = params
const url = normalizeUrl(rawUrl)
logger.info('Starting Stagehand extraction process', {
@@ -71,13 +73,28 @@ export async function POST(request: NextRequest) {
)
}
if (!apiKey || typeof apiKey !== 'string' || !apiKey.startsWith('sk-')) {
if (!apiKey || typeof apiKey !== 'string') {
logger.error('API key is required')
return NextResponse.json({ error: 'API key is required' }, { status: 400 })
}
if (provider === 'openai' && !apiKey.startsWith('sk-')) {
logger.error('Invalid OpenAI API key format')
return NextResponse.json({ error: 'Invalid OpenAI API key format' }, { status: 400 })
}
if (provider === 'anthropic' && !apiKey.startsWith('sk-ant-')) {
logger.error('Invalid Anthropic API key format')
return NextResponse.json({ error: 'Invalid Anthropic API key format' }, { status: 400 })
}
try {
logger.info('Initializing Stagehand with Browserbase (v3)')
const modelName =
provider === 'anthropic' ? 'anthropic/claude-3-7-sonnet-latest' : 'openai/gpt-4.1'
logger.info('Initializing Stagehand with Browserbase (v3)', { provider, modelName })
const { Stagehand } = await import('@browserbasehq/stagehand')
stagehand = new Stagehand({
env: 'BROWSERBASE',
@@ -86,7 +103,7 @@ export async function POST(request: NextRequest) {
verbose: 1,
logger: (msg) => logger.info(typeof msg === 'string' ? msg : JSON.stringify(msg)),
model: {
modelName: 'openai/gpt-4o',
modelName,
apiKey: apiKey,
},
})

View File

@@ -1,32 +1,55 @@
import { type NextRequest, NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { NextResponse } from 'next/server'
import { authorizeCredentialUse } from '@/lib/auth/credential-access'
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request'
import { createLogger } from '@/lib/logs/console/logger'
import { getOAuthToken } from '@/app/api/auth/oauth/utils'
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
const logger = createLogger('WebflowCollectionsAPI')
export const dynamic = 'force-dynamic'
export async function GET(request: NextRequest) {
export async function POST(request: Request) {
try {
const session = await getSession()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
const requestId = generateRequestId()
const body = await request.json()
const { credential, workflowId, siteId } = body
if (!credential) {
logger.error('Missing credential in request')
return NextResponse.json({ error: 'Credential is required' }, { status: 400 })
}
const { searchParams } = new URL(request.url)
const siteId = searchParams.get('siteId')
if (!siteId) {
return NextResponse.json({ error: 'Missing siteId parameter' }, { status: 400 })
const siteIdValidation = validateAlphanumericId(siteId, 'siteId')
if (!siteIdValidation.isValid) {
logger.error('Invalid siteId', { error: siteIdValidation.error })
return NextResponse.json({ error: siteIdValidation.error }, { status: 400 })
}
const accessToken = await getOAuthToken(session.user.id, 'webflow')
const authz = await authorizeCredentialUse(request as any, {
credentialId: credential,
workflowId,
})
if (!authz.ok || !authz.credentialOwnerUserId) {
return NextResponse.json({ error: authz.error || 'Unauthorized' }, { status: 403 })
}
const accessToken = await refreshAccessTokenIfNeeded(
credential,
authz.credentialOwnerUserId,
requestId
)
if (!accessToken) {
logger.error('Failed to get access token', {
credentialId: credential,
userId: authz.credentialOwnerUserId,
})
return NextResponse.json(
{ error: 'No Webflow access token found. Please connect your Webflow account.' },
{ status: 404 }
{
error: 'Could not retrieve access token',
authRequired: true,
},
{ status: 401 }
)
}
@@ -58,11 +81,11 @@ export async function GET(request: NextRequest) {
name: collection.displayName || collection.slug || collection.id,
}))
return NextResponse.json({ collections: formattedCollections }, { status: 200 })
} catch (error: any) {
logger.error('Error fetching Webflow collections', error)
return NextResponse.json({ collections: formattedCollections })
} catch (error) {
logger.error('Error processing Webflow collections request:', error)
return NextResponse.json(
{ error: 'Internal server error', details: error.message },
{ error: 'Failed to retrieve Webflow collections', details: (error as Error).message },
{ status: 500 }
)
}

View File

@@ -0,0 +1,106 @@
import { NextResponse } from 'next/server'
import { authorizeCredentialUse } from '@/lib/auth/credential-access'
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request'
import { createLogger } from '@/lib/logs/console/logger'
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
const logger = createLogger('WebflowItemsAPI')
export const dynamic = 'force-dynamic'
export async function POST(request: Request) {
try {
const requestId = generateRequestId()
const body = await request.json()
const { credential, workflowId, collectionId, search } = body
if (!credential) {
logger.error('Missing credential in request')
return NextResponse.json({ error: 'Credential is required' }, { status: 400 })
}
const collectionIdValidation = validateAlphanumericId(collectionId, 'collectionId')
if (!collectionIdValidation.isValid) {
logger.error('Invalid collectionId', { error: collectionIdValidation.error })
return NextResponse.json({ error: collectionIdValidation.error }, { status: 400 })
}
const authz = await authorizeCredentialUse(request as any, {
credentialId: credential,
workflowId,
})
if (!authz.ok || !authz.credentialOwnerUserId) {
return NextResponse.json({ error: authz.error || 'Unauthorized' }, { status: 403 })
}
const accessToken = await refreshAccessTokenIfNeeded(
credential,
authz.credentialOwnerUserId,
requestId
)
if (!accessToken) {
logger.error('Failed to get access token', {
credentialId: credential,
userId: authz.credentialOwnerUserId,
})
return NextResponse.json(
{
error: 'Could not retrieve access token',
authRequired: true,
},
{ status: 401 }
)
}
const response = await fetch(
`https://api.webflow.com/v2/collections/${collectionId}/items?limit=100`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
accept: 'application/json',
},
}
)
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
logger.error('Failed to fetch Webflow items', {
status: response.status,
error: errorData,
collectionId,
})
return NextResponse.json(
{ error: 'Failed to fetch Webflow items', details: errorData },
{ status: response.status }
)
}
const data = await response.json()
const items = data.items || []
let formattedItems = items.map((item: any) => {
const fieldData = item.fieldData || {}
const name = fieldData.name || fieldData.title || fieldData.slug || item.id
return {
id: item.id,
name,
}
})
if (search) {
const searchLower = search.toLowerCase()
formattedItems = formattedItems.filter((item: { id: string; name: string }) =>
item.name.toLowerCase().includes(searchLower)
)
}
return NextResponse.json({ items: formattedItems })
} catch (error) {
logger.error('Error processing Webflow items request:', error)
return NextResponse.json(
{ error: 'Failed to retrieve Webflow items', details: (error as Error).message },
{ status: 500 }
)
}
}

View File

@@ -1,25 +1,48 @@
import { type NextRequest, NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { NextResponse } from 'next/server'
import { authorizeCredentialUse } from '@/lib/auth/credential-access'
import { generateRequestId } from '@/lib/core/utils/request'
import { createLogger } from '@/lib/logs/console/logger'
import { getOAuthToken } from '@/app/api/auth/oauth/utils'
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
const logger = createLogger('WebflowSitesAPI')
export const dynamic = 'force-dynamic'
export async function GET(request: NextRequest) {
export async function POST(request: Request) {
try {
const session = await getSession()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
const requestId = generateRequestId()
const body = await request.json()
const { credential, workflowId } = body
if (!credential) {
logger.error('Missing credential in request')
return NextResponse.json({ error: 'Credential is required' }, { status: 400 })
}
const accessToken = await getOAuthToken(session.user.id, 'webflow')
const authz = await authorizeCredentialUse(request as any, {
credentialId: credential,
workflowId,
})
if (!authz.ok || !authz.credentialOwnerUserId) {
return NextResponse.json({ error: authz.error || 'Unauthorized' }, { status: 403 })
}
const accessToken = await refreshAccessTokenIfNeeded(
credential,
authz.credentialOwnerUserId,
requestId
)
if (!accessToken) {
logger.error('Failed to get access token', {
credentialId: credential,
userId: authz.credentialOwnerUserId,
})
return NextResponse.json(
{ error: 'No Webflow access token found. Please connect your Webflow account.' },
{ status: 404 }
{
error: 'Could not retrieve access token',
authRequired: true,
},
{ status: 401 }
)
}
@@ -50,11 +73,11 @@ export async function GET(request: NextRequest) {
name: site.displayName || site.shortName || site.id,
}))
return NextResponse.json({ sites: formattedSites }, { status: 200 })
} catch (error: any) {
logger.error('Error fetching Webflow sites', error)
return NextResponse.json({ sites: formattedSites })
} catch (error) {
logger.error('Error processing Webflow sites request:', error)
return NextResponse.json(
{ error: 'Internal server error', details: error.message },
{ error: 'Failed to retrieve Webflow sites', details: (error as Error).message },
{ status: 500 }
)
}

View File

@@ -35,19 +35,18 @@
* GET /api/v1/admin/organizations/:id - Get organization details
* PATCH /api/v1/admin/organizations/:id - Update organization
* GET /api/v1/admin/organizations/:id/members - List organization members
* POST /api/v1/admin/organizations/:id/members - Add/update member in organization
* POST /api/v1/admin/organizations/:id/members - Add/update member (validates seat availability)
* GET /api/v1/admin/organizations/:id/members/:mid - Get member details
* PATCH /api/v1/admin/organizations/:id/members/:mid - Update member role
* DELETE /api/v1/admin/organizations/:id/members/:mid - Remove member
* GET /api/v1/admin/organizations/:id/billing - Get org billing summary
* PATCH /api/v1/admin/organizations/:id/billing - Update org usage limit
* GET /api/v1/admin/organizations/:id/seats - Get seat analytics
* PATCH /api/v1/admin/organizations/:id/seats - Update seat count
*
* Subscriptions:
* GET /api/v1/admin/subscriptions - List all subscriptions
* GET /api/v1/admin/subscriptions/:id - Get subscription details
* PATCH /api/v1/admin/subscriptions/:id - Update subscription
* DELETE /api/v1/admin/subscriptions/:id - Cancel subscription (?atPeriodEnd=true for scheduled)
*/
export type { AdminAuthFailure, AdminAuthResult, AdminAuthSuccess } from '@/app/api/v1/admin/auth'

View File

@@ -12,6 +12,9 @@
* POST /api/v1/admin/organizations/[id]/members
*
* Add a user to an organization with full billing logic.
* Validates seat availability before adding (uses same logic as invitation flow):
* - Team plans: checks seats column
* - Enterprise plans: checks metadata.seats
* Handles Pro usage snapshot and subscription cancellation like the invitation flow.
* If user is already a member, updates their role if different.
*
@@ -29,6 +32,7 @@ import { db } from '@sim/db'
import { member, organization, user, userStats } from '@sim/db/schema'
import { count, eq } from 'drizzle-orm'
import { addUserToOrganization } from '@/lib/billing/organizations/membership'
import { requireStripeClient } from '@/lib/billing/stripe-client'
import { createLogger } from '@/lib/logs/console/logger'
import { withAdminAuthParams } from '@/app/api/v1/admin/middleware'
import {
@@ -223,6 +227,29 @@ export const POST = withAdminAuthParams<RouteParams>(async (request, context) =>
return badRequestResponse(result.error || 'Failed to add member')
}
// Sync Pro subscription cancellation with Stripe (same as invitation flow)
if (result.billingActions.proSubscriptionToCancel?.stripeSubscriptionId) {
try {
const stripe = requireStripeClient()
await stripe.subscriptions.update(
result.billingActions.proSubscriptionToCancel.stripeSubscriptionId,
{ cancel_at_period_end: true }
)
logger.info('Admin API: Synced Pro cancellation with Stripe', {
userId: body.userId,
subscriptionId: result.billingActions.proSubscriptionToCancel.subscriptionId,
stripeSubscriptionId: result.billingActions.proSubscriptionToCancel.stripeSubscriptionId,
})
} catch (stripeError) {
logger.error('Admin API: Failed to sync Pro cancellation with Stripe', {
userId: body.userId,
subscriptionId: result.billingActions.proSubscriptionToCancel.subscriptionId,
stripeSubscriptionId: result.billingActions.proSubscriptionToCancel.stripeSubscriptionId,
error: stripeError,
})
}
}
const data: AdminMember = {
id: result.memberId!,
userId: body.userId,

View File

@@ -4,26 +4,12 @@
* Get organization seat analytics including member activity.
*
* Response: AdminSingleResponse<AdminSeatAnalytics>
*
* PATCH /api/v1/admin/organizations/[id]/seats
*
* Update organization seat count with Stripe sync (matches user flow).
*
* Body:
* - seats: number - New seat count (positive integer)
*
* Response: AdminSingleResponse<{ success: true, seats: number, plan: string, stripeUpdated?: boolean }>
*/
import { db } from '@sim/db'
import { organization, subscription } from '@sim/db/schema'
import { and, eq } from 'drizzle-orm'
import { requireStripeClient } from '@/lib/billing/stripe-client'
import { getOrganizationSeatAnalytics } from '@/lib/billing/validation/seat-management'
import { createLogger } from '@/lib/logs/console/logger'
import { withAdminAuthParams } from '@/app/api/v1/admin/middleware'
import {
badRequestResponse,
internalErrorResponse,
notFoundResponse,
singleResponse,
@@ -75,122 +61,3 @@ export const GET = withAdminAuthParams<RouteParams>(async (_, context) => {
return internalErrorResponse('Failed to get organization seats')
}
})
export const PATCH = withAdminAuthParams<RouteParams>(async (request, context) => {
const { id: organizationId } = await context.params
try {
const body = await request.json()
if (typeof body.seats !== 'number' || body.seats < 1 || !Number.isInteger(body.seats)) {
return badRequestResponse('seats must be a positive integer')
}
const [orgData] = await db
.select({ id: organization.id })
.from(organization)
.where(eq(organization.id, organizationId))
.limit(1)
if (!orgData) {
return notFoundResponse('Organization')
}
const [subData] = await db
.select()
.from(subscription)
.where(and(eq(subscription.referenceId, organizationId), eq(subscription.status, 'active')))
.limit(1)
if (!subData) {
return notFoundResponse('Subscription')
}
const newSeatCount = body.seats
let stripeUpdated = false
if (subData.plan === 'enterprise') {
const currentMetadata = (subData.metadata as Record<string, unknown>) || {}
const newMetadata = {
...currentMetadata,
seats: newSeatCount,
}
await db
.update(subscription)
.set({ metadata: newMetadata })
.where(eq(subscription.id, subData.id))
logger.info(`Admin API: Updated enterprise seats for organization ${organizationId}`, {
seats: newSeatCount,
})
} else if (subData.plan === 'team') {
if (subData.stripeSubscriptionId) {
const stripe = requireStripeClient()
const stripeSubscription = await stripe.subscriptions.retrieve(subData.stripeSubscriptionId)
if (stripeSubscription.status !== 'active') {
return badRequestResponse('Stripe subscription is not active')
}
const subscriptionItem = stripeSubscription.items.data[0]
if (!subscriptionItem) {
return internalErrorResponse('No subscription item found in Stripe subscription')
}
const currentSeats = subData.seats || 1
logger.info('Admin API: Updating Stripe subscription quantity', {
organizationId,
stripeSubscriptionId: subData.stripeSubscriptionId,
subscriptionItemId: subscriptionItem.id,
currentSeats,
newSeatCount,
})
await stripe.subscriptions.update(subData.stripeSubscriptionId, {
items: [
{
id: subscriptionItem.id,
quantity: newSeatCount,
},
],
proration_behavior: 'create_prorations',
})
stripeUpdated = true
}
await db
.update(subscription)
.set({ seats: newSeatCount })
.where(eq(subscription.id, subData.id))
logger.info(`Admin API: Updated team seats for organization ${organizationId}`, {
seats: newSeatCount,
stripeUpdated,
})
} else {
await db
.update(subscription)
.set({ seats: newSeatCount })
.where(eq(subscription.id, subData.id))
logger.info(`Admin API: Updated seats for organization ${organizationId}`, {
seats: newSeatCount,
plan: subData.plan,
})
}
return singleResponse({
success: true,
seats: newSeatCount,
plan: subData.plan,
stripeUpdated,
})
} catch (error) {
logger.error('Admin API: Failed to update organization seats', { error, organizationId })
return internalErrorResponse('Failed to update organization seats')
}
})

Some files were not shown because too many files have changed in this diff Show More