diff --git a/apps/docs/content/docs/de/tools/kalshi.mdx b/apps/docs/content/docs/de/tools/kalshi.mdx index 5759facdba..9646a4cf0d 100644 --- a/apps/docs/content/docs/de/tools/kalshi.mdx +++ b/apps/docs/content/docs/de/tools/kalshi.mdx @@ -123,8 +123,6 @@ Kontostand und Portfoliowert von Kalshi abrufen | --------- | ---- | ----------- | | `balance` | number | Kontostand in Cent | | `portfolioValue` | number | Portfoliowert in Cent | -| `balanceDollars` | number | Kontostand in Dollar | -| `portfolioValueDollars` | number | Portfoliowert in Dollar | ### `kalshi_get_positions` diff --git a/apps/docs/content/docs/de/tools/supabase.mdx b/apps/docs/content/docs/de/tools/supabase.mdx index 91ac39b87b..4d591faf85 100644 --- a/apps/docs/content/docs/de/tools/supabase.mdx +++ b/apps/docs/content/docs/de/tools/supabase.mdx @@ -47,10 +47,11 @@ Daten aus einer Supabase-Tabelle abfragen | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | -| `projectId` | string | Ja | Ihre Supabase-Projekt-ID \(z. B. jdrkgepadsdopsntdlom\) | +| `projectId` | string | Ja | Ihre Supabase-Projekt-ID \(z.B. jdrkgepadsdopsntdlom\) | | `table` | string | Ja | Der Name der abzufragenden Supabase-Tabelle | | `schema` | string | Nein | Datenbankschema für die Abfrage \(Standard: public\). Verwenden Sie dies, um auf Tabellen in anderen Schemas zuzugreifen. | -| `filter` | string | Nein | PostgREST-Filter \(z. B. "id=eq.123"\) | +| `select` | string | Nein | Zurückzugebende Spalten \(durch Komma getrennt\). Standard ist * \(alle Spalten\) | +| `filter` | string | Nein | PostgREST-Filter \(z.B. "id=eq.123"\) | | `orderBy` | string | Nein | Spalte zum Sortieren \(fügen Sie DESC für absteigende Sortierung hinzu\) | | `limit` | number | Nein | Maximale Anzahl der zurückzugebenden Zeilen | | `apiKey` | string | Ja | Ihr Supabase Service Role Secret Key | @@ -91,10 +92,11 @@ Eine einzelne Zeile aus einer Supabase-Tabelle basierend auf Filterkriterien abr | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | -| `projectId` | string | Ja | Ihre Supabase-Projekt-ID \(z. B. jdrkgepadsdopsntdlom\) | +| `projectId` | string | Ja | Ihre Supabase-Projekt-ID \(z.B. jdrkgepadsdopsntdlom\) | | `table` | string | Ja | Der Name der abzufragenden Supabase-Tabelle | | `schema` | string | Nein | Datenbankschema für die Abfrage \(Standard: public\). Verwenden Sie dies, um auf Tabellen in anderen Schemas zuzugreifen. | -| `filter` | string | Ja | PostgREST-Filter zum Auffinden der spezifischen Zeile \(z. B. "id=eq.123"\) | +| `select` | string | Nein | Zurückzugebende Spalten \(durch Komma getrennt\). Standard ist * \(alle Spalten\) | +| `filter` | string | Ja | PostgREST-Filter zum Finden der spezifischen Zeile \(z.B. "id=eq.123"\) | | `apiKey` | string | Ja | Ihr Supabase Service Role Secret Key | #### Ausgabe diff --git a/apps/docs/content/docs/en/tools/kalshi.mdx b/apps/docs/content/docs/en/tools/kalshi.mdx index 7d976ceba7..199ec05425 100644 --- a/apps/docs/content/docs/en/tools/kalshi.mdx +++ b/apps/docs/content/docs/en/tools/kalshi.mdx @@ -126,8 +126,6 @@ Retrieve your account balance and portfolio value from Kalshi | --------- | ---- | ----------- | | `balance` | number | Account balance in cents | | `portfolioValue` | number | Portfolio value in cents | -| `balanceDollars` | number | Account balance in dollars | -| `portfolioValueDollars` | number | Portfolio value in dollars | ### `kalshi_get_positions` diff --git a/apps/docs/content/docs/en/tools/supabase.mdx b/apps/docs/content/docs/en/tools/supabase.mdx index 2c6ba254ff..a6e285c9a8 100644 --- a/apps/docs/content/docs/en/tools/supabase.mdx +++ b/apps/docs/content/docs/en/tools/supabase.mdx @@ -53,6 +53,7 @@ Query data from a Supabase table | `projectId` | string | Yes | Your Supabase project ID \(e.g., jdrkgepadsdopsntdlom\) | | `table` | string | Yes | The name of the Supabase table to query | | `schema` | string | No | Database schema to query from \(default: public\). Use this to access tables in other schemas. | +| `select` | string | No | Columns to return \(comma-separated\). Defaults to * \(all columns\) | | `filter` | string | No | PostgREST filter \(e.g., "id=eq.123"\) | | `orderBy` | string | No | Column to order by \(add DESC for descending\) | | `limit` | number | No | Maximum number of rows to return | @@ -97,6 +98,7 @@ Get a single row from a Supabase table based on filter criteria | `projectId` | string | Yes | Your Supabase project ID \(e.g., jdrkgepadsdopsntdlom\) | | `table` | string | Yes | The name of the Supabase table to query | | `schema` | string | No | Database schema to query from \(default: public\). Use this to access tables in other schemas. | +| `select` | string | No | Columns to return \(comma-separated\). Defaults to * \(all columns\) | | `filter` | string | Yes | PostgREST filter to find the specific row \(e.g., "id=eq.123"\) | | `apiKey` | string | Yes | Your Supabase service role secret key | diff --git a/apps/docs/content/docs/es/tools/kalshi.mdx b/apps/docs/content/docs/es/tools/kalshi.mdx index 7276486f62..5b9911914c 100644 --- a/apps/docs/content/docs/es/tools/kalshi.mdx +++ b/apps/docs/content/docs/es/tools/kalshi.mdx @@ -122,9 +122,7 @@ Recuperar el saldo de tu cuenta y el valor de la cartera desde Kalshi | Parámetro | Tipo | Descripción | | --------- | ---- | ----------- | | `balance` | number | Saldo de la cuenta en centavos | -| `portfolioValue` | number | Valor de la cartera en centavos | -| `balanceDollars` | number | Saldo de la cuenta en dólares | -| `portfolioValueDollars` | number | Valor de la cartera en dólares | +| `portfolioValue` | number | Valor del portafolio en centavos | ### `kalshi_get_positions` diff --git a/apps/docs/content/docs/es/tools/supabase.mdx b/apps/docs/content/docs/es/tools/supabase.mdx index 9e50d3d294..07b8a2bc81 100644 --- a/apps/docs/content/docs/es/tools/supabase.mdx +++ b/apps/docs/content/docs/es/tools/supabase.mdx @@ -46,12 +46,13 @@ Consultar datos de una tabla de Supabase #### Entrada | Parámetro | Tipo | Obligatorio | Descripción | -| --------- | ---- | ----------- | ----------- | +| --------- | ---- | -------- | ----------- | | `projectId` | string | Sí | ID de tu proyecto Supabase \(p. ej., jdrkgepadsdopsntdlom\) | | `table` | string | Sí | Nombre de la tabla Supabase a consultar | -| `schema` | string | No | Esquema de base de datos desde donde consultar \(predeterminado: public\). Usa esto para acceder a tablas en otros esquemas. | +| `schema` | string | No | Esquema de base de datos desde el que consultar \(predeterminado: public\). Usa esto para acceder a tablas en otros esquemas. | +| `select` | string | No | Columnas a devolver \(separadas por comas\). Predeterminado: * \(todas las columnas\) | | `filter` | string | No | Filtro PostgREST \(p. ej., "id=eq.123"\) | -| `orderBy` | string | No | Columna para ordenar \(añade DESC para descendente\) | +| `orderBy` | string | No | Columna por la que ordenar \(añade DESC para orden descendente\) | | `limit` | number | No | Número máximo de filas a devolver | | `apiKey` | string | Sí | Tu clave secreta de rol de servicio de Supabase | @@ -90,10 +91,11 @@ Obtener una sola fila de una tabla de Supabase basada en criterios de filtro #### Entrada | Parámetro | Tipo | Obligatorio | Descripción | -| --------- | ---- | ----------- | ----------- | +| --------- | ---- | -------- | ----------- | | `projectId` | string | Sí | ID de tu proyecto Supabase \(p. ej., jdrkgepadsdopsntdlom\) | | `table` | string | Sí | Nombre de la tabla Supabase a consultar | -| `schema` | string | No | Esquema de base de datos desde donde consultar \(predeterminado: public\). Usa esto para acceder a tablas en otros esquemas. | +| `schema` | string | No | Esquema de base de datos desde el que consultar \(predeterminado: public\). Usa esto para acceder a tablas en otros esquemas. | +| `select` | string | No | Columnas a devolver \(separadas por comas\). Predeterminado: * \(todas las columnas\) | | `filter` | string | Sí | Filtro PostgREST para encontrar la fila específica \(p. ej., "id=eq.123"\) | | `apiKey` | string | Sí | Tu clave secreta de rol de servicio de Supabase | diff --git a/apps/docs/content/docs/fr/tools/kalshi.mdx b/apps/docs/content/docs/fr/tools/kalshi.mdx index 3aaf1ecd81..2f23abedbd 100644 --- a/apps/docs/content/docs/fr/tools/kalshi.mdx +++ b/apps/docs/content/docs/fr/tools/kalshi.mdx @@ -123,8 +123,6 @@ Récupérer le solde de votre compte et la valeur de votre portefeuille depuis K | --------- | ---- | ----------- | | `balance` | number | Solde du compte en centimes | | `portfolioValue` | number | Valeur du portefeuille en centimes | -| `balanceDollars` | number | Solde du compte en dollars | -| `portfolioValueDollars` | number | Valeur du portefeuille en dollars | ### `kalshi_get_positions` diff --git a/apps/docs/content/docs/fr/tools/supabase.mdx b/apps/docs/content/docs/fr/tools/supabase.mdx index ad95a25c36..cc7380ba5a 100644 --- a/apps/docs/content/docs/fr/tools/supabase.mdx +++ b/apps/docs/content/docs/fr/tools/supabase.mdx @@ -49,7 +49,8 @@ Interroger des données d'une table Supabase | --------- | ---- | ----------- | ----------- | | `projectId` | string | Oui | L'ID de votre projet Supabase \(ex. : jdrkgepadsdopsntdlom\) | | `table` | string | Oui | Le nom de la table Supabase à interroger | -| `schema` | string | Non | Schéma de base de données à interroger \(par défaut : public\). Utilisez ceci pour accéder aux tables dans d'autres schémas. | +| `schema` | string | Non | Schéma de base de données à partir duquel interroger \(par défaut : public\). Utilisez ceci pour accéder aux tables dans d'autres schémas. | +| `select` | string | Non | Colonnes à retourner \(séparées par des virgules\). Par défaut * \(toutes les colonnes\) | | `filter` | string | Non | Filtre PostgREST \(ex. : "id=eq.123"\) | | `orderBy` | string | Non | Colonne pour le tri \(ajoutez DESC pour l'ordre décroissant\) | | `limit` | number | Non | Nombre maximum de lignes à retourner | @@ -93,7 +94,8 @@ Obtenir une seule ligne d'une table Supabase selon des critères de filtrage | --------- | ---- | ----------- | ----------- | | `projectId` | string | Oui | L'ID de votre projet Supabase \(ex. : jdrkgepadsdopsntdlom\) | | `table` | string | Oui | Le nom de la table Supabase à interroger | -| `schema` | string | Non | Schéma de base de données à interroger \(par défaut : public\). Utilisez ceci pour accéder aux tables dans d'autres schémas. | +| `schema` | string | Non | Schéma de base de données à partir duquel interroger \(par défaut : public\). Utilisez ceci pour accéder aux tables dans d'autres schémas. | +| `select` | string | Non | Colonnes à retourner \(séparées par des virgules\). Par défaut * \(toutes les colonnes\) | | `filter` | string | Oui | Filtre PostgREST pour trouver la ligne spécifique \(ex. : "id=eq.123"\) | | `apiKey` | string | Oui | Votre clé secrète de rôle de service Supabase | diff --git a/apps/docs/content/docs/ja/tools/kalshi.mdx b/apps/docs/content/docs/ja/tools/kalshi.mdx index aebf8383e9..4172610500 100644 --- a/apps/docs/content/docs/ja/tools/kalshi.mdx +++ b/apps/docs/content/docs/ja/tools/kalshi.mdx @@ -121,10 +121,8 @@ Kalshiからアカウント残高とポートフォリオ価値を取得 | パラメータ | 型 | 説明 | | --------- | ---- | ----------- | -| `balance` | number | セント単位のアカウント残高 | -| `portfolioValue` | number | セント単位のポートフォリオ価値 | -| `balanceDollars` | number | ドル単位のアカウント残高 | -| `portfolioValueDollars` | number | ドル単位のポートフォリオ価値 | +| `balance` | number | アカウント残高(セント単位) | +| `portfolioValue` | number | ポートフォリオ価値(セント単位) | ### `kalshi_get_positions` diff --git a/apps/docs/content/docs/ja/tools/supabase.mdx b/apps/docs/content/docs/ja/tools/supabase.mdx index 4cf1f5c8b7..006203d590 100644 --- a/apps/docs/content/docs/ja/tools/supabase.mdx +++ b/apps/docs/content/docs/ja/tools/supabase.mdx @@ -49,7 +49,8 @@ Supabaseテーブルからデータを照会する | --------- | ---- | -------- | ----------- | | `projectId` | string | はい | あなたのSupabaseプロジェクトID(例:jdrkgepadsdopsntdlom) | | `table` | string | はい | クエリするSupabaseテーブルの名前 | -| `schema` | string | いいえ | クエリするデータベーススキーマ(デフォルト:public)。他のスキーマのテーブルにアクセスする場合に使用します。 | +| `schema` | string | いいえ | クエリ元のデータベーススキーマ(デフォルト:public)。他のスキーマのテーブルにアクセスする場合に使用します。 | +| `select` | string | いいえ | 返す列(カンマ区切り)。デフォルトは*(すべての列) | | `filter` | string | いいえ | PostgRESTフィルター(例:"id=eq.123") | | `orderBy` | string | いいえ | 並べ替える列(降順の場合はDESCを追加) | | `limit` | number | いいえ | 返す最大行数 | @@ -93,7 +94,8 @@ Supabaseテーブルにデータを挿入する | --------- | ---- | -------- | ----------- | | `projectId` | string | はい | あなたのSupabaseプロジェクトID(例:jdrkgepadsdopsntdlom) | | `table` | string | はい | クエリするSupabaseテーブルの名前 | -| `schema` | string | いいえ | クエリするデータベーススキーマ(デフォルト:public)。他のスキーマのテーブルにアクセスする場合に使用します。 | +| `schema` | string | いいえ | クエリ元のデータベーススキーマ(デフォルト:public)。他のスキーマのテーブルにアクセスする場合に使用します。 | +| `select` | string | いいえ | 返す列(カンマ区切り)。デフォルトは*(すべての列) | | `filter` | string | はい | 特定の行を見つけるためのPostgRESTフィルター(例:"id=eq.123") | | `apiKey` | string | はい | あなたのSupabaseサービスロールシークレットキー | diff --git a/apps/docs/content/docs/zh/tools/kalshi.mdx b/apps/docs/content/docs/zh/tools/kalshi.mdx index 85e076bfef..335adfdfd3 100644 --- a/apps/docs/content/docs/zh/tools/kalshi.mdx +++ b/apps/docs/content/docs/zh/tools/kalshi.mdx @@ -123,8 +123,6 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" | --------- | ---- | ----------- | | `balance` | number | 账户余额(以分为单位) | | `portfolioValue` | number | 投资组合价值(以分为单位) | -| `balanceDollars` | number | 账户余额(以美元为单位) | -| `portfolioValueDollars` | number | 投资组合价值(以美元为单位) | ### `kalshi_get_positions` diff --git a/apps/docs/content/docs/zh/tools/supabase.mdx b/apps/docs/content/docs/zh/tools/supabase.mdx index 71a132eeaf..7602efcb0c 100644 --- a/apps/docs/content/docs/zh/tools/supabase.mdx +++ b/apps/docs/content/docs/zh/tools/supabase.mdx @@ -50,8 +50,9 @@ Sim 的 Supabase 集成使您能够轻松地将代理工作流连接到您的 Su | `projectId` | string | 是 | 您的 Supabase 项目 ID \(例如:jdrkgepadsdopsntdlom\) | | `table` | string | 是 | 要查询的 Supabase 表名 | | `schema` | string | 否 | 要查询的数据库 schema \(默认:public\)。用于访问其他 schema 下的表。| +| `select` | string | 否 | 要返回的列(逗号分隔)。默认为 *(所有列)| | `filter` | string | 否 | PostgREST 过滤条件 \(例如:"id=eq.123"\) | -| `orderBy` | string | 否 | 排序的列名 \(添加 DESC 表示降序\) | +| `orderBy` | string | 否 | 排序的列(添加 DESC 表示降序)| | `limit` | number | 否 | 返回的最大行数 | | `apiKey` | string | 是 | 您的 Supabase 服务角色密钥 | @@ -94,7 +95,8 @@ Sim 的 Supabase 集成使您能够轻松地将代理工作流连接到您的 Su | `projectId` | string | 是 | 您的 Supabase 项目 ID \(例如:jdrkgepadsdopsntdlom\) | | `table` | string | 是 | 要查询的 Supabase 表名 | | `schema` | string | 否 | 要查询的数据库 schema \(默认:public\)。用于访问其他 schema 下的表。| -| `filter` | string | 是 | 用于查找特定行的 PostgREST 过滤条件 \(例如:"id=eq.123"\) | +| `select` | string | 否 | 要返回的列(逗号分隔)。默认为 *(所有列)| +| `filter` | string | 是 | PostgREST 过滤条件,用于查找特定行 \(例如:"id=eq.123"\) | | `apiKey` | string | 是 | 您的 Supabase 服务角色密钥 | #### 输出 diff --git a/apps/docs/i18n.lock b/apps/docs/i18n.lock index 12a327d908..f4f7648ac2 100644 --- a/apps/docs/i18n.lock +++ b/apps/docs/i18n.lock @@ -700,7 +700,7 @@ checksums: content/11: 04bd9805ef6a50af8469463c34486dbf content/12: a3671dd7ba76a87dc75464d9bf9b7b4b content/13: 371d0e46b4bd2c23f559b8bc112f6955 - content/14: 80578981b8b3a1cf579e52ff05e7468d + content/14: 5102b3705883f9e0c5440aeabafd1d24 content/15: bcadfc362b69078beee0088e5936c98b content/16: 09ed43219d02501c829594dbf4128959 content/17: 88ae2285d728c80937e1df8194d92c60 @@ -712,7 +712,7 @@ checksums: content/23: 7d96d99e45880195ccbd34bddaac6319 content/24: 75d05f96dff406db06b338d9ab8d0bd7 content/25: 371d0e46b4bd2c23f559b8bc112f6955 - content/26: cfd801fa517b4bcfa5fa034b2c4e908a + content/26: 38373ac018fd7db3a20ba5308beac81e content/27: bcadfc362b69078beee0088e5936c98b content/28: a0284632eb0a15e66f69479ec477c5b1 content/29: b1e60734e590a8ad894a96581a253bf4 @@ -48276,7 +48276,7 @@ checksums: content/35: 371d0e46b4bd2c23f559b8bc112f6955 content/36: bddd30707802c07aac61620721bfaf16 content/37: bcadfc362b69078beee0088e5936c98b - content/38: fa2c581e6fb204f5ddbd0ffcbf0f7123 + content/38: 4619dad6a45478396332397f1e53db85 content/39: 65de097e276f762b71d59fa7f9b0a207 content/40: 013f52c249b5919fdb6d96700b25f379 content/41: 371d0e46b4bd2c23f559b8bc112f6955 diff --git a/apps/sim/app/api/knowledge/utils.test.ts b/apps/sim/app/api/knowledge/utils.test.ts index eb4b92eb37..9ae1372c0f 100644 --- a/apps/sim/app/api/knowledge/utils.test.ts +++ b/apps/sim/app/api/knowledge/utils.test.ts @@ -136,16 +136,29 @@ vi.mock('@sim/db', () => { }, }), }), + delete: () => ({ + where: () => Promise.resolve(), + }), + insert: () => ({ + values: (records: any) => { + dbOps.order.push('insert') + dbOps.insertRecords.push(records) + return Promise.resolve() + }, + }), transaction: vi.fn(async (fn: any) => { await fn({ - insert: (table: any) => ({ + delete: () => ({ + where: () => Promise.resolve(), + }), + insert: () => ({ values: (records: any) => { dbOps.order.push('insert') dbOps.insertRecords.push(records) return Promise.resolve() }, }), - update: (table: any) => ({ + update: () => ({ set: (payload: any) => ({ where: () => { dbOps.updatePayloads.push(payload) diff --git a/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts b/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts index 9feef89bf3..6c0f44ff54 100644 --- a/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts +++ b/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts @@ -21,14 +21,15 @@ export async function POST( ) { const { workflowId, executionId, contextId } = await params + // Allow resume from dashboard without requiring deployment const access = await validateWorkflowAccess(request, workflowId, false) if (access.error) { return NextResponse.json({ error: access.error.message }, { status: access.error.status }) } - const workflow = access.workflow! + const workflow = access.workflow - let payload: any = {} + let payload: Record = {} try { payload = await request.json() } catch { @@ -148,6 +149,7 @@ export async function GET( ) { const { workflowId, executionId, contextId } = await params + // Allow access without API key for browser-based UI (same as parent execution endpoint) const access = await validateWorkflowAccess(request, workflowId, false) if (access.error) { return NextResponse.json({ error: access.error.message }, { status: access.error.status }) diff --git a/apps/sim/app/resume/[workflowId]/[executionId]/resume-page-client.tsx b/apps/sim/app/resume/[workflowId]/[executionId]/resume-page-client.tsx index d96b890b3d..0c0a5ece36 100644 --- a/apps/sim/app/resume/[workflowId]/[executionId]/resume-page-client.tsx +++ b/apps/sim/app/resume/[workflowId]/[executionId]/resume-page-client.tsx @@ -1,10 +1,23 @@ 'use client' import { useCallback, useEffect, useMemo, useState } from 'react' +import { RefreshCw } from 'lucide-react' import { useRouter } from 'next/navigation' -import { Badge, Button, Textarea } from '@/components/emcn' -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' +import { + Badge, + Button, + Code, + Input, + Label, + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, + Textarea, + Tooltip, +} from '@/components/emcn' import { Select, SelectContent, @@ -12,9 +25,7 @@ import { SelectTrigger, SelectValue, } from '@/components/ui/select' -import { Separator } from '@/components/ui/separator' import { useBrandConfig } from '@/lib/branding/branding' -import { cn } from '@/lib/core/utils/cn' import Nav from '@/app/(landing)/components/nav/nav' import type { ResumeStatus } from '@/executor/types' @@ -60,7 +71,8 @@ interface ResumeQueueEntrySummary { interface PausePointWithQueue { contextId: string - triggerBlockId: string + triggerBlockId?: string + blockId?: string response: any registeredAt: string resumeStatus: ResumeStatus @@ -105,14 +117,12 @@ interface ResumeExecutionPageProps { initialContextId?: string | null } -const RESUME_STATUS_STYLES: Record = { - paused: 'border-[var(--c-F59E0B)]/30 bg-[var(--c-F59E0B)]/10 text-[var(--c-F59E0B)]', - queued: - 'border-[var(--brand-tertiary)]/30 bg-[var(--brand-tertiary)]/10 text-[var(--brand-tertiary)]', - resuming: - 'border-[var(--brand-primary)]/30 bg-[var(--brand-primary)]/10 text-[var(--brand-primary)]', - resumed: 'border-[var(--text-success)]/30 bg-[var(--text-success)]/10 text-[var(--text-success)]', - failed: 'border-[var(--text-error)]/30 bg-[var(--text-error)]/10 text-[var(--text-error)]', +const STATUS_BADGE_VARIANT: Record = { + paused: 'orange', + queued: 'blue', + resuming: 'blue', + resumed: 'green', + failed: 'red', } function formatDate(value: string | null): string { @@ -129,17 +139,31 @@ function getStatusLabel(status: string): string { return status.charAt(0).toUpperCase() + status.slice(1) } -function ResumeStatusBadge({ status }: { status: string }) { - const style = - RESUME_STATUS_STYLES[status] ?? - 'border-[var(--border)] bg-[var(--surface-2)] text-[var(--text-secondary)]' +function StatusBadge({ status }: { status: string }) { return ( - + {getStatusLabel(status)} ) } +function getBlockNameFromSnapshot( + executionSnapshot: { snapshot?: string } | null | undefined, + blockId: string | undefined +): string | null { + if (!executionSnapshot?.snapshot || !blockId) return null + try { + const parsed = JSON.parse(executionSnapshot.snapshot) + const workflowState = parsed?.workflow + if (!workflowState?.blocks || !Array.isArray(workflowState.blocks)) return null + // Blocks are stored as an array of serialized blocks with id and metadata.name + const block = workflowState.blocks.find((b: { id: string }) => b.id === blockId) + return block?.metadata?.name || null + } catch { + return null + } +} + export default function ResumeExecutionPage({ params, initialExecutionDetail, @@ -152,9 +176,6 @@ export default function ResumeExecutionPage({ const [executionDetail, setExecutionDetail] = useState( initialExecutionDetail ) - const totalPauses = executionDetail?.totalPauseCount ?? 0 - const resumedCount = executionDetail?.resumedCount ?? 0 - const pendingCount = Math.max(0, totalPauses - resumedCount) const pausePoints = executionDetail?.pausePoints ?? [] const defaultContextId = useMemo(() => { @@ -164,20 +185,6 @@ export default function ResumeExecutionPage({ pausePoints[0]?.contextId ) }, [initialContextId, pausePoints]) - const actionablePausePoints = useMemo( - () => pausePoints.filter((point) => point.resumeStatus === 'paused'), - [pausePoints] - ) - - const groupedPausePoints = useMemo(() => { - const activeStatuses = new Set(['paused', 'queued', 'resuming']) - const resolvedStatuses = new Set(['resumed', 'failed']) - - return { - active: pausePoints.filter((point) => activeStatuses.has(point.resumeStatus)), - resolved: pausePoints.filter((point) => resolvedStatuses.has(point.resumeStatus)), - } - }, [pausePoints]) const [selectedContextId, setSelectedContextId] = useState( defaultContextId ?? null @@ -201,44 +208,32 @@ export default function ResumeExecutionPage({ const normalizeInputFormatFields = useCallback((raw: any): NormalizedInputField[] => { if (!Array.isArray(raw)) return [] - return raw .map((field: any, index: number) => { if (!field || typeof field !== 'object') return null - const name = typeof field.name === 'string' ? field.name.trim() : '' if (!name) return null - - const id = typeof field.id === 'string' && field.id.length > 0 ? field.id : `field_${index}` - const label = - typeof field.label === 'string' && field.label.trim().length > 0 - ? field.label.trim() - : name - const type = - typeof field.type === 'string' && field.type.trim().length > 0 ? field.type : 'string' - const description = - typeof field.description === 'string' && field.description.trim().length > 0 - ? field.description.trim() - : undefined - const placeholder = - typeof field.placeholder === 'string' && field.placeholder.trim().length > 0 - ? field.placeholder.trim() - : undefined - const required = field.required === true - const options = Array.isArray(field.options) ? field.options : undefined - const rows = typeof field.rows === 'number' ? field.rows : undefined - return { - id, + id: typeof field.id === 'string' && field.id.length > 0 ? field.id : `field_${index}`, name, - label, - type, - description, - placeholder, + label: + typeof field.label === 'string' && field.label.trim().length > 0 + ? field.label.trim() + : name, + type: + typeof field.type === 'string' && field.type.trim().length > 0 ? field.type : 'string', + description: + typeof field.description === 'string' && field.description.trim().length > 0 + ? field.description.trim() + : undefined, + placeholder: + typeof field.placeholder === 'string' && field.placeholder.trim().length > 0 + ? field.placeholder.trim() + : undefined, value: field.value, - required, - options, - rows, + required: field.required === true, + options: Array.isArray(field.options) ? field.options : undefined, + rows: typeof field.rows === 'number' ? field.rows : undefined, } as NormalizedInputField }) .filter((field): field is NormalizedInputField => field !== null) @@ -246,36 +241,23 @@ export default function ResumeExecutionPage({ const formatValueForInputField = useCallback( (field: NormalizedInputField, value: any): string => { - if (value === undefined || value === null) { - return '' - } - + if (value === undefined || value === null) return '' switch (field.type) { case 'boolean': - if (typeof value === 'boolean') { - return value ? 'true' : 'false' - } + if (typeof value === 'boolean') return value ? 'true' : 'false' if (typeof value === 'string') { const normalized = value.trim().toLowerCase() - if (normalized === 'true' || normalized === 'false') { - return normalized - } + if (normalized === 'true' || normalized === 'false') return normalized } return '' case 'number': - if (typeof value === 'number') { - return Number.isFinite(value) ? String(value) : '' - } - if (typeof value === 'string') { - return value - } + if (typeof value === 'number') return Number.isFinite(value) ? String(value) : '' + if (typeof value === 'string') return value return '' case 'array': case 'object': case 'files': - if (typeof value === 'string') { - return value - } + if (typeof value === 'string') return value try { return JSON.stringify(value, null, 2) } catch { @@ -291,14 +273,11 @@ export default function ResumeExecutionPage({ const buildInitialFormValues = useCallback( (fields: NormalizedInputField[], submission?: Record) => { const initial: Record = {} - for (const field of fields) { const candidate = submission && Object.hasOwn(submission, field.name) ? submission[field.name] : field.value - initial[field.name] = formatValueForInputField(field, candidate) } - return initial }, [formatValueForInputField] @@ -318,16 +297,11 @@ export default function ResumeExecutionPage({ const parseFormValue = useCallback( (field: NormalizedInputField, rawValue: string): { value: any; error?: string } => { const value = rawValue ?? '' - switch (field.type) { case 'number': { - if (!value.trim()) { - return { value: null } - } + if (!value.trim()) return { value: null } const numericValue = Number(value) - if (Number.isNaN(numericValue)) { - return { value: null, error: 'Enter a valid number.' } - } + if (Number.isNaN(numericValue)) return { value: null, error: 'Enter a valid number.' } return { value: numericValue } } case 'boolean': { @@ -359,17 +333,13 @@ export default function ResumeExecutionPage({ const handleFormFieldChange = useCallback( (fieldName: string, newValue: string) => { if (!selectedContextId) return - setFormValues((prev) => { const updated = { ...prev, [fieldName]: newValue } setFormValuesByContext((map) => ({ ...map, [selectedContextId]: updated })) return updated }) - setFormErrors((prev) => { - if (!prev[fieldName]) { - return prev - } + if (!prev[fieldName]) return prev const { [fieldName]: _, ...rest } = prev return rest }) @@ -380,7 +350,6 @@ export default function ResumeExecutionPage({ const renderFieldInput = useCallback( (field: NormalizedInputField) => { const value = formValues[field.name] ?? '' - switch (field.type) { case 'boolean': { const selectValue = value === 'true' || value === 'false' ? value : '__unset__' @@ -389,12 +358,8 @@ export default function ResumeExecutionPage({ value={selectValue} onValueChange={(val) => handleFormFieldChange(field.name, val)} > - - + + {!field.required && Not set} @@ -409,7 +374,7 @@ export default function ResumeExecutionPage({ handleFormFieldChange(field.name, event.target.value)} + onChange={(e) => handleFormFieldChange(field.name, e.target.value)} placeholder={field.placeholder ?? 'Enter a number...'} /> ) @@ -419,27 +384,26 @@ export default function ResumeExecutionPage({ return (