Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1145f5c
fix(shortcut): fixed global keyboard commands provider to follow `lat…
waleedlatif1 Dec 24, 2025
b1cd8d1
fix(executor): workflow abort has to send abort signal to route for c…
icecrasher321 Dec 24, 2025
cb8b9c5
fix(router): update router to handle azure creds the same way the age…
waleedlatif1 Dec 24, 2025
77521a3
fix(cancel-workflow-exec): move cancellation tracking for multi-task …
icecrasher321 Dec 24, 2025
92b2e34
feat(autolayout): add fitToView on autolayout and reduce horizontal s…
waleedlatif1 Dec 25, 2025
da7eca9
fix(change-detection): move change detection logic to client-side to …
waleedlatif1 Dec 25, 2025
40a6bf5
improvement(variables): update workflows to use deployed variables, n…
waleedlatif1 Dec 25, 2025
47a259b
feat(byok): byok for hosted model capabilities (#2574)
icecrasher321 Dec 25, 2025
66766a9
improvement(byok): remove web search block exa (#2579)
icecrasher321 Dec 25, 2025
9737253
feat(i18n): update translations (#2578)
waleedlatif1 Dec 25, 2025
26ec125
improvement(byok): updated styling for byok page (#2581)
waleedlatif1 Dec 25, 2025
f604ca3
feat(chat-otp): added db fallback for chat otp (#2582)
waleedlatif1 Dec 25, 2025
d79696b
feat(docs): added vector search (#2583)
waleedlatif1 Dec 25, 2025
3201aba
improvement(schedules): use tanstack query to fetch schedule data, cl…
waleedlatif1 Dec 25, 2025
61e7213
feat(i18n): update translations (#2585)
waleedlatif1 Dec 25, 2025
b7f6bab
feat(tests): added testing package, overhauled tests (#2586)
waleedlatif1 Dec 26, 2025
d707d18
fix(build): update dockerfile to contain testing package deps (#2591)
waleedlatif1 Dec 26, 2025
88cda3a
improvement(billing): migrate to decimaljs from number.parseFloat (#2…
waleedlatif1 Dec 26, 2025
1f0e3f2
feat: light mode (#2457)
emir-karabeg Dec 26, 2025
27ec412
fix(tools): fixed tool outputs (#2534)
aadamgough Dec 26, 2025
66b8434
fix(block-name): updating block name should update downstream var ref…
icecrasher321 Dec 26, 2025
7793a6d
feat(kb): added tags information to kb docs table (#2589)
waleedlatif1 Dec 26, 2025
b60b98e
improvement(tag-dropdown): added option to select block in tag dropdo…
waleedlatif1 Dec 27, 2025
298546d
fix(parallel): add parallel sentinel to make parallel-parallel and pa…
icecrasher321 Dec 27, 2025
a60a1fc
improvement(edges): drag edge over block (#2596)
aadamgough Dec 27, 2025
bd0eca0
fix(tag-dropdown): fix the way variables are displayed in the tag dro…
waleedlatif1 Dec 27, 2025
5add261
improvement(easyconnect): use native reactflow getIntersectingNodes i…
waleedlatif1 Dec 27, 2025
3d75445
feat(tools): added new firecrawl agent endpoint (#2603)
waleedlatif1 Dec 27, 2025
3054d6c
fix: bg styling outside workspace (#2605)
emir-karabeg Dec 27, 2025
8651896
feat(i18n): update translations (#2604)
waleedlatif1 Dec 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
142 changes: 126 additions & 16 deletions apps/docs/app/api/search/route.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,126 @@
import { createFromSource } from 'fumadocs-core/search/server'
import { source } from '@/lib/source'

export const revalidate = 3600 // Revalidate every hour

export const { GET } = createFromSource(source, {
localeMap: {
en: { language: 'english' },
es: { language: 'spanish' },
fr: { language: 'french' },
de: { language: 'german' },
// ja and zh are not supported by the stemmer library, so we'll skip language config for them
ja: {},
zh: {},
},
})
import { sql } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { db, docsEmbeddings } from '@/lib/db'
import { generateSearchEmbedding } from '@/lib/embeddings'

export const runtime = 'nodejs'
export const revalidate = 0

/**
* Hybrid search API endpoint
* - English: Vector embeddings + keyword search
* - Other languages: Keyword search only
*/
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams
const query = searchParams.get('query') || searchParams.get('q') || ''
const locale = searchParams.get('locale') || 'en'
const limit = Number.parseInt(searchParams.get('limit') || '10', 10)

if (!query || query.trim().length === 0) {
return NextResponse.json([])
}

const candidateLimit = limit * 3
const similarityThreshold = 0.6

const localeMap: Record<string, string> = {
en: 'english',
es: 'spanish',
fr: 'french',
de: 'german',
ja: 'simple', // PostgreSQL doesn't have Japanese support, use simple
zh: 'simple', // PostgreSQL doesn't have Chinese support, use simple
}
const tsConfig = localeMap[locale] || 'simple'

const useVectorSearch = locale === 'en'
let vectorResults: Array<{
chunkId: string
chunkText: string
sourceDocument: string
sourceLink: string
headerText: string
headerLevel: number
similarity: number
searchType: string
}> = []

if (useVectorSearch) {
const queryEmbedding = await generateSearchEmbedding(query)
vectorResults = await db
.select({
chunkId: docsEmbeddings.chunkId,
chunkText: docsEmbeddings.chunkText,
sourceDocument: docsEmbeddings.sourceDocument,
sourceLink: docsEmbeddings.sourceLink,
headerText: docsEmbeddings.headerText,
headerLevel: docsEmbeddings.headerLevel,
similarity: sql<number>`1 - (${docsEmbeddings.embedding} <=> ${JSON.stringify(queryEmbedding)}::vector)`,
searchType: sql<string>`'vector'`,
})
.from(docsEmbeddings)
.where(
sql`1 - (${docsEmbeddings.embedding} <=> ${JSON.stringify(queryEmbedding)}::vector) >= ${similarityThreshold}`
)
.orderBy(sql`${docsEmbeddings.embedding} <=> ${JSON.stringify(queryEmbedding)}::vector`)
.limit(candidateLimit)
}

const keywordResults = await db
.select({
chunkId: docsEmbeddings.chunkId,
chunkText: docsEmbeddings.chunkText,
sourceDocument: docsEmbeddings.sourceDocument,
sourceLink: docsEmbeddings.sourceLink,
headerText: docsEmbeddings.headerText,
headerLevel: docsEmbeddings.headerLevel,
similarity: sql<number>`ts_rank(${docsEmbeddings.chunkTextTsv}, plainto_tsquery(${tsConfig}, ${query}))`,
searchType: sql<string>`'keyword'`,
})
.from(docsEmbeddings)
.where(sql`${docsEmbeddings.chunkTextTsv} @@ plainto_tsquery(${tsConfig}, ${query})`)
.orderBy(
sql`ts_rank(${docsEmbeddings.chunkTextTsv}, plainto_tsquery(${tsConfig}, ${query})) DESC`
)
.limit(candidateLimit)

const seenIds = new Set<string>()
const mergedResults = []

for (let i = 0; i < Math.max(vectorResults.length, keywordResults.length); i++) {
if (i < vectorResults.length && !seenIds.has(vectorResults[i].chunkId)) {
mergedResults.push(vectorResults[i])
seenIds.add(vectorResults[i].chunkId)
}
if (i < keywordResults.length && !seenIds.has(keywordResults[i].chunkId)) {
mergedResults.push(keywordResults[i])
seenIds.add(keywordResults[i].chunkId)
}
}

const filteredResults = mergedResults.slice(0, limit)
const searchResults = filteredResults.map((result) => {
const title = result.headerText || result.sourceDocument.replace('.mdx', '')
const pathParts = result.sourceDocument
.replace('.mdx', '')
.split('/')
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))

return {
id: result.chunkId,
type: 'page' as const,
url: result.sourceLink,
content: title,
breadcrumbs: pathParts,
}
})

return NextResponse.json(searchResults)
} catch (error) {
console.error('Semantic search error:', error)

return NextResponse.json([])
}
}
13 changes: 13 additions & 0 deletions apps/docs/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,19 @@ export function SlackIcon(props: SVGProps<SVGSVGElement>) {
)
}

export function SlackMonoIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg' fill='currentColor' {...props}>
<g>
<path d='M53.8412698,161.320635 C53.8412698,176.152381 41.8539683,188.139683 27.0222222,188.139683 C12.1904762,188.139683 0.203174603,176.152381 0.203174603,161.320635 C0.203174603,146.488889 12.1904762,134.501587 27.0222222,134.501587 L53.8412698,134.501587 L53.8412698,161.320635 Z M67.2507937,161.320635 C67.2507937,146.488889 79.2380952,134.501587 94.0698413,134.501587 C108.901587,134.501587 120.888889,146.488889 120.888889,161.320635 L120.888889,228.368254 C120.888889,243.2 108.901587,255.187302 94.0698413,255.187302 C79.2380952,255.187302 67.2507937,243.2 67.2507937,228.368254 L67.2507937,161.320635 Z' />
<path d='M94.0698413,53.6380952 C79.2380952,53.6380952 67.2507937,41.6507937 67.2507937,26.8190476 C67.2507937,11.9873016 79.2380952,-7.10542736e-15 94.0698413,-7.10542736e-15 C108.901587,-7.10542736e-15 120.888889,11.9873016 120.888889,26.8190476 L120.888889,53.6380952 L94.0698413,53.6380952 Z M94.0698413,67.2507937 C108.901587,67.2507937 120.888889,79.2380952 120.888889,94.0698413 C120.888889,108.901587 108.901587,120.888889 94.0698413,120.888889 L26.8190476,120.888889 C11.9873016,120.888889 0,108.901587 0,94.0698413 C0,79.2380952 11.9873016,67.2507937 26.8190476,67.2507937 L94.0698413,67.2507937 Z' />
<path d='M201.549206,94.0698413 C201.549206,79.2380952 213.536508,67.2507937 228.368254,67.2507937 C243.2,67.2507937 255.187302,79.2380952 255.187302,94.0698413 C255.187302,108.901587 243.2,120.888889 228.368254,120.888889 L201.549206,120.888889 L201.549206,94.0698413 Z M188.139683,94.0698413 C188.139683,108.901587 176.152381,120.888889 161.320635,120.888889 C146.488889,120.888889 134.501587,108.901587 134.501587,94.0698413 L134.501587,26.8190476 C134.501587,11.9873016 146.488889,-1.42108547e-14 161.320635,-1.42108547e-14 C176.152381,-1.42108547e-14 188.139683,11.9873016 188.139683,26.8190476 L188.139683,94.0698413 Z' />
<path d='M161.320635,201.549206 C176.152381,201.549206 188.139683,213.536508 188.139683,228.368254 C188.139683,243.2 176.152381,255.187302 161.320635,255.187302 C146.488889,255.187302 134.501587,243.2 134.501587,228.368254 L134.501587,201.549206 L161.320635,201.549206 Z M161.320635,188.139683 C146.488889,188.139683 134.501587,176.152381 134.501587,161.320635 C134.501587,146.488889 146.488889,134.501587 161.320635,134.501587 L228.571429,134.501587 C243.403175,134.501587 255.390476,146.488889 255.390476,161.320635 C255.390476,176.152381 243.403175,188.139683 228.571429,188.139683 L161.320635,188.139683 Z' />
</g>
</svg>
)
}

export function GithubIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} width='26' height='26' viewBox='0 0 26 26' xmlns='http://www.w3.org/2000/svg'>
Expand Down
80 changes: 42 additions & 38 deletions apps/docs/content/docs/de/execution/costs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,32 @@ Die Modellaufschlüsselung zeigt:
Die angezeigten Preise entsprechen den Tarifen vom 10. September 2025. Überprüfen Sie die Dokumentation der Anbieter für aktuelle Preise.
</Callout>

## Bring Your Own Key (BYOK)

Sie können Ihre eigenen API-Schlüssel für gehostete Modelle (OpenAI, Anthropic, Google, Mistral) unter **Einstellungen → BYOK** verwenden, um Basispreise zu zahlen. Schlüssel werden verschlüsselt und gelten arbeitsbereichsweit.

## Strategien zur Kostenoptimierung

- **Modellauswahl**: Wählen Sie Modelle basierend auf der Komplexität der Aufgabe. Einfache Aufgaben können GPT-4.1-nano verwenden, während komplexes Denken möglicherweise o1 oder Claude Opus erfordert.
- **Prompt-Engineering**: Gut strukturierte, präzise Prompts reduzieren den Token-Verbrauch ohne Qualitätseinbußen.
- **Modellauswahl**: Wählen Sie Modelle basierend auf der Aufgabenkomplexität. Einfache Aufgaben können GPT-4.1-nano verwenden, während komplexes Reasoning o1 oder Claude Opus erfordern könnte.
- **Prompt Engineering**: Gut strukturierte, prägnante Prompts reduzieren den Token-Verbrauch ohne Qualitätsverlust.
- **Lokale Modelle**: Verwenden Sie Ollama oder VLLM für unkritische Aufgaben, um API-Kosten vollständig zu eliminieren.
- **Caching und Wiederverwendung**: Speichern Sie häufig verwendete Ergebnisse in Variablen oder Dateien, um wiederholte KI-Modellaufrufe zu vermeiden.
- **Batch-Verarbeitung**: Verarbeiten Sie mehrere Elemente in einer einzigen KI-Anfrage anstatt einzelne Aufrufe zu tätigen.
- **Caching und Wiederverwendung**: Speichern Sie häufig verwendete Ergebnisse in Variablen oder Dateien, um wiederholte AI-Modellaufrufe zu vermeiden.
- **Batch-Verarbeitung**: Verarbeiten Sie mehrere Elemente in einer einzigen AI-Anfrage, anstatt einzelne Aufrufe zu tätigen.

## Nutzungsüberwachung

Überwachen Sie Ihre Nutzung und Abrechnung unter Einstellungen → Abonnement:

- **Aktuelle Nutzung**: Echtzeit-Nutzung und -Kosten für den aktuellen Zeitraum
- **Nutzungslimits**: Plangrenzen mit visuellen Fortschrittsanzeigen
- **Aktuelle Nutzung**: Echtzeit-Nutzung und Kosten für den aktuellen Zeitraum
- **Nutzungslimits**: Plan-Limits mit visuellen Fortschrittsindikatoren
- **Abrechnungsdetails**: Prognostizierte Gebühren und Mindestverpflichtungen
- **Planverwaltung**: Upgrade-Optionen und Abrechnungsverlauf
- **Plan-Verwaltung**: Upgrade-Optionen und Abrechnungsverlauf

### Programmatische Nutzungsverfolgung
### Programmatisches Nutzungs-Tracking

Sie können Ihre aktuelle Nutzung und Limits programmatisch über die API abfragen:

**Endpunkt:**
**Endpoint:**

```text
GET /api/users/me/usage-limits
Expand Down Expand Up @@ -172,69 +176,69 @@ curl -X GET -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" htt
```

**Rate-Limit-Felder:**
- `requestsPerMinute`: Dauerhafte Rate-Begrenzung (Tokens werden mit dieser Rate aufgefüllt)
- `maxBurst`: Maximale Tokens, die Sie ansammeln können (Burst-Kapazität)
- `remaining`: Aktuell verfügbare Tokens (können bis zu `maxBurst` sein)
- `requestsPerMinute`: Dauerhaftes Rate-Limit (Tokens werden mit dieser Rate aufgefüllt)
- `maxBurst`: Maximale Tokens, die Sie akkumulieren können (Burst-Kapazität)
- `remaining`: Aktuell verfügbare Tokens (kann bis zu `maxBurst` betragen)

**Antwortfelder:**
- `currentPeriodCost` spiegelt die Nutzung in der aktuellen Abrechnungsperiode wider
- `limit` wird von individuellen Limits (Free/Pro) oder gepoolten Organisationslimits (Team/Enterprise) abgeleitet
- `plan` ist der aktive Plan mit der höchsten Priorität, der mit Ihrem Benutzer verknüpft ist
- `currentPeriodCost` spiegelt die Nutzung im aktuellen Abrechnungszeitraum wider
- `limit` wird aus individuellen Limits (Free/Pro) oder gepoolten Organisationslimits (Team/Enterprise) abgeleitet
- `plan` ist der Plan mit der höchsten Priorität, der Ihrem Benutzer zugeordnet ist

## Plan-Limits

Verschiedene Abonnementpläne haben unterschiedliche Nutzungslimits:
Verschiedene Abonnement-Pläne haben unterschiedliche Nutzungslimits:

| Plan | Monatliches Nutzungslimit | Ratenlimits (pro Minute) |
|------|-------------------|-------------------------|
| **Free** | 20 $ | 5 synchron, 10 asynchron |
| **Pro** | 100 $ | 10 synchron, 50 asynchron |
| **Team** | 500 $ (gepoolt) | 50 synchron, 100 asynchron |
| **Free** | 20 $ | 5 sync, 10 async |
| **Pro** | 100 $ | 10 sync, 50 async |
| **Team** | 500 $ (gemeinsam) | 50 sync, 100 async |
| **Enterprise** | Individuell | Individuell |

## Abrechnungsmodell

Sim verwendet ein **Basisabonnement + Mehrverbrauch**-Abrechnungsmodell:
Sim verwendet ein **Basis-Abonnement + Mehrverbrauch**-Abrechnungsmodell:

### Wie es funktioniert
### So funktioniert es

**Pro-Plan ($20/Monat):**
- Monatliches Abonnement beinhaltet $20 Nutzung
- Nutzung unter $20 → Keine zusätzlichen Kosten
- Nutzung über $20 → Zahlen Sie den Mehrverbrauch am Monatsende
- Beispiel: $35 Nutzung = $20 (Abonnement) + $15 (Mehrverbrauch)
**Pro-Plan (20 $/Monat):**
- Monatsabonnement beinhaltet 20 $ Nutzung
- Nutzung unter 20 $ → Keine zusätzlichen Gebühren
- Nutzung über 20 $ → Mehrverbrauch am Monatsende zahlen
- Beispiel: 35 $ Nutzung = 20 $ (Abonnement) + 15 $ (Mehrverbrauch)

**Team-Plan ($40/Benutzer/Monat):**
- Gepoolte Nutzung für alle Teammitglieder
- Mehrverbrauch wird aus der Gesamtnutzung des Teams berechnet
**Team-Plan (40 $/Platz/Monat):**
- Gemeinsame Nutzung über alle Teammitglieder
- Mehrverbrauch wird aus der gesamten Team-Nutzung berechnet
- Organisationsinhaber erhält eine Rechnung

**Enterprise-Pläne:**
- Fester monatlicher Preis, kein Mehrverbrauch
- Fester Monatspreis, kein Mehrverbrauch
- Individuelle Nutzungslimits gemäß Vereinbarung

### Schwellenwert-Abrechnung

Wenn der nicht abgerechnete Mehrverbrauch $50 erreicht, berechnet Sim automatisch den gesamten nicht abgerechneten Betrag.
Wenn der nicht abgerechnete Mehrverbrauch 50 $ erreicht, rechnet Sim automatisch den gesamten nicht abgerechneten Betrag ab.

**Beispiel:**
- Tag 10: $70 Mehrverbrauch → Sofortige Abrechnung von $70
- Tag 15: Zusätzliche $35 Nutzung ($105 insgesamt) → Bereits abgerechnet, keine Aktion
- Tag 20: Weitere $50 Nutzung ($155 insgesamt, $85 nicht abgerechnet) → Sofortige Abrechnung von $85
- Tag 10: 70 $ Mehrverbrauch → 70 $ sofort abrechnen
- Tag 15: Zusätzliche 35 $ Nutzung (105 $ gesamt) → Bereits abgerechnet, keine Aktion
- Tag 20: Weitere 50 $ Nutzung (155 $ gesamt, 85 $ nicht abgerechnet) → 85 $ sofort abrechnen

Dies verteilt große Überziehungsgebühren über den Monat, anstatt eine große Rechnung am Ende des Abrechnungszeitraums zu erhalten.
Dies verteilt große Mehrverbrauchsgebühren über den Monat, anstatt einer großen Rechnung am Periodenende.

## Best Practices für Kostenmanagement

1. **Regelmäßig überwachen**: Überprüfen Sie Ihr Nutzungs-Dashboard häufig, um Überraschungen zu vermeiden
2. **Budgets festlegen**: Nutzen Sie Planlimits als Leitplanken für Ihre Ausgaben
2. **Budgets festlegen**: Nutzen Sie Plan-Limits als Leitplanken für Ihre Ausgaben
3. **Workflows optimieren**: Überprüfen Sie kostenintensive Ausführungen und optimieren Sie Prompts oder Modellauswahl
4. **Passende Modelle verwenden**: Passen Sie die Modellkomplexität an die Aufgabenanforderungen an
5. **Ähnliche Aufgaben bündeln**: Kombinieren Sie wenn möglich mehrere Anfragen, um den Overhead zu reduzieren
5. **Ähnliche Aufgaben bündeln**: Kombinieren Sie mehrere Anfragen, wenn möglich, um Overhead zu reduzieren

## Nächste Schritte

- Überprüfen Sie Ihre aktuelle Nutzung unter [Einstellungen → Abonnement](https://sim.ai/settings/subscription)
- Erfahren Sie mehr über [Protokollierung](/execution/logging), um Ausführungsdetails zu verfolgen
- Erkunden Sie die [Externe API](/execution/api) für programmatische Kostenüberwachung
- Entdecken Sie die [externe API](/execution/api) für programmatische Kostenüberwachung
- Sehen Sie sich [Workflow-Optimierungstechniken](/blocks) an, um Kosten zu reduzieren
26 changes: 26 additions & 0 deletions apps/docs/content/docs/de/tools/firecrawl.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,32 @@ Extrahieren Sie strukturierte Daten aus vollständigen Webseiten mithilfe von na
| `success` | boolean | Ob der Extraktionsvorgang erfolgreich war |
| `data` | object | Extrahierte strukturierte Daten gemäß dem Schema oder der Eingabeaufforderung |

### `firecrawl_agent`

Autonomer Web-Datenextraktions-Agent. Sucht und sammelt Informationen basierend auf natürlichsprachlichen Anweisungen, ohne dass spezifische URLs erforderlich sind.

#### Eingabe

| Parameter | Typ | Erforderlich | Beschreibung |
| --------- | ---- | -------- | ----------- |
| `prompt` | string | Ja | Natürlichsprachliche Beschreibung der zu extrahierenden Daten \(max. 10.000 Zeichen\) |
| `urls` | json | Nein | Optionales Array von URLs, auf die sich der Agent konzentrieren soll |
| `schema` | json | Nein | JSON-Schema, das die Struktur der zu extrahierenden Daten definiert |
| `maxCredits` | number | Nein | Maximale Credits, die für diese Agent-Aufgabe verwendet werden sollen |
| `strictConstrainToURLs` | boolean | Nein | Wenn true, besucht der Agent nur URLs, die im urls-Array angegeben sind |
| `apiKey` | string | Ja | Firecrawl API-Schlüssel |

#### Ausgabe

| Parameter | Typ | Beschreibung |
| --------- | ---- | ----------- |
| `success` | boolean | Ob die Agent-Operation erfolgreich war |
| `status` | string | Aktueller Status des Agent-Jobs \(processing, completed, failed\) |
| `data` | object | Vom Agent extrahierte Daten |
| `creditsUsed` | number | Anzahl der von dieser Agent-Aufgabe verbrauchten Credits |
| `expiresAt` | string | Zeitstempel, wann die Ergebnisse ablaufen \(24 Stunden\) |
| `sources` | object | Array der vom Agent verwendeten Quell-URLs |

## Hinweise

- Kategorie: `tools`
Expand Down
Loading
Loading