From d7efcb86f953edcbfc36f388205a2c492ad8f00a Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Fri, 20 Mar 2026 15:28:52 +0000 Subject: [PATCH 01/24] feat: prompt management with service layer, dashboard UI, and AI span integration --- .../app/components/BlankStatePanels.tsx | 54 + .../app/components/code/TSQLResultsTable.tsx | 29 +- .../webapp/app/components/code/TextEditor.tsx | 125 ++ .../app/components/metrics/PromptsFilter.tsx | 125 ++ .../app/components/metrics/QueryWidget.tsx | 5 + .../app/components/navigation/SideMenu.tsx | 33 + .../app/components/primitives/Resizable.tsx | 23 +- .../components/runs/v3/PromptSpanDetails.tsx | 163 ++ .../app/components/runs/v3/SpanTitle.tsx | 8 +- .../components/runs/v3/ai/AIChatMessages.tsx | 75 +- .../components/runs/v3/ai/AIModelSummary.tsx | 43 +- .../components/runs/v3/ai/AISpanDetails.tsx | 152 +- .../runs/v3/ai/extractAISpanData.ts | 13 + .../webapp/app/components/runs/v3/ai/types.ts | 8 + .../presenters/v3/BuiltInDashboards.server.ts | 11 +- .../v3/MetricDashboardPresenter.server.ts | 2 +- .../presenters/v3/PromptPresenter.server.ts | 332 +++ .../app/presenters/v3/SpanPresenter.server.ts | 93 +- .../route.tsx | 23 + .../route.tsx | 1870 +++++++++++++++++ .../route.tsx | 191 ++ .../route.tsx | 21 +- ...pi.v1.prompts.$slug.override.reactivate.ts | 71 + .../routes/api.v1.prompts.$slug.override.ts | 117 ++ .../routes/api.v1.prompts.$slug.promote.ts | 71 + .../webapp/app/routes/api.v1.prompts.$slug.ts | 174 ++ .../routes/api.v1.prompts.$slug.versions.ts | 56 + .../app/routes/api.v1.prompts._index.ts | 37 + apps/webapp/app/routes/resources.metric.tsx | 8 + ...nvParam.prompts.$promptSlug.generations.ts | 74 + .../route.tsx | 6 + .../app/services/authorization.server.ts | 2 +- .../app/services/queryService.server.ts | 5 + apps/webapp/app/utils/pathBuilder.ts | 19 + .../clickhouseEventRepository.server.ts | 2 + .../eventRepository/eventRepository.types.ts | 2 + apps/webapp/app/v3/querySchemas.ts | 27 + .../services/createBackgroundWorker.server.ts | 132 ++ .../app/v3/services/promptService.server.ts | 142 ++ .../v3/utils/enrichCreatableEvents.server.ts | 33 + ...5_add_prompt_columns_to_llm_metrics_v1.sql | 13 + .../clickhouse/src/llmMetrics.ts | 3 + .../migration.sql | 74 + .../migration.sql | 5 + .../database/prisma/schema.prisma | 81 +- package.json | 3 +- packages/cli-v3/src/dev/devSupervisor.ts | 1 + .../src/entryPoints/dev-index-worker.ts | 19 + .../src/entryPoints/managed-index-worker.ts | 19 + packages/cli-v3/src/mcp/config.ts | 42 + packages/cli-v3/src/mcp/tools.ts | 21 + packages/cli-v3/src/mcp/tools/prompts.ts | 386 ++++ packages/core/src/v3/apiClient/index.ts | 19 + .../core/src/v3/resource-catalog/catalog.ts | 8 +- .../core/src/v3/resource-catalog/index.ts | 20 +- .../resource-catalog/noopResourceCatalog.ts | 20 +- .../standardResourceCatalog.ts | 70 +- packages/core/src/v3/schemas/api.ts | 21 + packages/core/src/v3/schemas/build.ts | 3 +- packages/core/src/v3/schemas/resources.ts | 18 + packages/core/src/v3/schemas/schemas.ts | 20 + packages/core/src/v3/types/tasks.ts | 8 + packages/trigger-sdk/src/v3/index.ts | 1 + packages/trigger-sdk/src/v3/prompt.ts | 236 +++ packages/trigger-sdk/src/v3/prompts.ts | 2 + patches/@window-splitter__state@0.4.1.patch | 28 + pnpm-lock.yaml | 545 +++-- references/hello-world/package.json | 2 + references/hello-world/src/trigger/prompts.ts | 284 +++ 69 files changed, 6106 insertions(+), 243 deletions(-) create mode 100644 apps/webapp/app/components/code/TextEditor.tsx create mode 100644 apps/webapp/app/components/metrics/PromptsFilter.tsx create mode 100644 apps/webapp/app/components/runs/v3/PromptSpanDetails.tsx create mode 100644 apps/webapp/app/presenters/v3/PromptPresenter.server.ts create mode 100644 apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.prompts.$promptSlug/route.tsx create mode 100644 apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.prompts._index/route.tsx create mode 100644 apps/webapp/app/routes/api.v1.prompts.$slug.override.reactivate.ts create mode 100644 apps/webapp/app/routes/api.v1.prompts.$slug.override.ts create mode 100644 apps/webapp/app/routes/api.v1.prompts.$slug.promote.ts create mode 100644 apps/webapp/app/routes/api.v1.prompts.$slug.ts create mode 100644 apps/webapp/app/routes/api.v1.prompts.$slug.versions.ts create mode 100644 apps/webapp/app/routes/api.v1.prompts._index.ts create mode 100644 apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.prompts.$promptSlug.generations.ts create mode 100644 apps/webapp/app/v3/services/promptService.server.ts create mode 100644 internal-packages/clickhouse/schema/025_add_prompt_columns_to_llm_metrics_v1.sql create mode 100644 internal-packages/database/prisma/migrations/20260317221618_add_prompt_management/migration.sql create mode 100644 internal-packages/database/prisma/migrations/20260318114244_add_prompt_friendly_id/migration.sql create mode 100644 packages/cli-v3/src/mcp/tools/prompts.ts create mode 100644 packages/trigger-sdk/src/v3/prompt.ts create mode 100644 packages/trigger-sdk/src/v3/prompts.ts create mode 100644 patches/@window-splitter__state@0.4.1.patch create mode 100644 references/hello-world/src/trigger/prompts.ts diff --git a/apps/webapp/app/components/BlankStatePanels.tsx b/apps/webapp/app/components/BlankStatePanels.tsx index 7423bd61ac8..111e4efebb8 100644 --- a/apps/webapp/app/components/BlankStatePanels.tsx +++ b/apps/webapp/app/components/BlankStatePanels.tsx @@ -4,11 +4,13 @@ import { BookOpenIcon, ChatBubbleLeftRightIcon, ClockIcon, + DocumentTextIcon, PlusIcon, QuestionMarkCircleIcon, RectangleGroupIcon, RectangleStackIcon, ServerStackIcon, + SparklesIcon, Squares2X2Icon, } from "@heroicons/react/20/solid"; import { useLocation } from "react-use"; @@ -686,3 +688,55 @@ function DeploymentOnboardingSteps() { ); } + +export function PromptsNone() { + return ( + + Prompt docs + + } + > + + Managed prompts let you define AI prompts in code with typesafe variables, then edit and + version them from the dashboard without redeploying. + + + Add a prompt to your project using prompts.define(): + +
+
+          import
+          {" { prompts } "}
+          from
+          {' "@trigger.dev/sdk";\n'}
+          import
+          {" { z } "}
+          from
+          {' "zod";\n\n'}
+          export const
+          {" myPrompt = "}
+          prompts.define
+          {"({\n"}
+          {"  id: "}
+          "my-prompt"
+          {",\n"}
+          {"  variables: z.object({\n"}
+          {"    name: z.string(),\n"}
+          {"  }),\n"}
+          {"  content: "}
+          {"`Hello {{name}}!`"}
+          {",\n"});
+
+ + Deploy your project and your prompts will appear here with version history and a live + editor. + +
+ ); +} diff --git a/apps/webapp/app/components/code/TSQLResultsTable.tsx b/apps/webapp/app/components/code/TSQLResultsTable.tsx index b2caf74dac6..73ca07180bf 100644 --- a/apps/webapp/app/components/code/TSQLResultsTable.tsx +++ b/apps/webapp/app/components/code/TSQLResultsTable.tsx @@ -460,10 +460,12 @@ function CellValueWrapper({ value, column, prettyFormatting, + row, }: { value: unknown; column: OutputColumnMetadata; prettyFormatting: boolean; + row?: Record; }) { const [hovered, setHovered] = useState(false); @@ -478,6 +480,7 @@ function CellValueWrapper({ column={column} prettyFormatting={prettyFormatting} hovered={hovered} + row={row} /> ); @@ -491,11 +494,13 @@ function CellValue({ column, prettyFormatting = true, hovered = false, + row, }: { value: unknown; column: OutputColumnMetadata; prettyFormatting?: boolean; hovered?: boolean; + row?: Record; }) { // Plain text mode - render everything as monospace text with truncation if (!prettyFormatting) { @@ -562,12 +567,20 @@ function CellValue({ switch (column.customRenderType) { case "runId": { if (typeof value === "string") { + const spanId = row?.["span_id"]; + const runPath = v3RunPathFromFriendlyId(value); + const href = typeof spanId === "string" && spanId + ? `${runPath}?span=${spanId}` + : runPath; + const tooltip = typeof spanId === "string" && spanId + ? "Jump to span" + : "Jump to run"; return (