Skip to content

Commit 07d50f8

Browse files
authored
v0.5.88: interactions api for gemini, trigger machine size increase, confluence ops
2 parents 2797395 + 52aff4d commit 07d50f8

File tree

36 files changed

+1980
-100
lines changed

36 files changed

+1980
-100
lines changed

apps/docs/content/docs/de/keyboard-shortcuts/index.mdx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ Diese Tastenkombinationen wechseln zwischen den Panel-Tabs auf der rechten Seite
4141

4242
| Tastenkombination | Aktion |
4343
|----------|--------|
44-
| `C` | Copilot-Tab fokussieren |
45-
| `T` | Toolbar-Tab fokussieren |
46-
| `E` | Editor-Tab fokussieren |
4744
| `Mod` + `F` | Toolbar-Suche fokussieren |
4845

4946
## Globale Navigation

apps/docs/content/docs/en/keyboard-shortcuts/index.mdx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ These shortcuts switch between panel tabs on the right side of the canvas.
4343

4444
| Shortcut | Action |
4545
|----------|--------|
46-
| `C` | Focus Copilot tab |
47-
| `T` | Focus Toolbar tab |
48-
| `E` | Focus Editor tab |
4946
| `Mod` + `F` | Focus Toolbar search |
5047

5148
## Global Navigation

apps/docs/content/docs/en/tools/confluence.mdx

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,28 @@ Create a new custom property (metadata) on a Confluence page.
399399
|`authorId` | string | Account ID of the version author |
400400
|`createdAt` | string | ISO 8601 timestamp of version creation |
401401

402+
### `confluence_delete_page_property`
403+
404+
Delete a content property from a Confluence page by its property ID.
405+
406+
#### Input
407+
408+
| Parameter | Type | Required | Description |
409+
| --------- | ---- | -------- | ----------- |
410+
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
411+
| `pageId` | string | Yes | The ID of the page containing the property |
412+
| `propertyId` | string | Yes | The ID of the property to delete |
413+
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
414+
415+
#### Output
416+
417+
| Parameter | Type | Description |
418+
| --------- | ---- | ----------- |
419+
| `ts` | string | ISO 8601 timestamp of the operation |
420+
| `pageId` | string | ID of the page |
421+
| `propertyId` | string | ID of the deleted property |
422+
| `deleted` | boolean | Deletion status |
423+
402424
### `confluence_search`
403425

404426
Search for content across Confluence pages, blog posts, and other content.
@@ -872,6 +894,90 @@ Add a label to a Confluence page for organization and categorization.
872894
| `labelName` | string | Name of the added label |
873895
| `labelId` | string | ID of the added label |
874896

897+
### `confluence_delete_label`
898+
899+
Remove a label from a Confluence page.
900+
901+
#### Input
902+
903+
| Parameter | Type | Required | Description |
904+
| --------- | ---- | -------- | ----------- |
905+
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
906+
| `pageId` | string | Yes | Confluence page ID to remove the label from |
907+
| `labelName` | string | Yes | Name of the label to remove |
908+
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
909+
910+
#### Output
911+
912+
| Parameter | Type | Description |
913+
| --------- | ---- | ----------- |
914+
| `ts` | string | ISO 8601 timestamp of the operation |
915+
| `pageId` | string | Page ID the label was removed from |
916+
| `labelName` | string | Name of the removed label |
917+
| `deleted` | boolean | Deletion status |
918+
919+
### `confluence_get_pages_by_label`
920+
921+
Retrieve all pages that have a specific label applied.
922+
923+
#### Input
924+
925+
| Parameter | Type | Required | Description |
926+
| --------- | ---- | -------- | ----------- |
927+
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
928+
| `labelId` | string | Yes | The ID of the label to get pages for |
929+
| `limit` | number | No | Maximum number of pages to return \(default: 50, max: 250\) |
930+
| `cursor` | string | No | Pagination cursor from previous response |
931+
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
932+
933+
#### Output
934+
935+
| Parameter | Type | Description |
936+
| --------- | ---- | ----------- |
937+
| `ts` | string | ISO 8601 timestamp of the operation |
938+
| `labelId` | string | ID of the label |
939+
| `pages` | array | Array of pages with this label |
940+
|`id` | string | Unique page identifier |
941+
|`title` | string | Page title |
942+
|`status` | string | Page status \(e.g., current, archived, trashed, draft\) |
943+
|`spaceId` | string | ID of the space containing the page |
944+
|`parentId` | string | ID of the parent page \(null if top-level\) |
945+
|`authorId` | string | Account ID of the page author |
946+
|`createdAt` | string | ISO 8601 timestamp when the page was created |
947+
|`version` | object | Page version information |
948+
|`number` | number | Version number |
949+
|`message` | string | Version message |
950+
|`minorEdit` | boolean | Whether this is a minor edit |
951+
|`authorId` | string | Account ID of the version author |
952+
|`createdAt` | string | ISO 8601 timestamp of version creation |
953+
| `nextCursor` | string | Cursor for fetching the next page of results |
954+
955+
### `confluence_list_space_labels`
956+
957+
List all labels associated with a Confluence space.
958+
959+
#### Input
960+
961+
| Parameter | Type | Required | Description |
962+
| --------- | ---- | -------- | ----------- |
963+
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
964+
| `spaceId` | string | Yes | The ID of the Confluence space to list labels from |
965+
| `limit` | number | No | Maximum number of labels to return \(default: 25, max: 250\) |
966+
| `cursor` | string | No | Pagination cursor from previous response |
967+
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
968+
969+
#### Output
970+
971+
| Parameter | Type | Description |
972+
| --------- | ---- | ----------- |
973+
| `ts` | string | ISO 8601 timestamp of the operation |
974+
| `spaceId` | string | ID of the space |
975+
| `labels` | array | Array of labels on the space |
976+
|`id` | string | Unique label identifier |
977+
|`name` | string | Label name |
978+
|`prefix` | string | Label prefix/type \(e.g., global, my, team\) |
979+
| `nextCursor` | string | Cursor for fetching the next page of results |
980+
875981
### `confluence_get_space`
876982

877983
Get details about a specific Confluence space.

apps/docs/content/docs/es/keyboard-shortcuts/index.mdx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ Estos atajos cambian entre las pestañas del panel en el lado derecho del lienzo
4242

4343
| Atajo | Acción |
4444
|----------|--------|
45-
| `C` | Enfocar pestaña Copilot |
46-
| `T` | Enfocar pestaña Barra de herramientas |
47-
| `E` | Enfocar pestaña Editor |
4845
| `Mod` + `F` | Enfocar búsqueda de Barra de herramientas |
4946

5047
## Navegación global

apps/docs/content/docs/fr/keyboard-shortcuts/index.mdx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ Ces raccourcis permettent de basculer entre les onglets du panneau sur le côté
4242

4343
| Raccourci | Action |
4444
|----------|--------|
45-
| `C` | Activer l'onglet Copilot |
46-
| `T` | Activer l'onglet Barre d'outils |
47-
| `E` | Activer l'onglet Éditeur |
4845
| `Mod` + `F` | Activer la recherche dans la barre d'outils |
4946

5047
## Navigation globale

apps/docs/content/docs/ja/keyboard-shortcuts/index.mdx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ import { Callout } from 'fumadocs-ui/components/callout'
4141

4242
| ショートカット | 操作 |
4343
|----------|--------|
44-
| `C` | Copilotタブにフォーカス |
45-
| `T` | Toolbarタブにフォーカス |
46-
| `E` | Editorタブにフォーカス |
4744
| `Mod` + `F` | Toolbar検索にフォーカス |
4845

4946
## グローバルナビゲーション

apps/docs/content/docs/zh/keyboard-shortcuts/index.mdx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ import { Callout } from 'fumadocs-ui/components/callout'
4141

4242
| 快捷键 | 操作 |
4343
|----------|--------|
44-
| `C` | 聚焦 Copilot 标签页 |
45-
| `T` | 聚焦 Toolbar 标签页 |
46-
| `E` | 聚焦 Editor 标签页 |
4744
| `Mod` + `F` | 聚焦 Toolbar 搜索 |
4845

4946
## 全局导航

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

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ const ChatMessageSchema = z.object({
113113
workflowId: z.string().optional(),
114114
knowledgeId: z.string().optional(),
115115
blockId: z.string().optional(),
116+
blockIds: z.array(z.string()).optional(),
116117
templateId: z.string().optional(),
117118
executionId: z.string().optional(),
118119
// For workflow_block, provide both workflowId and blockId
@@ -159,6 +160,20 @@ export async function POST(req: NextRequest) {
159160
commands,
160161
} = ChatMessageSchema.parse(body)
161162

163+
const normalizedContexts = Array.isArray(contexts)
164+
? contexts.map((ctx) => {
165+
if (ctx.kind !== 'blocks') return ctx
166+
if (Array.isArray(ctx.blockIds) && ctx.blockIds.length > 0) return ctx
167+
if (ctx.blockId) {
168+
return {
169+
...ctx,
170+
blockIds: [ctx.blockId],
171+
}
172+
}
173+
return ctx
174+
})
175+
: contexts
176+
162177
// Resolve workflowId - if not provided, use first workflow or find by name
163178
const resolved = await resolveWorkflowIdForUser(
164179
authenticatedUserId,
@@ -176,10 +191,10 @@ export async function POST(req: NextRequest) {
176191
const userMessageIdToUse = userMessageId || crypto.randomUUID()
177192
try {
178193
logger.info(`[${tracker.requestId}] Received chat POST`, {
179-
hasContexts: Array.isArray(contexts),
180-
contextsCount: Array.isArray(contexts) ? contexts.length : 0,
181-
contextsPreview: Array.isArray(contexts)
182-
? contexts.map((c: any) => ({
194+
hasContexts: Array.isArray(normalizedContexts),
195+
contextsCount: Array.isArray(normalizedContexts) ? normalizedContexts.length : 0,
196+
contextsPreview: Array.isArray(normalizedContexts)
197+
? normalizedContexts.map((c: any) => ({
183198
kind: c?.kind,
184199
chatId: c?.chatId,
185200
workflowId: c?.workflowId,
@@ -191,17 +206,25 @@ export async function POST(req: NextRequest) {
191206
} catch {}
192207
// Preprocess contexts server-side
193208
let agentContexts: Array<{ type: string; content: string }> = []
194-
if (Array.isArray(contexts) && contexts.length > 0) {
209+
if (Array.isArray(normalizedContexts) && normalizedContexts.length > 0) {
195210
try {
196211
const { processContextsServer } = await import('@/lib/copilot/process-contents')
197-
const processed = await processContextsServer(contexts as any, authenticatedUserId, message)
212+
const processed = await processContextsServer(
213+
normalizedContexts as any,
214+
authenticatedUserId,
215+
message
216+
)
198217
agentContexts = processed
199218
logger.info(`[${tracker.requestId}] Contexts processed for request`, {
200219
processedCount: agentContexts.length,
201220
kinds: agentContexts.map((c) => c.type),
202221
lengthPreview: agentContexts.map((c) => c.content?.length ?? 0),
203222
})
204-
if (Array.isArray(contexts) && contexts.length > 0 && agentContexts.length === 0) {
223+
if (
224+
Array.isArray(normalizedContexts) &&
225+
normalizedContexts.length > 0 &&
226+
agentContexts.length === 0
227+
) {
205228
logger.warn(
206229
`[${tracker.requestId}] Contexts provided but none processed. Check executionId for logs contexts.`
207230
)
@@ -246,11 +269,13 @@ export async function POST(req: NextRequest) {
246269
mode,
247270
model: selectedModel,
248271
provider,
272+
conversationId: effectiveConversationId,
249273
conversationHistory,
250274
contexts: agentContexts,
251275
fileAttachments,
252276
commands,
253277
chatId: actualChatId,
278+
prefetch,
254279
implicitFeedback,
255280
},
256281
{
@@ -432,10 +457,15 @@ export async function POST(req: NextRequest) {
432457
content: message,
433458
timestamp: new Date().toISOString(),
434459
...(fileAttachments && fileAttachments.length > 0 && { fileAttachments }),
435-
...(Array.isArray(contexts) && contexts.length > 0 && { contexts }),
436-
...(Array.isArray(contexts) &&
437-
contexts.length > 0 && {
438-
contentBlocks: [{ type: 'contexts', contexts: contexts as any, timestamp: Date.now() }],
460+
...(Array.isArray(normalizedContexts) &&
461+
normalizedContexts.length > 0 && {
462+
contexts: normalizedContexts,
463+
}),
464+
...(Array.isArray(normalizedContexts) &&
465+
normalizedContexts.length > 0 && {
466+
contentBlocks: [
467+
{ type: 'contexts', contexts: normalizedContexts as any, timestamp: Date.now() },
468+
],
439469
}),
440470
}
441471

apps/sim/app/api/tools/confluence/labels/route.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,84 @@ export async function GET(request: NextRequest) {
191191
)
192192
}
193193
}
194+
195+
// Delete a label from a page
196+
export async function DELETE(request: NextRequest) {
197+
try {
198+
const auth = await checkSessionOrInternalAuth(request)
199+
if (!auth.success || !auth.userId) {
200+
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
201+
}
202+
203+
const {
204+
domain,
205+
accessToken,
206+
cloudId: providedCloudId,
207+
pageId,
208+
labelName,
209+
} = await request.json()
210+
211+
if (!domain) {
212+
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
213+
}
214+
215+
if (!accessToken) {
216+
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
217+
}
218+
219+
if (!pageId) {
220+
return NextResponse.json({ error: 'Page ID is required' }, { status: 400 })
221+
}
222+
223+
if (!labelName) {
224+
return NextResponse.json({ error: 'Label name is required' }, { status: 400 })
225+
}
226+
227+
const pageIdValidation = validateAlphanumericId(pageId, 'pageId', 255)
228+
if (!pageIdValidation.isValid) {
229+
return NextResponse.json({ error: pageIdValidation.error }, { status: 400 })
230+
}
231+
232+
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
233+
234+
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
235+
if (!cloudIdValidation.isValid) {
236+
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
237+
}
238+
239+
const encodedLabel = encodeURIComponent(labelName.trim())
240+
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/rest/api/content/${pageId}/label?name=${encodedLabel}`
241+
242+
const response = await fetch(url, {
243+
method: 'DELETE',
244+
headers: {
245+
Accept: 'application/json',
246+
Authorization: `Bearer ${accessToken}`,
247+
},
248+
})
249+
250+
if (!response.ok) {
251+
const errorData = await response.json().catch(() => null)
252+
logger.error('Confluence API error response:', {
253+
status: response.status,
254+
statusText: response.statusText,
255+
error: JSON.stringify(errorData, null, 2),
256+
})
257+
const errorMessage =
258+
errorData?.message || `Failed to delete Confluence label (${response.status})`
259+
return NextResponse.json({ error: errorMessage }, { status: response.status })
260+
}
261+
262+
return NextResponse.json({
263+
pageId,
264+
labelName,
265+
deleted: true,
266+
})
267+
} catch (error) {
268+
logger.error('Error deleting Confluence label:', error)
269+
return NextResponse.json(
270+
{ error: (error as Error).message || 'Internal server error' },
271+
{ status: 500 }
272+
)
273+
}
274+
}

0 commit comments

Comments
 (0)