diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5f51aca438..40d1324323 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -374,7 +374,7 @@ In addition, you will need to update the registries: Add your block to the blocks registry (`/apps/sim/blocks/registry.ts`): ```typescript:/apps/sim/blocks/registry.ts - import { PineconeBlock } from './blocks/pinecone' + import { PineconeBlock } from '@/blocks/blocks/pinecone' // Registry of all available blocks export const registry: Record = { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 007563d026..3db18c5d41 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: name: Build AMD64 needs: test-build if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: blacksmith-8vcpu-ubuntu-2404 permissions: contents: read packages: write @@ -162,7 +162,7 @@ jobs: # Create GHCR multi-arch manifests (only for main, after both builds) create-ghcr-manifests: name: Create GHCR Manifests - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: blacksmith-8vcpu-ubuntu-2404 needs: [build-amd64, build-ghcr-arm64] if: github.event_name == 'push' && github.ref == 'refs/heads/main' permissions: @@ -198,18 +198,30 @@ jobs: "${IMAGE_BASE}:${{ github.sha }}-arm64" docker manifest push "${IMAGE_BASE}:${{ github.sha }}" - # Deploy Trigger.dev (after ECR images are pushed, runs in parallel with process-docs) - trigger-deploy: - name: Deploy Trigger.dev - needs: build-amd64 - if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') - uses: ./.github/workflows/trigger-deploy.yml - secrets: inherit + # Check if docs changed + check-docs-changes: + name: Check Docs Changes + runs-on: blacksmith-4vcpu-ubuntu-2404 + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + outputs: + docs_changed: ${{ steps.filter.outputs.docs }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 # Need at least 2 commits to detect changes + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + docs: + - 'apps/docs/content/docs/en/**' + - 'apps/sim/scripts/process-docs.ts' + - 'apps/sim/lib/chunkers/**' - # Process docs embeddings (after ECR images are pushed, runs in parallel with trigger-deploy) + # Process docs embeddings (only when docs change, after ECR images are pushed) process-docs: name: Process Docs - needs: build-amd64 - if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') + needs: [build-amd64, check-docs-changes] + if: needs.check-docs-changes.outputs.docs_changed == 'true' uses: ./.github/workflows/docs-embeddings.yml secrets: inherit diff --git a/.github/workflows/docs-embeddings.yml b/.github/workflows/docs-embeddings.yml index e01024a0e6..35cd540cd0 100644 --- a/.github/workflows/docs-embeddings.yml +++ b/.github/workflows/docs-embeddings.yml @@ -7,8 +7,8 @@ on: jobs: process-docs-embeddings: name: Process Documentation Embeddings - runs-on: blacksmith-4vcpu-ubuntu-2404 - if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging' + runs-on: blacksmith-8vcpu-ubuntu-2404 + if: github.ref == 'refs/heads/main' steps: - name: Checkout code @@ -41,6 +41,6 @@ jobs: - name: Process docs embeddings working-directory: ./apps/sim env: - DATABASE_URL: ${{ github.ref == 'refs/heads/main' && secrets.DATABASE_URL || secrets.STAGING_DATABASE_URL }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} run: bun run scripts/process-docs.ts --clear diff --git a/.github/workflows/images.yml b/.github/workflows/images.yml index 365539ca9f..d708d4c4de 100644 --- a/.github/workflows/images.yml +++ b/.github/workflows/images.yml @@ -12,7 +12,7 @@ permissions: jobs: build-amd64: name: Build AMD64 - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: blacksmith-8vcpu-ubuntu-2404 strategy: fail-fast: false matrix: @@ -146,7 +146,7 @@ jobs: create-ghcr-manifests: name: Create GHCR Manifests - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: blacksmith-8vcpu-ubuntu-2404 needs: [build-amd64, build-ghcr-arm64] if: github.ref == 'refs/heads/main' strategy: diff --git a/.github/workflows/trigger-deploy.yml b/.github/workflows/trigger-deploy.yml deleted file mode 100644 index a3fed7619e..0000000000 --- a/.github/workflows/trigger-deploy.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Trigger.dev Deploy - -on: - workflow_call: - workflow_dispatch: - -jobs: - deploy: - name: Deploy to Trigger.dev - runs-on: blacksmith-4vcpu-ubuntu-2404 - concurrency: - group: trigger-deploy-${{ github.ref }} - cancel-in-progress: false - env: - TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }} - TRIGGER_PROJECT_ID: ${{ secrets.TRIGGER_PROJECT_ID }} - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: latest - - - name: Setup Bun - uses: oven-sh/setup-bun@v2 - with: - bun-version: 1.2.22 - - - name: Cache Bun dependencies - uses: actions/cache@v4 - with: - path: | - ~/.bun/install/cache - node_modules - **/node_modules - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} - restore-keys: | - ${{ runner.os }}-bun- - - - name: Install dependencies - run: bun install --frozen-lockfile - - - name: Deploy to Trigger.dev (Staging) - if: github.ref == 'refs/heads/staging' - working-directory: ./apps/sim - run: npx --yes trigger.dev@4.0.4 deploy -e staging - - - name: Deploy to Trigger.dev (Production) - if: github.ref == 'refs/heads/main' - working-directory: ./apps/sim - run: npx --yes trigger.dev@4.0.4 deploy - diff --git a/apps/docs/components/ui/block-info-card.tsx b/apps/docs/components/ui/block-info-card.tsx index b9d034898f..6474f24acc 100644 --- a/apps/docs/components/ui/block-info-card.tsx +++ b/apps/docs/components/ui/block-info-card.tsx @@ -1,7 +1,7 @@ 'use client' import type * as React from 'react' -import { blockTypeToIconMap } from './icon-mapping' +import { blockTypeToIconMap } from '@/components/ui/icon-mapping' interface BlockInfoCardProps { type: string diff --git a/apps/docs/components/ui/image.tsx b/apps/docs/components/ui/image.tsx index 88864af923..6cf9f2d478 100644 --- a/apps/docs/components/ui/image.tsx +++ b/apps/docs/components/ui/image.tsx @@ -2,8 +2,8 @@ import { useState } from 'react' import NextImage, { type ImageProps as NextImageProps } from 'next/image' +import { Lightbox } from '@/components/ui/lightbox' import { cn } from '@/lib/utils' -import { Lightbox } from './lightbox' interface ImageProps extends Omit { className?: string diff --git a/apps/docs/content/docs/de/tools/linear.mdx b/apps/docs/content/docs/de/tools/linear.mdx index d62fa2dc77..570f867b7c 100644 --- a/apps/docs/content/docs/de/tools/linear.mdx +++ b/apps/docs/content/docs/de/tools/linear.mdx @@ -39,14 +39,24 @@ Tickets von Linear abrufen und filtern | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | -| `teamId` | string | Ja | Linear Team-ID | -| `projectId` | string | Ja | Linear Projekt-ID | +| `teamId` | string | Nein | Linear Team-ID zum Filtern | +| `projectId` | string | Nein | Linear Projekt-ID zum Filtern | +| `assigneeId` | string | Nein | Benutzer-ID zum Filtern nach Zugewiesenem | +| `stateId` | string | Nein | Workflow-Status-ID zum Filtern nach Status | +| `priority` | number | Nein | Priorität zum Filtern \(0=Keine Priorität, 1=Dringend, 2=Hoch, 3=Normal, 4=Niedrig\) | +| `labelIds` | array | Nein | Array von Label-IDs zum Filtern | +| `createdAfter` | string | Nein | Tickets filtern, die nach diesem Datum erstellt wurden \(ISO 8601 Format\) | +| `updatedAfter` | string | Nein | Tickets filtern, die nach diesem Datum aktualisiert wurden \(ISO 8601 Format\) | +| `includeArchived` | boolean | Nein | Archivierte Tickets einschließen \(Standard: false\) | +| `first` | number | Nein | Anzahl der zurückzugebenden Tickets \(Standard: 50, max: 250\) | +| `after` | string | Nein | Paginierungscursor für die nächste Seite | +| `orderBy` | string | Nein | Sortierreihenfolge: "createdAt" oder "updatedAt" \(Standard: "updatedAt"\) | #### Ausgabe | Parameter | Typ | Beschreibung | | --------- | ---- | ----------- | -| `issues` | array | Array von Tickets aus dem angegebenen Linear Team und Projekt, jedes enthält id, title, description, state, teamId und projectId | +| `issues` | array | Array von gefilterten Tickets aus Linear | ### `linear_get_issue` @@ -73,15 +83,25 @@ Ein neues Ticket in Linear erstellen | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | | `teamId` | string | Ja | Linear Team-ID | -| `projectId` | string | Ja | Linear Projekt-ID | +| `projectId` | string | Nein | Linear Projekt-ID | | `title` | string | Ja | Ticket-Titel | | `description` | string | Nein | Ticket-Beschreibung | +| `stateId` | string | Nein | Workflow-Status-ID \(Status\) | +| `assigneeId` | string | Nein | Benutzer-ID, dem das Ticket zugewiesen werden soll | +| `priority` | number | Nein | Priorität \(0=Keine Priorität, 1=Dringend, 2=Hoch, 3=Normal, 4=Niedrig\) | +| `estimate` | number | Nein | Schätzung in Punkten | +| `labelIds` | array | Nein | Array von Label-IDs, die dem Ticket zugewiesen werden sollen | +| `cycleId` | string | Nein | Zyklus-ID, dem das Ticket zugewiesen werden soll | +| `parentId` | string | Nein | Übergeordnete Ticket-ID \(für die Erstellung von Untertickets\) | +| `dueDate` | string | Nein | Fälligkeitsdatum im ISO 8601-Format \(nur Datum: JJJJ-MM-TT\) | +| `subscriberIds` | array | Nein | Array von Benutzer-IDs, die das Ticket abonnieren sollen | +| `projectMilestoneId` | string | Nein | Projektmeilenstein-ID, die mit dem Ticket verknüpft werden soll | #### Ausgabe | Parameter | Typ | Beschreibung | | --------- | ---- | ----------- | -| `issue` | object | Das erstellte Ticket mit id, title, description, state, teamId und projectId | +| `issue` | object | Das erstellte Ticket mit allen seinen Eigenschaften | ### `linear_update_issue` @@ -98,7 +118,13 @@ Ein bestehendes Ticket in Linear aktualisieren | `assigneeId` | string | Nein | Benutzer-ID, dem das Ticket zugewiesen werden soll | | `priority` | number | Nein | Priorität \(0=Keine Priorität, 1=Dringend, 2=Hoch, 3=Normal, 4=Niedrig\) | | `estimate` | number | Nein | Schätzung in Punkten | -| `labelIds` | array | Nein | Array von Label-IDs, die dem Ticket zugewiesen werden sollen | +| `labelIds` | array | Nein | Array von Label-IDs, die für das Ticket gesetzt werden sollen \(ersetzt alle vorhandenen Labels\) | +| `projectId` | string | Nein | Projekt-ID, zu der das Ticket verschoben werden soll | +| `cycleId` | string | Nein | Zyklus-ID, dem das Ticket zugewiesen werden soll | +| `parentId` | string | Nein | Übergeordnete Ticket-ID \(um dieses zu einem Unterticket zu machen\) | +| `dueDate` | string | Nein | Fälligkeitsdatum im ISO 8601-Format \(nur Datum: JJJJ-MM-TT\) | +| `addedLabelIds` | array | Nein | Array von Label-IDs, die dem Ticket hinzugefügt werden sollen \(ohne vorhandene Labels zu ersetzen\) | +| `removedLabelIds` | array | Nein | Array von Label-IDs, die vom Ticket entfernt werden sollen | #### Ausgabe @@ -236,8 +262,8 @@ Einen Kommentar in Linear bearbeiten | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | -| `commentId` | string | Ja | Kommentar-ID, die aktualisiert werden soll | -| `body` | string | Ja | Neuer Kommentartext \(unterstützt Markdown\) | +| `commentId` | string | Ja | Kommentar-ID zum Aktualisieren | +| `body` | string | Nein | Neuer Kommentartext \(unterstützt Markdown\) | #### Ausgabe @@ -344,14 +370,14 @@ Ein bestehendes Projekt in Linear aktualisieren | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | -| `projectId` | string | Ja | Projekt-ID, die aktualisiert werden soll | +| `projectId` | string | Ja | Projekt-ID zum Aktualisieren | | `name` | string | Nein | Neuer Projektname | | `description` | string | Nein | Neue Projektbeschreibung | -| `state` | string | Nein | Projektstatus (geplant, gestartet, abgeschlossen, abgebrochen) | +| `state` | string | Nein | Projektstatus \(planned, started, completed, canceled\) | | `leadId` | string | Nein | Benutzer-ID des Projektleiters | -| `startDate` | string | Nein | Projektstartdatum (ISO-Format) | -| `targetDate` | string | Nein | Projektzieldatum (ISO-Format) | -| `priority` | number | Nein | Projektpriorität (0-4) | +| `startDate` | string | Nein | Projektstartdatum \(ISO-Format: JJJJ-MM-TT\) | +| `targetDate` | string | Nein | Projektzieldatum \(ISO-Format: JJJJ-MM-TT\) | +| `priority` | number | Nein | Projektpriorität \(0=Keine Priorität, 1=Dringend, 2=Hoch, 3=Normal, 4=Niedrig\) | #### Ausgabe @@ -525,11 +551,11 @@ Einen neuen Workflow-Status in Linear erstellen | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | -| `teamId` | string | Ja | Team-ID, in dem der Status erstellt werden soll | -| `name` | string | Ja | Name des Status \(z.B. "In Prüfung"\) | -| `color` | string | Ja | Farbe des Status \(Hex-Format\) | +| `teamId` | string | Ja | Team-ID, in der der Status erstellt werden soll | +| `name` | string | Ja | Statusname \(z.B. "In Prüfung"\) | +| `color` | string | Nein | Statusfarbe \(Hex-Format\) | | `type` | string | Ja | Statustyp: "backlog", "unstarted", "started", "completed" oder "canceled" | -| `description` | string | Nein | Beschreibung des Status | +| `description` | string | Nein | Statusbeschreibung | | `position` | number | Nein | Position im Workflow | #### Ausgabe @@ -635,9 +661,9 @@ Einen Anhang zu einem Ticket in Linear hinzufügen | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | -| `issueId` | string | Ja | Ticket-ID, an die der Anhang angehängt werden soll | +| `issueId` | string | Ja | Ticket-ID, an die angehängt werden soll | | `url` | string | Ja | URL des Anhangs | -| `title` | string | Nein | Titel des Anhangs | +| `title` | string | Ja | Titel des Anhangs | | `subtitle` | string | Nein | Untertitel/Beschreibung des Anhangs | #### Ausgabe @@ -673,7 +699,7 @@ Metadaten eines Anhangs in Linear aktualisieren | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | | `attachmentId` | string | Ja | Anhang-ID zum Aktualisieren | -| `title` | string | Nein | Neuer Titel des Anhangs | +| `title` | string | Ja | Neuer Titel des Anhangs | | `subtitle` | string | Nein | Neuer Untertitel des Anhangs | #### Ausgabe @@ -707,8 +733,8 @@ Zwei Tickets in Linear miteinander verknüpfen (blockiert, bezieht sich auf, dup | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | | `issueId` | string | Ja | Quell-Ticket-ID | -| `relatedIssueId` | string | Ja | Ziel-Ticket-ID für die Verknüpfung | -| `type` | string | Ja | Beziehungstyp: "blocks", "blocked", "duplicate", "related" | +| `relatedIssueId` | string | Ja | Ziel-Ticket-ID, mit der verknüpft werden soll | +| `type` | string | Ja | Beziehungstyp: "blocks", "duplicate" oder "related". Hinweis: Wenn "blocks" von A nach B erstellt wird, wird die umgekehrte Beziehung \(B blockiert durch A\) automatisch erstellt. | #### Ausgabe @@ -1217,7 +1243,8 @@ Ein neues Projekt-Label in Linear erstellen | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | -| `name` | string | Ja | Projekt-Label-Name | +| `projectId` | string | Ja | Das Projekt für dieses Label | +| `name` | string | Ja | Projektlabel-Name | | `color` | string | Nein | Label-Farbe \(Hex-Code\) | | `description` | string | Nein | Label-Beschreibung | | `isGroup` | boolean | Nein | Ob dies eine Label-Gruppe ist | @@ -1394,6 +1421,7 @@ Einen neuen Projektstatus in Linear erstellen | Parameter | Typ | Erforderlich | Beschreibung | | --------- | ---- | -------- | ----------- | +| `projectId` | string | Ja | Das Projekt, für das der Status erstellt werden soll | | `name` | string | Ja | Name des Projektstatus | | `color` | string | Ja | Statusfarbe \(Hex-Code\) | | `description` | string | Nein | Statusbeschreibung | diff --git a/apps/docs/content/docs/en/tools/linear.mdx b/apps/docs/content/docs/en/tools/linear.mdx index ac5aedde45..bf1814774a 100644 --- a/apps/docs/content/docs/en/tools/linear.mdx +++ b/apps/docs/content/docs/en/tools/linear.mdx @@ -44,12 +44,22 @@ Fetch and filter issues from Linear | --------- | ---- | -------- | ----------- | | `teamId` | string | No | Linear team ID to filter by | | `projectId` | string | No | Linear project ID to filter by | +| `assigneeId` | string | No | User ID to filter by assignee | +| `stateId` | string | No | Workflow state ID to filter by status | +| `priority` | number | No | Priority to filter by \(0=No priority, 1=Urgent, 2=High, 3=Normal, 4=Low\) | +| `labelIds` | array | No | Array of label IDs to filter by | +| `createdAfter` | string | No | Filter issues created after this date \(ISO 8601 format\) | +| `updatedAfter` | string | No | Filter issues updated after this date \(ISO 8601 format\) | +| `includeArchived` | boolean | No | Include archived issues \(default: false\) | +| `first` | number | No | Number of issues to return \(default: 50, max: 250\) | +| `after` | string | No | Pagination cursor for next page | +| `orderBy` | string | No | Sort order: "createdAt" or "updatedAt" \(default: "updatedAt"\) | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `issues` | array | Array of issues from the specified Linear team and project, each containing id, title, description, state, teamId, and projectId | +| `issues` | array | Array of filtered issues from Linear | ### `linear_get_issue` @@ -79,12 +89,22 @@ Create a new issue in Linear | `projectId` | string | No | Linear project ID | | `title` | string | Yes | Issue title | | `description` | string | No | Issue description | +| `stateId` | string | No | Workflow state ID \(status\) | +| `assigneeId` | string | No | User ID to assign the issue to | +| `priority` | number | No | Priority \(0=No priority, 1=Urgent, 2=High, 3=Normal, 4=Low\) | +| `estimate` | number | No | Estimate in points | +| `labelIds` | array | No | Array of label IDs to set on the issue | +| `cycleId` | string | No | Cycle ID to assign the issue to | +| `parentId` | string | No | Parent issue ID \(for creating sub-issues\) | +| `dueDate` | string | No | Due date in ISO 8601 format \(date only: YYYY-MM-DD\) | +| `subscriberIds` | array | No | Array of user IDs to subscribe to the issue | +| `projectMilestoneId` | string | No | Project milestone ID to associate with the issue | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `issue` | object | The created issue containing id, title, description, state, teamId, and projectId | +| `issue` | object | The created issue with all its properties | ### `linear_update_issue` @@ -101,7 +121,13 @@ Update an existing issue in Linear | `assigneeId` | string | No | User ID to assign the issue to | | `priority` | number | No | Priority \(0=No priority, 1=Urgent, 2=High, 3=Normal, 4=Low\) | | `estimate` | number | No | Estimate in points | -| `labelIds` | array | No | Array of label IDs to set on the issue | +| `labelIds` | array | No | Array of label IDs to set on the issue \(replaces all existing labels\) | +| `projectId` | string | No | Project ID to move the issue to | +| `cycleId` | string | No | Cycle ID to assign the issue to | +| `parentId` | string | No | Parent issue ID \(for making this a sub-issue\) | +| `dueDate` | string | No | Due date in ISO 8601 format \(date only: YYYY-MM-DD\) | +| `addedLabelIds` | array | No | Array of label IDs to add to the issue \(without replacing existing labels\) | +| `removedLabelIds` | array | No | Array of label IDs to remove from the issue | #### Output @@ -352,9 +378,9 @@ Update an existing project in Linear | `description` | string | No | New project description | | `state` | string | No | Project state \(planned, started, completed, canceled\) | | `leadId` | string | No | User ID of the project lead | -| `startDate` | string | No | Project start date \(ISO format\) | -| `targetDate` | string | No | Project target date \(ISO format\) | -| `priority` | number | No | Project priority \(0-4\) | +| `startDate` | string | No | Project start date \(ISO format: YYYY-MM-DD\) | +| `targetDate` | string | No | Project target date \(ISO format: YYYY-MM-DD\) | +| `priority` | number | No | Project priority \(0=No priority, 1=Urgent, 2=High, 3=Normal, 4=Low\) | #### Output @@ -530,7 +556,7 @@ Create a new workflow state (status) in Linear | --------- | ---- | -------- | ----------- | | `teamId` | string | Yes | Team ID to create the state in | | `name` | string | Yes | State name \(e.g., "In Review"\) | -| `color` | string | Yes | State color \(hex format\) | +| `color` | string | No | State color \(hex format\) | | `type` | string | Yes | State type: "backlog", "unstarted", "started", "completed", or "canceled" | | `description` | string | No | State description | | `position` | number | No | Position in the workflow | @@ -711,7 +737,7 @@ Link two issues together in Linear (blocks, relates to, duplicates) | --------- | ---- | -------- | ----------- | | `issueId` | string | Yes | Source issue ID | | `relatedIssueId` | string | Yes | Target issue ID to link to | -| `type` | string | Yes | Relation type: "blocks", "blocked", "duplicate", "related" | +| `type` | string | Yes | Relation type: "blocks", "duplicate", or "related". Note: When creating "blocks" from A to B, the inverse relation \(B blocked by A\) is automatically created. | #### Output @@ -1220,6 +1246,7 @@ Create a new project label in Linear | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | +| `projectId` | string | Yes | The project for this label | | `name` | string | Yes | Project label name | | `color` | string | No | Label color \(hex code\) | | `description` | string | No | Label description | @@ -1397,6 +1424,7 @@ Create a new project status in Linear | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | +| `projectId` | string | Yes | The project to create the status for | | `name` | string | Yes | Project status name | | `color` | string | Yes | Status color \(hex code\) | | `description` | string | No | Status description | diff --git a/apps/docs/content/docs/es/tools/linear.mdx b/apps/docs/content/docs/es/tools/linear.mdx index 7d032d2f9e..8144738897 100644 --- a/apps/docs/content/docs/es/tools/linear.mdx +++ b/apps/docs/content/docs/es/tools/linear.mdx @@ -39,14 +39,24 @@ Obtener y filtrar incidencias de Linear | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | -| `teamId` | string | Sí | ID del equipo de Linear | -| `projectId` | string | Sí | ID del proyecto de Linear | +| `teamId` | string | No | ID del equipo de Linear para filtrar | +| `projectId` | string | No | ID del proyecto de Linear para filtrar | +| `assigneeId` | string | No | ID del usuario para filtrar por asignado | +| `stateId` | string | No | ID del estado del flujo de trabajo para filtrar por estado | +| `priority` | number | No | Prioridad para filtrar \(0=Sin prioridad, 1=Urgente, 2=Alta, 3=Normal, 4=Baja\) | +| `labelIds` | array | No | Array de IDs de etiquetas para filtrar | +| `createdAfter` | string | No | Filtrar incidencias creadas después de esta fecha \(formato ISO 8601\) | +| `updatedAfter` | string | No | Filtrar incidencias actualizadas después de esta fecha \(formato ISO 8601\) | +| `includeArchived` | boolean | No | Incluir incidencias archivadas \(predeterminado: false\) | +| `first` | number | No | Número de incidencias a devolver \(predeterminado: 50, máximo: 250\) | +| `after` | string | No | Cursor de paginación para la siguiente página | +| `orderBy` | string | No | Orden de clasificación: "createdAt" o "updatedAt" \(predeterminado: "updatedAt"\) | #### Salida | Parámetro | Tipo | Descripción | | --------- | ---- | ----------- | -| `issues` | array | Array de incidencias del equipo y proyecto de Linear especificados, cada una contiene id, título, descripción, estado, teamId y projectId | +| `issues` | array | Array de incidencias filtradas de Linear | ### `linear_get_issue` @@ -73,15 +83,25 @@ Crear una nueva incidencia en Linear | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | | `teamId` | string | Sí | ID del equipo de Linear | -| `projectId` | string | Sí | ID del proyecto de Linear | +| `projectId` | string | No | ID del proyecto de Linear | | `title` | string | Sí | Título de la incidencia | | `description` | string | No | Descripción de la incidencia | +| `stateId` | string | No | ID del estado del flujo de trabajo \(estado\) | +| `assigneeId` | string | No | ID del usuario al que asignar la incidencia | +| `priority` | number | No | Prioridad \(0=Sin prioridad, 1=Urgente, 2=Alta, 3=Normal, 4=Baja\) | +| `estimate` | number | No | Estimación en puntos | +| `labelIds` | array | No | Array de IDs de etiquetas para establecer en la incidencia | +| `cycleId` | string | No | ID del ciclo al que asignar la incidencia | +| `parentId` | string | No | ID de la incidencia padre \(para crear subincidencias\) | +| `dueDate` | string | No | Fecha de vencimiento en formato ISO 8601 \(solo fecha: AAAA-MM-DD\) | +| `subscriberIds` | array | No | Array de IDs de usuarios para suscribirse a la incidencia | +| `projectMilestoneId` | string | No | ID del hito del proyecto para asociar con la incidencia | #### Salida | Parámetro | Tipo | Descripción | | --------- | ---- | ----------- | -| `issue` | object | La incidencia creada que contiene id, título, descripción, estado, teamId y projectId | +| `issue` | object | La incidencia creada con todas sus propiedades | ### `linear_update_issue` @@ -91,14 +111,20 @@ Actualizar una incidencia existente en Linear | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | -| `issueId` | string | Sí | ID de la incidencia de Linear a actualizar | +| `issueId` | string | Sí | ID de la incidencia de Linear para actualizar | | `title` | string | No | Nuevo título de la incidencia | | `description` | string | No | Nueva descripción de la incidencia | | `stateId` | string | No | ID del estado del flujo de trabajo \(estado\) | | `assigneeId` | string | No | ID del usuario al que asignar la incidencia | | `priority` | number | No | Prioridad \(0=Sin prioridad, 1=Urgente, 2=Alta, 3=Normal, 4=Baja\) | | `estimate` | number | No | Estimación en puntos | -| `labelIds` | array | No | Array de IDs de etiquetas para establecer en la incidencia | +| `labelIds` | array | No | Array de IDs de etiquetas para establecer en la incidencia \(reemplaza todas las etiquetas existentes\) | +| `projectId` | string | No | ID del proyecto al que mover la incidencia | +| `cycleId` | string | No | ID del ciclo al que asignar la incidencia | +| `parentId` | string | No | ID de la incidencia padre \(para convertir esta en una subincidencia\) | +| `dueDate` | string | No | Fecha de vencimiento en formato ISO 8601 \(solo fecha: AAAA-MM-DD\) | +| `addedLabelIds` | array | No | Array de IDs de etiquetas para añadir a la incidencia \(sin reemplazar las etiquetas existentes\) | +| `removedLabelIds` | array | No | Array de IDs de etiquetas para eliminar de la incidencia | #### Salida @@ -237,7 +263,7 @@ Editar un comentario en Linear | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | | `commentId` | string | Sí | ID del comentario a actualizar | -| `body` | string | Sí | Nuevo texto del comentario \(admite Markdown\) | +| `body` | string | No | Nuevo texto del comentario \(admite Markdown\) | #### Salida @@ -347,11 +373,11 @@ Actualizar un proyecto existente en Linear | `projectId` | string | Sí | ID del proyecto a actualizar | | `name` | string | No | Nuevo nombre del proyecto | | `description` | string | No | Nueva descripción del proyecto | -| `state` | string | No | Estado del proyecto (planned, started, completed, canceled) | +| `state` | string | No | Estado del proyecto \(planned, started, completed, canceled\) | | `leadId` | string | No | ID del usuario líder del proyecto | -| `startDate` | string | No | Fecha de inicio del proyecto (formato ISO) | -| `targetDate` | string | No | Fecha objetivo del proyecto (formato ISO) | -| `priority` | number | No | Prioridad del proyecto (0-4) | +| `startDate` | string | No | Fecha de inicio del proyecto \(formato ISO: YYYY-MM-DD\) | +| `targetDate` | string | No | Fecha objetivo del proyecto \(formato ISO: YYYY-MM-DD\) | +| `priority` | number | No | Prioridad del proyecto \(0=Sin prioridad, 1=Urgente, 2=Alta, 3=Normal, 4=Baja\) | #### Salida @@ -526,8 +552,8 @@ Crear un nuevo estado de flujo de trabajo (estado) en Linear | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | | `teamId` | string | Sí | ID del equipo donde crear el estado | -| `name` | string | Sí | Nombre del estado (p. ej., "En revisión") | -| `color` | string | Sí | Color del estado (formato hex) | +| `name` | string | Sí | Nombre del estado \(p. ej., "En revisión"\) | +| `color` | string | No | Color del estado \(formato hex\) | | `type` | string | Sí | Tipo de estado: "backlog", "unstarted", "started", "completed", o "canceled" | | `description` | string | No | Descripción del estado | | `position` | number | No | Posición en el flujo de trabajo | @@ -637,7 +663,7 @@ Añadir un adjunto a una incidencia en Linear | --------- | ---- | ----------- | ----------- | | `issueId` | string | Sí | ID de la incidencia a la que adjuntar | | `url` | string | Sí | URL del adjunto | -| `title` | string | No | Título del adjunto | +| `title` | string | Sí | Título del adjunto | | `subtitle` | string | No | Subtítulo/descripción del adjunto | #### Salida @@ -673,7 +699,7 @@ Actualizar los metadatos de un adjunto en Linear | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | | `attachmentId` | string | Sí | ID del adjunto a actualizar | -| `title` | string | No | Nuevo título del adjunto | +| `title` | string | Sí | Nuevo título del adjunto | | `subtitle` | string | No | Nuevo subtítulo del adjunto | #### Salida @@ -707,8 +733,8 @@ Vincular dos incidencias en Linear (bloquea, se relaciona con, duplica) | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | | `issueId` | string | Sí | ID de la incidencia de origen | -| `relatedIssueId` | string | Sí | ID de la incidencia de destino a vincular | -| `type` | string | Sí | Tipo de relación: "blocks", "blocked", "duplicate", "related" | +| `relatedIssueId` | string | Sí | ID de la incidencia de destino a la que vincular | +| `type` | string | Sí | Tipo de relación: "blocks", "duplicate", o "related". Nota: Al crear "blocks" de A a B, la relación inversa \(B bloqueada por A\) se crea automáticamente. | #### Salida @@ -1217,10 +1243,11 @@ Crear una nueva etiqueta de proyecto en Linear | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | -| `name` | string | Sí | Nombre de la etiqueta de proyecto | -| `color` | string | No | Color de la etiqueta (código hexadecimal) | +| `projectId` | string | Sí | El proyecto para esta etiqueta | +| `name` | string | Sí | Nombre de la etiqueta del proyecto | +| `color` | string | No | Color de la etiqueta \(código hex\) | | `description` | string | No | Descripción de la etiqueta | -| `isGroup` | boolean | No | Indica si es un grupo de etiquetas | +| `isGroup` | boolean | No | Indica si esta es un grupo de etiquetas | | `parentId` | string | No | ID del grupo de etiquetas padre | #### Salida @@ -1394,10 +1421,11 @@ Crear un nuevo estado de proyecto en Linear | Parámetro | Tipo | Obligatorio | Descripción | | --------- | ---- | ----------- | ----------- | +| `projectId` | string | Sí | El proyecto para el que crear el estado | | `name` | string | Sí | Nombre del estado del proyecto | -| `color` | string | Sí | Color del estado \(código hex\) | +| `color` | string | Sí | Color del estado (código hex) | | `description` | string | No | Descripción del estado | -| `indefinite` | boolean | No | Indica si el estado es indefinido | +| `indefinite` | boolean | No | Si el estado es indefinido | | `position` | number | No | Posición en la lista de estados | #### Salida diff --git a/apps/docs/content/docs/fr/tools/linear.mdx b/apps/docs/content/docs/fr/tools/linear.mdx index df4f385897..fcf6aa57a3 100644 --- a/apps/docs/content/docs/fr/tools/linear.mdx +++ b/apps/docs/content/docs/fr/tools/linear.mdx @@ -39,14 +39,24 @@ Récupérer et filtrer les tickets depuis Linear | Paramètre | Type | Obligatoire | Description | | --------- | ---- | ----------- | ----------- | -| `teamId` | chaîne | Oui | ID de l'équipe Linear | -| `projectId` | chaîne | Oui | ID du projet Linear | +| `teamId` | chaîne | Non | ID de l'équipe Linear pour filtrer | +| `projectId` | chaîne | Non | ID du projet Linear pour filtrer | +| `assigneeId` | chaîne | Non | ID de l'utilisateur pour filtrer par assigné | +| `stateId` | chaîne | Non | ID de l'état du flux de travail pour filtrer par statut | +| `priority` | nombre | Non | Priorité pour filtrer \(0=Pas de priorité, 1=Urgent, 2=Élevée, 3=Normale, 4=Faible\) | +| `labelIds` | tableau | Non | Tableau des IDs d'étiquettes pour filtrer | +| `createdAfter` | chaîne | Non | Filtrer les tickets créés après cette date \(format ISO 8601\) | +| `updatedAfter` | chaîne | Non | Filtrer les tickets mis à jour après cette date \(format ISO 8601\) | +| `includeArchived` | booléen | Non | Inclure les tickets archivés \(par défaut : false\) | +| `first` | nombre | Non | Nombre de tickets à retourner \(par défaut : 50, max : 250\) | +| `after` | chaîne | Non | Curseur de pagination pour la page suivante | +| `orderBy` | chaîne | Non | Ordre de tri : "createdAt" ou "updatedAt" \(par défaut : "updatedAt"\) | #### Sortie | Paramètre | Type | Description | | --------- | ---- | ----------- | -| `issues` | tableau | Tableau des tickets du projet et de l'équipe Linear spécifiés, chacun contenant id, titre, description, état, teamId et projectId | +| `issues` | tableau | Tableau des tickets filtrés de Linear | ### `linear_get_issue` @@ -73,15 +83,25 @@ Créer un nouveau ticket dans Linear | Paramètre | Type | Obligatoire | Description | | --------- | ---- | ----------- | ----------- | | `teamId` | chaîne | Oui | ID de l'équipe Linear | -| `projectId` | chaîne | Oui | ID du projet Linear | +| `projectId` | chaîne | Non | ID du projet Linear | | `title` | chaîne | Oui | Titre du ticket | | `description` | chaîne | Non | Description du ticket | +| `stateId` | chaîne | Non | ID de l'état du flux de travail \(statut\) | +| `assigneeId` | chaîne | Non | ID de l'utilisateur à qui assigner le ticket | +| `priority` | nombre | Non | Priorité \(0=Pas de priorité, 1=Urgent, 2=Élevée, 3=Normale, 4=Faible\) | +| `estimate` | nombre | Non | Estimation en points | +| `labelIds` | tableau | Non | Tableau des IDs d'étiquettes à définir sur le ticket | +| `cycleId` | chaîne | Non | ID du cycle auquel assigner le ticket | +| `parentId` | chaîne | Non | ID du ticket parent \(pour créer des sous-tickets\) | +| `dueDate` | chaîne | Non | Date d'échéance au format ISO 8601 \(date uniquement : AAAA-MM-JJ\) | +| `subscriberIds` | tableau | Non | Tableau des IDs d'utilisateurs à abonner au ticket | +| `projectMilestoneId` | chaîne | Non | ID de l'étape clé du projet à associer au ticket | #### Sortie | Paramètre | Type | Description | | --------- | ---- | ----------- | -| `issue` | objet | Le ticket créé contenant id, titre, description, état, teamId et projectId | +| `issue` | objet | Le ticket créé avec toutes ses propriétés | ### `linear_update_issue` @@ -94,11 +114,17 @@ Mettre à jour un ticket existant dans Linear | `issueId` | chaîne | Oui | ID du ticket Linear à mettre à jour | | `title` | chaîne | Non | Nouveau titre du ticket | | `description` | chaîne | Non | Nouvelle description du ticket | -| `stateId` | chaîne | Non | ID de l'état du flux de travail \(statut\) | +| `stateId` | chaîne | Non | ID de l'état du workflow \(statut\) | | `assigneeId` | chaîne | Non | ID de l'utilisateur à qui assigner le ticket | -| `priority` | nombre | Non | Priorité \(0=Pas de priorité, 1=Urgent, 2=Élevée, 3=Normale, 4=Faible\) | +| `priority` | nombre | Non | Priorité \(0=Aucune priorité, 1=Urgent, 2=Élevée, 3=Normale, 4=Faible\) | | `estimate` | nombre | Non | Estimation en points | -| `labelIds` | tableau | Non | Tableau des IDs d'étiquettes à définir sur le ticket | +| `labelIds` | tableau | Non | Tableau des ID d'étiquettes à définir sur le ticket \(remplace toutes les étiquettes existantes\) | +| `projectId` | chaîne | Non | ID du projet vers lequel déplacer le ticket | +| `cycleId` | chaîne | Non | ID du cycle auquel assigner le ticket | +| `parentId` | chaîne | Non | ID du ticket parent \(pour en faire un sous-ticket\) | +| `dueDate` | chaîne | Non | Date d'échéance au format ISO 8601 \(date uniquement : AAAA-MM-JJ\) | +| `addedLabelIds` | tableau | Non | Tableau des ID d'étiquettes à ajouter au ticket \(sans remplacer les étiquettes existantes\) | +| `removedLabelIds` | tableau | Non | Tableau des ID d'étiquettes à supprimer du ticket | #### Sortie @@ -237,7 +263,7 @@ Modifier un commentaire dans Linear | Paramètre | Type | Obligatoire | Description | | --------- | ---- | ----------- | ----------- | | `commentId` | chaîne | Oui | ID du commentaire à mettre à jour | -| `body` | chaîne | Oui | Nouveau texte du commentaire \(supporte le Markdown\) | +| `body` | chaîne | Non | Nouveau texte du commentaire \(supporte le Markdown\) | #### Sortie @@ -349,9 +375,9 @@ Mettre à jour un projet existant dans Linear | `description` | chaîne | Non | Nouvelle description du projet | | `state` | chaîne | Non | État du projet \(planned, started, completed, canceled\) | | `leadId` | chaîne | Non | ID de l'utilisateur responsable du projet | -| `startDate` | chaîne | Non | Date de début du projet \(format ISO\) | -| `targetDate` | chaîne | Non | Date cible du projet \(format ISO\) | -| `priority` | nombre | Non | Priorité du projet \(0-4\) | +| `startDate` | chaîne | Non | Date de début du projet \(format ISO : YYYY-MM-DD\) | +| `targetDate` | chaîne | Non | Date cible du projet \(format ISO : YYYY-MM-DD\) | +| `priority` | nombre | Non | Priorité du projet \(0=Pas de priorité, 1=Urgent, 2=Élevée, 3=Normale, 4=Faible\) | #### Sortie @@ -526,11 +552,11 @@ Créer un nouvel état de workflow (statut) dans Linear | Paramètre | Type | Obligatoire | Description | | --------- | ---- | ----------- | ----------- | | `teamId` | chaîne | Oui | ID de l'équipe dans laquelle créer l'état | -| `name` | chaîne | Oui | Nom de l'état \(ex., "En révision"\) | -| `color` | chaîne | Oui | Couleur de l'état \(format hexadécimal\) | +| `name` | chaîne | Oui | Nom de l'état \(ex. : "En révision"\) | +| `color` | chaîne | Non | Couleur de l'état \(format hexadécimal\) | | `type` | chaîne | Oui | Type d'état : "backlog", "unstarted", "started", "completed", ou "canceled" | | `description` | chaîne | Non | Description de l'état | -| `position` | nombre | Non | Position dans le workflow | +| `position` | nombre | Non | Position dans le flux de travail | #### Sortie @@ -635,9 +661,9 @@ Ajouter une pièce jointe à un ticket dans Linear | Paramètre | Type | Obligatoire | Description | | --------- | ---- | ----------- | ----------- | -| `issueId` | chaîne | Oui | ID du ticket auquel joindre la pièce | +| `issueId` | chaîne | Oui | ID du ticket auquel joindre | | `url` | chaîne | Oui | URL de la pièce jointe | -| `title` | chaîne | Non | Titre de la pièce jointe | +| `title` | chaîne | Oui | Titre de la pièce jointe | | `subtitle` | chaîne | Non | Sous-titre/description de la pièce jointe | #### Sortie @@ -673,7 +699,7 @@ Mettre à jour les métadonnées d'une pièce jointe dans Linear | Paramètre | Type | Obligatoire | Description | | --------- | ---- | ----------- | ----------- | | `attachmentId` | chaîne | Oui | ID de la pièce jointe à mettre à jour | -| `title` | chaîne | Non | Nouveau titre de la pièce jointe | +| `title` | chaîne | Oui | Nouveau titre de la pièce jointe | | `subtitle` | chaîne | Non | Nouveau sous-titre de la pièce jointe | #### Sortie @@ -708,7 +734,7 @@ Lier deux tickets ensemble dans Linear (bloque, est lié à, duplique) | --------- | ---- | ----------- | ----------- | | `issueId` | chaîne | Oui | ID du ticket source | | `relatedIssueId` | chaîne | Oui | ID du ticket cible à lier | -| `type` | chaîne | Oui | Type de relation : "blocks", "blocked", "duplicate", "related" | +| `type` | chaîne | Oui | Type de relation : "blocks", "duplicate", ou "related". Remarque : Lors de la création d'une relation "blocks" de A vers B, la relation inverse \(B bloqué par A\) est automatiquement créée. | #### Sortie @@ -1217,6 +1243,7 @@ Créer une nouvelle étiquette de projet dans Linear | Paramètre | Type | Obligatoire | Description | | --------- | ---- | ----------- | ----------- | +| `projectId` | chaîne | Oui | Le projet pour cette étiquette | | `name` | chaîne | Oui | Nom de l'étiquette de projet | | `color` | chaîne | Non | Couleur de l'étiquette \(code hexadécimal\) | | `description` | chaîne | Non | Description de l'étiquette | @@ -1394,7 +1421,8 @@ Créer un nouveau statut de projet dans Linear | Paramètre | Type | Obligatoire | Description | | --------- | ---- | ----------- | ----------- | -| `name` | chaîne | Oui | Nom du statut du projet | +| `projectId` | chaîne | Oui | Le projet pour lequel créer le statut | +| `name` | chaîne | Oui | Nom du statut de projet | | `color` | chaîne | Oui | Couleur du statut \(code hexadécimal\) | | `description` | chaîne | Non | Description du statut | | `indefinite` | booléen | Non | Indique si le statut est indéfini | diff --git a/apps/docs/content/docs/ja/tools/linear.mdx b/apps/docs/content/docs/ja/tools/linear.mdx index eda30a8832..70d9f419fe 100644 --- a/apps/docs/content/docs/ja/tools/linear.mdx +++ b/apps/docs/content/docs/ja/tools/linear.mdx @@ -39,14 +39,24 @@ Linearから課題を取得してフィルタリングする | パラメータ | 型 | 必須 | 説明 | | --------- | ---- | -------- | ----------- | -| `teamId` | string | はい | LinearチームID | -| `projectId` | string | はい | LinearプロジェクトID | +| `teamId` | string | いいえ | フィルタリングするLinearチームID | +| `projectId` | string | いいえ | フィルタリングするLinearプロジェクトID | +| `assigneeId` | string | いいえ | 担当者でフィルタリングするユーザーID | +| `stateId` | string | いいえ | ステータスでフィルタリングするワークフロー状態ID | +| `priority` | number | いいえ | フィルタリングする優先度(0=優先度なし、1=緊急、2=高、3=普通、4=低) | +| `labelIds` | array | いいえ | フィルタリングするラベルIDの配列 | +| `createdAfter` | string | いいえ | この日付以降に作成された課題をフィルタリング(ISO 8601形式) | +| `updatedAfter` | string | いいえ | この日付以降に更新された課題をフィルタリング(ISO 8601形式) | +| `includeArchived` | boolean | いいえ | アーカイブされた課題を含める(デフォルト:false) | +| `first` | number | いいえ | 返す課題の数(デフォルト:50、最大:250) | +| `after` | string | いいえ | 次のページのページネーションカーソル | +| `orderBy` | string | いいえ | ソート順:"createdAt"または"updatedAt"(デフォルト:"updatedAt") | #### 出力 | パラメータ | 型 | 説明 | | --------- | ---- | ----------- | -| `issues` | array | 指定されたLinearチームとプロジェクトからの課題の配列。各課題にはid、title、description、state、teamId、projectIdが含まれます | +| `issues` | array | Linearからフィルタリングされた課題の配列 | ### `linear_get_issue` @@ -73,15 +83,25 @@ Linearに新しい課題を作成する | パラメータ | 型 | 必須 | 説明 | | --------- | ---- | -------- | ----------- | | `teamId` | string | はい | LinearチームID | -| `projectId` | string | はい | LinearプロジェクトID | +| `projectId` | string | いいえ | LinearプロジェクトID | | `title` | string | はい | 課題のタイトル | | `description` | string | いいえ | 課題の説明 | +| `stateId` | string | いいえ | ワークフロー状態ID(ステータス) | +| `assigneeId` | string | いいえ | 課題を割り当てるユーザーID | +| `priority` | number | いいえ | 優先度(0=優先度なし、1=緊急、2=高、3=普通、4=低) | +| `estimate` | number | いいえ | ポイント単位の見積もり | +| `labelIds` | array | いいえ | 課題に設定するラベルIDの配列 | +| `cycleId` | string | いいえ | 課題を割り当てるサイクルID | +| `parentId` | string | いいえ | 親課題ID(サブ課題を作成する場合) | +| `dueDate` | string | いいえ | ISO 8601形式の期日(日付のみ:YYYY-MM-DD) | +| `subscriberIds` | array | いいえ | 課題をサブスクライブするユーザーIDの配列 | +| `projectMilestoneId` | string | いいえ | 課題に関連付けるプロジェクトマイルストーンID | #### 出力 | パラメータ | 型 | 説明 | | --------- | ---- | ----------- | -| `issue` | object | 作成された課題(id、title、description、state、teamId、projectIdを含む) | +| `issue` | object | すべてのプロパティを含む作成された課題 | ### `linear_update_issue` @@ -97,8 +117,14 @@ Linearの既存の課題を更新する | `stateId` | string | いいえ | ワークフロー状態ID(ステータス) | | `assigneeId` | string | いいえ | 課題を割り当てるユーザーID | | `priority` | number | いいえ | 優先度(0=優先度なし、1=緊急、2=高、3=普通、4=低) | -| `estimate` | number | いいえ | ポイント単位の見積もり | -| `labelIds` | array | いいえ | 課題に設定するラベルIDの配列 | +| `estimate` | number | いいえ | ポイントでの見積もり | +| `labelIds` | array | いいえ | 課題に設定するラベルIDの配列(既存のすべてのラベルを置き換え) | +| `projectId` | string | いいえ | 課題を移動するプロジェクトID | +| `cycleId` | string | いいえ | 課題を割り当てるサイクルID | +| `parentId` | string | いいえ | 親課題ID(これをサブ課題にする場合) | +| `dueDate` | string | いいえ | ISO 8601形式の期日(日付のみ:YYYY-MM-DD) | +| `addedLabelIds` | array | いいえ | 課題に追加するラベルIDの配列(既存のラベルを置き換えない) | +| `removedLabelIds` | array | いいえ | 課題から削除するラベルIDの配列 | #### 出力 @@ -237,7 +263,7 @@ Linearでコメントを編集する | パラメータ | 型 | 必須 | 説明 | | --------- | ---- | -------- | ----------- | | `commentId` | string | はい | 更新するコメントID | -| `body` | string | はい | 新しいコメントテキスト(Markdownをサポート) | +| `body` | string | いいえ | 新しいコメントテキスト(Markdownをサポート) | #### 出力 @@ -349,9 +375,9 @@ Linearの既存プロジェクトを更新する | `description` | string | いいえ | 新しいプロジェクトの説明 | | `state` | string | いいえ | プロジェクトの状態(計画中、開始済み、完了、キャンセル) | | `leadId` | string | いいえ | プロジェクトリーダーのユーザーID | -| `startDate` | string | いいえ | プロジェクト開始日(ISO形式) | -| `targetDate` | string | いいえ | プロジェクト目標日(ISO形式) | -| `priority` | number | いいえ | プロジェクト優先度(0-4) | +| `startDate` | string | いいえ | プロジェクト開始日(ISO形式:YYYY-MM-DD) | +| `targetDate` | string | いいえ | プロジェクト目標日(ISO形式:YYYY-MM-DD) | +| `priority` | number | いいえ | プロジェクト優先度(0=優先度なし、1=緊急、2=高、3=普通、4=低) | #### 出力 @@ -527,7 +553,7 @@ Linearに新しいワークフローステータス(状態)を作成する | --------- | ---- | -------- | ----------- | | `teamId` | string | はい | ステータスを作成するチームID | | `name` | string | はい | ステータス名(例:「レビュー中」) | -| `color` | string | はい | ステータスの色(16進形式) | +| `color` | string | いいえ | ステータスの色(16進形式) | | `type` | string | はい | ステータスタイプ:「backlog」、「unstarted」、「started」、「completed」、または「canceled」 | | `description` | string | いいえ | ステータスの説明 | | `position` | number | いいえ | ワークフロー内の位置 | @@ -635,9 +661,9 @@ Linearの課題に添付ファイルを追加する | パラメータ | 型 | 必須 | 説明 | | --------- | ---- | -------- | ----------- | -| `issueId` | string | はい | 添付先の課題ID | +| `issueId` | string | はい | 添付する課題ID | | `url` | string | はい | 添付ファイルのURL | -| `title` | string | いいえ | 添付ファイルのタイトル | +| `title` | string | はい | 添付ファイルのタイトル | | `subtitle` | string | いいえ | 添付ファイルのサブタイトル/説明 | #### 出力 @@ -673,7 +699,7 @@ Linearで添付ファイルのメタデータを更新する | パラメータ | 型 | 必須 | 説明 | | --------- | ---- | -------- | ----------- | | `attachmentId` | string | はい | 更新する添付ファイルID | -| `title` | string | いいえ | 新しい添付ファイルのタイトル | +| `title` | string | はい | 新しい添付ファイルのタイトル | | `subtitle` | string | いいえ | 新しい添付ファイルのサブタイトル | #### 出力 @@ -708,7 +734,7 @@ Linearで2つの課題を関連付ける(ブロック、関連、重複) | --------- | ---- | -------- | ----------- | | `issueId` | string | はい | ソース課題ID | | `relatedIssueId` | string | はい | リンク先のターゲット課題ID | -| `type` | string | はい | 関係タイプ:「blocks」、「blocked」、「duplicate」、「related」 | +| `type` | string | はい | 関係タイプ:"blocks"、"duplicate"、または"related"。注意:AからBへの"blocks"を作成すると、逆の関係(BはAによってブロックされる)が自動的に作成されます。 | #### 出力 @@ -1217,6 +1243,7 @@ Linearで新しいプロジェクトラベルを作成する | パラメータ | 型 | 必須 | 説明 | | --------- | ---- | -------- | ----------- | +| `projectId` | string | はい | このラベルのプロジェクト | | `name` | string | はい | プロジェクトラベル名 | | `color` | string | いいえ | ラベルの色(16進コード) | | `description` | string | いいえ | ラベルの説明 | @@ -1394,6 +1421,7 @@ Linearで新しいプロジェクトステータスを作成する | パラメータ | 型 | 必須 | 説明 | | --------- | ---- | -------- | ----------- | +| `projectId` | string | はい | ステータスを作成するプロジェクト | | `name` | string | はい | プロジェクトステータス名 | | `color` | string | はい | ステータスの色(16進コード) | | `description` | string | いいえ | ステータスの説明 | diff --git a/apps/docs/content/docs/zh/tools/linear.mdx b/apps/docs/content/docs/zh/tools/linear.mdx index 1d4e22737a..a440d89b79 100644 --- a/apps/docs/content/docs/zh/tools/linear.mdx +++ b/apps/docs/content/docs/zh/tools/linear.mdx @@ -39,14 +39,24 @@ Linear 的主要功能包括: | 参数 | 类型 | 必需 | 描述 | | --------- | ---- | -------- | ----------- | -| `teamId` | string | 是 | Linear 团队 ID | -| `projectId` | string | 是 | Linear 项目 ID | +| `teamId` | string | 否 | 按 Linear 团队 ID 筛选 | +| `projectId` | string | 否 | 按 Linear 项目 ID 筛选 | +| `assigneeId` | string | 否 | 按分配的用户 ID 筛选 | +| `stateId` | string | 否 | 按工作流状态 ID 筛选(状态)| +| `priority` | number | 否 | 按优先级筛选(0=无优先级,1=紧急,2=高,3=正常,4=低)| +| `labelIds` | array | 否 | 按标签 ID 数组筛选 | +| `createdAfter` | string | 否 | 筛选创建日期晚于此日期的问题(ISO 8601 格式)| +| `updatedAfter` | string | 否 | 筛选更新日期晚于此日期的问题(ISO 8601 格式)| +| `includeArchived` | boolean | 否 | 包括已归档的问题(默认值:false)| +| `first` | number | 否 | 返回的问题数量(默认值:50,最大值:250)| +| `after` | string | 否 | 下一页的分页游标 | +| `orderBy` | string | 否 | 排序顺序:"createdAt" 或 "updatedAt"(默认值:"updatedAt")| #### 输出 | 参数 | 类型 | 描述 | | --------- | ---- | ----------- | -| `issues` | array | 来自指定 Linear 团队和项目的问题数组,每个问题包含 id、title、description、state、teamId 和 projectId | +| `issues` | array | 从 Linear 筛选的问题数组 | ### `linear_get_issue` @@ -73,15 +83,25 @@ Linear 的主要功能包括: | 参数 | 类型 | 必需 | 描述 | | --------- | ---- | -------- | ----------- | | `teamId` | string | 是 | Linear 团队 ID | -| `projectId` | string | 是 | Linear 项目 ID | +| `projectId` | string | 否 | Linear 项目 ID | | `title` | string | 是 | 问题标题 | | `description` | string | 否 | 问题描述 | +| `stateId` | string | 否 | 工作流状态 ID(状态)| +| `assigneeId` | string | 否 | 要分配问题的用户 ID | +| `priority` | number | 否 | 优先级(0=无优先级,1=紧急,2=高,3=正常,4=低)| +| `estimate` | number | 否 | 以点数估算 | +| `labelIds` | array | 否 | 要设置在问题上的标签 ID 数组 | +| `cycleId` | string | 否 | 要分配问题的周期 ID | +| `parentId` | string | 否 | 父问题 ID(用于创建子问题)| +| `dueDate` | string | 否 | 到期日期(ISO 8601 格式,仅日期:YYYY-MM-DD)| +| `subscriberIds` | array | 否 | 要订阅问题的用户 ID 数组 | +| `projectMilestoneId` | string | 否 | 要与问题关联的项目里程碑 ID | #### 输出 | 参数 | 类型 | 描述 | | --------- | ---- | ----------- | -| `issue` | object | 创建的问题,包含 id、title、description、state、teamId 和 projectId | +| `issue` | object | 创建的包含所有属性的问题 | ### `linear_update_issue` @@ -94,11 +114,17 @@ Linear 的主要功能包括: | `issueId` | string | 是 | 要更新的 Linear 问题 ID | | `title` | string | 否 | 新的问题标题 | | `description` | string | 否 | 新的问题描述 | -| `stateId` | string | 否 | 工作流状态 ID(状态) | -| `assigneeId` | string | 否 | 要分配问题的用户 ID | -| `priority` | number | 否 | 优先级(0=无优先级,1=紧急,2=高,3=正常,4=低) | -| `estimate` | number | 否 | 以点数估算 | -| `labelIds` | array | 否 | 要设置在问题上的标签 ID 数组 | +| `stateId` | string | 否 | 工作流状态 ID(状态)| +| `assigneeId` | string | 否 | 分配给问题的用户 ID | +| `priority` | number | 否 | 优先级(0=无优先级,1=紧急,2=高,3=正常,4=低)| +| `estimate` | number | 否 | 估算点数 | +| `labelIds` | array | 否 | 设置在问题上的标签 ID 数组(替换所有现有标签)| +| `projectId` | string | 否 | 要移动问题到的项目 ID | +| `cycleId` | string | 否 | 分配给问题的周期 ID | +| `parentId` | string | 否 | 父问题 ID(将其设为子问题)| +| `dueDate` | string | 否 | ISO 8601 格式的截止日期(仅日期:YYYY-MM-DD)| +| `addedLabelIds` | array | 否 | 添加到问题的标签 ID 数组(不替换现有标签)| +| `removedLabelIds` | array | 否 | 从问题中移除的标签 ID 数组 | #### 输出 @@ -237,7 +263,7 @@ Linear 的主要功能包括: | 参数 | 类型 | 必需 | 描述 | | --------- | ---- | -------- | ----------- | | `commentId` | string | 是 | 要更新的评论 ID | -| `body` | string | 是 | 新的评论文本(支持 Markdown) | +| `body` | string | 否 | 新的评论文本(支持 Markdown) | #### 输出 @@ -347,11 +373,11 @@ Linear 的主要功能包括: | `projectId` | string | 是 | 要更新的项目 ID | | `name` | string | 否 | 新的项目名称 | | `description` | string | 否 | 新的项目描述 | -| `state` | string | 否 | 项目状态(计划中、已开始、已完成、已取消)| +| `state` | string | 否 | 项目状态(planned、started、completed、canceled) | | `leadId` | string | 否 | 项目负责人的用户 ID | -| `startDate` | string | 否 | 项目开始日期(ISO 格式)| -| `targetDate` | string | 否 | 项目目标日期(ISO 格式)| -| `priority` | number | 否 | 项目优先级(0-4)| +| `startDate` | string | 否 | 项目开始日期(ISO 格式: YYYY-MM-DD)| +| `targetDate` | string | 否 | 项目目标日期(ISO 格式: YYYY-MM-DD)| +| `priority` | number | 否 | 项目优先级(0=无优先级,1=紧急,2=高,3=正常,4=低) | #### 输出 @@ -525,10 +551,10 @@ Linear 的主要功能包括: | 参数 | 类型 | 必需 | 描述 | | --------- | ---- | -------- | ----------- | -| `teamId` | string | 是 | 要创建状态的团队 ID | -| `name` | string | 是 | 状态名称 \(例如,"In Review"\) | -| `color` | string | 是 | 状态颜色 \(十六进制格式\) | -| `type` | string | 是 | 状态类型:"backlog"、"unstarted"、"started"、"completed" 或 "canceled" | +| `teamId` | string | 是 | 要在其中创建状态的团队 ID | +| `name` | string | 是 | 状态名称(例如 "In Review")| +| `color` | string | 否 | 状态颜色(十六进制格式)| +| `type` | string | 是 | 状态类型: "backlog"、"unstarted"、"started"、"completed" 或 "canceled" | | `description` | string | 否 | 状态描述 | | `position` | number | 否 | 工作流中的位置 | @@ -637,7 +663,7 @@ Linear 的主要功能包括: | --------- | ---- | -------- | ----------- | | `issueId` | string | 是 | 要附加的 Issue ID | | `url` | string | 是 | 附件的 URL | -| `title` | string | 否 | 附件标题 | +| `title` | string | 是 | 附件标题 | | `subtitle` | string | 否 | 附件副标题/描述 | #### 输出 @@ -673,7 +699,7 @@ Linear 的主要功能包括: | 参数 | 类型 | 必需 | 描述 | | --------- | ---- | -------- | ----------- | | `attachmentId` | string | 是 | 要更新的附件 ID | -| `title` | string | 否 | 新的附件标题 | +| `title` | string | 是 | 新的附件标题 | | `subtitle` | string | 否 | 新的附件副标题 | #### 输出 @@ -708,7 +734,7 @@ Linear 的主要功能包括: | --------- | ---- | -------- | ----------- | | `issueId` | string | 是 | 源问题 ID | | `relatedIssueId` | string | 是 | 要链接的目标问题 ID | -| `type` | string | 是 | 关系类型:"blocks"(阻止)、"blocked"(被阻止)、"duplicate"(重复)、"related"(相关) | +| `type` | string | 是 | 关系类型: "blocks"、"duplicate" 或 "related"。注意:当从 A 到 B 创建 "blocks" 时,会自动创建反向关系 \(B 被 A 阻止\)。 | #### 输出 @@ -1217,6 +1243,7 @@ Linear 的主要功能包括: | 参数 | 类型 | 必需 | 描述 | | --------- | ---- | -------- | ----------- | +| `projectId` | string | 是 | 此标签所属的项目 | | `name` | string | 是 | 项目标签名称 | | `color` | string | 否 | 标签颜色 \(十六进制代码\) | | `description` | string | 否 | 标签描述 | @@ -1394,6 +1421,7 @@ Linear 的主要功能包括: | 参数 | 类型 | 必需 | 描述 | | --------- | ---- | -------- | ----------- | +| `projectId` | string | 是 | 要为其创建状态的项目 | | `name` | string | 是 | 项目状态名称 | | `color` | string | 是 | 状态颜色 \(十六进制代码\) | | `description` | string | 否 | 状态描述 | diff --git a/apps/docs/i18n.lock b/apps/docs/i18n.lock index 1122beb304..509faafe9d 100644 --- a/apps/docs/i18n.lock +++ b/apps/docs/i18n.lock @@ -1964,9 +1964,9 @@ checksums: content/10: dc0cd9ecdd8caafc0a4a7c60b68daa2f content/11: 67ffd9a9b55ad6c1259af98deafb5d0a content/12: 371d0e46b4bd2c23f559b8bc112f6955 - content/13: 1b7e0cec71c2ad722e356ba1f569da6b + content/13: 8b8b040a8485fabfa0c94482163fc39c content/14: bcadfc362b69078beee0088e5936c98b - content/15: b6cfb067664d66c5793de41ace6a3ef3 + content/15: bbc717461139df90f307b1e5715978bf content/16: 29a606473b5216cceb515b5a8b433f63 content/17: 731e123330335c611fcbf70919e955b9 content/18: 371d0e46b4bd2c23f559b8bc112f6955 @@ -1976,13 +1976,13 @@ checksums: content/22: e4b5d2b30f9a5ac7456d9e2403ff6fc1 content/23: ba6b661f58f6c55fceb6666247b185be content/24: 371d0e46b4bd2c23f559b8bc112f6955 - content/25: 1813df0e019589847b73769342f51bc3 + content/25: 8373a4b5ffe81061f22326e0f8e9f84e content/26: bcadfc362b69078beee0088e5936c98b - content/27: d64618728def8031137bc39f9c14072b + content/27: 6e88d2c0bd7f3563d0d024c74855361b content/28: 4240d9c02238325392a6c56fe55587ec content/29: 456d6e5be5f40d6290b6783b638e316b content/30: 371d0e46b4bd2c23f559b8bc112f6955 - content/31: e292bf642654431b8795f9559c07f330 + content/31: 0a5e9e47873a22622a9ab035199df6d2 content/32: bcadfc362b69078beee0088e5936c98b content/33: e13d950ad68beff6352319bb0d102fec content/34: 0b78c3741f5caf86271cd3fcad674785 @@ -2030,7 +2030,7 @@ checksums: content/76: 2ce20e0b75472e89c4ad0e5bbb588bea content/77: 1e6015e207ad5512fe81843588b1c8a7 content/78: 371d0e46b4bd2c23f559b8bc112f6955 - content/79: a3c0aad623f2b68eb7caa312031855e0 + content/79: 9023fec7d6c0d587d0de217d8ec3145c content/80: bcadfc362b69078beee0088e5936c98b content/81: 3f738270799daa8b08c67b1e1a8fc6ce content/82: 5a2a4e06bf108686b2eade2cda5a0213 @@ -2066,7 +2066,7 @@ checksums: content/112: 36b1e6fea4549c6b0f3c93fb51d0baa6 content/113: e01cc332d94f7aeda13d63e9e5159498 content/114: 371d0e46b4bd2c23f559b8bc112f6955 - content/115: 1066dc3f18676022fc28ad2ac3dbdcbe + content/115: ce33b88492725c3912f8cc46d7959e92 content/116: bcadfc362b69078beee0088e5936c98b content/117: 0b7ea576dff35049039f27e93f492baa content/118: e72ce72b4ba59689765e1520bebd673d @@ -2126,7 +2126,7 @@ checksums: content/172: 6ac5231c6f1e4af355f4a8e9cc131c8c content/173: c4e86be3717bab3a162af6fd7d07d40f content/174: 371d0e46b4bd2c23f559b8bc112f6955 - content/175: f875917d0ddc6c49724cb05d6dbc20d3 + content/175: a6bb9e81a93241a9f5f4f0c54a8e158f content/176: bcadfc362b69078beee0088e5936c98b content/177: 4bd7f106ee69c2b18cb2a41ce8a45c49 content/178: dfdf7e15f125ed33d381182421afd071 @@ -2162,7 +2162,7 @@ checksums: content/208: 289b4c3ba8ddf2b116b89e8f42c42f7a content/209: 70f307005f7268b098c2666493f83760 content/210: 371d0e46b4bd2c23f559b8bc112f6955 - content/211: 2ad4046ebf806f5832618a982f3e5759 + content/211: 2d3e84b61c7050a6278ee34ea1b6a30d content/212: bcadfc362b69078beee0088e5936c98b content/213: 00240f5f806fa8ce1cd54e332befbcf4 content/214: 5905f216a56867439934135577706de6 @@ -2174,7 +2174,7 @@ checksums: content/220: 3a75b78856cc47e4fda093d997f74b3d content/221: 658f7e9229c459b86172cd017c239e80 content/222: 371d0e46b4bd2c23f559b8bc112f6955 - content/223: 44e98a1518d5fc5b56ffba994cda9c7f + content/223: 2236e1a16509d71cbec735d45e1f8982 content/224: bcadfc362b69078beee0088e5936c98b content/225: 1ee2ba1b12abc61e709857685e82b029 content/226: 7bd180fada856c4e3acf6f4aa2dbd866 @@ -2186,7 +2186,7 @@ checksums: content/232: eec28b7a4994e560ebfe7b65eb9489f5 content/233: e686dab5089c0869f094700f53492a4d content/234: 371d0e46b4bd2c23f559b8bc112f6955 - content/235: 0ac1e8cb148c61dc238236c47904da52 + content/235: 9c6e8834385fa1a104f2a49561e19e8b content/236: bcadfc362b69078beee0088e5936c98b content/237: 81f1f23936bbd1dc4b21bf71e84bd28c content/238: e93d92ffdc4d1d66b5100773399d93c0 @@ -2354,7 +2354,7 @@ checksums: content/400: f17b5c16f106085925c714b22959cc0f content/401: c50d1424ef13db47c44f10dfee39a920 content/402: 371d0e46b4bd2c23f559b8bc112f6955 - content/403: 4fb3b6ac2f4416abd838807e4f0efb68 + content/403: 587400a0f1fd869064c9ce3f9e1ec394 content/404: bcadfc362b69078beee0088e5936c98b content/405: 48a91e9804204fb902733bbcb519d8f3 content/406: 417531850860835ff8d1bc4990576f8a @@ -2414,7 +2414,7 @@ checksums: content/460: 4278f1ea3ef8e4e141aa55455dc45b7f content/461: 2563a5d8d8c790ce109d706ce3443807 content/462: 371d0e46b4bd2c23f559b8bc112f6955 - content/463: b12446be8e7501c8ad4a32634c07cd0a + content/463: 8a4f40f409c0eb1cf8b23a2f3f369c09 content/464: bcadfc362b69078beee0088e5936c98b content/465: eaff49649d1ae705346a12e04ea3b741 content/466: b5d7ba66d1bfee635d2b79d1069d542b diff --git a/apps/sim/app/(auth)/components/auth-background.tsx b/apps/sim/app/(auth)/components/auth-background.tsx index 0f522c521d..ec12774a19 100644 --- a/apps/sim/app/(auth)/components/auth-background.tsx +++ b/apps/sim/app/(auth)/components/auth-background.tsx @@ -1,5 +1,5 @@ import { cn } from '@/lib/utils' -import AuthBackgroundSVG from './auth-background-svg' +import AuthBackgroundSVG from '@/app/(auth)/components/auth-background-svg' type AuthBackgroundProps = { className?: string diff --git a/apps/sim/app/(auth)/components/social-login-buttons.tsx b/apps/sim/app/(auth)/components/social-login-buttons.tsx index 12efe9a6af..19d2a8cb5c 100644 --- a/apps/sim/app/(auth)/components/social-login-buttons.tsx +++ b/apps/sim/app/(auth)/components/social-login-buttons.tsx @@ -4,7 +4,7 @@ import { type ReactNode, useEffect, useState } from 'react' import { GithubIcon, GoogleIcon } from '@/components/icons' import { Button } from '@/components/ui/button' import { client } from '@/lib/auth-client' -import { inter } from '@/app/fonts/inter/inter' +import { inter } from '@/app/_styles/fonts/inter/inter' interface SocialLoginButtonsProps { githubAvailable: boolean diff --git a/apps/sim/app/(auth)/layout.tsx b/apps/sim/app/(auth)/layout.tsx index 3a8131337f..aaa76e0bf1 100644 --- a/apps/sim/app/(auth)/layout.tsx +++ b/apps/sim/app/(auth)/layout.tsx @@ -1,8 +1,8 @@ 'use client' import { useEffect } from 'react' +import AuthBackground from '@/app/(auth)/components/auth-background' import Nav from '@/app/(landing)/components/nav/nav' -import AuthBackground from './components/auth-background' // Helper to detect if a color is dark function isColorDark(hexColor: string): boolean { diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-form.tsx index b37ae78647..37a948f4f9 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-form.tsx @@ -20,10 +20,10 @@ import { getEnv, isFalsy, isTruthy } from '@/lib/env' import { createLogger } from '@/lib/logs/console/logger' import { getBaseUrl } from '@/lib/urls/utils' import { cn } from '@/lib/utils' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import { SocialLoginButtons } from '@/app/(auth)/components/social-login-buttons' import { SSOLoginButton } from '@/app/(auth)/components/sso-login-button' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' const logger = createLogger('LoginForm') diff --git a/apps/sim/app/(auth)/reset-password/page.tsx b/apps/sim/app/(auth)/reset-password/page.tsx index f70c372887..e1d2112645 100644 --- a/apps/sim/app/(auth)/reset-password/page.tsx +++ b/apps/sim/app/(auth)/reset-password/page.tsx @@ -4,9 +4,9 @@ import { Suspense, useEffect, useState } from 'react' import Link from 'next/link' import { useRouter, useSearchParams } from 'next/navigation' import { createLogger } from '@/lib/logs/console/logger' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import { SetNewPasswordForm } from '@/app/(auth)/reset-password/reset-password-form' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' const logger = createLogger('ResetPasswordPage') diff --git a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx b/apps/sim/app/(auth)/reset-password/reset-password-form.tsx index 8d22e54838..5c8a30e842 100644 --- a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx +++ b/apps/sim/app/(auth)/reset-password/reset-password-form.tsx @@ -6,7 +6,7 @@ import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { cn } from '@/lib/utils' -import { inter } from '@/app/fonts/inter/inter' +import { inter } from '@/app/_styles/fonts/inter/inter' interface RequestResetFormProps { email: string diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-form.tsx index 4dbc4cb0ab..c908d006a9 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-form.tsx @@ -12,10 +12,10 @@ import { quickValidateEmail } from '@/lib/email/validation' import { getEnv, isFalsy, isTruthy } from '@/lib/env' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import { SocialLoginButtons } from '@/app/(auth)/components/social-login-buttons' import { SSOLoginButton } from '@/app/(auth)/components/sso-login-button' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' const logger = createLogger('SignupForm') diff --git a/apps/sim/app/(auth)/sso/page.tsx b/apps/sim/app/(auth)/sso/page.tsx index 4ecb92f9bf..ba8b82d022 100644 --- a/apps/sim/app/(auth)/sso/page.tsx +++ b/apps/sim/app/(auth)/sso/page.tsx @@ -1,6 +1,6 @@ import { redirect } from 'next/navigation' import { getEnv, isTruthy } from '@/lib/env' -import SSOForm from './sso-form' +import SSOForm from '@/app/(auth)/sso/sso-form' export const dynamic = 'force-dynamic' diff --git a/apps/sim/app/(auth)/sso/sso-form.tsx b/apps/sim/app/(auth)/sso/sso-form.tsx index 1fb6544487..497a4d8c27 100644 --- a/apps/sim/app/(auth)/sso/sso-form.tsx +++ b/apps/sim/app/(auth)/sso/sso-form.tsx @@ -11,8 +11,8 @@ import { quickValidateEmail } from '@/lib/email/validation' import { env, isFalsy } from '@/lib/env' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' const logger = createLogger('SSOForm') diff --git a/apps/sim/app/(auth)/verify/verify-content.tsx b/apps/sim/app/(auth)/verify/verify-content.tsx index 2ebdb4944f..d622f4257d 100644 --- a/apps/sim/app/(auth)/verify/verify-content.tsx +++ b/apps/sim/app/(auth)/verify/verify-content.tsx @@ -5,9 +5,9 @@ import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp' import { cn } from '@/lib/utils' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import { useVerification } from '@/app/(auth)/verify/use-verification' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' interface VerifyContentProps { hasEmailService: boolean diff --git a/apps/sim/app/(landing)/careers/page.tsx b/apps/sim/app/(landing)/careers/page.tsx index 15640865bd..f531615264 100644 --- a/apps/sim/app/(landing)/careers/page.tsx +++ b/apps/sim/app/(landing)/careers/page.tsx @@ -17,9 +17,9 @@ import { quickValidateEmail } from '@/lib/email/validation' import { isHosted } from '@/lib/environment' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import Footer from '@/app/(landing)/components/footer/footer' import Nav from '@/app/(landing)/components/nav/nav' -import { soehne } from '@/app/fonts/soehne/soehne' const logger = createLogger('CareersPage') diff --git a/apps/sim/app/(landing)/components/footer/footer.tsx b/apps/sim/app/(landing)/components/footer/footer.tsx index acccebef0e..11a7446175 100644 --- a/apps/sim/app/(landing)/components/footer/footer.tsx +++ b/apps/sim/app/(landing)/components/footer/footer.tsx @@ -7,7 +7,7 @@ import { LinkedInIcon, xIcon as XIcon, } from '@/components/icons' -import { inter } from '@/app/fonts/inter/inter' +import { inter } from '@/app/_styles/fonts/inter/inter' const blocks = [ 'Agent', diff --git a/apps/sim/app/(landing)/components/hero/components/index.ts b/apps/sim/app/(landing)/components/hero/components/index.ts index 067f6bdcb5..6bda3e756c 100644 --- a/apps/sim/app/(landing)/components/hero/components/index.ts +++ b/apps/sim/app/(landing)/components/hero/components/index.ts @@ -1,11 +1,9 @@ -// Hero Components export { IconButton } from './icon-button' export { DotPattern } from './landing-canvas/dot-pattern' export type { LandingBlockProps, LandingCardData, } from './landing-canvas/landing-block/landing-block' -// Landing Block export { LandingBlock } from './landing-canvas/landing-block/landing-block' export type { LoopNodeData } from './landing-canvas/landing-block/landing-loop-node' export { LandingLoopNode } from './landing-canvas/landing-block/landing-loop-node' @@ -22,9 +20,7 @@ export type { LandingManualBlock, LandingViewportApi, } from './landing-canvas/landing-canvas' -// Landing Canvas export { CARD_HEIGHT, CARD_WIDTH, LandingCanvas } from './landing-canvas/landing-canvas' -// Landing Edge export { LandingEdge } from './landing-canvas/landing-edge/landing-edge' export type { LandingFlowProps } from './landing-canvas/landing-flow' export { LandingFlow } from './landing-canvas/landing-flow' diff --git a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-block.tsx b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-block.tsx index eb6212cb8c..7233eeed30 100644 --- a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-block.tsx +++ b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-block.tsx @@ -1,6 +1,9 @@ import React from 'react' import { BookIcon } from 'lucide-react' -import { Tag, type TagProps } from './tag' +import { + Tag, + type TagProps, +} from '@/app/(landing)/components/hero/components/landing-canvas/landing-block/tag' /** * Data structure for a landing card component diff --git a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-loop-node.tsx b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-loop-node.tsx index 1cdcaa3b95..af5f19dc18 100644 --- a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-loop-node.tsx +++ b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-loop-node.tsx @@ -1,7 +1,7 @@ 'use client' import React from 'react' -import { LoopBlock } from './loop-block' +import { LoopBlock } from '@/app/(landing)/components/hero/components/landing-canvas/landing-block/loop-block' /** * Data structure for the loop node diff --git a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-node.tsx b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-node.tsx index 7ca7e4df3b..3ef3eb9878 100644 --- a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-node.tsx +++ b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-node.tsx @@ -2,7 +2,10 @@ import React from 'react' import { Handle, Position } from 'reactflow' -import { LandingBlock, type LandingCardData } from './landing-block' +import { + LandingBlock, + type LandingCardData, +} from '@/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-block' /** * React Flow node component for the landing canvas diff --git a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-canvas.tsx b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-canvas.tsx index 1f7dad539d..0cb2f41e10 100644 --- a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-canvas.tsx +++ b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-canvas.tsx @@ -3,9 +3,9 @@ import React from 'react' import type { Edge, Node } from 'reactflow' import { ReactFlowProvider } from 'reactflow' -import { DotPattern } from './dot-pattern' -import type { LandingCardData } from './landing-block/landing-block' -import { LandingFlow } from './landing-flow' +import { DotPattern } from '@/app/(landing)/components/hero/components/landing-canvas/dot-pattern' +import type { LandingCardData } from '@/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-block' +import { LandingFlow } from '@/app/(landing)/components/hero/components/landing-canvas/landing-flow' /** * Visual constants for landing node dimensions diff --git a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-flow.tsx b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-flow.tsx index 5f856f6eb6..c63cba043a 100644 --- a/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-flow.tsx +++ b/apps/sim/app/(landing)/components/hero/components/landing-canvas/landing-flow.tsx @@ -3,10 +3,13 @@ import React from 'react' import ReactFlow, { applyNodeChanges, type NodeChange, useReactFlow } from 'reactflow' import 'reactflow/dist/style.css' -import { LandingLoopNode } from './landing-block/landing-loop-node' -import { LandingNode } from './landing-block/landing-node' -import { CARD_WIDTH, type LandingCanvasProps } from './landing-canvas' -import { LandingEdge } from './landing-edge/landing-edge' +import { LandingLoopNode } from '@/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-loop-node' +import { LandingNode } from '@/app/(landing)/components/hero/components/landing-canvas/landing-block/landing-node' +import { + CARD_WIDTH, + type LandingCanvasProps, +} from '@/app/(landing)/components/hero/components/landing-canvas/landing-canvas' +import { LandingEdge } from '@/app/(landing)/components/hero/components/landing-canvas/landing-edge/landing-edge' /** * Props for the LandingFlow component diff --git a/apps/sim/app/(landing)/components/hero/hero.tsx b/apps/sim/app/(landing)/components/hero/hero.tsx index 1b274ea33b..c925147e6f 100644 --- a/apps/sim/app/(landing)/components/hero/hero.tsx +++ b/apps/sim/app/(landing)/components/hero/hero.tsx @@ -33,7 +33,7 @@ import { SupabaseIcon, } from '@/components/icons' import { LandingPromptStorage } from '@/lib/browser-storage' -import { soehne } from '@/app/fonts/soehne/soehne' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import { CARD_WIDTH, IconButton, @@ -41,7 +41,7 @@ import { type LandingGroupData, type LandingManualBlock, type LandingViewportApi, -} from './components' +} from '@/app/(landing)/components/hero/components' /** * Service-specific template messages for the hero input diff --git a/apps/sim/app/(landing)/components/integrations/integrations.tsx b/apps/sim/app/(landing)/components/integrations/integrations.tsx index df29c8d975..5da1786bb2 100644 --- a/apps/sim/app/(landing)/components/integrations/integrations.tsx +++ b/apps/sim/app/(landing)/components/integrations/integrations.tsx @@ -1,5 +1,5 @@ import * as Icons from '@/components/icons' -import { inter } from '@/app/fonts/inter/inter' +import { inter } from '@/app/_styles/fonts/inter/inter' const modelProviderIcons = [ { icon: Icons.OpenAIIcon, label: 'OpenAI' }, diff --git a/apps/sim/app/(landing)/components/landing-pricing/landing-pricing.tsx b/apps/sim/app/(landing)/components/landing-pricing/landing-pricing.tsx index 647688f16e..012f5b6de7 100644 --- a/apps/sim/app/(landing)/components/landing-pricing/landing-pricing.tsx +++ b/apps/sim/app/(landing)/components/landing-pricing/landing-pricing.tsx @@ -14,7 +14,7 @@ import { import { useRouter } from 'next/navigation' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' -import { inter } from '@/app/fonts/inter/inter' +import { inter } from '@/app/_styles/fonts/inter/inter' import { ENTERPRISE_PLAN_FEATURES, PRO_PLAN_FEATURES, diff --git a/apps/sim/app/(landing)/components/landing-templates/components/landing-template-preview.tsx b/apps/sim/app/(landing)/components/landing-templates/components/landing-template-preview.tsx index 287a6d060e..4acf9fbd52 100644 --- a/apps/sim/app/(landing)/components/landing-templates/components/landing-template-preview.tsx +++ b/apps/sim/app/(landing)/components/landing-templates/components/landing-template-preview.tsx @@ -1,4 +1,4 @@ -import { inter } from '@/app/fonts/inter/inter' +import { inter } from '@/app/_styles/fonts/inter/inter' interface LandingTemplatePreviewProps { previewImage: string diff --git a/apps/sim/app/(landing)/components/landing-templates/landing-templates.tsx b/apps/sim/app/(landing)/components/landing-templates/landing-templates.tsx index 91c047ea4e..343511b27f 100644 --- a/apps/sim/app/(landing)/components/landing-templates/landing-templates.tsx +++ b/apps/sim/app/(landing)/components/landing-templates/landing-templates.tsx @@ -1,7 +1,6 @@ -import { inter } from '@/app/fonts/inter/inter' -import LandingTemplatePreview from './components/landing-template-preview' +import { inter } from '@/app/_styles/fonts/inter/inter' +import LandingTemplatePreview from '@/app/(landing)/components/landing-templates/components/landing-template-preview' -// Mock data for templates const templates = [ { id: 1, diff --git a/apps/sim/app/(landing)/components/legal-layout.tsx b/apps/sim/app/(landing)/components/legal-layout.tsx index 203eaeb637..d817fd60f5 100644 --- a/apps/sim/app/(landing)/components/legal-layout.tsx +++ b/apps/sim/app/(landing)/components/legal-layout.tsx @@ -1,9 +1,9 @@ 'use client' import { isHosted } from '@/lib/environment' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import Footer from '@/app/(landing)/components/footer/footer' import Nav from '@/app/(landing)/components/nav/nav' -import { soehne } from '@/app/fonts/soehne/soehne' interface LegalLayoutProps { title: string diff --git a/apps/sim/app/(landing)/components/nav/nav.tsx b/apps/sim/app/(landing)/components/nav/nav.tsx index dbf722e488..cb5010a4ab 100644 --- a/apps/sim/app/(landing)/components/nav/nav.tsx +++ b/apps/sim/app/(landing)/components/nav/nav.tsx @@ -9,8 +9,8 @@ import { GithubIcon } from '@/components/icons' import { useBrandConfig } from '@/lib/branding/branding' import { isHosted } from '@/lib/environment' import { createLogger } from '@/lib/logs/console/logger' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import { getFormattedGitHubStars } from '@/app/(landing)/actions/github' -import { soehne } from '@/app/fonts/soehne/soehne' const logger = createLogger('nav') diff --git a/apps/sim/app/(landing)/components/structured-data.tsx b/apps/sim/app/(landing)/components/structured-data.tsx index e83f81e02d..5afc2caa57 100644 --- a/apps/sim/app/(landing)/components/structured-data.tsx +++ b/apps/sim/app/(landing)/components/structured-data.tsx @@ -38,7 +38,7 @@ export default function StructuredData() { url: 'https://sim.ai', name: 'Sim - AI Agent Workflow Builder', description: - 'Open-source AI agent workflow builder. 50,000+ developers build and deploy agentic workflows. SOC2 and HIPAA compliant.', + 'Open-source AI agent workflow builder. 60,000+ developers build and deploy agentic workflows. SOC2 and HIPAA compliant.', publisher: { '@id': 'https://sim.ai/#organization', }, @@ -98,7 +98,7 @@ export default function StructuredData() { '@id': 'https://sim.ai/#software', name: 'Sim - AI Agent Workflow Builder', description: - 'Open-source AI agent workflow builder used by 50,000+ developers. Build agentic workflows with visual drag-and-drop interface. SOC2 and HIPAA compliant. Integrate with 100+ apps.', + 'Open-source AI agent workflow builder used by 60,000+ developers. Build agentic workflows with visual drag-and-drop interface. SOC2 and HIPAA compliant. Integrate with 100+ apps.', applicationCategory: 'DeveloperApplication', applicationSubCategory: 'AI Development Tools', operatingSystem: 'Web, Windows, macOS, Linux', @@ -198,7 +198,7 @@ export default function StructuredData() { name: 'What is Sim?', acceptedAnswer: { '@type': 'Answer', - text: 'Sim is an open-source AI agent workflow builder used by 50,000+ developers at trail-blazing startups to Fortune 500 companies. It provides a visual drag-and-drop interface for building and deploying agentic workflows. Sim is SOC2 and HIPAA compliant.', + text: 'Sim is an open-source AI agent workflow builder used by 60,000+ developers at trail-blazing startups to Fortune 500 companies. It provides a visual drag-and-drop interface for building and deploying agentic workflows. Sim is SOC2 and HIPAA compliant.', }, }, { diff --git a/apps/sim/app/(landing)/components/testimonials/testimonials.tsx b/apps/sim/app/(landing)/components/testimonials/testimonials.tsx index 359924613d..3542e20332 100644 --- a/apps/sim/app/(landing)/components/testimonials/testimonials.tsx +++ b/apps/sim/app/(landing)/components/testimonials/testimonials.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react' import Image from 'next/image' -import { inter } from '@/app/fonts/inter/inter' +import { inter } from '@/app/_styles/fonts/inter/inter' interface Testimonial { text: string diff --git a/apps/sim/app/(landing)/studio/[slug]/page.tsx b/apps/sim/app/(landing)/studio/[slug]/page.tsx index 85b8043bce..db5092b297 100644 --- a/apps/sim/app/(landing)/studio/[slug]/page.tsx +++ b/apps/sim/app/(landing)/studio/[slug]/page.tsx @@ -5,7 +5,7 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { FAQ } from '@/lib/blog/faq' import { getAllPostMeta, getPostBySlug, getRelatedPosts } from '@/lib/blog/registry' import { buildArticleJsonLd, buildBreadcrumbJsonLd, buildPostMetadata } from '@/lib/blog/seo' -import { soehne } from '@/app/fonts/soehne/soehne' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' export async function generateStaticParams() { const posts = await getAllPostMeta() diff --git a/apps/sim/app/(landing)/studio/authors/[id]/page.tsx b/apps/sim/app/(landing)/studio/authors/[id]/page.tsx index 0a6b0fe529..6a4f0c9b33 100644 --- a/apps/sim/app/(landing)/studio/authors/[id]/page.tsx +++ b/apps/sim/app/(landing)/studio/authors/[id]/page.tsx @@ -1,7 +1,7 @@ import Image from 'next/image' import Link from 'next/link' import { getAllPostMeta } from '@/lib/blog/registry' -import { soehne } from '@/app/fonts/soehne/soehne' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' export const revalidate = 3600 diff --git a/apps/sim/app/(landing)/studio/page.tsx b/apps/sim/app/(landing)/studio/page.tsx index 4acd4d48b9..76c51fc83d 100644 --- a/apps/sim/app/(landing)/studio/page.tsx +++ b/apps/sim/app/(landing)/studio/page.tsx @@ -2,7 +2,7 @@ import Image from 'next/image' import Link from 'next/link' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { getAllPostMeta } from '@/lib/blog/registry' -import { soehne } from '@/app/fonts/soehne/soehne' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' export const revalidate = 3600 diff --git a/apps/sim/app/hydration-error-handler.tsx b/apps/sim/app/_shell/hydration-error-handler.tsx similarity index 100% rename from apps/sim/app/hydration-error-handler.tsx rename to apps/sim/app/_shell/hydration-error-handler.tsx diff --git a/apps/sim/lib/posthog/provider.tsx b/apps/sim/app/_shell/providers/posthog-provider.tsx similarity index 96% rename from apps/sim/lib/posthog/provider.tsx rename to apps/sim/app/_shell/providers/posthog-provider.tsx index b2cc8c0619..01261cbeba 100644 --- a/apps/sim/lib/posthog/provider.tsx +++ b/apps/sim/app/_shell/providers/posthog-provider.tsx @@ -3,7 +3,7 @@ import { useEffect } from 'react' import posthog from 'posthog-js' import { PostHogProvider as PHProvider } from 'posthog-js/react' -import { getEnv, isTruthy } from '../env' +import { getEnv, isTruthy } from '../../../lib/env' export function PostHogProvider({ children }: { children: React.ReactNode }) { useEffect(() => { diff --git a/apps/sim/app/providers/query-client-provider.tsx b/apps/sim/app/_shell/providers/query-provider.tsx similarity index 100% rename from apps/sim/app/providers/query-client-provider.tsx rename to apps/sim/app/_shell/providers/query-provider.tsx diff --git a/apps/sim/lib/session/session-context.tsx b/apps/sim/app/_shell/providers/session-provider.tsx similarity index 100% rename from apps/sim/lib/session/session-context.tsx rename to apps/sim/app/_shell/providers/session-provider.tsx diff --git a/apps/sim/app/theme-provider.tsx b/apps/sim/app/_shell/providers/theme-provider.tsx similarity index 100% rename from apps/sim/app/theme-provider.tsx rename to apps/sim/app/_shell/providers/theme-provider.tsx diff --git a/apps/sim/app/zoom-prevention.tsx b/apps/sim/app/_shell/zoom-prevention.tsx similarity index 100% rename from apps/sim/app/zoom-prevention.tsx rename to apps/sim/app/_shell/zoom-prevention.tsx diff --git a/apps/sim/app/fonts/inter/inter.ts b/apps/sim/app/_styles/fonts/inter/inter.ts similarity index 100% rename from apps/sim/app/fonts/inter/inter.ts rename to apps/sim/app/_styles/fonts/inter/inter.ts diff --git a/apps/sim/app/fonts/season/SeasonSans-Bold.woff b/apps/sim/app/_styles/fonts/season/SeasonSans-Bold.woff similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Bold.woff rename to apps/sim/app/_styles/fonts/season/SeasonSans-Bold.woff diff --git a/apps/sim/app/fonts/season/SeasonSans-Bold.woff2 b/apps/sim/app/_styles/fonts/season/SeasonSans-Bold.woff2 similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Bold.woff2 rename to apps/sim/app/_styles/fonts/season/SeasonSans-Bold.woff2 diff --git a/apps/sim/app/fonts/season/SeasonSans-Heavy.woff b/apps/sim/app/_styles/fonts/season/SeasonSans-Heavy.woff similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Heavy.woff rename to apps/sim/app/_styles/fonts/season/SeasonSans-Heavy.woff diff --git a/apps/sim/app/fonts/season/SeasonSans-Heavy.woff2 b/apps/sim/app/_styles/fonts/season/SeasonSans-Heavy.woff2 similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Heavy.woff2 rename to apps/sim/app/_styles/fonts/season/SeasonSans-Heavy.woff2 diff --git a/apps/sim/app/fonts/season/SeasonSans-Light.woff b/apps/sim/app/_styles/fonts/season/SeasonSans-Light.woff similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Light.woff rename to apps/sim/app/_styles/fonts/season/SeasonSans-Light.woff diff --git a/apps/sim/app/fonts/season/SeasonSans-Light.woff2 b/apps/sim/app/_styles/fonts/season/SeasonSans-Light.woff2 similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Light.woff2 rename to apps/sim/app/_styles/fonts/season/SeasonSans-Light.woff2 diff --git a/apps/sim/app/fonts/season/SeasonSans-Medium.woff b/apps/sim/app/_styles/fonts/season/SeasonSans-Medium.woff similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Medium.woff rename to apps/sim/app/_styles/fonts/season/SeasonSans-Medium.woff diff --git a/apps/sim/app/fonts/season/SeasonSans-Medium.woff2 b/apps/sim/app/_styles/fonts/season/SeasonSans-Medium.woff2 similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Medium.woff2 rename to apps/sim/app/_styles/fonts/season/SeasonSans-Medium.woff2 diff --git a/apps/sim/app/fonts/season/SeasonSans-Regular.woff b/apps/sim/app/_styles/fonts/season/SeasonSans-Regular.woff similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Regular.woff rename to apps/sim/app/_styles/fonts/season/SeasonSans-Regular.woff diff --git a/apps/sim/app/fonts/season/SeasonSans-Regular.woff2 b/apps/sim/app/_styles/fonts/season/SeasonSans-Regular.woff2 similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-Regular.woff2 rename to apps/sim/app/_styles/fonts/season/SeasonSans-Regular.woff2 diff --git a/apps/sim/app/fonts/season/SeasonSans-SemiBold.woff b/apps/sim/app/_styles/fonts/season/SeasonSans-SemiBold.woff similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-SemiBold.woff rename to apps/sim/app/_styles/fonts/season/SeasonSans-SemiBold.woff diff --git a/apps/sim/app/fonts/season/SeasonSans-SemiBold.woff2 b/apps/sim/app/_styles/fonts/season/SeasonSans-SemiBold.woff2 similarity index 100% rename from apps/sim/app/fonts/season/SeasonSans-SemiBold.woff2 rename to apps/sim/app/_styles/fonts/season/SeasonSans-SemiBold.woff2 diff --git a/apps/sim/app/fonts/season/SeasonSansUprightsVF.woff b/apps/sim/app/_styles/fonts/season/SeasonSansUprightsVF.woff similarity index 100% rename from apps/sim/app/fonts/season/SeasonSansUprightsVF.woff rename to apps/sim/app/_styles/fonts/season/SeasonSansUprightsVF.woff diff --git a/apps/sim/app/fonts/season/SeasonSansUprightsVF.woff2 b/apps/sim/app/_styles/fonts/season/SeasonSansUprightsVF.woff2 similarity index 100% rename from apps/sim/app/fonts/season/SeasonSansUprightsVF.woff2 rename to apps/sim/app/_styles/fonts/season/SeasonSansUprightsVF.woff2 diff --git a/apps/sim/app/fonts/season/season.ts b/apps/sim/app/_styles/fonts/season/season.ts similarity index 100% rename from apps/sim/app/fonts/season/season.ts rename to apps/sim/app/_styles/fonts/season/season.ts diff --git a/apps/sim/app/fonts/soehne/soehne-buch-kursiv.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-buch-kursiv.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-buch-kursiv.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-buch-kursiv.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-buch.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-buch.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-buch.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-buch.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-dreiviertelfett-kursiv.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-dreiviertelfett-kursiv.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-dreiviertelfett-kursiv.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-dreiviertelfett-kursiv.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-dreiviertelfett.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-dreiviertelfett.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-dreiviertelfett.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-dreiviertelfett.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-halbfett-kursiv.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-halbfett-kursiv.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-halbfett-kursiv.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-halbfett-kursiv.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-halbfett.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-halbfett.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-halbfett.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-halbfett.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-kraftig-kursiv.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-kraftig-kursiv.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-kraftig-kursiv.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-kraftig-kursiv.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-kraftig.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-kraftig.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-kraftig.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-kraftig.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-leicht-kursiv.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-leicht-kursiv.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-leicht-kursiv.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-leicht-kursiv.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne-leicht.woff2 b/apps/sim/app/_styles/fonts/soehne/soehne-leicht.woff2 similarity index 100% rename from apps/sim/app/fonts/soehne/soehne-leicht.woff2 rename to apps/sim/app/_styles/fonts/soehne/soehne-leicht.woff2 diff --git a/apps/sim/app/fonts/soehne/soehne.ts b/apps/sim/app/_styles/fonts/soehne/soehne.ts similarity index 100% rename from apps/sim/app/fonts/soehne/soehne.ts rename to apps/sim/app/_styles/fonts/soehne/soehne.ts diff --git a/apps/sim/app/globals.css b/apps/sim/app/_styles/globals.css similarity index 100% rename from apps/sim/app/globals.css rename to apps/sim/app/_styles/globals.css diff --git a/apps/sim/types/creator-profile.ts b/apps/sim/app/_types/creator-profile.ts similarity index 100% rename from apps/sim/types/creator-profile.ts rename to apps/sim/app/_types/creator-profile.ts diff --git a/apps/sim/app/api/chat/[identifier]/route.test.ts b/apps/sim/app/api/chat/[identifier]/route.test.ts index c95102cf88..f872e35ee6 100644 --- a/apps/sim/app/api/chat/[identifier]/route.test.ts +++ b/apps/sim/app/api/chat/[identifier]/route.test.ts @@ -6,6 +6,36 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { createMockRequest } from '@/app/api/__test-utils__/utils' +vi.mock('@/lib/execution/preprocessing', () => ({ + preprocessExecution: vi.fn().mockResolvedValue({ + success: true, + actorUserId: 'test-user-id', + workflowRecord: { + id: 'test-workflow-id', + userId: 'test-user-id', + isDeployed: true, + workspaceId: 'test-workspace-id', + variables: {}, + }, + userSubscription: { + plan: 'pro', + status: 'active', + }, + rateLimitInfo: { + allowed: true, + remaining: 100, + resetAt: new Date(), + }, + }), +})) + +vi.mock('@/lib/logs/execution/logging-session', () => ({ + LoggingSession: vi.fn().mockImplementation(() => ({ + safeStart: vi.fn().mockResolvedValue(undefined), + safeCompleteWithError: vi.fn().mockResolvedValue(undefined), + })), +})) + describe('Chat Identifier API Route', () => { const createMockStream = () => { return new ReadableStream({ @@ -307,48 +337,16 @@ describe('Chat Identifier API Route', () => { }) it('should return 503 when workflow is not available', async () => { - // Override the default workflow result to return non-deployed - vi.doMock('@sim/db', () => { - // Track call count to return different results - let callCount = 0 - - const mockLimit = vi.fn().mockImplementation(() => { - callCount++ - if (callCount === 1) { - // First call - chat query - return [ - { - id: 'chat-id', - workflowId: 'unavailable-workflow', - userId: 'user-id', - isActive: true, - authType: 'public', - outputConfigs: [{ blockId: 'block-1', path: 'output' }], - }, - ] - } - if (callCount === 2) { - // Second call - workflow query - return [ - { - isDeployed: false, - }, - ] - } - return [] - }) - - const mockWhere = vi.fn().mockReturnValue({ limit: mockLimit }) - const mockFrom = vi.fn().mockReturnValue({ where: mockWhere }) - const mockSelect = vi.fn().mockReturnValue({ from: mockFrom }) - - return { - db: { - select: mockSelect, - }, - chat: {}, - workflow: {}, - } + const { preprocessExecution } = await import('@/lib/execution/preprocessing') + const originalImplementation = vi.mocked(preprocessExecution).getMockImplementation() + + vi.mocked(preprocessExecution).mockResolvedValueOnce({ + success: false, + error: { + message: 'Workflow is not deployed', + statusCode: 403, + logCreated: true, + }, }) const req = createMockRequest('POST', { input: 'Hello' }) @@ -358,11 +356,15 @@ describe('Chat Identifier API Route', () => { const response = await POST(req, { params }) - expect(response.status).toBe(503) + expect(response.status).toBe(403) const data = await response.json() expect(data).toHaveProperty('error') - expect(data).toHaveProperty('message', 'Chat workflow is not available') + expect(data).toHaveProperty('message', 'Workflow is not deployed') + + if (originalImplementation) { + vi.mocked(preprocessExecution).mockImplementation(originalImplementation) + } }) it('should return streaming response for valid chat messages', async () => { @@ -378,7 +380,6 @@ describe('Chat Identifier API Route', () => { expect(response.headers.get('Cache-Control')).toBe('no-cache') expect(response.headers.get('Connection')).toBe('keep-alive') - // Verify createStreamingResponse was called with correct workflow info expect(mockCreateStreamingResponse).toHaveBeenCalledWith( expect.objectContaining({ workflow: expect.objectContaining({ @@ -408,7 +409,6 @@ describe('Chat Identifier API Route', () => { expect(response.status).toBe(200) expect(response.body).toBeInstanceOf(ReadableStream) - // Test that we can read from the response stream if (response.body) { const reader = response.body.getReader() const { value, done } = await reader.read() @@ -447,7 +447,6 @@ describe('Chat Identifier API Route', () => { }) it('should handle invalid JSON in request body', async () => { - // Create a request with invalid JSON const req = { method: 'POST', headers: new Headers(), diff --git a/apps/sim/app/api/chat/[identifier]/route.ts b/apps/sim/app/api/chat/[identifier]/route.ts index e9d8cdd8bd..cac8f60dff 100644 --- a/apps/sim/app/api/chat/[identifier]/route.ts +++ b/apps/sim/app/api/chat/[identifier]/route.ts @@ -1,9 +1,10 @@ +import { randomUUID } from 'crypto' import { db } from '@sim/db' -import { chat, workflow, workspace } from '@sim/db/schema' +import { chat } from '@sim/db/schema' import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { z } from 'zod' +import { preprocessExecution } from '@/lib/execution/preprocessing' import { createLogger } from '@/lib/logs/console/logger' import { LoggingSession } from '@/lib/logs/execution/logging-session' import { ChatFiles } from '@/lib/uploads' @@ -93,7 +94,7 @@ export async function POST( if (!deployment.isActive) { logger.warn(`[${requestId}] Chat is not active: ${identifier}`) - const executionId = uuidv4() + const executionId = randomUUID() const loggingSession = new LoggingSession( deployment.workflowId, executionId, @@ -140,82 +141,35 @@ export async function POST( return addCorsHeaders(createErrorResponse('No input provided', 400), request) } - const workflowResult = await db - .select({ - isDeployed: workflow.isDeployed, - workspaceId: workflow.workspaceId, - variables: workflow.variables, - }) - .from(workflow) - .where(eq(workflow.id, deployment.workflowId)) - .limit(1) + const executionId = randomUUID() - if (workflowResult.length === 0 || !workflowResult[0].isDeployed) { - logger.warn(`[${requestId}] Workflow not found or not deployed: ${deployment.workflowId}`) - - const executionId = uuidv4() - const loggingSession = new LoggingSession( - deployment.workflowId, - executionId, - 'chat', - requestId - ) + const loggingSession = new LoggingSession(deployment.workflowId, executionId, 'chat', requestId) - await loggingSession.safeStart({ - userId: deployment.userId, - workspaceId: workflowResult[0]?.workspaceId || '', - variables: {}, - }) + const preprocessResult = await preprocessExecution({ + workflowId: deployment.workflowId, + userId: deployment.userId, + triggerType: 'chat', + executionId, + requestId, + checkRateLimit: false, // Chat bypasses rate limits + checkDeployment: true, // Chat requires deployed workflows + loggingSession, + }) - await loggingSession.safeCompleteWithError({ - error: { - message: 'Chat workflow is not available. The workflow is not deployed.', - stackTrace: undefined, - }, - traceSpans: [], - }) - - return addCorsHeaders(createErrorResponse('Chat workflow is not available', 503), request) + if (!preprocessResult.success) { + logger.warn(`[${requestId}] Preprocessing failed: ${preprocessResult.error?.message}`) + return addCorsHeaders( + createErrorResponse( + preprocessResult.error?.message || 'Failed to process request', + preprocessResult.error?.statusCode || 500 + ), + request + ) } - let workspaceOwnerId = deployment.userId - if (workflowResult[0].workspaceId) { - const workspaceData = await db - .select({ ownerId: workspace.ownerId }) - .from(workspace) - .where(eq(workspace.id, workflowResult[0].workspaceId)) - .limit(1) - - if (workspaceData.length === 0) { - logger.error(`[${requestId}] Workspace not found for workflow ${deployment.workflowId}`) - - const executionId = uuidv4() - const loggingSession = new LoggingSession( - deployment.workflowId, - executionId, - 'chat', - requestId - ) - - await loggingSession.safeStart({ - userId: deployment.userId, - workspaceId: workflowResult[0].workspaceId || '', - variables: {}, - }) - - await loggingSession.safeCompleteWithError({ - error: { - message: 'Workspace not found. Critical configuration error - please contact support.', - stackTrace: undefined, - }, - traceSpans: [], - }) - - return addCorsHeaders(createErrorResponse('Workspace not found', 500), request) - } - - workspaceOwnerId = workspaceData[0].ownerId - } + const { actorUserId, workflowRecord } = preprocessResult + const workspaceOwnerId = actorUserId! + const workspaceId = workflowRecord?.workspaceId || '' try { const selectedOutputs: string[] = [] @@ -232,12 +186,10 @@ export async function POST( const { SSE_HEADERS } = await import('@/lib/utils') const { createFilteredResult } = await import('@/app/api/workflows/[id]/execute/route') - const executionId = crypto.randomUUID() - const workflowInput: any = { input, conversationId } if (files && Array.isArray(files) && files.length > 0) { const executionContext = { - workspaceId: workflowResult[0].workspaceId || '', + workspaceId, workflowId: deployment.workflowId, executionId, } @@ -257,20 +209,13 @@ export async function POST( } catch (fileError: any) { logger.error(`[${requestId}] Failed to process chat files:`, fileError) - const fileLoggingSession = new LoggingSession( - deployment.workflowId, - executionId, - 'chat', - requestId - ) - - await fileLoggingSession.safeStart({ + await loggingSession.safeStart({ userId: workspaceOwnerId, - workspaceId: workflowResult[0].workspaceId || '', + workspaceId, variables: {}, }) - await fileLoggingSession.safeCompleteWithError({ + await loggingSession.safeCompleteWithError({ error: { message: `File upload failed: ${fileError.message || 'Unable to process uploaded files'}`, stackTrace: fileError.stack, @@ -285,9 +230,9 @@ export async function POST( const workflowForExecution = { id: deployment.workflowId, userId: deployment.userId, - workspaceId: workflowResult[0].workspaceId, - isDeployed: true, - variables: workflowResult[0].variables || {}, + workspaceId, + isDeployed: workflowRecord?.isDeployed ?? false, + variables: workflowRecord?.variables || {}, } const stream = await createStreamingResponse({ diff --git a/apps/sim/app/api/chat/manage/[id]/route.test.ts b/apps/sim/app/api/chat/manage/[id]/route.test.ts index 84e297507d..9cd7a9a4e4 100644 --- a/apps/sim/app/api/chat/manage/[id]/route.test.ts +++ b/apps/sim/app/api/chat/manage/[id]/route.test.ts @@ -19,6 +19,7 @@ describe('Chat Edit API Route', () => { const mockCreateErrorResponse = vi.fn() const mockEncryptSecret = vi.fn() const mockCheckChatAccess = vi.fn() + const mockGetSession = vi.fn() beforeEach(() => { vi.resetModules() @@ -42,6 +43,10 @@ describe('Chat Edit API Route', () => { chat: { id: 'id', identifier: 'identifier', userId: 'userId' }, })) + vi.doMock('@/lib/auth', () => ({ + getSession: mockGetSession, + })) + vi.doMock('@/lib/logs/console/logger', () => ({ createLogger: vi.fn().mockReturnValue({ info: vi.fn(), @@ -89,9 +94,7 @@ describe('Chat Edit API Route', () => { describe('GET', () => { it('should return 401 when user is not authenticated', async () => { - vi.doMock('@/lib/auth', () => ({ - getSession: vi.fn().mockResolvedValue(null), - })) + mockGetSession.mockResolvedValueOnce(null) const req = new NextRequest('http://localhost:3000/api/chat/manage/chat-123') const { GET } = await import('@/app/api/chat/manage/[id]/route') @@ -102,11 +105,9 @@ describe('Chat Edit API Route', () => { }) it('should return 404 when chat not found or access denied', async () => { - vi.doMock('@/lib/auth', () => ({ - getSession: vi.fn().mockResolvedValue({ - user: { id: 'user-id' }, - }), - })) + mockGetSession.mockResolvedValueOnce({ + user: { id: 'user-id' }, + }) mockCheckChatAccess.mockResolvedValue({ hasAccess: false }) diff --git a/apps/sim/app/api/chat/utils.test.ts b/apps/sim/app/api/chat/utils.test.ts index 30ec46c628..bc7bca71a2 100644 --- a/apps/sim/app/api/chat/utils.test.ts +++ b/apps/sim/app/api/chat/utils.test.ts @@ -71,13 +71,13 @@ describe('Chat API Utils', () => { }) describe('Auth token utils', () => { - it('should encrypt and validate auth tokens', async () => { - const { encryptAuthToken, validateAuthToken } = await import('@/app/api/chat/utils') + it('should validate auth tokens', async () => { + const { validateAuthToken } = await import('@/app/api/chat/utils') const chatId = 'test-chat-id' const type = 'password' - const token = encryptAuthToken(chatId, type) + const token = Buffer.from(`${chatId}:${type}:${Date.now()}`).toString('base64') expect(typeof token).toBe('string') expect(token.length).toBeGreaterThan(0) @@ -92,7 +92,6 @@ describe('Chat API Utils', () => { const { validateAuthToken } = await import('@/app/api/chat/utils') const chatId = 'test-chat-id' - // Create an expired token by directly constructing it with an old timestamp const expiredToken = Buffer.from( `${chatId}:password:${Date.now() - 25 * 60 * 60 * 1000}` ).toString('base64') @@ -166,20 +165,6 @@ describe('Chat API Utils', () => { 'Content-Type, X-Requested-With' ) }) - - it('should handle OPTIONS request', async () => { - const { OPTIONS } = await import('@/app/api/chat/utils') - - const mockRequest = { - headers: { - get: vi.fn().mockReturnValue('http://localhost:3000'), - }, - } as any - - const response = await OPTIONS(mockRequest) - - expect(response.status).toBe(204) - }) }) describe('Chat auth validation', () => { @@ -355,10 +340,8 @@ describe('Chat API Utils', () => { describe('Execution Result Processing', () => { it('should process logs regardless of overall success status', () => { - // Test that logs are processed even when overall execution fails - // This is key for partial success scenarios const executionResult = { - success: false, // Overall execution failed + success: false, output: {}, logs: [ { @@ -383,16 +366,13 @@ describe('Chat API Utils', () => { metadata: { duration: 1000 }, } - // Test the key logic: logs should be processed regardless of overall success expect(executionResult.success).toBe(false) expect(executionResult.logs).toBeDefined() expect(executionResult.logs).toHaveLength(2) - // First log should be successful expect(executionResult.logs[0].success).toBe(true) expect(executionResult.logs[0].output?.content).toBe('Agent 1 succeeded') - // Second log should be failed expect(executionResult.logs[1].success).toBe(false) expect(executionResult.logs[1].error).toBe('Agent 2 failed') }) @@ -405,18 +385,15 @@ describe('Chat API Utils', () => { metadata: { duration: 100 }, } - // Test direct ExecutionResult const directResult = executionResult const extractedDirect = directResult expect(extractedDirect).toBe(executionResult) - // Test StreamingExecution with embedded ExecutionResult const streamingResult = { stream: new ReadableStream(), execution: executionResult, } - // Test that streaming execution wraps the result correctly const extractedFromStreaming = streamingResult && typeof streamingResult === 'object' && 'execution' in streamingResult ? streamingResult.execution diff --git a/apps/sim/app/api/chat/utils.ts b/apps/sim/app/api/chat/utils.ts index 1b3b348e69..88c2062f32 100644 --- a/apps/sim/app/api/chat/utils.ts +++ b/apps/sim/app/api/chat/utils.ts @@ -1,7 +1,7 @@ import { db } from '@sim/db' import { chat, workflow } from '@sim/db/schema' import { eq } from 'drizzle-orm' -import { type NextRequest, NextResponse } from 'next/server' +import type { NextRequest, NextResponse } from 'next/server' import { isDev } from '@/lib/environment' import { createLogger } from '@/lib/logs/console/logger' import { hasAdminPermission } from '@/lib/permissions/utils' @@ -77,7 +77,7 @@ export async function checkChatAccess( return { hasAccess: false } } -export const encryptAuthToken = (chatId: string, type: string): string => { +const encryptAuthToken = (chatId: string, type: string): string => { return Buffer.from(`${chatId}:${type}:${Date.now()}`).toString('base64') } @@ -104,7 +104,6 @@ export const validateAuthToken = (token: string, chatId: string): boolean => { } } -// Set cookie helper function export const setChatAuthCookie = (response: NextResponse, chatId: string, type: string): void => { const token = encryptAuthToken(chatId, type) response.cookies.set({ @@ -118,7 +117,6 @@ export const setChatAuthCookie = (response: NextResponse, chatId: string, type: }) } -// Helper function to add CORS headers to responses export function addCorsHeaders(response: NextResponse, request: NextRequest) { const origin = request.headers.get('origin') || '' @@ -132,12 +130,6 @@ export function addCorsHeaders(response: NextResponse, request: NextRequest) { return response } -export async function OPTIONS(request: NextRequest) { - const response = new NextResponse(null, { status: 204 }) - return addCorsHeaders(response, request) -} - -// Validate authentication for chat access export async function validateChatAuth( requestId: string, deployment: any, @@ -146,12 +138,10 @@ export async function validateChatAuth( ): Promise<{ authorized: boolean; error?: string }> { const authType = deployment.authType || 'public' - // Public chats are accessible to everyone if (authType === 'public') { return { authorized: true } } - // Check for auth cookie first const cookieName = `chat_auth_${deployment.id}` const authCookie = request.cookies.get(cookieName) @@ -159,9 +149,7 @@ export async function validateChatAuth( return { authorized: true } } - // For password protection, check the password in the request body if (authType === 'password') { - // For GET requests, we just notify the client that authentication is required if (request.method === 'GET') { return { authorized: false, error: 'auth_required_password' } } @@ -198,22 +186,18 @@ export async function validateChatAuth( } } - // For email access control, check the email in the request body if (authType === 'email') { - // For GET requests, we just notify the client that authentication is required if (request.method === 'GET') { return { authorized: false, error: 'auth_required_email' } } try { - // Use the parsed body if provided, otherwise the auth check is not applicable if (!parsedBody) { return { authorized: false, error: 'Email is required' } } const { email, input } = parsedBody - // If this is a chat message, not an auth attempt if (input && !email) { return { authorized: false, error: 'auth_required_email' } } @@ -224,17 +208,12 @@ export async function validateChatAuth( const allowedEmails = deployment.allowedEmails || [] - // Check exact email matches if (allowedEmails.includes(email)) { - // Email is allowed but still needs OTP verification - // Return a special error code that the client will recognize return { authorized: false, error: 'otp_required' } } - // Check domain matches (prefixed with @) const domain = email.split('@')[1] if (domain && allowedEmails.some((allowed: string) => allowed === `@${domain}`)) { - // Domain is allowed but still needs OTP verification return { authorized: false, error: 'otp_required' } } @@ -257,6 +236,10 @@ export async function validateChatAuth( const { email, input, checkSSOAccess } = parsedBody + if (input && !checkSSOAccess) { + return { authorized: false, error: 'auth_required_sso' } + } + if (checkSSOAccess) { if (!email) { return { authorized: false, error: 'Email is required' } diff --git a/apps/sim/app/api/copilot/chat/route.test.ts b/apps/sim/app/api/copilot/chat/route.test.ts index e2950cced3..80b30dabf5 100644 --- a/apps/sim/app/api/copilot/chat/route.test.ts +++ b/apps/sim/app/api/copilot/chat/route.test.ts @@ -563,6 +563,8 @@ describe('Copilot Chat API Route', () => { ], messageCount: 4, previewYaml: null, + config: null, + planArtifact: null, createdAt: '2024-01-01T00:00:00.000Z', updatedAt: '2024-01-02T00:00:00.000Z', }, @@ -576,6 +578,8 @@ describe('Copilot Chat API Route', () => { ], messageCount: 2, previewYaml: null, + config: null, + planArtifact: null, createdAt: '2024-01-03T00:00:00.000Z', updatedAt: '2024-01-04T00:00:00.000Z', }, diff --git a/apps/sim/app/api/copilot/chat/route.ts b/apps/sim/app/api/copilot/chat/route.ts index 5a90b167bd..9240373cb4 100644 --- a/apps/sim/app/api/copilot/chat/route.ts +++ b/apps/sim/app/api/copilot/chat/route.ts @@ -43,6 +43,12 @@ const ChatMessageSchema = z.object({ 'gpt-5', 'gpt-5-medium', 'gpt-5-high', + 'gpt-5.1-fast', + 'gpt-5.1', + 'gpt-5.1-medium', + 'gpt-5.1-high', + 'gpt-5-codex', + 'gpt-5.1-codex', 'gpt-4o', 'gpt-4.1', 'o3', @@ -53,7 +59,7 @@ const ChatMessageSchema = z.object({ ]) .optional() .default('claude-4.5-sonnet'), - mode: z.enum(['ask', 'agent']).optional().default('agent'), + mode: z.enum(['ask', 'agent', 'plan']).optional().default('agent'), prefetch: z.boolean().optional(), createNewChat: z.boolean().optional().default(false), stream: z.boolean().optional().default(true), @@ -880,6 +886,8 @@ export async function GET(req: NextRequest) { title: copilotChats.title, model: copilotChats.model, messages: copilotChats.messages, + planArtifact: copilotChats.planArtifact, + config: copilotChats.config, createdAt: copilotChats.createdAt, updatedAt: copilotChats.updatedAt, }) @@ -897,6 +905,8 @@ export async function GET(req: NextRequest) { messages: Array.isArray(chat.messages) ? chat.messages : [], messageCount: Array.isArray(chat.messages) ? chat.messages.length : 0, previewYaml: null, // Not needed for chat list + planArtifact: chat.planArtifact || null, + config: chat.config || null, createdAt: chat.createdAt, updatedAt: chat.updatedAt, })) diff --git a/apps/sim/app/api/copilot/chat/update-messages/route.ts b/apps/sim/app/api/copilot/chat/update-messages/route.ts index d4e0ebfae8..f58e2f7a53 100644 --- a/apps/sim/app/api/copilot/chat/update-messages/route.ts +++ b/apps/sim/app/api/copilot/chat/update-messages/route.ts @@ -37,6 +37,14 @@ const UpdateMessagesSchema = z.object({ .optional(), }) ), + planArtifact: z.string().nullable().optional(), + config: z + .object({ + mode: z.enum(['ask', 'build', 'plan']).optional(), + model: z.string().optional(), + }) + .nullable() + .optional(), }) export async function POST(req: NextRequest) { @@ -49,7 +57,7 @@ export async function POST(req: NextRequest) { } const body = await req.json() - const { chatId, messages } = UpdateMessagesSchema.parse(body) + const { chatId, messages, planArtifact, config } = UpdateMessagesSchema.parse(body) // Verify that the chat belongs to the user const [chat] = await db @@ -62,18 +70,27 @@ export async function POST(req: NextRequest) { return createNotFoundResponse('Chat not found or unauthorized') } - // Update chat with new messages - await db - .update(copilotChats) - .set({ - messages: messages, - updatedAt: new Date(), - }) - .where(eq(copilotChats.id, chatId)) + // Update chat with new messages, plan artifact, and config + const updateData: Record = { + messages: messages, + updatedAt: new Date(), + } + + if (planArtifact !== undefined) { + updateData.planArtifact = planArtifact + } + + if (config !== undefined) { + updateData.config = config + } + + await db.update(copilotChats).set(updateData).where(eq(copilotChats.id, chatId)) - logger.info(`[${tracker.requestId}] Successfully updated chat messages`, { + logger.info(`[${tracker.requestId}] Successfully updated chat`, { chatId, newMessageCount: messages.length, + hasPlanArtifact: !!planArtifact, + hasConfig: !!config, }) return NextResponse.json({ diff --git a/apps/sim/app/api/copilot/user-models/route.ts b/apps/sim/app/api/copilot/user-models/route.ts index a0e8c65e11..4802a2ca8a 100644 --- a/apps/sim/app/api/copilot/user-models/route.ts +++ b/apps/sim/app/api/copilot/user-models/route.ts @@ -12,8 +12,14 @@ const DEFAULT_ENABLED_MODELS: Record = { 'gpt-4.1': false, 'gpt-5-fast': false, 'gpt-5': true, - 'gpt-5-medium': true, + 'gpt-5-medium': false, 'gpt-5-high': false, + 'gpt-5.1-fast': false, + 'gpt-5.1': true, + 'gpt-5.1-medium': true, + 'gpt-5.1-high': false, + 'gpt-5-codex': false, + 'gpt-5.1-codex': true, o3: true, 'claude-4-sonnet': false, 'claude-4.5-haiku': true, diff --git a/apps/sim/app/api/creator-profiles/route.ts b/apps/sim/app/api/creator-profiles/route.ts index db0dfa63e2..f6f67ea3d5 100644 --- a/apps/sim/app/api/creator-profiles/route.ts +++ b/apps/sim/app/api/creator-profiles/route.ts @@ -7,7 +7,7 @@ import { z } from 'zod' import { getSession } from '@/lib/auth' import { createLogger } from '@/lib/logs/console/logger' import { generateRequestId } from '@/lib/utils' -import type { CreatorProfileDetails } from '@/types/creator-profile' +import type { CreatorProfileDetails } from '@/app/_types/creator-profile' const logger = createLogger('CreatorProfilesAPI') diff --git a/apps/sim/app/api/files/utils.test.ts b/apps/sim/app/api/files/utils.test.ts index b3deae47bd..a31c7ca42f 100644 --- a/apps/sim/app/api/files/utils.test.ts +++ b/apps/sim/app/api/files/utils.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { createFileResponse, extractFilename, findLocalFile } from './utils' +import { createFileResponse, extractFilename, findLocalFile } from '@/app/api/files/utils' describe('extractFilename', () => { describe('legitimate file paths', () => { diff --git a/apps/sim/app/api/knowledge/search/route.ts b/apps/sim/app/api/knowledge/search/route.ts index 6f97c68e31..645ecd040c 100644 --- a/apps/sim/app/api/knowledge/search/route.ts +++ b/apps/sim/app/api/knowledge/search/route.ts @@ -6,8 +6,6 @@ import { createLogger } from '@/lib/logs/console/logger' import { estimateTokenCount } from '@/lib/tokenization/estimators' import { generateRequestId } from '@/lib/utils' import { getUserId } from '@/app/api/auth/oauth/utils' -import { checkKnowledgeBaseAccess } from '@/app/api/knowledge/utils' -import { calculateCost } from '@/providers/utils' import { generateSearchEmbedding, getDocumentNamesByIds, @@ -16,7 +14,9 @@ import { handleTagOnlySearch, handleVectorOnlySearch, type SearchResult, -} from './utils' +} from '@/app/api/knowledge/search/utils' +import { checkKnowledgeBaseAccess } from '@/app/api/knowledge/utils' +import { calculateCost } from '@/providers/utils' const logger = createLogger('VectorSearchAPI') diff --git a/apps/sim/app/api/knowledge/search/utils.test.ts b/apps/sim/app/api/knowledge/search/utils.test.ts index f3fae93ee2..c95a07fceb 100644 --- a/apps/sim/app/api/knowledge/search/utils.test.ts +++ b/apps/sim/app/api/knowledge/search/utils.test.ts @@ -42,7 +42,7 @@ import { handleTagAndVectorSearch, handleTagOnlySearch, handleVectorOnlySearch, -} from './utils' +} from '@/app/api/knowledge/search/utils' describe('Knowledge Search Utils', () => { beforeEach(() => { 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 a1b7b781b1..7185519756 100644 --- a/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts +++ b/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts @@ -1,5 +1,8 @@ +import { randomUUID } from 'crypto' import { type NextRequest, NextResponse } from 'next/server' +import { preprocessExecution } from '@/lib/execution/preprocessing' import { createLogger } from '@/lib/logs/console/logger' +import { generateRequestId } from '@/lib/utils' import { PauseResumeManager } from '@/lib/workflows/executor/human-in-the-loop-manager' import { validateWorkflowAccess } from '@/app/api/workflows/middleware' @@ -35,6 +38,54 @@ export async function POST( const resumeInput = payload?.input ?? payload ?? {} const userId = workflow.userId ?? '' + const resumeExecutionId = randomUUID() + const requestId = generateRequestId() + + logger.info(`[${requestId}] Preprocessing resume execution`, { + workflowId, + parentExecutionId: executionId, + resumeExecutionId, + userId, + }) + + const preprocessResult = await preprocessExecution({ + workflowId, + userId, + triggerType: 'manual', // Resume is a manual trigger + executionId: resumeExecutionId, + requestId, + checkRateLimit: false, // Manual triggers bypass rate limits + checkDeployment: false, // Resuming existing execution, deployment already checked + skipUsageLimits: true, // Resume is continuation of authorized execution - don't recheck limits + workspaceId: workflow.workspaceId || undefined, + isResumeContext: true, // Enable billing fallback for paused workflow resumes + }) + + if (!preprocessResult.success) { + logger.warn(`[${requestId}] Preprocessing failed for resume`, { + workflowId, + parentExecutionId: executionId, + error: preprocessResult.error?.message, + statusCode: preprocessResult.error?.statusCode, + }) + + return NextResponse.json( + { + error: + preprocessResult.error?.message || + 'Failed to validate resume execution. Please try again.', + }, + { status: preprocessResult.error?.statusCode || 400 } + ) + } + + logger.info(`[${requestId}] Preprocessing passed, proceeding with resume`, { + workflowId, + parentExecutionId: executionId, + resumeExecutionId, + actorUserId: preprocessResult.actorUserId, + }) + try { const enqueueResult = await PauseResumeManager.enqueueOrStartResume({ executionId, diff --git a/apps/sim/app/api/templates/approved/sanitized/route.ts b/apps/sim/app/api/templates/approved/sanitized/route.ts new file mode 100644 index 0000000000..7615f145b8 --- /dev/null +++ b/apps/sim/app/api/templates/approved/sanitized/route.ts @@ -0,0 +1,140 @@ +import { db } from '@sim/db' +import { templates } from '@sim/db/schema' +import { eq } from 'drizzle-orm' +import { type NextRequest, NextResponse } from 'next/server' +import { checkInternalApiKey } from '@/lib/copilot/utils' +import { createLogger } from '@/lib/logs/console/logger' +import { generateRequestId } from '@/lib/utils' +import { sanitizeForCopilot } from '@/lib/workflows/json-sanitizer' + +const logger = createLogger('TemplatesSanitizedAPI') + +export const revalidate = 0 + +/** + * GET /api/templates/approved/sanitized + * Returns all approved templates with their sanitized JSONs, names, and descriptions + * Requires internal API secret authentication via X-API-Key header + */ +export async function GET(request: NextRequest) { + const requestId = generateRequestId() + + try { + const url = new URL(request.url) + const hasApiKey = !!request.headers.get('x-api-key') + + // Check internal API key authentication + const authResult = checkInternalApiKey(request) + if (!authResult.success) { + logger.warn(`[${requestId}] Authentication failed for approved sanitized templates`, { + error: authResult.error, + hasApiKey, + howToUse: 'Add header: X-API-Key: ', + }) + return NextResponse.json( + { + error: authResult.error, + hint: 'Include X-API-Key header with INTERNAL_API_SECRET value', + }, + { status: 401 } + ) + } + + // Fetch all approved templates + const approvedTemplates = await db + .select({ + id: templates.id, + name: templates.name, + details: templates.details, + state: templates.state, + tags: templates.tags, + requiredCredentials: templates.requiredCredentials, + }) + .from(templates) + .where(eq(templates.status, 'approved')) + + // Process each template to sanitize for copilot + const sanitizedTemplates = approvedTemplates + .map((template) => { + try { + const copilotSanitized = sanitizeForCopilot(template.state as any) + + if (copilotSanitized?.blocks) { + Object.values(copilotSanitized.blocks).forEach((block: any) => { + if (block && typeof block === 'object') { + block.outputs = undefined + block.position = undefined + block.height = undefined + block.layout = undefined + block.horizontalHandles = undefined + + // Also clean nested nodes recursively + if (block.nestedNodes) { + Object.values(block.nestedNodes).forEach((nestedBlock: any) => { + if (nestedBlock && typeof nestedBlock === 'object') { + nestedBlock.outputs = undefined + nestedBlock.position = undefined + nestedBlock.height = undefined + nestedBlock.layout = undefined + nestedBlock.horizontalHandles = undefined + } + }) + } + } + }) + } + + const details = template.details as { tagline?: string; about?: string } | null + const description = details?.tagline || details?.about || '' + + return { + id: template.id, + name: template.name, + description, + tags: template.tags, + requiredCredentials: template.requiredCredentials, + sanitizedJson: copilotSanitized, + } + } catch (error) { + logger.error(`[${requestId}] Error sanitizing template ${template.id}`, { + error: error instanceof Error ? error.message : String(error), + }) + return null + } + }) + .filter((t): t is NonNullable => t !== null) + + const response = { + templates: sanitizedTemplates, + count: sanitizedTemplates.length, + } + + return NextResponse.json(response) + } catch (error) { + logger.error(`[${requestId}] Error fetching approved sanitized templates`, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }) + return NextResponse.json( + { + error: 'Internal server error', + requestId, + }, + { status: 500 } + ) + } +} + +// Add a helpful OPTIONS handler for CORS preflight +export async function OPTIONS(request: NextRequest) { + const requestId = generateRequestId() + logger.info(`[${requestId}] OPTIONS request received for /api/templates/approved/sanitized`) + + return new NextResponse(null, { + status: 200, + headers: { + 'Access-Control-Allow-Methods': 'GET, OPTIONS', + 'Access-Control-Allow-Headers': 'X-API-Key, Content-Type', + }, + }) +} diff --git a/apps/sim/app/api/v1/middleware.ts b/apps/sim/app/api/v1/middleware.ts index ebf27a489b..32b31fb390 100644 --- a/apps/sim/app/api/v1/middleware.ts +++ b/apps/sim/app/api/v1/middleware.ts @@ -1,8 +1,8 @@ import { type NextRequest, NextResponse } from 'next/server' import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription' import { createLogger } from '@/lib/logs/console/logger' +import { authenticateV1Request } from '@/app/api/v1/auth' import { RateLimiter } from '@/services/queue/RateLimiter' -import { authenticateV1Request } from './auth' const logger = createLogger('V1Middleware') const rateLimiter = new RateLimiter() diff --git a/apps/sim/app/api/webhooks/test/[id]/route.ts b/apps/sim/app/api/webhooks/test/[id]/route.ts index 6601745781..44b49fa1b5 100644 --- a/apps/sim/app/api/webhooks/test/[id]/route.ts +++ b/apps/sim/app/api/webhooks/test/[id]/route.ts @@ -2,7 +2,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { createLogger } from '@/lib/logs/console/logger' import { generateRequestId } from '@/lib/utils' import { - checkRateLimits, + checkWebhookPreprocessing, findWebhookAndWorkflow, handleProviderChallenges, parseWebhookBody, @@ -67,9 +67,39 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ return authError } - const rateLimitError = await checkRateLimits(foundWorkflow, foundWebhook, requestId) - if (rateLimitError) { - return rateLimitError + let preprocessError: NextResponse | null = null + try { + preprocessError = await checkWebhookPreprocessing( + foundWorkflow, + foundWebhook, + requestId, + true // testMode - skips usage limits + ) + if (preprocessError) { + return preprocessError + } + } catch (error) { + logger.error(`[${requestId}] Unexpected error during webhook preprocessing`, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + webhookId: foundWebhook.id, + workflowId: foundWorkflow.id, + }) + + if (foundWebhook.provider === 'microsoft-teams') { + return NextResponse.json( + { + type: 'message', + text: 'An unexpected error occurred during preprocessing', + }, + { status: 500 } + ) + } + + return NextResponse.json( + { error: 'An unexpected error occurred during preprocessing' }, + { status: 500 } + ) } logger.info( diff --git a/apps/sim/app/api/webhooks/trigger/[path]/route.test.ts b/apps/sim/app/api/webhooks/trigger/[path]/route.test.ts index e0bec7e4dc..672f19fd5e 100644 --- a/apps/sim/app/api/webhooks/trigger/[path]/route.test.ts +++ b/apps/sim/app/api/webhooks/trigger/[path]/route.test.ts @@ -88,6 +88,35 @@ vi.mock('@/executor', () => ({ })), })) +vi.mock('@/lib/execution/preprocessing', () => ({ + preprocessExecution: vi.fn().mockResolvedValue({ + success: true, + actorUserId: 'test-user-id', + workflowRecord: { + id: 'test-workflow-id', + userId: 'test-user-id', + isDeployed: true, + workspaceId: 'test-workspace-id', + }, + userSubscription: { + plan: 'pro', + status: 'active', + }, + rateLimitInfo: { + allowed: true, + remaining: 100, + resetAt: new Date(), + }, + }), +})) + +vi.mock('@/lib/logs/execution/logging-session', () => ({ + LoggingSession: vi.fn().mockImplementation(() => ({ + safeStart: vi.fn().mockResolvedValue(undefined), + safeCompleteWithError: vi.fn().mockResolvedValue(undefined), + })), +})) + process.env.DATABASE_URL = 'postgresql://test:test@localhost:5432/test' vi.mock('drizzle-orm/postgres-js', () => ({ @@ -190,19 +219,6 @@ describe('Webhook Trigger API Route', () => { }) describe('Generic Webhook Authentication', () => { - beforeEach(() => { - vi.doMock('@/lib/billing/core/subscription', () => ({ - getHighestPrioritySubscription: vi.fn().mockResolvedValue({ - plan: 'pro', - status: 'active', - }), - })) - - vi.doMock('@/lib/billing', () => ({ - checkServerSideUsageLimits: vi.fn().mockResolvedValue(null), - })) - }) - it('should process generic webhook without authentication', async () => { globalMockData.webhooks.push({ id: 'generic-webhook-id', diff --git a/apps/sim/app/api/webhooks/trigger/[path]/route.ts b/apps/sim/app/api/webhooks/trigger/[path]/route.ts index 0de3c1a632..8d63c55799 100644 --- a/apps/sim/app/api/webhooks/trigger/[path]/route.ts +++ b/apps/sim/app/api/webhooks/trigger/[path]/route.ts @@ -2,8 +2,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { createLogger } from '@/lib/logs/console/logger' import { generateRequestId } from '@/lib/utils' import { - checkRateLimits, - checkUsageLimits, + checkWebhookPreprocessing, findWebhookAndWorkflow, handleProviderChallenges, parseWebhookBody, @@ -124,14 +123,39 @@ export async function POST( return authError } - const rateLimitError = await checkRateLimits(foundWorkflow, foundWebhook, requestId) - if (rateLimitError) { - return rateLimitError - } + let preprocessError: NextResponse | null = null + try { + preprocessError = await checkWebhookPreprocessing( + foundWorkflow, + foundWebhook, + requestId, + false // testMode + ) + if (preprocessError) { + return preprocessError + } + } catch (error) { + logger.error(`[${requestId}] Unexpected error during webhook preprocessing`, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + webhookId: foundWebhook.id, + workflowId: foundWorkflow.id, + }) + + if (foundWebhook.provider === 'microsoft-teams') { + return NextResponse.json( + { + type: 'message', + text: 'An unexpected error occurred during preprocessing', + }, + { status: 500 } + ) + } - const usageLimitError = await checkUsageLimits(foundWorkflow, foundWebhook, requestId, false) - if (usageLimitError) { - return usageLimitError + return NextResponse.json( + { error: 'An unexpected error occurred during preprocessing' }, + { status: 500 } + ) } if (foundWebhook.blockId) { diff --git a/apps/sim/app/api/workflows/[id]/execute/route.ts b/apps/sim/app/api/workflows/[id]/execute/route.ts index dabd563cae..e9a9023162 100644 --- a/apps/sim/app/api/workflows/[id]/execute/route.ts +++ b/apps/sim/app/api/workflows/[id]/execute/route.ts @@ -2,8 +2,8 @@ import { type NextRequest, NextResponse } from 'next/server' import { validate as uuidValidate, v4 as uuidv4 } from 'uuid' import { z } from 'zod' import { checkHybridAuth } from '@/lib/auth/hybrid' -import { checkServerSideUsageLimits } from '@/lib/billing' import { processInputFileFields } from '@/lib/execution/files' +import { preprocessExecution } from '@/lib/execution/preprocessing' import { createLogger } from '@/lib/logs/console/logger' import { LoggingSession } from '@/lib/logs/execution/logging-session' import { generateRequestId, SSE_HEADERS } from '@/lib/utils' @@ -16,7 +16,6 @@ import { type ExecutionEvent, encodeSSEEvent } from '@/lib/workflows/executor/ex import { PauseResumeManager } from '@/lib/workflows/executor/human-in-the-loop-manager' import { createStreamingResponse } from '@/lib/workflows/streaming' import { createHttpResponseFromBlock, workflowHasResponseBlock } from '@/lib/workflows/utils' -import { validateWorkflowAccess } from '@/app/api/workflows/middleware' import { type ExecutionMetadata, ExecutionSnapshot } from '@/executor/execution/snapshot' import type { StreamingExecution } from '@/executor/types' import { Serializer } from '@/serializer' @@ -30,7 +29,6 @@ const ExecuteWorkflowSchema = z.object({ stream: z.boolean().optional(), useDraftState: z.boolean().optional(), input: z.any().optional(), - startBlockId: z.string().optional(), // Optional workflow state override (for executing diff workflows) workflowStateOverride: z .object({ @@ -45,30 +43,21 @@ const ExecuteWorkflowSchema = z.object({ export const runtime = 'nodejs' export const dynamic = 'force-dynamic' -class UsageLimitError extends Error { - statusCode: number - constructor(message: string, statusCode = 402) { - super(message) - this.statusCode = statusCode - } -} - /** * Execute workflow with streaming support - used by chat and other streaming endpoints * + * This function assumes preprocessing has already been completed. + * Callers must run preprocessExecution() first to validate workflow, check usage limits, + * and resolve actor before calling this function. + * * This is a wrapper function that: - * - Checks usage limits before execution (protects chat and streaming paths) - * - Logs usage limit errors to the database for user visibility * - Supports streaming callbacks (onStream, onBlockComplete) * - Returns ExecutionResult instead of NextResponse + * - Handles pause/resume logic * * Used by: * - Chat execution (/api/chat/[identifier]/route.ts) * - Streaming responses (lib/workflows/streaming.ts) - * - * Note: The POST handler in this file calls executeWorkflowCore() directly and has - * its own usage check. This wrapper provides convenience and built-in protection - * for callers that need streaming support. */ export async function executeWorkflow( workflow: any, @@ -92,38 +81,6 @@ export async function executeWorkflow( const loggingSession = new LoggingSession(workflowId, executionId, triggerType, requestId) try { - const usageCheck = await checkServerSideUsageLimits(actorUserId) - if (usageCheck.isExceeded) { - logger.warn( - `[${requestId}] User ${actorUserId} has exceeded usage limits. Blocking workflow execution.`, - { - currentUsage: usageCheck.currentUsage, - limit: usageCheck.limit, - workflowId, - triggerType, - } - ) - - await loggingSession.safeStart({ - userId: actorUserId, - workspaceId: workflow.workspaceId || '', - variables: {}, - }) - - await loggingSession.safeCompleteWithError({ - error: { - message: - usageCheck.message || 'Usage limit exceeded. Please upgrade your plan to continue.', - stackTrace: undefined, - }, - traceSpans: [], - }) - - throw new UsageLimitError( - usageCheck.message || 'Usage limit exceeded. Please upgrade your plan to continue.' - ) - } - const metadata: ExecutionMetadata = { requestId, executionId, @@ -270,23 +227,12 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: const { id: workflowId } = await params try { - // Authenticate user (API key, session, or internal JWT) const auth = await checkHybridAuth(req, { requireWorkflowId: false }) if (!auth.success || !auth.userId) { return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) } const userId = auth.userId - // Validate workflow access (don't require deployment for manual client runs) - const workflowValidation = await validateWorkflowAccess(req, workflowId, false) - if (workflowValidation.error) { - return NextResponse.json( - { error: workflowValidation.error.message }, - { status: workflowValidation.error.status } - ) - } - const workflow = workflowValidation.workflow! - let body: any = {} try { const text = await req.text() @@ -375,43 +321,33 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: requestId ) - // Check usage limits for this POST handler execution path - // Architecture note: This handler calls executeWorkflowCore() directly (both SSE and non-SSE paths). - // The executeWorkflow() wrapper function (used by chat) has its own check (line 54). - const usageCheck = await checkServerSideUsageLimits(userId) - if (usageCheck.isExceeded) { - logger.warn(`[${requestId}] User ${userId} has exceeded usage limits. Blocking execution.`, { - currentUsage: usageCheck.currentUsage, - limit: usageCheck.limit, - workflowId, - triggerType, - }) - - await loggingSession.safeStart({ - userId, - workspaceId: workflow.workspaceId || '', - variables: {}, - }) - - await loggingSession.safeCompleteWithError({ - error: { - message: - usageCheck.message || 'Usage limit exceeded. Please upgrade your plan to continue.', - stackTrace: undefined, - }, - traceSpans: [], - }) + const preprocessResult = await preprocessExecution({ + workflowId, + userId, + triggerType: loggingTriggerType, + executionId, + requestId, + checkRateLimit: false, // Manual executions bypass rate limits + checkDeployment: !shouldUseDraftState, // Check deployment unless using draft + loggingSession, + }) + if (!preprocessResult.success) { return NextResponse.json( - { - error: - usageCheck.message || 'Usage limit exceeded. Please upgrade your plan to continue.', - }, - { status: 402 } + { error: preprocessResult.error!.message }, + { status: preprocessResult.error!.statusCode } ) } - // Process file fields in workflow input (base64/URL to UserFile conversion) + const actorUserId = preprocessResult.actorUserId! + const workflow = preprocessResult.workflowRecord! + + logger.info(`[${requestId}] Preprocessing passed`, { + workflowId, + actorUserId, + workspaceId: workflow.workspaceId, + }) + let processedInput = input try { const workflowData = shouldUseDraftState @@ -438,14 +374,14 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: serializedWorkflow.blocks, executionContext, requestId, - userId + actorUserId ) } } catch (fileError) { logger.error(`[${requestId}] Failed to process input file fields:`, fileError) await loggingSession.safeStart({ - userId, + userId: actorUserId, workspaceId: workflow.workspaceId || '', variables: {}, }) @@ -473,8 +409,8 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: requestId, executionId, workflowId, - workspaceId: workflow.workspaceId, - userId, + workspaceId: workflow.workspaceId ?? undefined, + userId: actorUserId, triggerType, useDraftState: shouldUseDraftState, startTime: new Date().toISOString(), @@ -516,8 +452,6 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: return NextResponse.json(filteredResult) } catch (error: any) { - // Block errors are already logged with full details by BlockExecutor - // Only log the error message here to avoid duplicate logging const errorMessage = error.message || 'Unknown error' logger.error(`[${requestId}] Non-SSE execution failed: ${errorMessage}`) @@ -549,9 +483,15 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: const resolvedSelectedOutputs = resolveOutputIds(selectedOutputs, deployedData?.blocks || {}) const stream = await createStreamingResponse({ requestId, - workflow, + workflow: { + id: workflow.id, + userId: actorUserId, + workspaceId: workflow.workspaceId, + isDeployed: workflow.isDeployed, + variables: (workflow as any).variables, + }, input: processedInput, - executingUserId: userId, + executingUserId: actorUserId, streamConfig: { selectedOutputs: resolvedSelectedOutputs, isSecureMode: false, @@ -732,8 +672,8 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: requestId, executionId, workflowId, - workspaceId: workflow.workspaceId, - userId, + workspaceId: workflow.workspaceId ?? undefined, + userId: actorUserId, triggerType, useDraftState: shouldUseDraftState, startTime: new Date().toISOString(), @@ -808,8 +748,6 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: }, }) } catch (error: any) { - // Block errors are already logged with full details by BlockExecutor - // Only log the error message here to avoid duplicate logging const errorMessage = error.message || 'Unknown error' logger.error(`[${requestId}] SSE execution failed: ${errorMessage}`) diff --git a/apps/sim/app/api/workflows/[id]/state/route.ts b/apps/sim/app/api/workflows/[id]/state/route.ts index a84afc4953..cbd07cf417 100644 --- a/apps/sim/app/api/workflows/[id]/state/route.ts +++ b/apps/sim/app/api/workflows/[id]/state/route.ts @@ -4,6 +4,7 @@ import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' +import { env } from '@/lib/env' import { createLogger } from '@/lib/logs/console/logger' import { generateRequestId } from '@/lib/utils' import { extractAndPersistCustomTools } from '@/lib/workflows/custom-tools-persistence' @@ -248,6 +249,26 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{ const elapsed = Date.now() - startTime logger.info(`[${requestId}] Successfully saved workflow ${workflowId} state in ${elapsed}ms`) + try { + const socketUrl = env.SOCKET_SERVER_URL || 'http://localhost:3002' + const notifyResponse = await fetch(`${socketUrl}/api/workflow-updated`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ workflowId }), + }) + + if (!notifyResponse.ok) { + logger.warn( + `[${requestId}] Failed to notify Socket.IO server about workflow ${workflowId} update` + ) + } + } catch (notificationError) { + logger.warn( + `[${requestId}] Error notifying Socket.IO server about workflow ${workflowId} update`, + notificationError + ) + } + return NextResponse.json({ success: true, warnings }, { status: 200 }) } catch (error: any) { const elapsed = Date.now() - startTime diff --git a/apps/sim/app/api/workflows/route.ts b/apps/sim/app/api/workflows/route.ts index e7b603c7c3..d89af62d51 100644 --- a/apps/sim/app/api/workflows/route.ts +++ b/apps/sim/app/api/workflows/route.ts @@ -7,7 +7,7 @@ import { getSession } from '@/lib/auth' import { createLogger } from '@/lib/logs/console/logger' import { getUserEntityPermissions } from '@/lib/permissions/utils' import { generateRequestId } from '@/lib/utils' -import { verifyWorkspaceMembership } from './utils' +import { verifyWorkspaceMembership } from '@/app/api/workflows/utils' const logger = createLogger('WorkflowAPI') diff --git a/apps/sim/app/changelog/components/changelog-content.tsx b/apps/sim/app/changelog/components/changelog-content.tsx index 60390eedb2..36c817e7f1 100644 --- a/apps/sim/app/changelog/components/changelog-content.tsx +++ b/apps/sim/app/changelog/components/changelog-content.tsx @@ -1,8 +1,8 @@ import { BookOpen, Github, Rss } from 'lucide-react' import Link from 'next/link' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' -import ChangelogList from './timeline-list' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' +import ChangelogList from '@/app/changelog/components/timeline-list' export interface ChangelogEntry { tag: string diff --git a/apps/sim/app/changelog/components/timeline-list.tsx b/apps/sim/app/changelog/components/timeline-list.tsx index e73b3ff142..9e2b81a03a 100644 --- a/apps/sim/app/changelog/components/timeline-list.tsx +++ b/apps/sim/app/changelog/components/timeline-list.tsx @@ -3,9 +3,9 @@ import React from 'react' import ReactMarkdown from 'react-markdown' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' -import type { ChangelogEntry } from './changelog-content' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' +import type { ChangelogEntry } from '@/app/changelog/components/changelog-content' type Props = { initialEntries: ChangelogEntry[] } diff --git a/apps/sim/app/changelog/page.tsx b/apps/sim/app/changelog/page.tsx index 39dbfeaa79..c94b650667 100644 --- a/apps/sim/app/changelog/page.tsx +++ b/apps/sim/app/changelog/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import ChangelogContent from './components/changelog-content' +import ChangelogContent from '@/app/changelog/components/changelog-content' export const metadata: Metadata = { title: 'Changelog', diff --git a/apps/sim/app/chat/components/auth/email/email-auth.tsx b/apps/sim/app/chat/components/auth/email/email-auth.tsx index f16199bf2b..d8161e5b33 100644 --- a/apps/sim/app/chat/components/auth/email/email-auth.tsx +++ b/apps/sim/app/chat/components/auth/email/email-auth.tsx @@ -9,9 +9,9 @@ import { Label } from '@/components/ui/label' import { quickValidateEmail } from '@/lib/email/validation' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import Nav from '@/app/(landing)/components/nav/nav' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' const logger = createLogger('EmailAuth') diff --git a/apps/sim/app/chat/components/auth/password/password-auth.tsx b/apps/sim/app/chat/components/auth/password/password-auth.tsx index b82880e872..5820ceefcb 100644 --- a/apps/sim/app/chat/components/auth/password/password-auth.tsx +++ b/apps/sim/app/chat/components/auth/password/password-auth.tsx @@ -7,9 +7,9 @@ import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import Nav from '@/app/(landing)/components/nav/nav' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' const logger = createLogger('PasswordAuth') diff --git a/apps/sim/app/chat/components/auth/sso/sso-auth.tsx b/apps/sim/app/chat/components/auth/sso/sso-auth.tsx index ad2bf5e97d..80da21f5d8 100644 --- a/apps/sim/app/chat/components/auth/sso/sso-auth.tsx +++ b/apps/sim/app/chat/components/auth/sso/sso-auth.tsx @@ -8,9 +8,9 @@ import { Label } from '@/components/ui/label' import { quickValidateEmail } from '@/lib/email/validation' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import Nav from '@/app/(landing)/components/nav/nav' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' const logger = createLogger('SSOAuth') diff --git a/apps/sim/app/chat/components/error-state/error-state.tsx b/apps/sim/app/chat/components/error-state/error-state.tsx index bc43f4c6a9..0f222beb00 100644 --- a/apps/sim/app/chat/components/error-state/error-state.tsx +++ b/apps/sim/app/chat/components/error-state/error-state.tsx @@ -4,9 +4,9 @@ import { useEffect, useState } from 'react' import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' import { useBrandConfig } from '@/lib/branding/branding' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' import Nav from '@/app/(landing)/components/nav/nav' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' interface ChatErrorStateProps { error: string diff --git a/apps/sim/app/chat/components/header/header.tsx b/apps/sim/app/chat/components/header/header.tsx index 0f742f1e57..049421c7e4 100644 --- a/apps/sim/app/chat/components/header/header.tsx +++ b/apps/sim/app/chat/components/header/header.tsx @@ -4,7 +4,7 @@ import Image from 'next/image' import Link from 'next/link' import { GithubIcon } from '@/components/icons' import { useBrandConfig } from '@/lib/branding/branding' -import { inter } from '@/app/fonts/inter/inter' +import { inter } from '@/app/_styles/fonts/inter/inter' interface ChatHeaderProps { chatConfig: { diff --git a/apps/sim/app/chat/components/message/message.tsx b/apps/sim/app/chat/components/message/message.tsx index 7147688205..3955285e62 100644 --- a/apps/sim/app/chat/components/message/message.tsx +++ b/apps/sim/app/chat/components/message/message.tsx @@ -3,7 +3,7 @@ import { memo, useMemo, useState } from 'react' import { Check, Copy, File as FileIcon, FileText, Image as ImageIcon } from 'lucide-react' import { Tooltip } from '@/components/emcn' -import MarkdownRenderer from './components/markdown-renderer' +import MarkdownRenderer from '@/app/chat/components/message/components/markdown-renderer' export interface ChatAttachment { id: string diff --git a/apps/sim/app/fonts/temp/SeasonSansBold.otf b/apps/sim/app/fonts/temp/SeasonSansBold.otf deleted file mode 100644 index f728de699f..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansBold.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansBold.ttf b/apps/sim/app/fonts/temp/SeasonSansBold.ttf deleted file mode 100644 index af9f722f3c..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansBold.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansBold.woff2 b/apps/sim/app/fonts/temp/SeasonSansBold.woff2 deleted file mode 100644 index b8d4759db8..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansBold.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansBoldItalic.otf b/apps/sim/app/fonts/temp/SeasonSansBoldItalic.otf deleted file mode 100644 index 5bc78a9219..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansBoldItalic.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansBoldItalic.ttf b/apps/sim/app/fonts/temp/SeasonSansBoldItalic.ttf deleted file mode 100644 index 4eeb731bec..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansBoldItalic.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansBoldItalic.woff2 b/apps/sim/app/fonts/temp/SeasonSansBoldItalic.woff2 deleted file mode 100644 index 43f7a79955..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansBoldItalic.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansHeavy.otf b/apps/sim/app/fonts/temp/SeasonSansHeavy.otf deleted file mode 100644 index a2d96d4a02..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansHeavy.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansHeavy.ttf b/apps/sim/app/fonts/temp/SeasonSansHeavy.ttf deleted file mode 100644 index 94ef71c1ff..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansHeavy.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansHeavy.woff2 b/apps/sim/app/fonts/temp/SeasonSansHeavy.woff2 deleted file mode 100644 index e645f7f1b3..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansHeavy.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.otf b/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.otf deleted file mode 100644 index 375dc1f893..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.ttf b/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.ttf deleted file mode 100644 index db3e12f062..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.woff2 b/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.woff2 deleted file mode 100644 index cd29aaef7b..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansHeavyItalic.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansLight.otf b/apps/sim/app/fonts/temp/SeasonSansLight.otf deleted file mode 100644 index 2836789c1a..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansLight.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansLight.ttf b/apps/sim/app/fonts/temp/SeasonSansLight.ttf deleted file mode 100644 index 5046aa88af..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansLight.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansLight.woff2 b/apps/sim/app/fonts/temp/SeasonSansLight.woff2 deleted file mode 100644 index b2ad434fa1..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansLight.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansLightItalic.otf b/apps/sim/app/fonts/temp/SeasonSansLightItalic.otf deleted file mode 100644 index 6d26d345d4..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansLightItalic.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansLightItalic.ttf b/apps/sim/app/fonts/temp/SeasonSansLightItalic.ttf deleted file mode 100644 index 23c7fcdded..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansLightItalic.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansLightItalic.woff2 b/apps/sim/app/fonts/temp/SeasonSansLightItalic.woff2 deleted file mode 100644 index cb2deb9078..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansLightItalic.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansMedium.otf b/apps/sim/app/fonts/temp/SeasonSansMedium.otf deleted file mode 100644 index 9555b305a2..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansMedium.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansMedium.ttf b/apps/sim/app/fonts/temp/SeasonSansMedium.ttf deleted file mode 100644 index aed9e5129d..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansMedium.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansMedium.woff2 b/apps/sim/app/fonts/temp/SeasonSansMedium.woff2 deleted file mode 100644 index 29dd441672..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansMedium.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansMediumItalic.otf b/apps/sim/app/fonts/temp/SeasonSansMediumItalic.otf deleted file mode 100644 index 9e87e7e9e4..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansMediumItalic.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansMediumItalic.ttf b/apps/sim/app/fonts/temp/SeasonSansMediumItalic.ttf deleted file mode 100644 index fb34ed6772..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansMediumItalic.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansMediumItalic.woff2 b/apps/sim/app/fonts/temp/SeasonSansMediumItalic.woff2 deleted file mode 100644 index b4332ff0f3..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansMediumItalic.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansRegular.otf b/apps/sim/app/fonts/temp/SeasonSansRegular.otf deleted file mode 100644 index fa903cc00d..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansRegular.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansRegular.ttf b/apps/sim/app/fonts/temp/SeasonSansRegular.ttf deleted file mode 100644 index 83f023bdc3..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansRegular.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansRegular.woff2 b/apps/sim/app/fonts/temp/SeasonSansRegular.woff2 deleted file mode 100644 index 2e73573f09..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansRegular.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansRegularItalic.otf b/apps/sim/app/fonts/temp/SeasonSansRegularItalic.otf deleted file mode 100644 index 7b1f5e5973..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansRegularItalic.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansRegularItalic.ttf b/apps/sim/app/fonts/temp/SeasonSansRegularItalic.ttf deleted file mode 100644 index a81ede3316..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansRegularItalic.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansRegularItalic.woff2 b/apps/sim/app/fonts/temp/SeasonSansRegularItalic.woff2 deleted file mode 100644 index a00f6e5edb..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansRegularItalic.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansSemiBold.otf b/apps/sim/app/fonts/temp/SeasonSansSemiBold.otf deleted file mode 100644 index cf33e9ec77..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansSemiBold.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansSemiBold.ttf b/apps/sim/app/fonts/temp/SeasonSansSemiBold.ttf deleted file mode 100644 index f0bf1af523..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansSemiBold.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansSemiBold.woff2 b/apps/sim/app/fonts/temp/SeasonSansSemiBold.woff2 deleted file mode 100644 index e8d9743e98..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansSemiBold.woff2 and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.otf b/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.otf deleted file mode 100644 index f1a777fa65..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.otf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.ttf b/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.ttf deleted file mode 100644 index 1aa17431c7..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.ttf and /dev/null differ diff --git a/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.woff2 b/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.woff2 deleted file mode 100644 index c705f5050f..0000000000 Binary files a/apps/sim/app/fonts/temp/SeasonSansSemiBoldItalic.woff2 and /dev/null differ diff --git a/apps/sim/app/invite/components/status-card.tsx b/apps/sim/app/invite/components/status-card.tsx index 4a31a6b3fd..65a2a30dc3 100644 --- a/apps/sim/app/invite/components/status-card.tsx +++ b/apps/sim/app/invite/components/status-card.tsx @@ -14,8 +14,8 @@ import { import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' import { useBrandConfig } from '@/lib/branding/branding' -import { inter } from '@/app/fonts/inter/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/_styles/fonts/inter/inter' +import { soehne } from '@/app/_styles/fonts/soehne/soehne' interface InviteStatusCardProps { type: 'login' | 'loading' | 'error' | 'success' | 'invitation' | 'warning' diff --git a/apps/sim/app/layout.tsx b/apps/sim/app/layout.tsx index 186f6837ea..bb40e8156f 100644 --- a/apps/sim/app/layout.tsx +++ b/apps/sim/app/layout.tsx @@ -3,16 +3,16 @@ import { PublicEnvScript } from 'next-runtime-env' import { BrandedLayout } from '@/components/branded-layout' import { generateThemeCSS } from '@/lib/branding/inject-theme' import { generateBrandedMetadata, generateStructuredData } from '@/lib/branding/metadata' -import { PostHogProvider } from '@/lib/posthog/provider' -import '@/app/globals.css' +import { PostHogProvider } from '@/app/_shell/providers/posthog-provider' +import '@/app/_styles/globals.css' import { OneDollarStats } from '@/components/analytics/onedollarstats' -import { SessionProvider } from '@/lib/session/session-context' -import { season } from '@/app/fonts/season/season' -import { HydrationErrorHandler } from '@/app/hydration-error-handler' -import { QueryProvider } from '@/app/providers/query-client-provider' -import { ThemeProvider } from '@/app/theme-provider' -import { ZoomPrevention } from '@/app/zoom-prevention' +import { HydrationErrorHandler } from '@/app/_shell/hydration-error-handler' +import { QueryProvider } from '@/app/_shell/providers/query-provider' +import { SessionProvider } from '@/app/_shell/providers/session-provider' +import { ThemeProvider } from '@/app/_shell/providers/theme-provider' +import { ZoomPrevention } from '@/app/_shell/zoom-prevention' +import { season } from '@/app/_styles/fonts/season/season' export const viewport: Viewport = { width: 'device-width', @@ -42,68 +42,56 @@ export default function RootLayout({ children }: { children: React.ReactNode }) }} /> - {/* Theme CSS Override */} - {themeCSS && ( -