Skip to content

Commit b6ba3b5

Browse files
authored
v0.5.44: keyboard shortcuts, autolayout, light mode, byok, testing improvements
2 parents b304233 + 8651896 commit b6ba3b5

File tree

1,452 files changed

+44833
-13419
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,452 files changed

+44833
-13419
lines changed

apps/docs/app/api/search/route.ts

Lines changed: 126 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,126 @@
1-
import { createFromSource } from 'fumadocs-core/search/server'
2-
import { source } from '@/lib/source'
3-
4-
export const revalidate = 3600 // Revalidate every hour
5-
6-
export const { GET } = createFromSource(source, {
7-
localeMap: {
8-
en: { language: 'english' },
9-
es: { language: 'spanish' },
10-
fr: { language: 'french' },
11-
de: { language: 'german' },
12-
// ja and zh are not supported by the stemmer library, so we'll skip language config for them
13-
ja: {},
14-
zh: {},
15-
},
16-
})
1+
import { sql } from 'drizzle-orm'
2+
import { type NextRequest, NextResponse } from 'next/server'
3+
import { db, docsEmbeddings } from '@/lib/db'
4+
import { generateSearchEmbedding } from '@/lib/embeddings'
5+
6+
export const runtime = 'nodejs'
7+
export const revalidate = 0
8+
9+
/**
10+
* Hybrid search API endpoint
11+
* - English: Vector embeddings + keyword search
12+
* - Other languages: Keyword search only
13+
*/
14+
export async function GET(request: NextRequest) {
15+
try {
16+
const searchParams = request.nextUrl.searchParams
17+
const query = searchParams.get('query') || searchParams.get('q') || ''
18+
const locale = searchParams.get('locale') || 'en'
19+
const limit = Number.parseInt(searchParams.get('limit') || '10', 10)
20+
21+
if (!query || query.trim().length === 0) {
22+
return NextResponse.json([])
23+
}
24+
25+
const candidateLimit = limit * 3
26+
const similarityThreshold = 0.6
27+
28+
const localeMap: Record<string, string> = {
29+
en: 'english',
30+
es: 'spanish',
31+
fr: 'french',
32+
de: 'german',
33+
ja: 'simple', // PostgreSQL doesn't have Japanese support, use simple
34+
zh: 'simple', // PostgreSQL doesn't have Chinese support, use simple
35+
}
36+
const tsConfig = localeMap[locale] || 'simple'
37+
38+
const useVectorSearch = locale === 'en'
39+
let vectorResults: Array<{
40+
chunkId: string
41+
chunkText: string
42+
sourceDocument: string
43+
sourceLink: string
44+
headerText: string
45+
headerLevel: number
46+
similarity: number
47+
searchType: string
48+
}> = []
49+
50+
if (useVectorSearch) {
51+
const queryEmbedding = await generateSearchEmbedding(query)
52+
vectorResults = await db
53+
.select({
54+
chunkId: docsEmbeddings.chunkId,
55+
chunkText: docsEmbeddings.chunkText,
56+
sourceDocument: docsEmbeddings.sourceDocument,
57+
sourceLink: docsEmbeddings.sourceLink,
58+
headerText: docsEmbeddings.headerText,
59+
headerLevel: docsEmbeddings.headerLevel,
60+
similarity: sql<number>`1 - (${docsEmbeddings.embedding} <=> ${JSON.stringify(queryEmbedding)}::vector)`,
61+
searchType: sql<string>`'vector'`,
62+
})
63+
.from(docsEmbeddings)
64+
.where(
65+
sql`1 - (${docsEmbeddings.embedding} <=> ${JSON.stringify(queryEmbedding)}::vector) >= ${similarityThreshold}`
66+
)
67+
.orderBy(sql`${docsEmbeddings.embedding} <=> ${JSON.stringify(queryEmbedding)}::vector`)
68+
.limit(candidateLimit)
69+
}
70+
71+
const keywordResults = await db
72+
.select({
73+
chunkId: docsEmbeddings.chunkId,
74+
chunkText: docsEmbeddings.chunkText,
75+
sourceDocument: docsEmbeddings.sourceDocument,
76+
sourceLink: docsEmbeddings.sourceLink,
77+
headerText: docsEmbeddings.headerText,
78+
headerLevel: docsEmbeddings.headerLevel,
79+
similarity: sql<number>`ts_rank(${docsEmbeddings.chunkTextTsv}, plainto_tsquery(${tsConfig}, ${query}))`,
80+
searchType: sql<string>`'keyword'`,
81+
})
82+
.from(docsEmbeddings)
83+
.where(sql`${docsEmbeddings.chunkTextTsv} @@ plainto_tsquery(${tsConfig}, ${query})`)
84+
.orderBy(
85+
sql`ts_rank(${docsEmbeddings.chunkTextTsv}, plainto_tsquery(${tsConfig}, ${query})) DESC`
86+
)
87+
.limit(candidateLimit)
88+
89+
const seenIds = new Set<string>()
90+
const mergedResults = []
91+
92+
for (let i = 0; i < Math.max(vectorResults.length, keywordResults.length); i++) {
93+
if (i < vectorResults.length && !seenIds.has(vectorResults[i].chunkId)) {
94+
mergedResults.push(vectorResults[i])
95+
seenIds.add(vectorResults[i].chunkId)
96+
}
97+
if (i < keywordResults.length && !seenIds.has(keywordResults[i].chunkId)) {
98+
mergedResults.push(keywordResults[i])
99+
seenIds.add(keywordResults[i].chunkId)
100+
}
101+
}
102+
103+
const filteredResults = mergedResults.slice(0, limit)
104+
const searchResults = filteredResults.map((result) => {
105+
const title = result.headerText || result.sourceDocument.replace('.mdx', '')
106+
const pathParts = result.sourceDocument
107+
.replace('.mdx', '')
108+
.split('/')
109+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
110+
111+
return {
112+
id: result.chunkId,
113+
type: 'page' as const,
114+
url: result.sourceLink,
115+
content: title,
116+
breadcrumbs: pathParts,
117+
}
118+
})
119+
120+
return NextResponse.json(searchResults)
121+
} catch (error) {
122+
console.error('Semantic search error:', error)
123+
124+
return NextResponse.json([])
125+
}
126+
}

apps/docs/components/icons.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,19 @@ export function SlackIcon(props: SVGProps<SVGSVGElement>) {
462462
)
463463
}
464464

465+
export function SlackMonoIcon(props: SVGProps<SVGSVGElement>) {
466+
return (
467+
<svg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg' fill='currentColor' {...props}>
468+
<g>
469+
<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' />
470+
<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' />
471+
<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' />
472+
<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' />
473+
</g>
474+
</svg>
475+
)
476+
}
477+
465478
export function GithubIcon(props: SVGProps<SVGSVGElement>) {
466479
return (
467480
<svg {...props} width='26' height='26' viewBox='0 0 26 26' xmlns='http://www.w3.org/2000/svg'>

apps/docs/content/docs/de/execution/costs.mdx

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -105,28 +105,32 @@ Die Modellaufschlüsselung zeigt:
105105
Die angezeigten Preise entsprechen den Tarifen vom 10. September 2025. Überprüfen Sie die Dokumentation der Anbieter für aktuelle Preise.
106106
</Callout>
107107

108+
## Bring Your Own Key (BYOK)
109+
110+
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.
111+
108112
## Strategien zur Kostenoptimierung
109113

110-
- **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.
111-
- **Prompt-Engineering**: Gut strukturierte, präzise Prompts reduzieren den Token-Verbrauch ohne Qualitätseinbußen.
114+
- **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.
115+
- **Prompt Engineering**: Gut strukturierte, prägnante Prompts reduzieren den Token-Verbrauch ohne Qualitätsverlust.
112116
- **Lokale Modelle**: Verwenden Sie Ollama oder VLLM für unkritische Aufgaben, um API-Kosten vollständig zu eliminieren.
113-
- **Caching und Wiederverwendung**: Speichern Sie häufig verwendete Ergebnisse in Variablen oder Dateien, um wiederholte KI-Modellaufrufe zu vermeiden.
114-
- **Batch-Verarbeitung**: Verarbeiten Sie mehrere Elemente in einer einzigen KI-Anfrage anstatt einzelne Aufrufe zu tätigen.
117+
- **Caching und Wiederverwendung**: Speichern Sie häufig verwendete Ergebnisse in Variablen oder Dateien, um wiederholte AI-Modellaufrufe zu vermeiden.
118+
- **Batch-Verarbeitung**: Verarbeiten Sie mehrere Elemente in einer einzigen AI-Anfrage, anstatt einzelne Aufrufe zu tätigen.
115119

116120
## Nutzungsüberwachung
117121

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

120-
- **Aktuelle Nutzung**: Echtzeit-Nutzung und -Kosten für den aktuellen Zeitraum
121-
- **Nutzungslimits**: Plangrenzen mit visuellen Fortschrittsanzeigen
124+
- **Aktuelle Nutzung**: Echtzeit-Nutzung und Kosten für den aktuellen Zeitraum
125+
- **Nutzungslimits**: Plan-Limits mit visuellen Fortschrittsindikatoren
122126
- **Abrechnungsdetails**: Prognostizierte Gebühren und Mindestverpflichtungen
123-
- **Planverwaltung**: Upgrade-Optionen und Abrechnungsverlauf
127+
- **Plan-Verwaltung**: Upgrade-Optionen und Abrechnungsverlauf
124128

125-
### Programmatische Nutzungsverfolgung
129+
### Programmatisches Nutzungs-Tracking
126130

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

129-
**Endpunkt:**
133+
**Endpoint:**
130134

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

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

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

184188
## Plan-Limits
185189

186-
Verschiedene Abonnementpläne haben unterschiedliche Nutzungslimits:
190+
Verschiedene Abonnement-Pläne haben unterschiedliche Nutzungslimits:
187191

188192
| Plan | Monatliches Nutzungslimit | Ratenlimits (pro Minute) |
189193
|------|-------------------|-------------------------|
190-
| **Free** | 20 $ | 5 synchron, 10 asynchron |
191-
| **Pro** | 100 $ | 10 synchron, 50 asynchron |
192-
| **Team** | 500 $ (gepoolt) | 50 synchron, 100 asynchron |
194+
| **Free** | 20 $ | 5 sync, 10 async |
195+
| **Pro** | 100 $ | 10 sync, 50 async |
196+
| **Team** | 500 $ (gemeinsam) | 50 sync, 100 async |
193197
| **Enterprise** | Individuell | Individuell |
194198

195199
## Abrechnungsmodell
196200

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

199-
### Wie es funktioniert
203+
### So funktioniert es
200204

201-
**Pro-Plan ($20/Monat):**
202-
- Monatliches Abonnement beinhaltet $20 Nutzung
203-
- Nutzung unter $20 → Keine zusätzlichen Kosten
204-
- Nutzung über $20 → Zahlen Sie den Mehrverbrauch am Monatsende
205-
- Beispiel: $35 Nutzung = $20 (Abonnement) + $15 (Mehrverbrauch)
205+
**Pro-Plan (20 $/Monat):**
206+
- Monatsabonnement beinhaltet 20 $ Nutzung
207+
- Nutzung unter 20 $ → Keine zusätzlichen Gebühren
208+
- Nutzung über 20 $ → Mehrverbrauch am Monatsende zahlen
209+
- Beispiel: 35 $ Nutzung = 20 $ (Abonnement) + 15 $ (Mehrverbrauch)
206210

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

212216
**Enterprise-Pläne:**
213-
- Fester monatlicher Preis, kein Mehrverbrauch
217+
- Fester Monatspreis, kein Mehrverbrauch
214218
- Individuelle Nutzungslimits gemäß Vereinbarung
215219

216220
### Schwellenwert-Abrechnung
217221

218-
Wenn der nicht abgerechnete Mehrverbrauch $50 erreicht, berechnet Sim automatisch den gesamten nicht abgerechneten Betrag.
222+
Wenn der nicht abgerechnete Mehrverbrauch 50 $ erreicht, rechnet Sim automatisch den gesamten nicht abgerechneten Betrag ab.
219223

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

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

227231
## Best Practices für Kostenmanagement
228232

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

235239
## Nächste Schritte
236240

237241
- Überprüfen Sie Ihre aktuelle Nutzung unter [Einstellungen → Abonnement](https://sim.ai/settings/subscription)
238242
- Erfahren Sie mehr über [Protokollierung](/execution/logging), um Ausführungsdetails zu verfolgen
239-
- Erkunden Sie die [Externe API](/execution/api) für programmatische Kostenüberwachung
243+
- Entdecken Sie die [externe API](/execution/api) für programmatische Kostenüberwachung
240244
- Sehen Sie sich [Workflow-Optimierungstechniken](/blocks) an, um Kosten zu reduzieren

apps/docs/content/docs/de/tools/firecrawl.mdx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,32 @@ Extrahieren Sie strukturierte Daten aus vollständigen Webseiten mithilfe von na
146146
| `success` | boolean | Ob der Extraktionsvorgang erfolgreich war |
147147
| `data` | object | Extrahierte strukturierte Daten gemäß dem Schema oder der Eingabeaufforderung |
148148

149+
### `firecrawl_agent`
150+
151+
Autonomer Web-Datenextraktions-Agent. Sucht und sammelt Informationen basierend auf natürlichsprachlichen Anweisungen, ohne dass spezifische URLs erforderlich sind.
152+
153+
#### Eingabe
154+
155+
| Parameter | Typ | Erforderlich | Beschreibung |
156+
| --------- | ---- | -------- | ----------- |
157+
| `prompt` | string | Ja | Natürlichsprachliche Beschreibung der zu extrahierenden Daten \(max. 10.000 Zeichen\) |
158+
| `urls` | json | Nein | Optionales Array von URLs, auf die sich der Agent konzentrieren soll |
159+
| `schema` | json | Nein | JSON-Schema, das die Struktur der zu extrahierenden Daten definiert |
160+
| `maxCredits` | number | Nein | Maximale Credits, die für diese Agent-Aufgabe verwendet werden sollen |
161+
| `strictConstrainToURLs` | boolean | Nein | Wenn true, besucht der Agent nur URLs, die im urls-Array angegeben sind |
162+
| `apiKey` | string | Ja | Firecrawl API-Schlüssel |
163+
164+
#### Ausgabe
165+
166+
| Parameter | Typ | Beschreibung |
167+
| --------- | ---- | ----------- |
168+
| `success` | boolean | Ob die Agent-Operation erfolgreich war |
169+
| `status` | string | Aktueller Status des Agent-Jobs \(processing, completed, failed\) |
170+
| `data` | object | Vom Agent extrahierte Daten |
171+
| `creditsUsed` | number | Anzahl der von dieser Agent-Aufgabe verbrauchten Credits |
172+
| `expiresAt` | string | Zeitstempel, wann die Ergebnisse ablaufen \(24 Stunden\) |
173+
| `sources` | object | Array der vom Agent verwendeten Quell-URLs |
174+
149175
## Hinweise
150176

151177
- Kategorie: `tools`

0 commit comments

Comments
 (0)