Skip to content

Commit b2ae9db

Browse files
committed
Merge branch 'staging' into feat/conc-control
2 parents 9612066 + 5e53757 commit b2ae9db

File tree

63 files changed

+17676
-1031
lines changed

Some content is hidden

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

63 files changed

+17676
-1031
lines changed

apps/docs/components/icons.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3132,6 +3132,22 @@ export function QdrantIcon(props: SVGProps<SVGSVGElement>) {
31323132
)
31333133
}
31343134

3135+
export function QuiverIcon(props: SVGProps<SVGSVGElement>) {
3136+
return (
3137+
<svg {...props} viewBox='0 0 250 250' fill='none' xmlns='http://www.w3.org/2000/svg'>
3138+
<path d='m249.3 0.88h-248.5v248.2h248.5v-248.2z' fill='#F6F6F7' />
3139+
<path
3140+
d='m124.3 25h-5.93l-1.95 0.59-7.9 0.29-1.47 0.88-7.9 1.18-1.18 0.88-9.09 2.85-0.88 0.88-11.86 5.93-0.88 1.18-6.23 2.55-8.29 8.3-7.61 4.75-5.34 8.6-5.04 4.75-4.46 8.6-2.05 1.18-3.26 8.6-0.88 0.59-3.85 12.16-0.59 0.59-2.35 13.04v1.47l-0.59 7.12 0.3 1.18-0.3 3.15 1.18 13.04 0.59 0.88 0.88 7.51 0.88 1.18 3.85 12.16 0.88 0.6 4.44 9.97 1.18 0.88 4.15 8 12.73 16.17 4.45 2.06 8.8 8.3 0.88 0.29 4.16 3.15h1.18l8.2 4.75h0.88l7.9 3.44h0.88l9.38 2.85 0.88 0.3 13.33 1.46h107.9v-101.3l-0.88-2.06v-8.3l-0.59-0.88v-4.16l-4.75-14.23v-4.16l-11.26-19.46-1.48-1.48-10.37-13.05-5.63-3.15-7.61-7.31-3.15-1.18-5.93-4.75-1.48-0.29-7.01-4.15h-1.18l-8.2-3.15h-0.88l-10.37-3.14h-1.18l-8.49-1.18-2.06-0.88h-7.5z'
3141+
fill='#333'
3142+
/>
3143+
<path
3144+
d='m78.38 72.26 118.6 41.21c4.65 1.69 3.47 8.5-1.47 8.5h-74v74.32c0 5.04-7.11 5.92-8.78 1.17l-40.58-118.5c-1.28-3.95 2.27-8.11 6.19-6.72z'
3145+
fill='#F9F9F9'
3146+
/>
3147+
</svg>
3148+
)
3149+
}
3150+
31353151
export function AshbyIcon(props: SVGProps<SVGSVGElement>) {
31363152
return (
31373153
<svg {...props} viewBox='0 0 254 260' fill='none' xmlns='http://www.w3.org/2000/svg'>

apps/docs/components/ui/icon-mapping.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ import {
126126
PosthogIcon,
127127
PulseIcon,
128128
QdrantIcon,
129+
QuiverIcon,
129130
RDSIcon,
130131
RedditIcon,
131132
RedisIcon,
@@ -298,6 +299,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
298299
posthog: PosthogIcon,
299300
pulse_v2: PulseIcon,
300301
qdrant: QdrantIcon,
302+
quiver: QuiverIcon,
301303
rds: RDSIcon,
302304
reddit: RedditIcon,
303305
redis: RedisIcon,

apps/docs/content/docs/en/tools/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
"posthog",
122122
"pulse",
123123
"qdrant",
124+
"quiver",
124125
"rds",
125126
"reddit",
126127
"redis",
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
title: Quiver
3+
description: Generate and vectorize SVGs
4+
---
5+
6+
import { BlockInfoCard } from "@/components/ui/block-info-card"
7+
8+
<BlockInfoCard
9+
type="quiver"
10+
color="#000000"
11+
/>
12+
13+
{/* MANUAL-CONTENT-START:intro */}
14+
[QuiverAI](https://quiver.ai/) is an AI-powered SVG generation platform that creates high-quality, scalable vector graphics from text descriptions or by vectorizing raster images. It produces clean, resolution-independent SVGs that are ideal for icons, illustrations, logos, and UI elements.
15+
16+
With Quiver, you can:
17+
18+
- **Generate SVGs from text prompts**: Describe the vector graphic you need and get production-ready SVG output
19+
- **Vectorize raster images**: Convert PNG, JPG, and other raster images into clean SVG vector format
20+
- **Provide reference images**: Upload up to 4 reference images to guide the style and composition of generated SVGs
21+
- **Control generation parameters**: Adjust temperature, number of outputs, and token limits to fine-tune results
22+
- **List available models**: Query available QuiverAI models to discover supported operations and capabilities
23+
- **Get clean SVG markup**: Receive raw SVG content alongside downloadable files for easy embedding
24+
25+
In Sim, the Quiver integration enables your workflows to generate and vectorize graphics on demand. This is useful for creating dynamic illustrations, converting raster assets to scalable vectors, generating icons for applications, producing visual assets for content pipelines, or building design automation workflows. The generated SVGs are returned as files that can be passed to downstream blocks for further processing, storage, or delivery.
26+
{/* MANUAL-CONTENT-END */}
27+
28+
29+
## Usage Instructions
30+
31+
Generate SVG images from text prompts or vectorize raster images into SVGs using QuiverAI. Supports reference images, style instructions, and multiple output generation.
32+
33+
34+
35+
## Tools
36+
37+
### `quiver_text_to_svg`
38+
39+
Generate SVG images from text prompts using QuiverAI
40+
41+
#### Input
42+
43+
| Parameter | Type | Required | Description |
44+
| --------- | ---- | -------- | ----------- |
45+
| `apiKey` | string | Yes | QuiverAI API key |
46+
| `prompt` | string | Yes | A text description of the desired SVG |
47+
| `model` | string | Yes | The model to use for SVG generation \(e.g., "arrow-preview"\) |
48+
| `instructions` | string | No | Style or formatting guidance for the SVG output |
49+
| `references` | file | No | Reference images to guide SVG generation \(up to 4\) |
50+
| `n` | number | No | Number of SVGs to generate \(1-16, default 1\) |
51+
| `temperature` | number | No | Sampling temperature \(0-2, default 1\) |
52+
| `top_p` | number | No | Nucleus sampling probability \(0-1, default 1\) |
53+
| `max_output_tokens` | number | No | Maximum output tokens \(1-131072\) |
54+
| `presence_penalty` | number | No | Token penalty for prior output \(-2 to 2, default 0\) |
55+
56+
#### Output
57+
58+
| Parameter | Type | Description |
59+
| --------- | ---- | ----------- |
60+
| `success` | boolean | Whether the SVG generation succeeded |
61+
| `output` | object | Generated SVG output |
62+
|`file` | file | Generated SVG file |
63+
|`svgContent` | string | Raw SVG markup content |
64+
|`id` | string | Generation request ID |
65+
|`usage` | json | Token usage statistics |
66+
|`totalTokens` | number | Total tokens used |
67+
|`inputTokens` | number | Input tokens used |
68+
|`outputTokens` | number | Output tokens used |
69+
70+
### `quiver_image_to_svg`
71+
72+
Convert raster images into vector SVG format using QuiverAI
73+
74+
#### Input
75+
76+
| Parameter | Type | Required | Description |
77+
| --------- | ---- | -------- | ----------- |
78+
| `apiKey` | string | Yes | QuiverAI API key |
79+
| `model` | string | Yes | The model to use for vectorization \(e.g., "arrow-preview"\) |
80+
| `image` | file | Yes | The raster image to vectorize into SVG |
81+
| `temperature` | number | No | Sampling temperature \(0-2, default 1\) |
82+
| `top_p` | number | No | Nucleus sampling probability \(0-1, default 1\) |
83+
| `max_output_tokens` | number | No | Maximum output tokens \(1-131072\) |
84+
| `presence_penalty` | number | No | Token penalty for prior output \(-2 to 2, default 0\) |
85+
| `auto_crop` | boolean | No | Automatically crop the image before vectorizing |
86+
| `target_size` | number | No | Square resize target in pixels \(128-4096\) |
87+
88+
#### Output
89+
90+
| Parameter | Type | Description |
91+
| --------- | ---- | ----------- |
92+
| `success` | boolean | Whether the vectorization succeeded |
93+
| `output` | object | Vectorized SVG output |
94+
|`file` | file | Generated SVG file |
95+
|`svgContent` | string | Raw SVG markup content |
96+
|`id` | string | Vectorization request ID |
97+
|`usage` | json | Token usage statistics |
98+
|`totalTokens` | number | Total tokens used |
99+
|`inputTokens` | number | Input tokens used |
100+
|`outputTokens` | number | Output tokens used |
101+
102+
### `quiver_list_models`
103+
104+
List all available QuiverAI models
105+
106+
#### Input
107+
108+
| Parameter | Type | Required | Description |
109+
| --------- | ---- | -------- | ----------- |
110+
| `apiKey` | string | Yes | QuiverAI API key |
111+
112+
#### Output
113+
114+
| Parameter | Type | Description |
115+
| --------- | ---- | ----------- |
116+
| `success` | boolean | Whether the request succeeded |
117+
| `output` | object | Available models |
118+
|`models` | json | List of available QuiverAI models |
119+
|`id` | string | Model identifier |
120+
|`name` | string | Human-readable model name |
121+
|`description` | string | Model capabilities summary |
122+
|`created` | number | Unix timestamp of creation |
123+
|`ownedBy` | string | Organization that owns the model |
124+
|`inputModalities` | json | Supported input types \(text, image, svg\) |
125+
|`outputModalities` | json | Supported output types \(text, image, svg\) |
126+
|`contextLength` | number | Maximum context window |
127+
|`maxOutputLength` | number | Maximum generation length |
128+
|`supportedOperations` | json | Available operations \(svg_generate, svg_edit, svg_animate, svg_vectorize, chat_completions\) |
129+
|`supportedSamplingParameters` | json | Supported sampling parameters \(temperature, top_p, top_k, repetition_penalty, presence_penalty, stop\) |
130+
131+

apps/sim/app/(landing)/integrations/data/icon-mapping.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ import {
126126
PosthogIcon,
127127
PulseIcon,
128128
QdrantIcon,
129+
QuiverIcon,
129130
RDSIcon,
130131
RedditIcon,
131132
RedisIcon,
@@ -298,6 +299,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
298299
posthog: PosthogIcon,
299300
pulse_v2: PulseIcon,
300301
qdrant: QdrantIcon,
302+
quiver: QuiverIcon,
301303
rds: RDSIcon,
302304
reddit: RedditIcon,
303305
redis: RedisIcon,

apps/sim/app/(landing)/integrations/data/integrations.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8518,6 +8518,37 @@
85188518
"integrationType": "databases",
85198519
"tags": ["vector-search", "knowledge-base"]
85208520
},
8521+
{
8522+
"type": "quiver",
8523+
"slug": "quiver",
8524+
"name": "Quiver",
8525+
"description": "Generate and vectorize SVGs",
8526+
"longDescription": "Generate SVG images from text prompts or vectorize raster images into SVGs using QuiverAI. Supports reference images, style instructions, and multiple output generation.",
8527+
"bgColor": "#000000",
8528+
"iconName": "QuiverIcon",
8529+
"docsUrl": "https://docs.sim.ai/tools/quiver",
8530+
"operations": [
8531+
{
8532+
"name": "Text to SVG",
8533+
"description": "Generate SVG images from text prompts using QuiverAI"
8534+
},
8535+
{
8536+
"name": "Image to SVG",
8537+
"description": "Convert raster images into vector SVG format using QuiverAI"
8538+
},
8539+
{
8540+
"name": "List Models",
8541+
"description": "List all available QuiverAI models"
8542+
}
8543+
],
8544+
"operationCount": 3,
8545+
"triggers": [],
8546+
"triggerCount": 0,
8547+
"authType": "api-key",
8548+
"category": "tools",
8549+
"integrationType": "design",
8550+
"tags": ["image-generation"]
8551+
},
85218552
{
85228553
"type": "reddit",
85238554
"slug": "reddit",

apps/sim/app/api/copilot/chat/route.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,6 @@ export async function POST(req: NextRequest) {
346346
goRoute: '/api/copilot',
347347
autoExecuteTools: true,
348348
interactive: true,
349-
promptForToolApproval: false,
350349
onComplete: async (result: OrchestratorResult) => {
351350
if (!actualChatId) return
352351

@@ -365,16 +364,25 @@ export async function POST(req: NextRequest) {
365364
const stored: Record<string, unknown> = { type: block.type }
366365
if (block.content) stored.content = block.content
367366
if (block.type === 'tool_call' && block.toolCall) {
367+
const state =
368+
block.toolCall.result?.success !== undefined
369+
? block.toolCall.result.success
370+
? 'success'
371+
: 'error'
372+
: block.toolCall.status
373+
const isSubagentTool = !!block.calledBy
374+
const isNonTerminal =
375+
state === 'cancelled' || state === 'pending' || state === 'executing'
368376
stored.toolCall = {
369377
id: block.toolCall.id,
370378
name: block.toolCall.name,
371-
state:
372-
block.toolCall.result?.success !== undefined
373-
? block.toolCall.result.success
374-
? 'success'
375-
: 'error'
376-
: block.toolCall.status,
377-
result: block.toolCall.result,
379+
state,
380+
...(isSubagentTool && isNonTerminal ? {} : { result: block.toolCall.result }),
381+
...(isSubagentTool && isNonTerminal
382+
? {}
383+
: block.toolCall.params
384+
? { params: block.toolCall.params }
385+
: {}),
378386
...(block.calledBy ? { calledBy: block.calledBy } : {}),
379387
}
380388
}
@@ -426,7 +434,6 @@ export async function POST(req: NextRequest) {
426434
goRoute: '/api/copilot',
427435
autoExecuteTools: true,
428436
interactive: true,
429-
promptForToolApproval: false,
430437
})
431438

432439
const responseData = {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* @vitest-environment node
3+
*/
4+
5+
import { NextRequest } from 'next/server'
6+
import { beforeEach, describe, expect, it, vi } from 'vitest'
7+
8+
const { getStreamMeta, readStreamEvents, authenticateCopilotRequestSessionOnly } = vi.hoisted(
9+
() => ({
10+
getStreamMeta: vi.fn(),
11+
readStreamEvents: vi.fn(),
12+
authenticateCopilotRequestSessionOnly: vi.fn(),
13+
})
14+
)
15+
16+
vi.mock('@/lib/copilot/orchestrator/stream/buffer', () => ({
17+
getStreamMeta,
18+
readStreamEvents,
19+
}))
20+
21+
vi.mock('@/lib/copilot/request-helpers', () => ({
22+
authenticateCopilotRequestSessionOnly,
23+
}))
24+
25+
import { GET } from '@/app/api/copilot/chat/stream/route'
26+
27+
describe('copilot chat stream replay route', () => {
28+
beforeEach(() => {
29+
vi.clearAllMocks()
30+
authenticateCopilotRequestSessionOnly.mockResolvedValue({
31+
userId: 'user-1',
32+
isAuthenticated: true,
33+
})
34+
readStreamEvents.mockResolvedValue([])
35+
})
36+
37+
it('stops replay polling when stream meta becomes cancelled', async () => {
38+
getStreamMeta
39+
.mockResolvedValueOnce({
40+
status: 'active',
41+
userId: 'user-1',
42+
})
43+
.mockResolvedValueOnce({
44+
status: 'cancelled',
45+
userId: 'user-1',
46+
})
47+
48+
const response = await GET(
49+
new NextRequest('http://localhost:3000/api/copilot/chat/stream?streamId=stream-1')
50+
)
51+
52+
const reader = response.body?.getReader()
53+
expect(reader).toBeTruthy()
54+
55+
const first = await reader!.read()
56+
expect(first.done).toBe(true)
57+
expect(getStreamMeta).toHaveBeenCalledTimes(2)
58+
})
59+
})

0 commit comments

Comments
 (0)