diff --git a/.claude/commands/Yaak:generate-release-notes.md b/.claude/commands/Yaak:generate-release-notes.md index 87377224..2710356f 100644 --- a/.claude/commands/Yaak:generate-release-notes.md +++ b/.claude/commands/Yaak:generate-release-notes.md @@ -8,7 +8,9 @@ Generate formatted release notes for Yaak releases by analyzing git history and ## What to do 1. Identifies the version tag and previous version -2. Retrieves all commits between versions (scoped to stable or beta) +2. Retrieves all commits between versions + - If the version is a beta version, it retrieves commits between the beta version and previous beta version + - If the version is a stable version, it retrieves commits between the stable version and the previous stable version 3. Fetches PR descriptions for linked issues to find: - Feedback URLs (feedback.yaak.app) - Additional context and descriptions diff --git a/packages/plugin-runtime/src/PluginInstance.ts b/packages/plugin-runtime/src/PluginInstance.ts index 0fd1059e..990a9b43 100644 --- a/packages/plugin-runtime/src/PluginInstance.ts +++ b/packages/plugin-runtime/src/PluginInstance.ts @@ -1,3 +1,7 @@ +import console from 'node:console'; +import { type Stats, statSync, watch } from 'node:fs'; +import path from 'node:path'; +import type { Context, PluginDefinition } from '@yaakapp/api'; import { applyFormInputDefaults, validateTemplateFunctionArgs, @@ -34,10 +38,6 @@ import type { UpsertModelResponse, WindowInfoResponse, } from '@yaakapp-internal/plugins'; -import type { Context, PluginDefinition } from '@yaakapp/api'; -import console from 'node:console'; -import { type Stats, statSync, watch } from 'node:fs'; -import path from 'node:path'; import { applyDynamicFormInput } from './common'; import { EventChannel } from './EventChannel'; import { migrateTemplateFunctionSelectOptions } from './migrations'; diff --git a/packages/plugin-runtime/src/index.ts b/packages/plugin-runtime/src/index.ts index de518771..76af712b 100644 --- a/packages/plugin-runtime/src/index.ts +++ b/packages/plugin-runtime/src/index.ts @@ -1,7 +1,7 @@ import type { InternalEvent } from '@yaakapp/api'; +import WebSocket from 'ws'; import { EventChannel } from './EventChannel'; import { PluginHandle } from './PluginHandle'; -import WebSocket from 'ws'; const port = process.env.PORT; if (!port) { @@ -67,3 +67,7 @@ async function handleIncoming(msg: string) { process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); }); + +process.on('uncaughtException', (error) => { + console.error('Uncaught Exception:', error); +}); diff --git a/plugins-external/mcp-server/src/tools/folder.ts b/plugins-external/mcp-server/src/tools/folder.ts index 0a6cc533..60ed92ee 100644 --- a/plugins-external/mcp-server/src/tools/folder.ts +++ b/plugins-external/mcp-server/src/tools/folder.ts @@ -1,5 +1,5 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import * as z from 'zod/v4'; +import * as z from 'zod'; import type { McpServerContext } from '../types.js'; import { getWorkspaceContext } from './helpers.js'; diff --git a/plugins-external/mcp-server/src/tools/httpRequest.ts b/plugins-external/mcp-server/src/tools/httpRequest.ts index 7cfc0927..630a6cb6 100644 --- a/plugins-external/mcp-server/src/tools/httpRequest.ts +++ b/plugins-external/mcp-server/src/tools/httpRequest.ts @@ -1,5 +1,5 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import * as z from 'zod/v4'; +import * as z from 'zod'; import type { McpServerContext } from '../types.js'; import { getWorkspaceContext } from './helpers.js'; @@ -131,6 +131,42 @@ export function registerHttpRequestTools(server: McpServer, ctx: McpServerContex ) .optional() .describe('URL query parameters'), + bodyType: z + .string() + .optional() + .describe( + 'Body type. Supported values: "binary", "graphql", "application/x-www-form-urlencoded", "multipart/form-data", or any text-based type (e.g., "application/json", "text/plain")', + ), + body: z + .record(z.string(), z.any()) + .optional() + .describe( + 'Body content object. Structure varies by bodyType:\n' + + '- "binary": { filePath: "/path/to/file" }\n' + + '- "graphql": { query: "{ users { name } }", variables: "{\\"id\\": \\"123\\"}" }\n' + + '- "application/x-www-form-urlencoded": { form: [{ name: "key", value: "val", enabled: true }] }\n' + + '- "multipart/form-data": { form: [{ name: "field", value: "text", file: "/path/to/file", enabled: true }] }\n' + + '- text-based (application/json, etc.): { text: "raw body content" }', + ), + authenticationType: z + .string() + .optional() + .describe( + 'Authentication type. Common values: "basic", "bearer", "oauth2", "apikey", "jwt", "awsv4", "oauth1", "ntlm", "none". Use null to inherit from parent folder/workspace.', + ), + authentication: z + .record(z.string(), z.any()) + .optional() + .describe( + 'Authentication configuration object. Structure varies by authenticationType:\n' + + '- "basic": { username: "user", password: "pass" }\n' + + '- "bearer": { token: "abc123", prefix: "Bearer" }\n' + + '- "oauth2": { clientId: "...", clientSecret: "...", grantType: "authorization_code", authorizationUrl: "...", accessTokenUrl: "...", scope: "...", ... }\n' + + '- "apikey": { location: "header" | "query", key: "X-API-Key", value: "..." }\n' + + '- "jwt": { algorithm: "HS256", secret: "...", payload: "{ ... }" }\n' + + '- "awsv4": { accessKeyId: "...", secretAccessKey: "...", service: "sts", region: "us-east-1", sessionToken: "..." }\n' + + '- "none": {}', + ), }), }, async ({ workspaceId: ogWorkspaceId, ...args }) => { @@ -158,10 +194,7 @@ export function registerHttpRequestTools(server: McpServer, ctx: McpServerContex description: 'Update an existing HTTP request', inputSchema: z.object({ id: z.string().describe('HTTP request ID to update'), - workspaceId: z - .string() - .optional() - .describe('Workspace ID (required if multiple workspaces are open)'), + workspaceId: z.string().describe('Workspace ID'), name: z.string().optional().describe('Request name'), url: z.string().optional().describe('Request URL'), method: z.string().optional().describe('HTTP method'), @@ -187,11 +220,57 @@ export function registerHttpRequestTools(server: McpServer, ctx: McpServerContex ) .optional() .describe('URL query parameters'), + bodyType: z + .string() + .optional() + .describe( + 'Body type. Supported values: "binary", "graphql", "application/x-www-form-urlencoded", "multipart/form-data", or any text-based type (e.g., "application/json", "text/plain")', + ), + body: z + .record(z.string(), z.any()) + .optional() + .describe( + 'Body content object. Structure varies by bodyType:\n' + + '- "binary": { filePath: "/path/to/file" }\n' + + '- "graphql": { query: "{ users { name } }", variables: "{\\"id\\": \\"123\\"}" }\n' + + '- "application/x-www-form-urlencoded": { form: [{ name: "key", value: "val", enabled: true }] }\n' + + '- "multipart/form-data": { form: [{ name: "field", value: "text", file: "/path/to/file", enabled: true }] }\n' + + '- text-based (application/json, etc.): { text: "raw body content" }', + ), + authenticationType: z + .string() + .optional() + .describe( + 'Authentication type. Common values: "basic", "bearer", "oauth2", "apikey", "jwt", "awsv4", "oauth1", "ntlm", "none". Use null to inherit from parent folder/workspace.', + ), + authentication: z + .record(z.string(), z.any()) + .optional() + .describe( + 'Authentication configuration object. Structure varies by authenticationType:\n' + + '- "basic": { username: "user", password: "pass" }\n' + + '- "bearer": { token: "abc123", prefix: "Bearer" }\n' + + '- "oauth2": { clientId: "...", clientSecret: "...", grantType: "authorization_code", authorizationUrl: "...", accessTokenUrl: "...", scope: "...", ... }\n' + + '- "apikey": { location: "header" | "query", key: "X-API-Key", value: "..." }\n' + + '- "jwt": { algorithm: "HS256", secret: "...", payload: "{ ... }" }\n' + + '- "awsv4": { accessKeyId: "...", secretAccessKey: "...", service: "sts", region: "us-east-1", sessionToken: "..." }\n' + + '- "none": {}', + ), }), }, async ({ id, workspaceId, ...updates }) => { const workspaceCtx = await getWorkspaceContext(ctx, workspaceId); - const httpRequest = await workspaceCtx.yaak.httpRequest.update({ id, ...updates }); + // Fetch existing request to merge with updates + const existing = await workspaceCtx.yaak.httpRequest.getById({ id }); + if (!existing) { + throw new Error(`HTTP request with ID ${id} not found`); + } + // Merge existing fields with updates + const httpRequest = await workspaceCtx.yaak.httpRequest.update({ + ...existing, + ...updates, + id, + }); return { content: [{ type: 'text' as const, text: JSON.stringify(httpRequest, null, 2) }], }; diff --git a/plugins-external/mcp-server/src/tools/toast.ts b/plugins-external/mcp-server/src/tools/toast.ts index e90a3c63..9c9250ee 100644 --- a/plugins-external/mcp-server/src/tools/toast.ts +++ b/plugins-external/mcp-server/src/tools/toast.ts @@ -1,6 +1,6 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { Color, Icon } from '@yaakapp/api'; -import * as z from 'zod/v4'; +import * as z from 'zod'; import type { McpServerContext } from '../types.js'; const ICON_VALUES = [ diff --git a/plugins-external/mcp-server/src/tools/window.ts b/plugins-external/mcp-server/src/tools/window.ts index a08ae9db..03e97af8 100644 --- a/plugins-external/mcp-server/src/tools/window.ts +++ b/plugins-external/mcp-server/src/tools/window.ts @@ -1,5 +1,5 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import * as z from 'zod/v4'; +import * as z from 'zod'; import type { McpServerContext } from '../types.js'; import { getWorkspaceContext } from './helpers.js'; diff --git a/plugins-external/mcp-server/src/tools/workspace.ts b/plugins-external/mcp-server/src/tools/workspace.ts index 480afd60..a3b59d98 100644 --- a/plugins-external/mcp-server/src/tools/workspace.ts +++ b/plugins-external/mcp-server/src/tools/workspace.ts @@ -1,5 +1,5 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import * as z from 'zod/v4'; +import * as z from 'zod'; import type { McpServerContext } from '../types.js'; export function registerWorkspaceTools(server: McpServer, ctx: McpServerContext) { diff --git a/plugins/themes-yaak/src/themes/synthwave-84.ts b/plugins/themes-yaak/src/themes/synthwave-84.ts index 4a2fb82c..e32d2ff0 100644 --- a/plugins/themes-yaak/src/themes/synthwave-84.ts +++ b/plugins/themes-yaak/src/themes/synthwave-84.ts @@ -10,9 +10,9 @@ export const synthwave84: Theme = { text: 'hsl(300, 50%, 90%)', textSubtle: 'hsl(280, 25%, 65%)', textSubtlest: 'hsl(280, 20%, 50%)', - primary: 'hsl(177, 100%, 55%)', + primary: 'hsl(320, 100%, 75%)', secondary: 'hsl(280, 20%, 60%)', - info: 'hsl(320, 100%, 75%)', + info: 'hsl(177, 100%, 55%)', success: 'hsl(83, 100%, 60%)', notice: 'hsl(57, 100%, 60%)', warning: 'hsl(30, 100%, 60%)', @@ -35,9 +35,9 @@ export const synthwave84: Theme = { border: 'hsl(253, 40%, 22%)', }, button: { - primary: 'hsl(177, 100%, 48%)', + primary: 'hsl(320, 100%, 68%)', secondary: 'hsl(280, 20%, 53%)', - info: 'hsl(320, 100%, 68%)', + info: 'hsl(177, 100%, 48%)', success: 'hsl(83, 100%, 53%)', notice: 'hsl(57, 100%, 53%)', warning: 'hsl(30, 100%, 53%)',