diff --git a/apps/server/package.json b/apps/server/package.json index 8e7b5b38591..657d436b0ae 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -23,6 +23,9 @@ }, "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.3.170", + "@copilotkit/channels-core": "0.7.3", + "@copilotkit/channels-discord": "0.7.3", + "@copilotkit/channels-ui": "0.7.3", "@effect/platform-bun": "catalog:", "@effect/platform-node": "catalog:", "@effect/platform-node-shared": "catalog:", @@ -32,7 +35,8 @@ "@pierre/diffs": "catalog:", "effect": "catalog:", "node-pty": "^1.1.0", - "yaml": "catalog:" + "yaml": "catalog:", + "zod": "^4.4.3" }, "devDependencies": { "@effect/vitest": "catalog:", diff --git a/apps/server/src/channels/T3CodeDiscordChannel.test.ts b/apps/server/src/channels/T3CodeDiscordChannel.test.ts new file mode 100644 index 00000000000..991efabd83f --- /dev/null +++ b/apps/server/src/channels/T3CodeDiscordChannel.test.ts @@ -0,0 +1,255 @@ +import { expect, it } from "@effect/vitest"; +import { + DiscordChannelSettings, + ProjectId, + ProviderDriverKind, + ProviderInstanceId, + type ServerProvider, + ThreadId, +} from "@t3tools/contracts"; +import * as Schema from "effect/Schema"; +import { describe } from "vite-plus/test"; +import { renderToIR } from "@copilotkit/channels-ui"; + +import { + assistantResponseText, + channelBranchName, + channelTaskState, + createDiscordClient, + discordModelOptions, + isDeliverableTaskResponse, + isDiscordChannelConfigured, + resolveDiscordModel, + taskStatusText, + taskStatusUi, + taskResponseUi, +} from "./T3CodeDiscordChannel.ts"; + +const decodeDiscordChannelSettings = Schema.decodeSync(DiscordChannelSettings); + +const configuredDiscord = { + enabled: true, + projectId: ProjectId.make("project-1"), + modelSelection: null, + threadEnvMode: "worktree", + baseBranch: "main", + branchPrefix: "demo/discord", + applicationId: "app-1", + guildId: "guild-1", + botToken: "token", + botTokenRedacted: true, +} as const; + +describe("Discord channel isolation", () => { + it("keeps isolated worktrees as the default for existing settings", () => { + const defaults = decodeDiscordChannelSettings({}); + expect(defaults.threadEnvMode).toBe("worktree"); + expect(defaults.modelSelection).toBeNull(); + }); + + it("creates a unique task branch below the configured prefix", () => { + expect( + channelBranchName({ + prefix: "/demo/discord/", + prompt: "Fix the flaky login test!", + suffix: "a1b2c3d4", + }), + ).toBe("demo/discord/fix-the-flaky-login-test-a1b2c3d4"); + }); + + it("never resolves a task branch to main", () => { + expect( + channelBranchName({ prefix: "demo/discord", prompt: "main", suffix: "12345678" }), + ).not.toBe("main"); + }); + + it("refuses to start without an isolated branch prefix", () => { + expect(isDiscordChannelConfigured({ ...configuredDiscord, branchPrefix: "" })).toBe(false); + }); + + it("does not require branch settings when tasks run in the project checkout", () => { + expect( + isDiscordChannelConfigured({ + ...configuredDiscord, + threadEnvMode: "local", + baseBranch: "", + branchPrefix: "", + }), + ).toBe(true); + }); + + it("refuses to start while the integration is disabled", () => { + expect(isDiscordChannelConfigured({ ...configuredDiscord, enabled: false })).toBe(false); + }); +}); + +describe("Discord channel model selection", () => { + const provider = { + instanceId: ProviderInstanceId.make("codex"), + driver: ProviderDriverKind.make("codex"), + displayName: "Codex", + enabled: true, + installed: true, + version: null, + status: "ready", + availability: "available", + auth: { status: "authenticated" }, + checkedAt: "2026-08-07T00:00:00.000Z", + models: [ + { + slug: "gpt-5.6-sol", + name: "GPT-5.6 Sol", + isCustom: false, + capabilities: null, + }, + { + slug: "gpt-5.4", + name: "GPT-5.4", + isCustom: false, + isLegacy: true, + capabilities: null, + }, + ], + slashCommands: [], + skills: [], + } satisfies ServerProvider; + + it("offers current models from runnable provider instances", () => { + expect(discordModelOptions([provider])).toEqual([ + { + value: "codex/gpt-5.6-sol", + label: "Codex · GPT-5.6 Sol", + selection: { + instanceId: ProviderInstanceId.make("codex"), + model: "gpt-5.6-sol", + }, + }, + ]); + expect( + discordModelOptions([{ ...provider, auth: { status: "unauthenticated" } } as ServerProvider]), + ).toEqual([]); + }); + + it("routes the selected Discord value to the exact provider and model", () => { + const models = discordModelOptions([provider]); + expect(resolveDiscordModel(models, "codex/gpt-5.6-sol")?.selection).toEqual({ + instanceId: ProviderInstanceId.make("codex"), + model: "gpt-5.6-sol", + }); + expect(resolveDiscordModel(models, "codex/missing")).toBeUndefined(); + }); + + it("renders a minimal CopilotKit status that can be edited as a task progresses", () => { + const task = { + threadId: ThreadId.make("thread-1"), + title: "Fix login", + branch: null, + threadEnvMode: "local", + modelSelection: { + instanceId: ProviderInstanceId.make("codex"), + model: "gpt-5.6-sol", + }, + state: "running", + assistantResponse: null, + } as const; + + expect(taskStatusText(task)).toBe("Fix login 🔄"); + expect( + taskStatusText({ + ...task, + state: "done", + assistantResponse: "Fixed the login flow and added coverage.", + }), + ).toBe("Fix login ✅"); + expect(taskStatusText(task)).not.toContain("Model:"); + expect(taskStatusText(task)).not.toContain("Target:"); + const rendered = renderToIR(taskStatusUi(task)); + expect(rendered).toMatchObject([ + { + type: "message", + props: { + fallbackText: "Fix login 🔄", + children: [{ type: "section" }, { type: "context" }], + }, + }, + ]); + expect(JSON.stringify(rendered)).toContain("Powered by CopilotKit"); + expect(JSON.stringify(renderToIR(taskResponseUi("Final response")))).toContain( + "Final response", + ); + expect( + isDeliverableTaskResponse(false, { ...task, state: "done", assistantResponse: "old" }), + ).toBe(false); + expect( + isDeliverableTaskResponse(true, { + ...task, + state: "done", + assistantResponse: "Final response", + }), + ).toBe(true); + expect( + channelTaskState({ + latestTurnState: null, + sessionStatus: "ready", + assistantResponse: "Final response", + }), + ).toBe("done"); + }); + + it("uses the final assistant message as the completed Discord response", () => { + expect( + assistantResponseText({ + assistantMessageId: "assistant-final", + turnId: "turn-1", + messages: [ + { id: "assistant-progress", role: "assistant", text: "Working", turnId: "turn-1" }, + { + id: "assistant-final", + role: "assistant", + text: " The requested change is complete. ", + turnId: "turn-1", + }, + ], + }), + ).toBe("The requested change is complete."); + }); + + it("updates the bot profile and sends a rendered reply to the status message", async () => { + const requests: Array<{ readonly url: string; readonly init?: RequestInit }> = []; + const fetchImpl = (async (url: string | URL | Request, init?: RequestInit) => { + const requestUrl = String(url); + requests.push({ url: requestUrl, ...(init ? { init } : {}) }); + return new Response( + JSON.stringify( + requestUrl.endsWith("/users/@me") && init?.method === "GET" + ? { username: "copilotkit-ad" } + : { id: "message-1" }, + ), + { + status: 200, + headers: { "Content-Type": "application/json" }, + }, + ); + }) as typeof fetch; + const client = createDiscordClient("secret", fetchImpl); + + await client.ensureBotUsername("copilotkit"); + await client.setGuildNickname("guild-1", "copilotkit"); + await client.reply( + { id: "status-1", channelId: "channel-1" }, + taskResponseUi("The task is complete."), + ); + + expect(requests.map(({ init }) => init?.method)).toEqual(["GET", "PATCH", "PATCH", "POST"]); + expect(requests[1]?.url).toContain("/users/@me"); + expect(requests[2]?.url).toContain("/guilds/guild-1/members/@me"); + expect(JSON.parse(String(requests[1]?.init?.body))).toEqual({ username: "copilotkit" }); + expect(JSON.parse(String(requests[2]?.init?.body))).toEqual({ nick: "copilotkit" }); + const replyBody = JSON.parse(String(requests[3]?.init?.body)); + expect(replyBody.message_reference).toEqual({ + message_id: "status-1", + channel_id: "channel-1", + }); + expect(JSON.stringify(replyBody.components)).toContain("The task is complete."); + }); +}); diff --git a/apps/server/src/channels/T3CodeDiscordChannel.ts b/apps/server/src/channels/T3CodeDiscordChannel.ts new file mode 100644 index 00000000000..a2a9d7471cd --- /dev/null +++ b/apps/server/src/channels/T3CodeDiscordChannel.ts @@ -0,0 +1,888 @@ +import { createChannel, defineChannelCommand } from "@copilotkit/channels-core"; +import { discord, renderDiscordMessage } from "@copilotkit/channels-discord"; +import { + Context, + Message, + Section, + type MessageRef, + type Renderable, + type Thread, + renderToIR, +} from "@copilotkit/channels-ui"; +import { + CommandId, + type DiscordChannelSettings, + MessageId, + type ModelSelection, + type ServerProvider, + type ServerSettings, + ThreadId, +} from "@t3tools/contracts"; +import * as Crypto from "effect/Crypto"; +import * as DateTime from "effect/DateTime"; +import * as Effect from "effect/Effect"; +import * as Layer from "effect/Layer"; +import * as Option from "effect/Option"; +import * as Ref from "effect/Ref"; +import * as Schedule from "effect/Schedule"; +import * as Schema from "effect/Schema"; +import * as Stream from "effect/Stream"; +import { z } from "zod"; + +import { GitWorkflowService } from "../git/GitWorkflowService.ts"; +import { OrchestrationEngineService } from "../orchestration/Services/OrchestrationEngine.ts"; +import { ProjectionSnapshotQuery } from "../orchestration/Services/ProjectionSnapshotQuery.ts"; +import { ProviderRegistry } from "../provider/Services/ProviderRegistry.ts"; +import { forkParked } from "../serverActivation.ts"; +import { ServerSettingsService } from "../serverSettings.ts"; + +const MAX_TITLE_LENGTH = 72; +const MAX_BRANCH_SLUG_LENGTH = 40; + +export interface ChannelTaskStatus { + readonly threadId: ThreadId; + readonly title: string; + readonly branch: string | null; + readonly threadEnvMode: "local" | "worktree"; + readonly modelSelection: ModelSelection; + readonly state: "queued" | "running" | "done" | "failed"; + readonly assistantResponse: string | null; +} + +export interface StartedChannelTask extends ChannelTaskStatus { + readonly state: "queued"; +} + +export interface T3CodeChannelOperations { + readonly startTask: ( + prompt: string, + config: DiscordChannelSettings, + modelSelection?: ModelSelection, + ) => Promise; + readonly getTaskStatus: ( + threadId: ThreadId, + assistantMessageId?: MessageId, + ) => Promise; + readonly listModels: () => Promise>; + readonly setDefaultModel: (modelSelection: ModelSelection) => Promise; +} + +interface LinkedConversationState { + readonly t3ThreadId?: string; + readonly modelSelection?: ModelSelection; +} + +export interface DiscordModelOption { + readonly value: string; + readonly label: string; + readonly selection: ModelSelection; +} + +export function discordModelOptions( + providers: ReadonlyArray, +): ReadonlyArray { + return providers.flatMap((provider) => { + if ( + !provider.enabled || + !provider.installed || + provider.auth.status === "unauthenticated" || + provider.availability === "unavailable" + ) { + return []; + } + return provider.models + .filter((model) => model.isLegacy !== true) + .map((model) => ({ + value: `${provider.instanceId}/${model.slug}`, + label: `${provider.displayName ?? provider.instanceId} · ${model.name}`, + selection: { instanceId: provider.instanceId, model: model.slug }, + })); + }); +} + +export function resolveDiscordModel( + models: ReadonlyArray, + value: string, +): DiscordModelOption | undefined { + return models.find((model) => model.value === value); +} + +type ChannelThread = Pick & { + readonly state: () => Promise; + readonly setState: (value: unknown) => Promise; +}; + +interface DiscordClient { + readonly ensureBotUsername: (username: string) => Promise; + readonly setGuildNickname: (guildId: string, nickname: string) => Promise; + readonly reply: (messageRef: MessageRef, ui: Renderable) => Promise; +} + +interface ActiveDiscordChannel { + readonly fingerprint: string; + readonly refreshTask: (threadId: ThreadId) => Promise; + readonly settleTask: (threadId: ThreadId) => Promise; + readonly deliverAssistantMessage: (threadId: ThreadId, messageId: MessageId) => Promise; + readonly refreshPendingTasks: () => Promise; + readonly stop: () => Promise; +} + +export function isDiscordChannelConfigured(config: DiscordChannelSettings): boolean { + return ( + config.enabled && + config.projectId !== null && + (config.threadEnvMode === "local" || + (config.baseBranch.trim().length > 0 && config.branchPrefix.trim().length > 0)) && + config.applicationId.length > 0 && + config.botToken.length > 0 + ); +} + +class DiscordChannelTaskError extends Schema.TaggedErrorClass()( + "DiscordChannelTaskError", + { message: Schema.String }, +) {} + +export function channelBranchName(input: { + readonly prefix: string; + readonly prompt: string; + readonly suffix: string; +}): string { + const slug = input.prompt + .toLocaleLowerCase() + .replace(/[^a-z0-9]+/gu, "-") + .replace(/^-+|-+$/gu, "") + .slice(0, MAX_BRANCH_SLUG_LENGTH) + .replace(/-+$/gu, ""); + const prefix = input.prefix.replace(/^\/+|\/+$/gu, ""); + return `${prefix}/${slug || "task"}-${input.suffix}`; +} + +function promptTitle(prompt: string): string { + const singleLine = prompt.replace(/\s+/gu, " ").trim(); + return singleLine.length <= MAX_TITLE_LENGTH + ? singleLine + : `${singleLine.slice(0, MAX_TITLE_LENGTH - 1).trimEnd()}…`; +} + +function cleanDiscordPrompt(input: string): string { + return input.replace(/<@!?\d+>/gu, "").trim(); +} + +function modelLabel(selection: ModelSelection): string { + return `${selection.instanceId}/${selection.model}`; +} + +function readConversationState(value: unknown): LinkedConversationState { + if (typeof value !== "object" || value === null) return {}; + const record = value as Record; + const t3ThreadId = typeof record.t3ThreadId === "string" ? record.t3ThreadId : undefined; + const candidate = record.modelSelection; + const modelSelection = + typeof candidate === "object" && + candidate !== null && + typeof (candidate as Record).instanceId === "string" && + typeof (candidate as Record).model === "string" + ? (candidate as ModelSelection) + : undefined; + return { ...(t3ThreadId ? { t3ThreadId } : {}), ...(modelSelection ? { modelSelection } : {}) }; +} + +export function taskStatusText(task: ChannelTaskStatus): string { + switch (task.state) { + case "queued": + return `${task.title} ⏳`; + case "running": + return `${task.title} 🔄`; + case "done": + return `${task.title} ✅`; + case "failed": + return `${task.title} ❌\n\nTask failed.`; + } +} + +export function taskStatusUi(task: ChannelTaskStatus): Renderable { + const text = taskStatusText(task); + return Message({ + fallbackText: text, + children: [Section({ children: text }), Context({ children: "Powered by CopilotKit" })], + }); +} + +export function taskResponseUi(response: string): Renderable { + return Message({ + fallbackText: response, + children: [Section({ children: response }), Context({ children: "Powered by CopilotKit" })], + }); +} + +export function isDeliverableTaskResponse(settled: boolean, task: ChannelTaskStatus): boolean { + return settled && task.state === "done" && task.assistantResponse !== null; +} + +export function channelTaskState(input: { + readonly latestTurnState: "running" | "interrupted" | "completed" | "error" | null | undefined; + readonly sessionStatus: + | "idle" + | "starting" + | "running" + | "ready" + | "interrupted" + | "stopped" + | "error" + | null + | undefined; + readonly assistantResponse: string | null; +}): ChannelTaskStatus["state"] { + if ( + input.latestTurnState === "error" || + input.latestTurnState === "interrupted" || + input.sessionStatus === "error" || + input.sessionStatus === "interrupted" || + input.sessionStatus === "stopped" + ) { + return "failed"; + } + if ( + input.latestTurnState === "completed" || + ((input.sessionStatus === "ready" || input.sessionStatus === "idle") && + input.assistantResponse !== null) + ) { + return "done"; + } + if (input.latestTurnState === "running" || input.sessionStatus === "running") return "running"; + return "queued"; +} + +export function assistantResponseText(input: { + readonly assistantMessageId: string | null | undefined; + readonly turnId: string | null | undefined; + readonly messages: ReadonlyArray<{ + readonly id: string; + readonly role: string; + readonly text: string; + readonly turnId: string | null; + }>; +}): string | null { + const exactMessage = input.assistantMessageId + ? input.messages.find((message) => message.id === input.assistantMessageId) + : undefined; + const fallbackMessage = input.turnId + ? input.messages.findLast( + (message) => message.role === "assistant" && message.turnId === input.turnId, + ) + : undefined; + const text = (exactMessage ?? fallbackMessage)?.text.trim(); + return text && text.length > 0 ? text : null; +} + +export function createDiscordClient( + botToken: string, + fetchImpl: typeof fetch = fetch, +): DiscordClient { + const request = async (url: string, method: "GET" | "POST" | "PATCH", body?: unknown) => { + const response = await fetchImpl(url, { + method, + headers: { + Authorization: `Bot ${botToken}`, + "Content-Type": "application/json", + }, + ...(body === undefined ? {} : { body: JSON.stringify(body) }), + }); + if (!response.ok) { + throw new Error(`Discord API request failed (${response.status})`); + } + return response; + }; + + return { + async ensureBotUsername(username) { + const current = await request("https://discord.com/api/v10/users/@me", "GET"); + const user = (await current.json()) as { readonly username?: unknown }; + if (user.username === username) return; + await request("https://discord.com/api/v10/users/@me", "PATCH", { username }); + }, + async setGuildNickname(guildId, nickname) { + await request(`https://discord.com/api/v10/guilds/${guildId}/members/@me`, "PATCH", { + nick: nickname, + }); + }, + async reply(messageRef, ui) { + const channelId = messageRef.channelId; + if (typeof channelId !== "string" || channelId.length === 0) { + throw new Error("Discord message reference did not include a channel id"); + } + const rendered = renderDiscordMessage(renderToIR(ui)); + await request(`https://discord.com/api/v10/channels/${channelId}/messages`, "POST", { + components: rendered.components.map((component) => component.toJSON()), + flags: rendered.flags, + message_reference: { + message_id: messageRef.id, + channel_id: channelId, + }, + allowed_mentions: { replied_user: false }, + }); + }, + }; +} + +function createT3CodeChannel(input: { + readonly config: DiscordChannelSettings; + readonly operations: T3CodeChannelOperations; + readonly models: ReadonlyArray; +}) { + const discordClient = createDiscordClient(input.config.botToken); + const linkedTasks = new Map< + string, + { + readonly thread: ChannelThread; + messageRef: MessageRef; + lastText: string; + settled: boolean; + settledPolls: number; + candidateAssistantMessageId: MessageId | null; + terminal: boolean; + } + >(); + const channel = createChannel({ + name: "t3-code", + identifyUser: "platform", + adapters: [ + discord({ + botToken: input.config.botToken, + appId: input.config.applicationId, + ...(input.config.guildId.length > 0 ? { guildId: input.config.guildId } : {}), + }), + ], + }); + + const postText = (thread: ChannelThread, text: string) => thread.post(text); + + const updateLinkedTask = async ( + threadId: ThreadId, + status: ChannelTaskStatus, + terminal = false, + ) => { + const linked = linkedTasks.get(threadId); + if (!linked) return; + const nextText = taskStatusText(status); + if (nextText !== linked.lastText) { + linked.messageRef = await linked.thread.update(linked.messageRef, taskStatusUi(status)); + linked.lastText = nextText; + } + linked.terminal = terminal || status.state === "failed"; + }; + + const completeLinkedTask = async (threadId: ThreadId, status: ChannelTaskStatus) => { + const linked = linkedTasks.get(threadId); + if (!linked || linked.terminal || status.assistantResponse === null) return; + await updateLinkedTask(threadId, status); + await discordClient.reply(linked.messageRef, taskResponseUi(status.assistantResponse)); + linked.terminal = true; + }; + + const postStatus = async (thread: ChannelThread, threadId: ThreadId) => { + const status = await input.operations.getTaskStatus(threadId); + if (!status) { + await postText(thread, "That T3 Code task no longer exists."); + return; + } + const linked = linkedTasks.get(threadId); + if (linked) { + if (isDeliverableTaskResponse(linked.settled, status)) { + await completeLinkedTask(threadId, status); + } else if (status.state !== "done") { + await updateLinkedTask(threadId, status, status.state === "failed"); + } + return; + } + const messageRef = await thread.post(taskStatusUi(status)); + if (status.state === "done" && status.assistantResponse !== null) { + await discordClient.reply(messageRef, taskResponseUi(status.assistantResponse)); + } + }; + + const handleText = async (thread: ChannelThread, rawText: string) => { + const text = cleanDiscordPrompt(rawText); + const state = readConversationState(await thread.state()); + if (text.toLocaleLowerCase() === "status") { + if (!state?.t3ThreadId) { + await postText(thread, "No T3 Code task is linked to this Discord thread yet."); + return; + } + await postStatus(thread, ThreadId.make(state.t3ThreadId)); + return; + } + if (text.length === 0) { + await postText(thread, "Use `/t3` with a coding task."); + return; + } + + if (state?.t3ThreadId) { + const current = await input.operations.getTaskStatus(ThreadId.make(state.t3ThreadId)); + if (current?.state === "queued" || current?.state === "running") { + await postStatus(thread, current.threadId); + return; + } + } + + try { + const task = await input.operations.startTask(text, input.config, state.modelSelection); + await thread.setState({ + ...state, + t3ThreadId: task.threadId, + } satisfies LinkedConversationState); + const initialText = taskStatusText(task); + const messageRef = await thread.post(taskStatusUi(task)); + linkedTasks.set(task.threadId, { + thread, + messageRef, + lastText: initialText, + settled: false, + settledPolls: 0, + candidateAssistantMessageId: null, + terminal: false, + }); + await postStatus(thread, task.threadId); + } catch { + await postText( + thread, + input.config.threadEnvMode === "worktree" + ? "❌ T3 Code could not start\nThe isolated worktree could not be created, so the agent did not run." + : "❌ T3 Code could not start\nCheck the project and provider configuration.", + ); + } + }; + + channel.onCommand( + defineChannelCommand({ + name: "t3", + description: "Run a coding task in T3 Code with the selected model.", + options: z.object({ + prompt: z.string().min(1).describe("The coding task for T3 Code"), + }), + handler: ({ thread, text, options }) => handleText(thread, options.prompt ?? text), + }), + ); + channel.onCommand( + defineChannelCommand({ + name: "status", + description: "Show the status of the T3 Code task linked to this channel.", + handler: ({ thread }) => handleText(thread, "status"), + }), + ); + + const selectableModels = input.models.slice(0, 25); + const modelValues = selectableModels.map(({ value }) => value); + const modelSchema = + modelValues.length > 0 ? z.enum(modelValues as [string, ...string[]]) : z.string().min(1); + channel.onCommand( + defineChannelCommand({ + name: "model", + description: "Choose the model used by future T3 Code tasks in this channel.", + options: z.object({ + model: modelSchema.describe("Provider and model"), + }), + async handler({ thread, options }) { + const selected = resolveDiscordModel(selectableModels, options.model); + if (!selected) { + await postText( + thread, + "That model is not currently available. Run `/models` to see the list.", + ); + return; + } + const state = readConversationState(await thread.state()); + await thread.setState({ + ...state, + modelSelection: selected.selection, + } satisfies LinkedConversationState); + await postText(thread, `Default model saved: ${selected.label} (${selected.value}).`); + await input.operations.setDefaultModel(selected.selection); + }, + }), + ); + channel.onCommand( + defineChannelCommand({ + name: "models", + description: "List models available to T3 Code and show the current selection.", + async handler({ thread }) { + const state = readConversationState(await thread.state()); + const effectiveSelection = state.modelSelection ?? input.config.modelSelection; + const current = effectiveSelection ? modelLabel(effectiveSelection) : "project default"; + const list = selectableModels.map(({ value, label }) => `- ${value} — ${label}`).join("\n"); + await postText( + thread, + `Current model: ${current}\n\n${list || "No runnable models are currently available."}`, + ); + }, + }), + ); + + const refreshTask = async (threadId: ThreadId) => { + const linked = linkedTasks.get(threadId); + if (!linked || linked.terminal) return; + const task = await input.operations.getTaskStatus(threadId); + if (!task) return; + if (task.state === "failed") { + await updateLinkedTask(threadId, task, true); + return; + } + if (task.state === "queued" || task.state === "running") { + await updateLinkedTask(threadId, task); + } + }; + + const settleTask = async (threadId: ThreadId) => { + const linked = linkedTasks.get(threadId); + if (!linked || linked.terminal) return; + // ProviderRuntimeIngestion projects `ready` before it flushes the buffered + // final assistant message. Mark the lifecycle boundary, but wait for the + // subsequent non-streaming message event before completing Discord. + linked.settled = true; + linked.settledPolls = 0; + linked.candidateAssistantMessageId = null; + const task = await input.operations.getTaskStatus(threadId); + if (task?.state === "failed") { + await updateLinkedTask(threadId, task, true); + } + }; + + const deliverAssistantMessage = async (threadId: ThreadId, messageId: MessageId) => { + const linked = linkedTasks.get(threadId); + if (!linked || linked.terminal || !linked.settled) return; + // A turn can flush multiple assistant segments. Keep the newest exact + // message id and let the quiet-period poll deliver only the final segment. + linked.candidateAssistantMessageId = messageId; + linked.settledPolls = 0; + }; + + return { + channel, + refreshTask, + settleTask, + deliverAssistantMessage, + refreshPendingTasks: async () => { + await Promise.all( + Array.from(linkedTasks) + .filter(([, linked]) => !linked.terminal) + .map(async ([threadId, linked]) => { + const id = ThreadId.make(threadId); + if (!linked.settled) { + await refreshTask(id); + return; + } + linked.settledPolls += 1; + if (linked.settledPolls < 2) return; + const task = await input.operations.getTaskStatus( + id, + linked.candidateAssistantMessageId ?? undefined, + ); + if (!task || !isDeliverableTaskResponse(linked.settled, task)) return; + await completeLinkedTask(id, task); + }), + ); + }, + setDisplayName: async () => { + const updates = [discordClient.ensureBotUsername("copilotkit")]; + if (input.config.guildId.length > 0) { + updates.push(discordClient.setGuildNickname(input.config.guildId, "copilotkit")); + } + const results = await Promise.allSettled(updates); + if (results.some((result) => result.status === "fulfilled")) return; + const failure = results.find((result) => result.status === "rejected"); + throw failure?.reason ?? new Error("Discord bot display name could not be updated"); + }, + stop: () => channel.ɵruntime.stop(), + }; +} + +const makeOperations = Effect.gen(function* () { + const crypto = yield* Crypto.Crypto; + const gitWorkflow = yield* GitWorkflowService; + const orchestrationEngine = yield* OrchestrationEngineService; + const projectionSnapshotQuery = yield* ProjectionSnapshotQuery; + const providerRegistry = yield* ProviderRegistry; + const settingsService = yield* ServerSettingsService; + const runtimeContext = yield* Effect.context(); + const runPromise = Effect.runPromiseWith(runtimeContext); + + const nextId = Effect.fn("T3CodeDiscordChannel.nextId")(function* (prefix: string) { + const uuid = yield* crypto.randomUUIDv4; + return `${prefix}-${uuid}`; + }); + + const createTaskWorktree = Effect.fn("T3CodeDiscordChannel.createTaskWorktree")(function* ( + prompt: string, + config: DiscordChannelSettings, + workspaceRoot: string, + ) { + const suffix = (yield* nextId("branch")).slice(-8); + const branch = channelBranchName({ + prefix: config.branchPrefix, + prompt, + suffix, + }); + if (branch === config.baseBranch) { + return yield* new DiscordChannelTaskError({ + message: "Discord channel branch must differ from its base branch", + }); + } + return yield* gitWorkflow.createWorktree({ + cwd: workspaceRoot, + refName: config.baseBranch, + baseRefName: config.baseBranch, + newRefName: branch, + path: null, + }); + }); + + const startTaskEffect = Effect.fn("T3CodeDiscordChannel.startTask")(function* ( + prompt: string, + config: DiscordChannelSettings, + requestedModelSelection?: ModelSelection, + ) { + if (config.projectId === null) { + return yield* new DiscordChannelTaskError({ + message: "Discord channel project is not configured", + }); + } + const projectOption = yield* projectionSnapshotQuery.getProjectShellById(config.projectId); + if (Option.isNone(projectOption)) { + return yield* new DiscordChannelTaskError({ + message: "Discord channel project was not found", + }); + } + const project = projectOption.value; + const modelSelection = + requestedModelSelection ?? config.modelSelection ?? project.defaultModelSelection; + if (modelSelection === null) { + return yield* new DiscordChannelTaskError({ + message: "Discord channel project has no default model", + }); + } + + const now = DateTime.formatIso(yield* DateTime.now); + const threadId = ThreadId.make(yield* nextId("channel-thread")); + const worktree = + config.threadEnvMode === "worktree" + ? yield* createTaskWorktree(prompt, config, project.workspaceRoot) + : null; + const title = promptTitle(prompt); + yield* orchestrationEngine.dispatch({ + type: "thread.create", + commandId: CommandId.make(yield* nextId("channel-create")), + threadId, + projectId: project.id, + title, + modelSelection, + runtimeMode: "full-access", + interactionMode: "default", + branch: worktree?.worktree.refName ?? null, + worktreePath: worktree?.worktree.path ?? null, + createdAt: now, + }); + yield* orchestrationEngine.dispatch({ + type: "thread.turn.start", + commandId: CommandId.make(yield* nextId("channel-turn")), + threadId, + message: { + messageId: MessageId.make(yield* nextId("channel-message")), + role: "user", + text: prompt, + attachments: [], + }, + runtimeMode: "full-access", + interactionMode: "default", + createdAt: now, + }); + return { + threadId, + title, + branch: worktree?.worktree.refName ?? null, + threadEnvMode: config.threadEnvMode, + modelSelection, + state: "queued" as const, + assistantResponse: null, + }; + }); + + const getTaskStatusEffect = Effect.fn("T3CodeDiscordChannel.getTaskStatus")(function* ( + threadId: ThreadId, + preferredAssistantMessageId?: MessageId, + ) { + const threadOption = yield* projectionSnapshotQuery.getThreadDetailById(threadId); + if (Option.isNone(threadOption)) return null; + const thread = threadOption.value; + const latestCompletedAssistantMessage = thread.messages.findLast( + (message) => message.role === "assistant" && !message.streaming, + ); + const resolvedAssistantMessageId = + preferredAssistantMessageId ?? + thread.latestTurn?.assistantMessageId ?? + latestCompletedAssistantMessage?.id; + const assistantResponse = assistantResponseText({ + assistantMessageId: resolvedAssistantMessageId, + turnId: resolvedAssistantMessageId ? undefined : thread.latestTurn?.turnId, + messages: thread.messages, + }); + const state = channelTaskState({ + latestTurnState: thread.latestTurn?.state, + sessionStatus: thread.session?.status, + assistantResponse, + }); + const threadEnvMode = thread.worktreePath === null ? ("local" as const) : ("worktree" as const); + return { + threadId, + title: thread.title, + branch: thread.branch, + threadEnvMode, + modelSelection: thread.modelSelection, + state, + assistantResponse, + }; + }); + + return { + startTask: (prompt, config, modelSelection) => + runPromise(startTaskEffect(prompt, config, modelSelection)), + getTaskStatus: (threadId, assistantMessageId) => + runPromise(getTaskStatusEffect(threadId, assistantMessageId)), + listModels: () => + runPromise(providerRegistry.getProviders.pipe(Effect.map(discordModelOptions))), + setDefaultModel: (modelSelection) => + runPromise( + settingsService + .updateSettings({ channelIntegrations: { discord: { modelSelection } } }) + .pipe(Effect.asVoid), + ), + } satisfies T3CodeChannelOperations; +}); + +function configFingerprint(config: DiscordChannelSettings): string { + return [ + config.enabled, + config.projectId, + config.modelSelection ? modelLabel(config.modelSelection) : "", + config.threadEnvMode, + config.baseBranch, + config.branchPrefix, + config.applicationId, + config.guildId, + config.botToken, + ].join("\u0000"); +} + +export const layer = Layer.effectDiscard( + Effect.gen(function* () { + const settingsService = yield* ServerSettingsService; + const orchestrationEngine = yield* OrchestrationEngineService; + const operations = yield* makeOperations; + const activeRef = yield* Ref.make(null); + + const stopActive = Effect.fn("T3CodeDiscordChannel.stopActive")(function* () { + const active = yield* Ref.getAndSet(activeRef, null); + if (!active) return; + yield* Effect.tryPromise(() => active.stop()).pipe(Effect.ignoreCause({ log: true })); + }); + + const reconcile = Effect.fn("T3CodeDiscordChannel.reconcile")(function* ( + settings: ServerSettings, + ) { + const config = settings.channelIntegrations.discord; + const fingerprint = configFingerprint(config); + const active = yield* Ref.get(activeRef); + if (active?.fingerprint === fingerprint) return; + yield* stopActive(); + if (!isDiscordChannelConfigured(config)) return; + + const models = yield* Effect.tryPromise(() => operations.listModels()).pipe( + Effect.orElseSucceed(() => []), + ); + const created = createT3CodeChannel({ config, operations, models }); + const connected = yield* Effect.tryPromise(() => created.channel.ɵruntime.start()).pipe( + Effect.timeout("15 seconds"), + Effect.as(true), + Effect.tapCause((cause) => + Effect.logWarning("Discord channel failed to connect", { cause }), + ), + Effect.catchCause(() => Effect.succeed(false)), + ); + if (!connected) { + yield* Effect.tryPromise(() => created.stop()).pipe(Effect.ignoreCause({ log: true })); + return; + } + yield* Effect.tryPromise(() => created.setDisplayName()).pipe( + Effect.timeout("5 seconds"), + Effect.ignoreCause({ log: true }), + ); + yield* Ref.set(activeRef, { + fingerprint, + refreshTask: created.refreshTask, + settleTask: created.settleTask, + deliverAssistantMessage: created.deliverAssistantMessage, + refreshPendingTasks: created.refreshPendingTasks, + stop: created.stop, + }); + }); + + yield* Effect.addFinalizer(() => stopActive()); + yield* forkParked( + Effect.scoped( + Effect.gen(function* () { + const changes = yield* settingsService.subscribeChanges; + yield* reconcile(yield* settingsService.getSettings); + yield* Stream.runForEach(changes, reconcile); + }), + ), + ); + yield* forkParked( + Stream.runForEach(orchestrationEngine.streamDomainEvents, (event) => { + if (event.type === "thread.message-sent") { + if (event.payload.role !== "assistant" || event.payload.streaming) { + return Effect.void; + } + return Ref.get(activeRef).pipe( + Effect.flatMap((active) => + active + ? Effect.tryPromise(() => + active.deliverAssistantMessage(event.payload.threadId, event.payload.messageId), + ).pipe(Effect.ignoreCause({ log: true })) + : Effect.void, + ), + ); + } + if (event.type !== "thread.session-set" && event.type !== "thread.turn-diff-completed") { + return Effect.void; + } + return Ref.get(activeRef).pipe( + Effect.flatMap((active) => + !active + ? Effect.void + : event.type === "thread.session-set" && + (event.payload.session.status === "ready" || + event.payload.session.status === "idle") + ? Effect.tryPromise(() => active.settleTask(event.payload.threadId)).pipe( + Effect.ignoreCause({ log: true }), + ) + : Effect.tryPromise(() => active.refreshTask(event.payload.threadId)).pipe( + Effect.ignoreCause({ log: true }), + ), + ), + ); + }), + ); + yield* forkParked( + Ref.get(activeRef).pipe( + Effect.flatMap((active) => + active + ? Effect.tryPromise(() => active.refreshPendingTasks()).pipe( + Effect.ignoreCause({ log: true }), + ) + : Effect.void, + ), + Effect.repeat(Schedule.spaced("1 second")), + ), + ); + }), +); diff --git a/apps/server/src/server.ts b/apps/server/src/server.ts index 49a3a31940f..7ddd7a30fae 100644 --- a/apps/server/src/server.ts +++ b/apps/server/src/server.ts @@ -65,6 +65,7 @@ import * as RepositoryIdentityResolver from "./project/RepositoryIdentityResolve import * as WorkspaceEntries from "./workspace/WorkspaceEntries.ts"; import * as WorkspaceFileSystem from "./workspace/WorkspaceFileSystem.ts"; import * as WorkspacePaths from "./workspace/WorkspacePaths.ts"; +import * as T3CodeDiscordChannel from "./channels/T3CodeDiscordChannel.ts"; import * as GitVcsDriver from "./vcs/GitVcsDriver.ts"; import * as VcsDriverRegistry from "./vcs/VcsDriverRegistry.ts"; import * as VcsProjectConfig from "./vcs/VcsProjectConfig.ts"; @@ -405,7 +406,11 @@ const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe( ), ); -const RuntimeDependenciesLive = RuntimeCoreDependenciesLive.pipe( +const RuntimeCoreWithChannelsLive = T3CodeDiscordChannel.layer.pipe( + Layer.provideMerge(RuntimeCoreDependenciesLive), +); + +const RuntimeDependenciesLive = RuntimeCoreWithChannelsLive.pipe( // Misc. Layer.provideMerge(BackgroundLayerLive), Layer.provideMerge(ResourceDiagnosticsLayerLive), diff --git a/apps/server/src/serverSettings.test.ts b/apps/server/src/serverSettings.test.ts index d38a3064910..c8d3d2cf63b 100644 --- a/apps/server/src/serverSettings.test.ts +++ b/apps/server/src/serverSettings.test.ts @@ -1,6 +1,7 @@ import * as NodeServices from "@effect/platform-node/NodeServices"; import { DEFAULT_SERVER_SETTINGS, + ProjectId, ProviderDriverKind, ProviderInstanceId, ServerSettings, @@ -691,4 +692,60 @@ it.layer(NodeServices.layer)("server settings", (it) => { ); }).pipe(Effect.provide(makeServerSettingsLayer())), ); + + it.effect("stores Discord channel credentials outside settings.json", () => + Effect.gen(function* () { + const serverSettings = yield* ServerSettingsModule.ServerSettingsService; + const serverConfig = yield* ServerConfig.ServerConfig; + const fileSystem = yield* FileSystem.FileSystem; + + const next = yield* serverSettings.updateSettings({ + channelIntegrations: { + discord: { + enabled: true, + projectId: ProjectId.make("project-1"), + threadEnvMode: "local", + baseBranch: "main", + branchPrefix: "demo/discord", + applicationId: "app-1", + guildId: "guild-1", + botToken: "discord-secret", + botTokenRedacted: false, + }, + }, + }); + + assert.equal(next.channelIntegrations.discord.botToken, "discord-secret"); + assert.equal(next.channelIntegrations.discord.threadEnvMode, "local"); + + const raw = yield* fileSystem.readFileString(serverConfig.settingsPath); + assert.notInclude(raw, "discord-secret"); + // @effect-diagnostics-next-line preferSchemaOverJson:off + const persisted = JSON.parse(raw).channelIntegrations.discord; + assert.equal(persisted.enabled, true); + assert.equal(persisted.projectId, "project-1"); + assert.equal(persisted.threadEnvMode, "local"); + assert.equal(persisted.baseBranch, "main"); + assert.equal(persisted.branchPrefix, "demo/discord"); + assert.equal(persisted.applicationId, "app-1"); + assert.equal(persisted.guildId, "guild-1"); + assert.equal(persisted.botToken, ""); + assert.equal(persisted.botTokenRedacted, true); + + const roundTripped = yield* serverSettings.updateSettings({ + channelIntegrations: { + discord: { + ...next.channelIntegrations.discord, + botToken: "", + botTokenRedacted: true, + }, + }, + }); + assert.equal(roundTripped.channelIntegrations.discord.botToken, "discord-secret"); + + const clientSettings = ServerSettingsModule.redactServerSettingsForClient(roundTripped); + assert.equal(clientSettings.channelIntegrations.discord.botToken, ""); + assert.equal(clientSettings.channelIntegrations.discord.botTokenRedacted, true); + }).pipe(Effect.provide(makeServerSettingsLayer())), + ); }); diff --git a/apps/server/src/serverSettings.ts b/apps/server/src/serverSettings.ts index 2798faf6f00..f133ae69e2a 100644 --- a/apps/server/src/serverSettings.ts +++ b/apps/server/src/serverSettings.ts @@ -83,6 +83,8 @@ function providerEnvironmentSecretName(input: { return `provider-env-${Buffer.from(input.instanceId, "utf8").toString("base64url")}-${Buffer.from(input.name, "utf8").toString("base64url")}`; } +const DISCORD_BOT_TOKEN_SECRET_NAME = "channel-discord-bot-token"; + function redactProviderEnvironmentVariable( variable: ProviderInstanceEnvironmentVariable, ): ProviderInstanceEnvironmentVariable { @@ -109,7 +111,19 @@ export function redactServerSettingsForClient(settings: ServerSettings): ServerS : instance, ]), ); - return { ...settings, providerInstances }; + const discord = settings.channelIntegrations.discord; + return { + ...settings, + providerInstances, + channelIntegrations: { + ...settings.channelIntegrations, + discord: { + ...discord, + botToken: "", + botTokenRedacted: discord.botToken.length > 0 || discord.botTokenRedacted, + }, + }, + }; } export class ServerSettingsService extends Context.Service< @@ -214,6 +228,7 @@ const ATOMIC_SETTINGS_KEYS: ReadonlySet = new Set([ "providerHealthRefreshInterval", "sourceControlWriterModelSelection", "textGenerationModelSelection", + "channelIntegrations", ]); function stripDefaultServerSettings(current: unknown, defaults: unknown): unknown | undefined { @@ -358,10 +373,46 @@ const make = Effect.gen(function* () { }; }); + const materializeChannelSecrets = ( + settings: ServerSettings, + ): Effect.Effect => + Effect.gen(function* () { + const discord = settings.channelIntegrations.discord; + const readSecret = (name: string) => + secretStore.get(name).pipe( + Effect.mapError( + (cause) => + new ServerSettingsError({ + settingsPath, + operation: "read-secret", + cause, + }), + ), + Effect.map(Option.map((value) => textDecoder.decode(value))), + Effect.map(Option.getOrElse(() => "")), + ); + const botToken = discord.botTokenRedacted + ? yield* readSecret(DISCORD_BOT_TOKEN_SECRET_NAME) + : discord.botToken; + return { + ...settings, + channelIntegrations: { + ...settings.channelIntegrations, + discord: { + ...discord, + botToken, + }, + }, + }; + }); + + const materializeServerSecrets = (settings: ServerSettings) => + materializeProviderEnvironmentSecrets(settings).pipe(Effect.flatMap(materializeChannelSecrets)); + const materializeChanges = (changes: Stream.Stream) => changes.pipe( Stream.mapEffect((settings) => - materializeProviderEnvironmentSecrets(settings).pipe( + materializeServerSecrets(settings).pipe( Effect.catch((error: ServerSettingsError) => Effect.logWarning("failed to materialize provider environment secrets", { operation: error.operation, @@ -476,6 +527,62 @@ const make = Effect.gen(function* () { }; }); + const persistChannelSecrets = ( + next: ServerSettings, + ): Effect.Effect => + Effect.gen(function* () { + const discord = next.channelIntegrations.discord; + const persistSecret = Effect.fn("ServerSettings.persistChannelSecret")(function* (input: { + readonly name: string; + readonly value: string; + readonly redacted: boolean; + }) { + if (input.redacted) { + return { value: "", redacted: true } as const; + } + if (input.value.length === 0) { + yield* secretStore.remove(input.name).pipe( + Effect.mapError( + (cause) => + new ServerSettingsError({ + settingsPath, + operation: "remove-secret", + cause, + }), + ), + ); + return { value: "", redacted: false } as const; + } + yield* secretStore.set(input.name, textEncoder.encode(input.value)).pipe( + Effect.mapError( + (cause) => + new ServerSettingsError({ + settingsPath, + operation: "write-secret", + cause, + }), + ), + ); + return { value: "", redacted: true } as const; + }); + const botToken = yield* persistSecret({ + name: DISCORD_BOT_TOKEN_SECRET_NAME, + value: discord.botToken, + redacted: discord.botTokenRedacted, + }); + return { + ...next, + channelIntegrations: { + ...next.channelIntegrations, + discord: { + ...discord, + botToken: botToken.value, + botTokenRedacted: botToken.redacted, + }, + }, + }; + }); + const writeSettingsAtomically = Effect.fnUntraced( function* (settings: ServerSettings) { const sparseSettingsJson = yield* encodeServerSettingsJson( @@ -572,22 +679,23 @@ const make = Effect.gen(function* () { start, ready: Deferred.await(startedDeferred), getSettings: getSettingsFromCache.pipe( - Effect.flatMap(materializeProviderEnvironmentSecrets), + Effect.flatMap(materializeServerSecrets), Effect.map(resolveTextGenerationProvider), ), updateSettings: (patch) => writeSemaphore.withPermits(1)( Effect.gen(function* () { const current = yield* getSettingsFromCache; - const nextPersisted = yield* persistProviderEnvironmentSecrets( + const nextProviderSecretsPersisted = yield* persistProviderEnvironmentSecrets( current, applyServerSettingsPatch(current, patch), ); + const nextPersisted = yield* persistChannelSecrets(nextProviderSecretsPersisted); const next = yield* normalizeServerSettings(nextPersisted); yield* writeSettingsAtomically(next); yield* Cache.set(settingsCache, cacheKey, next); yield* emitChange(next); - const materialized = yield* materializeProviderEnvironmentSecrets(next); + const materialized = yield* materializeServerSecrets(next); return resolveTextGenerationProvider(materialized); }), ), diff --git a/apps/web/src/components/settings/ChannelSettings.tsx b/apps/web/src/components/settings/ChannelSettings.tsx new file mode 100644 index 00000000000..e1be1f0a9d9 --- /dev/null +++ b/apps/web/src/components/settings/ChannelSettings.tsx @@ -0,0 +1,443 @@ +import { useAtomValue } from "@effect/atom-react"; +import { BotIcon, ExternalLinkIcon, GitBranchIcon, ShieldCheckIcon } from "lucide-react"; +import { type ModelSelection, ProjectId, type ServerSettingsPatch } from "@t3tools/contracts"; +import { createModelSelection } from "@t3tools/shared/model"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; + +import { usePersistPrimaryServerSettings, usePrimarySettings } from "../../hooks/useSettings"; +import { ensureLocalApi } from "../../localApi"; +import { + getCustomModelOptionsByInstance, + resolveAppModelSelectionState, +} from "../../modelSelection"; +import { + applyProviderInstanceSettings, + deriveProviderInstanceEntries, + sortProviderInstanceEntries, +} from "../../providerInstances"; +import { useProjects } from "../../state/entities"; +import { usePrimaryEnvironment } from "../../state/environments"; +import { primaryServerProvidersAtom } from "../../state/server"; +import { ProviderModelPicker } from "../chat/ProviderModelPicker"; +import { Badge } from "../ui/badge"; +import { Button } from "../ui/button"; +import { Input } from "../ui/input"; +import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "../ui/select"; +import { Switch } from "../ui/switch"; +import { SettingsPageContainer, SettingsRow, SettingsSection } from "./settingsLayout"; +import { searchableSetting } from "./settingsSearch"; +import { buildDiscordInstallUrl } from "./discordInstallUrl"; + +function SecretInput({ + label, + stored, + value, + onChange, + onBlur, +}: { + readonly label: string; + readonly stored: boolean; + readonly value: string; + readonly onChange: (value: string) => void; + readonly onBlur: () => void; +}) { + return ( + onChange(event.currentTarget.value)} + onBlur={onBlur} + placeholder={stored ? "Stored securely — type to replace" : label} + aria-label={label} + /> + ); +} + +type DiscordChannelPatch = NonNullable< + NonNullable["discord"] +>; + +type SaveStatus = "idle" | "unsaved" | "saving" | "saved" | "error"; +type DirtyField = "applicationId" | "guildId" | "botToken" | "baseBranch" | "branchPrefix"; + +export function ChannelSettings() { + const allSettings = usePrimarySettings(); + const settings = allSettings.channelIntegrations.discord; + const persistServerSettings = usePersistPrimaryServerSettings(); + const primaryEnvironment = usePrimaryEnvironment(); + const allProjects = useProjects(); + const serverProviders = useAtomValue(primaryServerProvidersAtom); + const projects = useMemo( + () => + primaryEnvironment + ? allProjects.filter( + (project) => project.environmentId === primaryEnvironment.environmentId, + ) + : [], + [allProjects, primaryEnvironment], + ); + const [enabled, setEnabled] = useState(settings.enabled); + const [projectId, setProjectId] = useState(settings.projectId); + const [modelSelection, setModelSelection] = useState( + settings.modelSelection, + ); + const [threadEnvMode, setThreadEnvMode] = useState(settings.threadEnvMode); + const [baseBranch, setBaseBranch] = useState(settings.baseBranch); + const [branchPrefix, setBranchPrefix] = useState(settings.branchPrefix); + const [applicationId, setApplicationId] = useState(settings.applicationId); + const [guildId, setGuildId] = useState(settings.guildId); + const [botToken, setBotToken] = useState(""); + const [botTokenChanged, setBotTokenChanged] = useState(false); + const [botTokenStored, setBotTokenStored] = useState(settings.botTokenRedacted); + const [saveStatus, setSaveStatus] = useState("idle"); + const dirtyFieldsRef = useRef(new Set()); + + useEffect(() => { + setEnabled(settings.enabled); + setProjectId(settings.projectId); + setModelSelection(settings.modelSelection); + setThreadEnvMode(settings.threadEnvMode); + if (!dirtyFieldsRef.current.has("baseBranch")) setBaseBranch(settings.baseBranch); + if (!dirtyFieldsRef.current.has("branchPrefix")) setBranchPrefix(settings.branchPrefix); + if (!dirtyFieldsRef.current.has("applicationId")) setApplicationId(settings.applicationId); + if (!dirtyFieldsRef.current.has("guildId")) setGuildId(settings.guildId); + if (!dirtyFieldsRef.current.has("botToken")) { + setBotTokenStored(settings.botTokenRedacted); + } + }, [settings]); + + const hasBotToken = botTokenChanged ? botToken.length > 0 : botTokenStored; + const setupComplete = + projectId !== null && + (threadEnvMode === "local" || + (baseBranch.trim().length > 0 && branchPrefix.trim().length > 0)) && + applicationId.trim().length > 0 && + hasBotToken; + const selectedProject = projects.find((project) => project.id === projectId) ?? null; + const fallbackModelSelection = useMemo( + () => resolveAppModelSelectionState(allSettings, serverProviders), + [allSettings, serverProviders], + ); + const activeModelSelection = useMemo( + () => modelSelection ?? selectedProject?.defaultModelSelection ?? fallbackModelSelection, + [fallbackModelSelection, modelSelection, selectedProject?.defaultModelSelection], + ); + const instanceEntries = useMemo( + () => + sortProviderInstanceEntries( + applyProviderInstanceSettings(deriveProviderInstanceEntries(serverProviders), allSettings), + ), + [allSettings, serverProviders], + ); + const modelOptionsByInstance = useMemo( + () => + getCustomModelOptionsByInstance( + allSettings, + serverProviders, + activeModelSelection.instanceId, + activeModelSelection.model, + ), + [activeModelSelection.instanceId, activeModelSelection.model, allSettings, serverProviders], + ); + const discordInstallUrl = buildDiscordInstallUrl(applicationId, guildId); + + const persistDiscordPatch = useCallback( + async (discord: DiscordChannelPatch, persistedFields: ReadonlyArray = []) => { + setSaveStatus("saving"); + const saved = await persistServerSettings({ channelIntegrations: { discord } }); + if (saved) { + for (const field of persistedFields) dirtyFieldsRef.current.delete(field); + } + setSaveStatus(saved ? "saved" : "error"); + return saved; + }, + [persistServerSettings], + ); + + const save = useCallback(async () => { + const saved = await persistDiscordPatch( + { + enabled, + projectId, + modelSelection, + threadEnvMode, + baseBranch, + branchPrefix, + applicationId, + guildId, + botToken: botTokenChanged ? botToken : "", + botTokenRedacted: botTokenChanged ? false : botTokenStored, + }, + ["applicationId", "guildId", "botToken", "baseBranch", "branchPrefix"], + ); + if (saved && botTokenChanged) { + setBotTokenChanged(false); + setBotTokenStored(botToken.length > 0); + } + }, [ + applicationId, + baseBranch, + botToken, + botTokenChanged, + botTokenStored, + branchPrefix, + enabled, + guildId, + modelSelection, + persistDiscordPatch, + projectId, + threadEnvMode, + ]); + + return ( + + } + headerAction={ + + {enabled && setupComplete ? "Configured" : enabled ? "Setup incomplete" : "Off"} + + } + > + { + const next = Boolean(checked); + setEnabled(next); + void persistDiscordPatch({ enabled: next }); + }} + aria-label="Enable Discord channel" + /> + } + /> + { + const next = value ? ProjectId.make(value) : null; + setProjectId(next); + void persistDiscordPatch({ projectId: next }); + }} + > + + + {selectedProject?.title ?? + (projects.length > 0 ? "Choose a project" : "No projects")} + + + + {projects.map((project) => ( + + {project.title} + + ))} + + + } + /> + { + const next = createModelSelection(instanceId, model); + setModelSelection(next); + void persistDiscordPatch({ modelSelection: next }); + }} + /> + } + /> + +
+ { + setApplicationId(event.currentTarget.value); + dirtyFieldsRef.current.add("applicationId"); + setSaveStatus("unsaved"); + }} + onBlur={() => void persistDiscordPatch({ applicationId }, ["applicationId"])} + placeholder="Application ID" + aria-label="Discord application ID" + /> + { + setGuildId(event.currentTarget.value); + dirtyFieldsRef.current.add("guildId"); + setSaveStatus("unsaved"); + }} + onBlur={() => void persistDiscordPatch({ guildId }, ["guildId"])} + placeholder="Server ID (optional)" + aria-label="Discord server ID" + /> + { + setBotToken(value); + setBotTokenChanged(true); + dirtyFieldsRef.current.add("botToken"); + setSaveStatus("unsaved"); + }} + onBlur={() => { + if (!botTokenChanged) return; + void persistDiscordPatch({ botToken, botTokenRedacted: false }, ["botToken"]).then( + (saved) => { + if (!saved) return; + setBotTokenChanged(false); + setBotTokenStored(botToken.length > 0); + }, + ); + }} + /> + +
+
+
+ + }> + { + const next = value === "local" ? "local" : "worktree"; + setThreadEnvMode(next); + void persistDiscordPatch({ threadEnvMode: next }); + }} + > + + + {threadEnvMode === "worktree" ? "Isolated worktree" : "Project checkout"} + + + + + Isolated worktree + + + Project checkout + + + + } + /> + + + {threadEnvMode === "worktree" ? "Isolated" : "Not isolated"} + + } + /> + {threadEnvMode === "worktree" ? ( + +
+
+ + { + setBaseBranch(event.currentTarget.value); + dirtyFieldsRef.current.add("baseBranch"); + setSaveStatus("unsaved"); + }} + onBlur={() => void persistDiscordPatch({ baseBranch }, ["baseBranch"])} + placeholder="main" + aria-label="Channel base branch" + /> +
+
+ + { + setBranchPrefix(event.currentTarget.value); + dirtyFieldsRef.current.add("branchPrefix"); + setSaveStatus("unsaved"); + }} + onBlur={() => void persistDiscordPatch({ branchPrefix }, ["branchPrefix"])} + placeholder="demo/discord" + aria-label="Channel branch prefix" + /> +
+
+
+ ) : null} +
+ +
+
+
+ ); +} diff --git a/apps/web/src/components/settings/SettingsSidebarNav.tsx b/apps/web/src/components/settings/SettingsSidebarNav.tsx index b7ca9afcf83..88bac823819 100644 --- a/apps/web/src/components/settings/SettingsSidebarNav.tsx +++ b/apps/web/src/components/settings/SettingsSidebarNav.tsx @@ -15,6 +15,7 @@ import { GitBranchIcon, KeyboardIcon, Link2Icon, + MessagesSquareIcon, PaletteIcon, SearchIcon, Settings2Icon, @@ -51,6 +52,7 @@ const SETTINGS_SECTION_ICONS: Readonly< "/settings/keybindings": KeyboardIcon, "/settings/providers": BotIcon, "/settings/source-control": GitBranchIcon, + "/settings/channels": MessagesSquareIcon, "/settings/connections": Link2Icon, "/settings/beta": FlaskConicalIcon, "/settings/archived": ArchiveIcon, diff --git a/apps/web/src/components/settings/discordInstallUrl.test.ts b/apps/web/src/components/settings/discordInstallUrl.test.ts new file mode 100644 index 00000000000..389d83fe42c --- /dev/null +++ b/apps/web/src/components/settings/discordInstallUrl.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, it } from "vite-plus/test"; + +import { buildDiscordInstallUrl } from "./discordInstallUrl"; + +describe("buildDiscordInstallUrl", () => { + it("requests only the scopes and permissions needed by the Discord channel", () => { + const result = buildDiscordInstallUrl("1535085613399933028", ""); + expect(result).not.toBeNull(); + + const url = new URL(result!); + expect(url.origin + url.pathname).toBe("https://discord.com/oauth2/authorize"); + expect(Object.fromEntries(url.searchParams)).toEqual({ + client_id: "1535085613399933028", + integration_type: "0", + permissions: "309304822784", + scope: "bot applications.commands", + }); + }); + + it("prefills a valid server ID and rejects an invalid application ID", () => { + const result = buildDiscordInstallUrl(" 1535085613399933028 ", " 123456789012345678 "); + expect(new URL(result!).searchParams.get("guild_id")).toBe("123456789012345678"); + expect(buildDiscordInstallUrl("not-an-id", "123456789012345678")).toBeNull(); + }); +}); diff --git a/apps/web/src/components/settings/discordInstallUrl.ts b/apps/web/src/components/settings/discordInstallUrl.ts new file mode 100644 index 00000000000..19aa2e524a5 --- /dev/null +++ b/apps/web/src/components/settings/discordInstallUrl.ts @@ -0,0 +1,17 @@ +const DISCORD_CHANNEL_PERMISSIONS = "309304822784"; + +export function buildDiscordInstallUrl(applicationId: string, guildId: string): string | null { + const clientId = applicationId.trim(); + if (!/^\d+$/.test(clientId)) return null; + + const searchParams = new URLSearchParams({ + client_id: clientId, + integration_type: "0", + permissions: DISCORD_CHANNEL_PERMISSIONS, + scope: "bot applications.commands", + }); + const serverId = guildId.trim(); + if (/^\d+$/.test(serverId)) searchParams.set("guild_id", serverId); + + return `https://discord.com/oauth2/authorize?${searchParams.toString()}`; +} diff --git a/apps/web/src/components/settings/settingsSearch.ts b/apps/web/src/components/settings/settingsSearch.ts index 1ba231a5835..9e00714038a 100644 --- a/apps/web/src/components/settings/settingsSearch.ts +++ b/apps/web/src/components/settings/settingsSearch.ts @@ -4,6 +4,7 @@ export type SettingsPath = | "/settings/keybindings" | "/settings/providers" | "/settings/source-control" + | "/settings/channels" | "/settings/connections" | "/settings/beta" | "/settings/archived"; @@ -25,6 +26,7 @@ export const SETTINGS_SECTION_LABELS: Readonly> = { "/settings/keybindings": "Keybindings", "/settings/providers": "Providers", "/settings/source-control": "Source Control", + "/settings/channels": "Channels", "/settings/connections": "Connections", "/settings/beta": "Beta", "/settings/archived": "Archive", @@ -166,6 +168,11 @@ export const SETTINGS_SEARCH_ITEMS = [ title: "Source control", to: "/settings/source-control", }, + { + id: "discord-channel", + title: "Discord channel", + to: "/settings/channels", + }, { id: "remote-environments", title: "Remote environments", diff --git a/apps/web/src/hooks/useSettings.ts b/apps/web/src/hooks/useSettings.ts index e58876b19f7..b39e6781a23 100644 --- a/apps/web/src/hooks/useSettings.ts +++ b/apps/web/src/hooks/useSettings.ts @@ -29,6 +29,7 @@ import { APP_STAGE_LABEL } from "~/branding"; import { resolveSidebarV2Enabled } from "~/branding.logic"; import { ensureLocalApi } from "~/localApi"; import * as Struct from "effect/Struct"; +import { AsyncResult } from "effect/unstable/reactivity"; import { primaryServerSettingsAtom, serverEnvironment } from "~/state/server"; import { usePrimaryEnvironment } from "~/state/environments"; import { useAtomCommand } from "~/state/use-atom-command"; @@ -323,6 +324,27 @@ export function useUpdatePrimarySettings() { return useUpdateSettingsTarget(usePrimaryEnvironment()?.environmentId ?? null); } +/** Persist a primary-environment server patch and report when the local write has completed. */ +export function usePersistPrimaryServerSettings() { + const environmentId = usePrimaryEnvironment()?.environmentId ?? null; + const persistServerSettings = useAtomCommand( + serverEnvironment.updateSettings, + "server settings update", + ); + + return useCallback( + async (patch: ServerSettingsPatch): Promise => { + if (environmentId === null) return false; + const result = await persistServerSettings({ + environmentId, + input: { patch }, + }); + return AsyncResult.isSuccess(result); + }, + [environmentId, persistServerSettings], + ); +} + export function useUpdateClientSettings() { return useCallback((patch: ClientSettingsPatch) => { persistClientSettings({ diff --git a/apps/web/src/routeTree.gen.ts b/apps/web/src/routeTree.gen.ts index 58ab4c3a714..bd09c7d4bd6 100644 --- a/apps/web/src/routeTree.gen.ts +++ b/apps/web/src/routeTree.gen.ts @@ -20,6 +20,7 @@ import { Route as SettingsKeybindingsRouteImport } from './routes/settings.keybi import { Route as SettingsGeneralRouteImport } from './routes/settings.general' import { Route as SettingsDiagnosticsRouteImport } from './routes/settings.diagnostics' import { Route as SettingsConnectionsRouteImport } from './routes/settings.connections' +import { Route as SettingsChannelsRouteImport } from './routes/settings.channels' import { Route as SettingsBetaRouteImport } from './routes/settings.beta' import { Route as SettingsArchivedRouteImport } from './routes/settings.archived' import { Route as SettingsAppearanceRouteImport } from './routes/settings.appearance' @@ -81,6 +82,11 @@ const SettingsConnectionsRoute = SettingsConnectionsRouteImport.update({ path: '/connections', getParentRoute: () => SettingsRoute, } as any) +const SettingsChannelsRoute = SettingsChannelsRouteImport.update({ + id: '/channels', + path: '/channels', + getParentRoute: () => SettingsRoute, +} as any) const SettingsBetaRoute = SettingsBetaRouteImport.update({ id: '/beta', path: '/beta', @@ -122,6 +128,7 @@ export interface FileRoutesByFullPath { '/settings/appearance': typeof SettingsAppearanceRoute '/settings/archived': typeof SettingsArchivedRoute '/settings/beta': typeof SettingsBetaRoute + '/settings/channels': typeof SettingsChannelsRoute '/settings/connections': typeof SettingsConnectionsRoute '/settings/diagnostics': typeof SettingsDiagnosticsRoute '/settings/general': typeof SettingsGeneralRoute @@ -139,6 +146,7 @@ export interface FileRoutesByTo { '/settings/appearance': typeof SettingsAppearanceRoute '/settings/archived': typeof SettingsArchivedRoute '/settings/beta': typeof SettingsBetaRoute + '/settings/channels': typeof SettingsChannelsRoute '/settings/connections': typeof SettingsConnectionsRoute '/settings/diagnostics': typeof SettingsDiagnosticsRoute '/settings/general': typeof SettingsGeneralRoute @@ -159,6 +167,7 @@ export interface FileRoutesById { '/settings/appearance': typeof SettingsAppearanceRoute '/settings/archived': typeof SettingsArchivedRoute '/settings/beta': typeof SettingsBetaRoute + '/settings/channels': typeof SettingsChannelsRoute '/settings/connections': typeof SettingsConnectionsRoute '/settings/diagnostics': typeof SettingsDiagnosticsRoute '/settings/general': typeof SettingsGeneralRoute @@ -180,6 +189,7 @@ export interface FileRouteTypes { | '/settings/appearance' | '/settings/archived' | '/settings/beta' + | '/settings/channels' | '/settings/connections' | '/settings/diagnostics' | '/settings/general' @@ -197,6 +207,7 @@ export interface FileRouteTypes { | '/settings/appearance' | '/settings/archived' | '/settings/beta' + | '/settings/channels' | '/settings/connections' | '/settings/diagnostics' | '/settings/general' @@ -216,6 +227,7 @@ export interface FileRouteTypes { | '/settings/appearance' | '/settings/archived' | '/settings/beta' + | '/settings/channels' | '/settings/connections' | '/settings/diagnostics' | '/settings/general' @@ -314,6 +326,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsConnectionsRouteImport parentRoute: typeof SettingsRoute } + '/settings/channels': { + id: '/settings/channels' + path: '/channels' + fullPath: '/settings/channels' + preLoaderRoute: typeof SettingsChannelsRouteImport + parentRoute: typeof SettingsRoute + } '/settings/beta': { id: '/settings/beta' path: '/beta' @@ -377,6 +396,7 @@ interface SettingsRouteChildren { SettingsAppearanceRoute: typeof SettingsAppearanceRoute SettingsArchivedRoute: typeof SettingsArchivedRoute SettingsBetaRoute: typeof SettingsBetaRoute + SettingsChannelsRoute: typeof SettingsChannelsRoute SettingsConnectionsRoute: typeof SettingsConnectionsRoute SettingsDiagnosticsRoute: typeof SettingsDiagnosticsRoute SettingsGeneralRoute: typeof SettingsGeneralRoute @@ -389,6 +409,7 @@ const SettingsRouteChildren: SettingsRouteChildren = { SettingsAppearanceRoute: SettingsAppearanceRoute, SettingsArchivedRoute: SettingsArchivedRoute, SettingsBetaRoute: SettingsBetaRoute, + SettingsChannelsRoute: SettingsChannelsRoute, SettingsConnectionsRoute: SettingsConnectionsRoute, SettingsDiagnosticsRoute: SettingsDiagnosticsRoute, SettingsGeneralRoute: SettingsGeneralRoute, diff --git a/apps/web/src/routes/settings.channels.tsx b/apps/web/src/routes/settings.channels.tsx new file mode 100644 index 00000000000..6230dc0faf5 --- /dev/null +++ b/apps/web/src/routes/settings.channels.tsx @@ -0,0 +1,7 @@ +import { createFileRoute } from "@tanstack/react-router"; + +import { ChannelSettings } from "../components/settings/ChannelSettings"; + +export const Route = createFileRoute("/settings/channels")({ + component: ChannelSettings, +}); diff --git a/docs/README.md b/docs/README.md index bc359826a04..441003dbb89 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,6 +8,7 @@ - [Remote access](./user/remote-access.md) - [Keeping app and server in sync](./user/updating.md) - [Source control integrations](./user/source-control.md) +- [Discord channels](./user/discord-channels.md) - [Background service (Linux)](./user/background-service.md) - Providers: [Codex](./user/providers-codex.md) · [Claude](./user/providers-claude.md) diff --git a/docs/user/discord-channels.md b/docs/user/discord-channels.md new file mode 100644 index 00000000000..928f4c1438f --- /dev/null +++ b/docs/user/discord-channels.md @@ -0,0 +1,10 @@ +# Discord channels + +Connect a Discord bot in **Settings → Channels** to start T3 Code tasks from a bot mention or the `/t3` command. Each request creates a T3 Code thread, and progress and completion are posted back to the Discord thread. + +Choose where channel tasks run: + +- **Isolated worktree** creates a dedicated branch and worktree for every request. If T3 Code cannot create them, the task does not start. +- **Project checkout** runs directly in the selected project's existing checkout. The agent can modify its currently checked-out branch, including `main`, and simultaneous tasks can affect the same files. + +Isolated worktrees are the default. Use the project checkout option when direct changes are intentional and you control who can send requests to the bot. diff --git a/packages/contracts/src/settings.ts b/packages/contracts/src/settings.ts index cbb547b95fb..821d5544d6c 100644 --- a/packages/contracts/src/settings.ts +++ b/packages/contracts/src/settings.ts @@ -2,7 +2,7 @@ import * as Effect from "effect/Effect"; import * as Duration from "effect/Duration"; import * as Schema from "effect/Schema"; import * as SchemaTransformation from "effect/SchemaTransformation"; -import { TrimmedNonEmptyString, TrimmedString } from "./baseSchemas.ts"; +import { ProjectId, TrimmedNonEmptyString, TrimmedString } from "./baseSchemas.ts"; import { DEFAULT_TEXT_GENERATION_MODEL, DEFAULT_TEXT_GENERATION_REASONING_EFFORT, @@ -534,6 +534,29 @@ export const BackgroundActivitySettings = Schema.Struct({ }).pipe(Schema.withDecodingDefault(Effect.succeed({}))); export type BackgroundActivitySettings = typeof BackgroundActivitySettings.Type; +export const DiscordChannelSettings = Schema.Struct({ + enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), + projectId: Schema.NullOr(ProjectId).pipe(Schema.withDecodingDefault(Effect.succeed(null))), + modelSelection: Schema.NullOr(ModelSelection).pipe( + Schema.withDecodingDefault(Effect.succeed(null)), + ), + threadEnvMode: ThreadEnvMode.pipe( + Schema.withDecodingDefault(Effect.succeed("worktree" as const satisfies ThreadEnvMode)), + ), + baseBranch: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed("main"))), + branchPrefix: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed("demo/discord"))), + applicationId: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), + guildId: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), + botToken: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), + botTokenRedacted: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), +}); +export type DiscordChannelSettings = typeof DiscordChannelSettings.Type; + +export const ChannelIntegrationSettings = Schema.Struct({ + discord: DiscordChannelSettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), +}).pipe(Schema.withDecodingDefault(Effect.succeed({}))); +export type ChannelIntegrationSettings = typeof ChannelIntegrationSettings.Type; + export const ServerSettings = Schema.Struct({ enableAssistantStreaming: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), enableProviderUpdateChecks: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), @@ -580,6 +603,7 @@ export const ServerSettings = Schema.Struct({ sourceControlWriterModelSelection: Schema.NullOr(ModelSelection).pipe( Schema.withDecodingDefault(Effect.succeed(null)), ), + channelIntegrations: ChannelIntegrationSettings, // Legacy single-instance-per-driver settings. Continues to be the source // of truth until `providerInstances` (below) lands per-driver migration @@ -723,6 +747,24 @@ export const ServerSettingsPatch = Schema.Struct({ }), ), sourceControlWriterModelSelection: Schema.optionalKey(Schema.NullOr(ModelSelection)), + channelIntegrations: Schema.optionalKey( + Schema.Struct({ + discord: Schema.optionalKey( + Schema.Struct({ + enabled: Schema.optionalKey(Schema.Boolean), + projectId: Schema.optionalKey(Schema.NullOr(ProjectId)), + modelSelection: Schema.optionalKey(Schema.NullOr(ModelSelection)), + threadEnvMode: Schema.optionalKey(ThreadEnvMode), + baseBranch: Schema.optionalKey(TrimmedString), + branchPrefix: Schema.optionalKey(TrimmedString), + applicationId: Schema.optionalKey(TrimmedString), + guildId: Schema.optionalKey(TrimmedString), + botToken: Schema.optionalKey(TrimmedString), + botTokenRedacted: Schema.optionalKey(Schema.Boolean), + }), + ), + }), + ), observability: Schema.optionalKey( Schema.Struct({ otlpTracesUrl: Schema.optionalKey(TrimmedString), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7c6f4cc1f5..105f1a0ade4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -104,7 +104,7 @@ importers: version: 7.0.0-dev.20260604.1 vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) apps/desktop: dependencies: @@ -168,7 +168,7 @@ importers: version: 4.3.0 vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) apps/marketing: dependencies: @@ -443,7 +443,16 @@ importers: dependencies: '@anthropic-ai/claude-agent-sdk': specifier: ^0.3.170 - version: 0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) + version: 0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(zod@4.4.3) + '@copilotkit/channels-core': + specifier: 0.7.3 + version: 0.7.3(vitest@4.1.9)(zod@4.4.3) + '@copilotkit/channels-discord': + specifier: 0.7.3 + version: 0.7.3(@ag-ui/core@0.0.57)(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vitest@4.1.9) + '@copilotkit/channels-ui': + specifier: 0.7.3 + version: 0.7.3(@ag-ui/core@0.0.57) '@effect/platform-bun': specifier: 4.0.0-beta.103 version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(utf-8-validate@6.0.6) @@ -474,6 +483,9 @@ importers: yaml: specifier: ^2.9.0 version: 2.9.0 + zod: + specifier: ^4.4.3 + version: 4.4.3 devDependencies: '@effect/vitest': specifier: 4.0.0-beta.103 @@ -504,7 +516,7 @@ importers: version: link:../../packages/effect-codex-app-server vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) apps/web: dependencies: @@ -649,7 +661,7 @@ importers: version: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) infra/relay: dependencies: @@ -676,10 +688,10 @@ importers: version: link:../../packages/shared alchemy: specifier: 2.0.0-beta.65 - version: 2.0.0-beta.65(a455401069e1fee89f31a277c51247f6) + version: 2.0.0-beta.65(cca023e78b21aab9077f3185bc54be18) drizzle-orm: specifier: 1.0.0-rc.4 - version: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3) + version: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@opentelemetry/api@1.9.1)(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3) effect: specifier: 4.0.0-beta.103 version: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9) @@ -704,7 +716,7 @@ importers: version: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) oxlint-plugin-t3code: dependencies: @@ -723,7 +735,7 @@ importers: version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) packages/client-runtime: dependencies: @@ -742,7 +754,7 @@ importers: version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) packages/contracts: dependencies: @@ -755,7 +767,7 @@ importers: version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) packages/effect-acp: dependencies: @@ -777,7 +789,7 @@ importers: version: 24.12.4 vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) packages/effect-codex-app-server: dependencies: @@ -799,7 +811,7 @@ importers: version: 24.12.4 vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) packages/shared: dependencies: @@ -833,7 +845,7 @@ importers: version: 24.12.4 vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) packages/ssh: dependencies: @@ -858,7 +870,7 @@ importers: version: 24.12.4 vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) packages/tailscale: dependencies: @@ -880,7 +892,7 @@ importers: version: 24.12.4 vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) scripts: dependencies: @@ -914,13 +926,25 @@ importers: version: 6.0.5 vite-plus: specifier: 'catalog:' - version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + version: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) packages: '@adobe/css-tools@4.5.0': resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==} + '@ag-ui/client@0.0.57': + resolution: {integrity: sha512-Xap2alG9Z0/j5kb3x4D7oTpe2sw1dfrC9rgJJr2NZu5vKcm8dzIPNd31mF2B4zS3BKqYIu245yxKPhEtT30MHw==} + + '@ag-ui/core@0.0.57': + resolution: {integrity: sha512-gho1OWjNE6E3Rl7ZEZ1wr2CEpUHjLFU0FqzCZZk439TicLu+BfLCMkMokB07bMGlRmbJ60hM6LW60iOVauCx+Q==} + + '@ag-ui/encoder@0.0.57': + resolution: {integrity: sha512-ifD9NctR4xyPDR58xF9GK1bj/S8oECFkTeDfuYD8tXdbcOstIJ2TOqU2zhiCKnw7Vw+zR9Qv3TbsM9E7Gi9X3Q==} + + '@ag-ui/proto@0.0.57': + resolution: {integrity: sha512-pPENOZt0P6ibH8sCTgq05wLYXi5t3P9B5r/1bWYehXjUxtyOdnukSlWM++SsCIwUXsQdm/b3aBgGjEeTF7RenA==} + '@alcalzone/ansi-tokenize@0.2.5': resolution: {integrity: sha512-3NX/MpTdroi0aKz134A6RC2Gb2iXVECN4QaAXnvCIxxIm3C3AVB1mkUe8NaaiyvOpDfsrqWhYtj+Q6a62RrTsw==} engines: {node: '>=18'} @@ -1657,6 +1681,9 @@ packages: cpu: [x64] os: [win32] + '@bufbuild/protobuf@2.13.0': + resolution: {integrity: sha512-acq7c49vxfm1ggJ95P70TX7ABDM0vxr1SYD3BB0o0jnBLB4OAqeHyKuN+cD3w80gXEDQ2zxHpR6CUeA+O/aU9g==} + '@callstack/liquid-glass@0.7.1': resolution: {integrity: sha512-N2rzs8g3kneI5G/98AZdVtjc6OUFBBFwPxVGVMoXUEI7QiioB4+aWwbImg5h8Z3Vb/T+fgLYWmmNhi27wHwE4g==} peerDependencies: @@ -1667,6 +1694,9 @@ packages: resolution: {integrity: sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==} engines: {node: '>=18'} + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + '@clack/core@0.5.0': resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==} @@ -1833,6 +1863,60 @@ packages: '@cloudflare/workers-types@5.20260726.1': resolution: {integrity: sha512-fKgRSm3sDmOdak1LGWehS4vSPSj7/zeu0NfmE62VPjBMqWgODcOGljYvq6A75sL+7YfY3iGFGb0jVEDYq+hlmw==} + '@copilotkit/channels-core@0.7.3': + resolution: {integrity: sha512-tj/Zil4Es6Z7MkSKH9Ak2n0xd0gyJwkqkW6VwseczZvTnJkPjt4Oq1K5ZT6tHtoaZKe33OqSkq9HDgRRj9tZWA==} + peerDependencies: + vitest: ^4.0.0 + peerDependenciesMeta: + vitest: + optional: true + + '@copilotkit/channels-discord@0.7.3': + resolution: {integrity: sha512-IbzAHbHW841bKishaSAYSlS9wShY9fNh0Xv4Yu+0vWcxdnMTTY2aB3WY784X8fZXkwDGwt/eMCvxrSe0PfTwHg==} + + '@copilotkit/channels-ui@0.7.3': + resolution: {integrity: sha512-uwRmhU9PlNKUFc/XXrhCJdcNHuQXa3rPE7lmjlPKr0matSXCHjsCfhMmDtgrDgTf8CCiVubwImT8CSH3vY3Y1A==} + + '@copilotkit/core@1.66.2': + resolution: {integrity: sha512-XWxbs72EkmhdCUgK80rRNjt+k3yTmbe0qP82iiU2cV5IWNbKbSvC9jO9ZAsa3Wbilhf2XTD1PSWa4dwN3xulHg==} + engines: {node: '>=18'} + + '@copilotkit/license-verifier@0.5.0': + resolution: {integrity: sha512-vrwKtIpYwF0FT9ZoYASH8owa2cGV0dhDvJGaCRaRMStwDxpc6DRdydKkhx8cWZXyBRxEYcq/Vygv4JvevhQQdQ==} + + '@copilotkit/shared@1.66.2': + resolution: {integrity: sha512-FmLAVm1jvSflxiVulozRbdft5dFPqP5EHyTq7Fl9CVwrxQR2Z2/CO9plifwKBJRkZpxIBsgp05i8NR3u6xUqgA==} + peerDependencies: + '@ag-ui/core': '>=0.0.48' + + '@discordjs/builders@1.14.1': + resolution: {integrity: sha512-gSKkhXLqs96TCzk66VZuHHl8z2bQMJFGwrXC0f33ngK+FLNau4hU1PYny3DNJfNdSH+gVMzE85/d5FQ2BpcNwQ==} + engines: {node: '>=16.11.0'} + + '@discordjs/collection@1.5.3': + resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==} + engines: {node: '>=16.11.0'} + + '@discordjs/collection@2.1.1': + resolution: {integrity: sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==} + engines: {node: '>=18'} + + '@discordjs/formatters@0.6.2': + resolution: {integrity: sha512-y4UPwWhH6vChKRkGdMB4odasUbHOUwy7KL+OVwF86PvT6QVOwElx+TiI1/6kcmcEe+g5YRXJFiXSXUdabqZOvQ==} + engines: {node: '>=16.11.0'} + + '@discordjs/rest@2.6.3': + resolution: {integrity: sha512-wvOylxNYJkwKjctS/Mn5GP1w9r3/rzyH+ThD1JlAca6zEdlHs8QWBBUQJpU5Q+W6DoIj/Ljh1IPlZs7hTU+UAg==} + engines: {node: '>=18'} + + '@discordjs/util@1.2.0': + resolution: {integrity: sha512-3LKP7F2+atl9vJFhaBjn4nOaSWahZ/yWjOvA4e5pnXkt2qyXRCHLxoBQy81GFtLGCq7K9lPm9R517M1U+/90Qg==} + engines: {node: '>=18'} + + '@discordjs/ws@1.2.3': + resolution: {integrity: sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==} + engines: {node: '>=16.11.0'} + '@distilled.cloud/aws@0.30.2': resolution: {integrity: sha512-Uw2yZf7PJ2ienrKG49HN1ajnke65mTtHBUrSb/3ykeZ/8cLaSgwVhPscHxSzGByY0TEtYcYKNNmfUVISgGQl9g==} peerDependencies: @@ -2095,12 +2179,18 @@ packages: '@emnapi/core@1.11.1': resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} '@emnapi/runtime@1.11.1': resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} @@ -3098,6 +3188,14 @@ packages: cpu: [x64] os: [win32] + '@lukeed/csprng@1.1.0': + resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} + engines: {node: '>=8'} + + '@lukeed/uuid@2.0.1': + resolution: {integrity: sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==} + engines: {node: '>=8'} + '@malept/cross-spawn-promise@2.0.0': resolution: {integrity: sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==} engines: {node: '>= 12.13.0'} @@ -3268,6 +3366,10 @@ packages: '@opencode-ai/sdk@1.15.13': resolution: {integrity: sha512-4TwojIoQ8EG6/mVBuUVYZXiFcwNmiiytEnjnvyuvSJjGwFIlw2YIBFxtSVC3FbwwbwHT63teh1RHiQUUC4U5xw==} + '@opentelemetry/api@1.9.1': + resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} + engines: {node: '>=8.0.0'} + '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} @@ -3284,6 +3386,9 @@ packages: '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-project/types@0.140.0': + resolution: {integrity: sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==} + '@oxfmt/binding-android-arm-eabi@0.57.0': resolution: {integrity: sha512-qVBsEO+KugOsCmUHcO8iqNnqc65p7PCKpCs8M66mPZ+Ri+CWbcpoQOEJBg2OTu03+0qu++NK1jj6IzvQVs0Sig==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3618,6 +3723,10 @@ packages: '@preact/signals-core@1.14.2': resolution: {integrity: sha512-RZHdBj9ZF4n40Rp4jS052EHHjBWf96P9oNdXPfhQTovCuWY9iQn3Gq+gOTJSgBO9A/JBuPfMOWsSX/lIU9Pc/A==} + '@protobuf-ts/protoc@2.11.1': + resolution: {integrity: sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==} + hasBin: true + '@radix-ui/primitive@1.1.3': resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} @@ -3985,6 +4094,12 @@ packages: cpu: [arm64] os: [android] + '@rolldown/binding-android-arm64@1.2.0': + resolution: {integrity: sha512-9yB1l95IrJuNGDFdOYe79vdApdz6WWBCObE+rQ2LUliYUlcyFwSYIb2xb5/Ifw7dAtMy2ZqNyd8QTSOc7duAKw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': resolution: {integrity: sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3997,6 +4112,12 @@ packages: cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-arm64@1.2.0': + resolution: {integrity: sha512-pexNaW9ACLUOaBITOpU6qVu4VrsOFIjTv6bzgu0YUATo4eUJx0V605PxwZfndpPOn0ilqGqvGQ0M8UW0IE24jg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.17': resolution: {integrity: sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4009,6 +4130,12 @@ packages: cpu: [x64] os: [darwin] + '@rolldown/binding-darwin-x64@1.2.0': + resolution: {integrity: sha512-NqKYaq0355ZmNMG4QGpxtEDxsc7tGDhjhCm4PpE0cwnBW+5Il95LJyq414niEiaKLVjnVHBEjSo1wngKxJNiFw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': resolution: {integrity: sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4021,6 +4148,12 @@ packages: cpu: [x64] os: [freebsd] + '@rolldown/binding-freebsd-x64@1.2.0': + resolution: {integrity: sha512-3vPoHzh6eBTz9IbB0/qZdSr0Qeks2echn+I4cHu2joV74VriPDdldswksEDzrl1mBB+oPRi+67+3Ib59paxIPQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': resolution: {integrity: sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4033,6 +4166,12 @@ packages: cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.2.0': + resolution: {integrity: sha512-E6NNefZ1bUVmKJq2tJkf45J4Zyczj7qm9rUT7NY+Xo2474Y13qWAwc2tvBt0BAVbmtXR1llkxXg0Ou1jbDf2SQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': resolution: {integrity: sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4047,6 +4186,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-arm64-gnu@1.2.0': + resolution: {integrity: sha512-D+TgkdgM1vu+7/Fpf8+v0ARW+RXEP9Ccazgm8zQ4JFFd9Q7SrYQ2TakU5S5ihazQDgpKyAgZDOcIFsvoHmTZ8w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4061,6 +4207,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-arm64-musl@1.2.0': + resolution: {integrity: sha512-wUqdwJBbAv0APN87GecstdMUtLjjNTs0hBALpxETD73mccFxdmt/XeizXDtN5RAlBwNKmI+Tg+blect2G+8IeQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4075,6 +4228,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-ppc64-gnu@1.2.0': + resolution: {integrity: sha512-9DtF35qR9/NrfhM4oxLplCzVVjE+KKm8Pjemi0i/sdhAWkUasjmSo8WTTubNJClhSHCfyk2yeyoXDQEDPtDAAw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4089,6 +4249,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.2.0': + resolution: {integrity: sha512-RzuHrBh8X8Hntd2N4VR02QGEciq/9JhcZoTpR/Cee6otRrlILGCf3cg2ygHuih+ZebUnWmMrDX6ITI85btO6rQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4103,6 +4270,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.2.0': + resolution: {integrity: sha512-MK7L0018jjh1jR3mh21G2j1zAVcpscJBlPo2z19pRjv2XOYGRhaV4LyiD8HO6nCDdZln9IFgCMIV5yt4E3klGQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4117,6 +4291,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-x64-musl@1.2.0': + resolution: {integrity: sha512-gyrxLQ9NfGb/9LoVnC4kb9miUghw1mghnkfYvNHSnVIXriabnfgGPUP4RLcJm87q3KgYz4FYUG8IDiWUT+CpSw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4129,6 +4310,12 @@ packages: cpu: [arm64] os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.2.0': + resolution: {integrity: sha512-/6VFMQGRmrhP77KXDC+StIxGzcNp5JOIyYtw0CQ8gPlzhpiIRucYfoM5FaFamHd5BJYIdH86yfP46l1p3WdrFA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': resolution: {integrity: sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4139,6 +4326,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.2.0': + resolution: {integrity: sha512-rwdbUL465kisF24WEJLvP3JrEG6E5GRuIHt5wpMwHGERtHe4Wm2CIvtf5gTBgr2tGOHKh5NdKEAFS2VkOPE91g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': resolution: {integrity: sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4151,6 +4343,12 @@ packages: cpu: [arm64] os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.2.0': + resolution: {integrity: sha512-+5suHwRiKGmhwyUaNT8a5QbrBvLFh2DbO910TEmGRH1aSxwrCezodvGQnulv4uiWEIv1Kq4ypRsJ5+O+ry1DiA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': resolution: {integrity: sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4163,6 +4361,12 @@ packages: cpu: [x64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.2.0': + resolution: {integrity: sha512-WfFv6/qGufotqBSBzBYwgpCkJBk8Nj7697LL9vTz/XWc67e0r3oewu8iMRwQj3AUL45GVD7wVsPjCsAAtW66Wg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/plugin-babel@0.2.3': resolution: {integrity: sha512-+zEk16yGlz1F9STiRr6uG9hmIXb6nprjLczV/htGptYuLoCuxb+itZ03RKCEeOhBpDDd1NU7qF6x1VLMUp62bw==} engines: {node: '>=22.12.0 || ^24.0.0'} @@ -4333,6 +4537,28 @@ packages: cpu: [x64] os: [win32] + '@sapphire/async-queue@1.5.5': + resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@sapphire/shapeshift@4.0.0': + resolution: {integrity: sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==} + engines: {node: '>=v16'} + + '@sapphire/snowflake@3.5.5': + resolution: {integrity: sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@segment/analytics-core@1.8.2': + resolution: {integrity: sha512-5FDy6l8chpzUfJcNlIcyqYQq4+JTUynlVoCeCUuVz+l+6W0PXg+ljKp34R4yLVCcY5VVZohuW+HH0VLWdwYVAg==} + + '@segment/analytics-generic-utils@1.2.0': + resolution: {integrity: sha512-DfnW6mW3YQOLlDQQdR89k4EqfHb0g/3XvBXkovH1FstUN93eL1kfW9CsDcVQyH3bAC5ZsFyjA/o/1Q2j0QeoWw==} + + '@segment/analytics-node@2.3.0': + resolution: {integrity: sha512-fOXLL8uY0uAWw/sTLmezze80hj8YGgXXlAfvSS6TUmivk4D/SP0C0sxnbpFdkUzWg2zT64qWIZj26afEtSnxUA==} + engines: {node: '>=20'} + '@shikijs/core@4.2.0': resolution: {integrity: sha512-Hc87Ab1Ld/vEbZRCbwx344I5v+4RU8CVToUTRkqXL1+TjbuOp9U5Xa0M23V4GEWHxVn+yO5otb+HkQVm3ptWQQ==} engines: {node: '>=20'} @@ -4670,6 +4896,10 @@ packages: resolution: {integrity: sha512-qhCRSFei0hokQr3xYcQXqxsRD/LKlgHCxHXtKHrQoImp4x2Zu6tUOpUGVH4y2qexIrzSu3aibQBNNfC3Eay6Mg==} engines: {node: '>=18'} + '@tanstack/pacer@0.20.1': + resolution: {integrity: sha512-ZNQ1bIL6eUXVKdic0tiImvBVkWrg/IoSK6VIacTrO3d3HAGnd70qFJNJagR/YOJIOw4EKGWnodwpYZkN1pWuVQ==} + engines: {node: '>=18'} + '@tanstack/query-core@5.100.14': resolution: {integrity: sha512-5X41dGpxgeaHISCRW2oYwcSycZeULZzAunaudXT9ov1KOTj9xwt0CH6hbwqP1/z74ZWF7rYFnDpyYH07XFcZew==} @@ -4866,6 +5096,9 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + '@types/webidl-conversions@7.0.3': resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} @@ -4993,6 +5226,10 @@ packages: '@vitest/utils@4.1.9': resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} + '@vladfrangu/async_event_emitter@2.4.7': + resolution: {integrity: sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + '@voidzero-dev/vite-plus-core@0.2.2': resolution: {integrity: sha512-yAbKexF3npOGjg1N5EtXxun+7vdM/0x6QE5jucO/dv0LFhCAIzSN3UvLVCeamJt/Bz3jt7DLqQHEgXXrjy8drA==} engines: {node: ^20.19.0 || ^22.18.0 || >=24.11.0} @@ -5613,6 +5850,9 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + bufferutil@4.1.0: resolution: {integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==} engines: {node: '>=6.14.2'} @@ -5861,6 +6101,9 @@ packages: resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} engines: {node: '>=0.10.0'} + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + compressible@2.0.18: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} @@ -6097,6 +6340,13 @@ packages: dir-compare@4.2.0: resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} + discord-api-types@0.38.52: + resolution: {integrity: sha512-uwe9EKfbjsmgWc2fdFjvDbj+dQqx3lp7wqDCmIha0jInuU+xeQjkCK9tMMn+p7RXfdVQORCInq4cD3U2ymDmyg==} + + discord.js@14.27.0: + resolution: {integrity: sha512-qHbFlFG2N7y3LjPySYsL6A1+BnX6bkTVgo842EX0CqVPk/KTMwZkojPHEXKsQUpWZNyz5BISNHK1cPpQw0+m4A==} + engines: {node: '>=18'} + dmg-builder@26.15.6: resolution: {integrity: sha512-nr5vQxEhM0REomp1qiHbc6V99yrfBZy+wUU56VXADfSOlLj8PdLqsHiRe7b+FbqKesiyv4ax+k1GVwGonYKuCg==} @@ -6824,6 +7074,9 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} + fast-json-patch@3.1.1: + resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==} + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -6932,8 +7185,8 @@ packages: resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==} engines: {node: '>=20'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} forwarded@0.2.0: @@ -7199,6 +7452,9 @@ packages: idb-keyval@6.2.1: resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -7422,6 +7678,9 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + jose@6.2.2: resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} @@ -7560,6 +7819,12 @@ packages: cpu: [arm64] os: [android] + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + lightningcss-darwin-arm64@1.30.1: resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} engines: {node: '>= 12.0.0'} @@ -7578,6 +7843,12 @@ packages: cpu: [arm64] os: [darwin] + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + lightningcss-darwin-x64@1.30.1: resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} engines: {node: '>= 12.0.0'} @@ -7596,6 +7867,12 @@ packages: cpu: [x64] os: [darwin] + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + lightningcss-freebsd-x64@1.30.1: resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} engines: {node: '>= 12.0.0'} @@ -7614,6 +7891,12 @@ packages: cpu: [x64] os: [freebsd] + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + lightningcss-linux-arm-gnueabihf@1.30.1: resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} engines: {node: '>= 12.0.0'} @@ -7632,6 +7915,12 @@ packages: cpu: [arm] os: [linux] + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + lightningcss-linux-arm64-gnu@1.30.1: resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} engines: {node: '>= 12.0.0'} @@ -7653,6 +7942,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + lightningcss-linux-arm64-musl@1.30.1: resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} engines: {node: '>= 12.0.0'} @@ -7674,6 +7970,13 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + lightningcss-linux-x64-gnu@1.30.1: resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} engines: {node: '>= 12.0.0'} @@ -7695,6 +7998,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + lightningcss-linux-x64-musl@1.30.1: resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} engines: {node: '>= 12.0.0'} @@ -7716,6 +8026,13 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + lightningcss-win32-arm64-msvc@1.30.1: resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} engines: {node: '>= 12.0.0'} @@ -7734,6 +8051,12 @@ packages: cpu: [arm64] os: [win32] + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + lightningcss-win32-x64-msvc@1.30.1: resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} engines: {node: '>= 12.0.0'} @@ -7752,6 +8075,12 @@ packages: cpu: [x64] os: [win32] + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + lightningcss@1.30.1: resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} engines: {node: '>= 12.0.0'} @@ -7764,6 +8093,10 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + locate-path@3.0.0: resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} engines: {node: '>=6'} @@ -7778,6 +8111,9 @@ packages: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + lodash.throttle@4.1.1: resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} @@ -7836,6 +8172,9 @@ packages: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true + magic-bytes.js@1.13.1: + resolution: {integrity: sha512-x5sn4UX2k5gCWlcfmoFwG4TPie8+dctESyqOBdhB5p6MsgWXdBKGmt9nXPObj/JI50TTL928lc5Yt1WntMn1bw==} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -8265,6 +8604,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@3.3.17: + resolution: {integrity: sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -8544,6 +8888,9 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + patch-console@2.0.0: resolution: {integrity: sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -8652,6 +8999,9 @@ packages: pgpass@1.0.5: resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + phoenix@1.8.9: + resolution: {integrity: sha512-/2qzAZB3P2s08fFAYaG65lqaNFmVXUSlXdY4/JDdDKIC81y2cFWkPwI8gycy4VLpv197JwZ5PpBf3VhoG32yGA==} + piccolore@0.1.3: resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==} @@ -8666,6 +9016,10 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + pkce-challenge@5.0.1: resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} engines: {node: '>=16.20.0'} @@ -8703,6 +9057,10 @@ packages: resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.25: + resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} + engines: {node: ^10 || ^12 || >=14} + postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -9270,6 +9628,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rolldown@1.2.0: + resolution: {integrity: sha512-u7tgm5l4Yw1iTqUL4EcYOAt7fFvCgQMLeidrnD4GALlC6aOznCjezYajgxeyKw27u0Q5N7fwgCzjVyPIWzwuBA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rollup@4.61.0: resolution: {integrity: sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -9282,6 +9645,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -9785,6 +10151,9 @@ packages: ts-algebra@2.0.0: resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + ts-mixer@6.0.4: + resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -9835,8 +10204,8 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - undici@6.26.0: - resolution: {integrity: sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==} + undici@6.28.0: + resolution: {integrity: sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==} engines: {node: '>=18.17'} undici@7.27.1: @@ -10000,6 +10369,9 @@ packages: until-async@3.0.2: resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} + untruncate-json@0.0.1: + resolution: {integrity: sha512-4W9enDK4X1y1s2S/Rz7ysw6kDuMS3VmRjMFg7GZrNO+98OSe+x5Lh7PKYoVjy3lW/1wmhs6HW0lusnQRHgMarA==} + unzipper@0.12.5: resolution: {integrity: sha512-tXYOi9R57Uj/2Z25SOs5RRSzq886MBQj2gY8dPL+xl/kv6s6SvByoKfAtvfVeEuhntWDgjd2o9p2lb4TVPAz0A==} @@ -10056,6 +10428,10 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@11.1.1: + resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==} + hasBin: true + uuid@14.0.1: resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} hasBin: true @@ -10101,6 +10477,49 @@ packages: '@vitest/browser-webdriverio': optional: true + vite@8.2.0: + resolution: {integrity: sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': 24.12.4 + '@vitejs/devtools': ^0.4.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.9.0 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + vitefu@1.1.3: resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} peerDependencies: @@ -10485,6 +10904,34 @@ snapshots: '@adobe/css-tools@4.5.0': optional: true + '@ag-ui/client@0.0.57': + dependencies: + '@ag-ui/core': 0.0.57 + '@ag-ui/encoder': 0.0.57 + '@ag-ui/proto': 0.0.57 + '@types/uuid': 10.0.0 + compare-versions: 6.1.1 + fast-json-patch: 3.1.1 + rxjs: 7.8.1 + untruncate-json: 0.0.1 + uuid: 11.1.1 + zod: 3.25.76 + + '@ag-ui/core@0.0.57': + dependencies: + zod: 3.25.76 + + '@ag-ui/encoder@0.0.57': + dependencies: + '@ag-ui/core': 0.0.57 + '@ag-ui/proto': 0.0.57 + + '@ag-ui/proto@0.0.57': + dependencies: + '@ag-ui/core': 0.0.57 + '@bufbuild/protobuf': 2.13.0 + '@protobuf-ts/protoc': 2.11.1 + '@alcalzone/ansi-tokenize@0.2.5': dependencies: ansi-styles: 6.2.3 @@ -10516,10 +10963,10 @@ snapshots: '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.170': optional: true - '@anthropic-ai/claude-agent-sdk@0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)': + '@anthropic-ai/claude-agent-sdk@0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(zod@4.4.3)': dependencies: '@anthropic-ai/sdk': 0.93.0(zod@4.4.3) - '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3) zod: 4.4.3 optionalDependencies: '@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.3.170 @@ -10609,7 +11056,7 @@ snapshots: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 js-yaml: 4.2.0 - picomatch: 4.0.4 + picomatch: 4.0.5 retext-smartypants: 6.2.0 shiki: 4.2.0 smol-toml: 1.7.0 @@ -11451,6 +11898,8 @@ snapshots: '@bruits/satteri-win32-x64-msvc@0.9.3': optional: true + '@bufbuild/protobuf@2.13.0': {} + '@callstack/liquid-glass@0.7.1(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)': dependencies: react: 19.2.3 @@ -11460,6 +11909,9 @@ snapshots: dependencies: fontkitten: 1.0.3 + '@cfworker/json-schema@4.1.1': + optional: true + '@clack/core@0.5.0': dependencies: picocolors: 1.1.1 @@ -11640,17 +12092,159 @@ snapshots: '@cloudflare/workers-types@5.20260726.1': {} - '@distilled.cloud/aws@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))': + '@copilotkit/channels-core@0.7.3(vitest@4.1.9)(zod@3.25.76)': dependencies: - '@aws-crypto/crc32': 5.2.0 - '@aws-crypto/util': 5.2.0 - '@aws-sdk/credential-providers': 3.1062.0 - '@aws-sdk/types': 3.973.10 - '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) - '@smithy/shared-ini-file-loader': 4.5.6 - '@smithy/types': 4.14.3 - '@smithy/util-base64': 4.4.6 - aws4fetch: 1.0.20 + '@ag-ui/client': 0.0.57 + '@ag-ui/core': 0.0.57 + '@copilotkit/channels-ui': 0.7.3(@ag-ui/core@0.0.57) + '@copilotkit/core': 1.66.2(@ag-ui/core@0.0.57)(zod@3.25.76) + '@copilotkit/shared': 1.66.2(@ag-ui/core@0.0.57) + zod-to-json-schema: 3.25.2(zod@3.25.76) + optionalDependencies: + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + transitivePeerDependencies: + - encoding + - zod + + '@copilotkit/channels-core@0.7.3(vitest@4.1.9)(zod@4.4.3)': + dependencies: + '@ag-ui/client': 0.0.57 + '@ag-ui/core': 0.0.57 + '@copilotkit/channels-ui': 0.7.3(@ag-ui/core@0.0.57) + '@copilotkit/core': 1.66.2(@ag-ui/core@0.0.57)(zod@4.4.3) + '@copilotkit/shared': 1.66.2(@ag-ui/core@0.0.57) + zod-to-json-schema: 3.25.2(zod@4.4.3) + optionalDependencies: + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + transitivePeerDependencies: + - encoding + - zod + + '@copilotkit/channels-discord@0.7.3(@ag-ui/core@0.0.57)(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vitest@4.1.9)': + dependencies: + '@ag-ui/client': 0.0.57 + '@copilotkit/channels-core': 0.7.3(vitest@4.1.9)(zod@3.25.76) + '@copilotkit/channels-ui': 0.7.3(@ag-ui/core@0.0.57) + discord.js: 14.27.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + zod: 3.25.76 + transitivePeerDependencies: + - '@ag-ui/core' + - bufferutil + - encoding + - utf-8-validate + - vitest + + '@copilotkit/channels-ui@0.7.3(@ag-ui/core@0.0.57)': + dependencies: + '@copilotkit/shared': 1.66.2(@ag-ui/core@0.0.57) + transitivePeerDependencies: + - '@ag-ui/core' + - encoding + + '@copilotkit/core@1.66.2(@ag-ui/core@0.0.57)(zod@3.25.76)': + dependencies: + '@ag-ui/client': 0.0.57 + '@copilotkit/shared': 1.66.2(@ag-ui/core@0.0.57) + '@tanstack/pacer': 0.20.1 + phoenix: 1.8.9 + rxjs: 7.8.1 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - '@ag-ui/core' + - encoding + - zod + + '@copilotkit/core@1.66.2(@ag-ui/core@0.0.57)(zod@4.4.3)': + dependencies: + '@ag-ui/client': 0.0.57 + '@copilotkit/shared': 1.66.2(@ag-ui/core@0.0.57) + '@tanstack/pacer': 0.20.1 + phoenix: 1.8.9 + rxjs: 7.8.1 + zod-to-json-schema: 3.25.2(zod@4.4.3) + transitivePeerDependencies: + - '@ag-ui/core' + - encoding + - zod + + '@copilotkit/license-verifier@0.5.0': {} + + '@copilotkit/shared@1.66.2(@ag-ui/core@0.0.57)': + dependencies: + '@ag-ui/client': 0.0.57 + '@ag-ui/core': 0.0.57 + '@copilotkit/license-verifier': 0.5.0 + '@segment/analytics-node': 2.3.0 + '@standard-schema/spec': 1.1.0 + chalk: 4.1.2 + graphql: 16.14.1 + partial-json: 0.1.7 + uuid: 11.1.1 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - encoding + + '@discordjs/builders@1.14.1': + dependencies: + '@discordjs/formatters': 0.6.2 + '@discordjs/util': 1.2.0 + '@sapphire/shapeshift': 4.0.0 + discord-api-types: 0.38.52 + fast-deep-equal: 3.1.3 + ts-mixer: 6.0.4 + tslib: 2.8.1 + + '@discordjs/collection@1.5.3': {} + + '@discordjs/collection@2.1.1': {} + + '@discordjs/formatters@0.6.2': + dependencies: + discord-api-types: 0.38.52 + + '@discordjs/rest@2.6.3': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/util': 1.2.0 + '@sapphire/async-queue': 1.5.5 + '@sapphire/snowflake': 3.5.5 + '@vladfrangu/async_event_emitter': 2.4.7 + discord-api-types: 0.38.52 + magic-bytes.js: 1.13.1 + tslib: 2.8.1 + undici: 6.28.0 + + '@discordjs/util@1.2.0': + dependencies: + discord-api-types: 0.38.52 + + '@discordjs/ws@1.2.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/rest': 2.6.3 + '@discordjs/util': 1.2.0 + '@sapphire/async-queue': 1.5.5 + '@types/ws': 8.18.1 + '@vladfrangu/async_event_emitter': 2.4.7 + discord-api-types: 0.38.52 + tslib: 2.8.1 + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@distilled.cloud/aws@0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/credential-providers': 3.1062.0 + '@aws-sdk/types': 3.973.10 + '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) + '@smithy/shared-ini-file-loader': 4.5.6 + '@smithy/types': 4.14.3 + '@smithy/util-base64': 4.4.6 + aws4fetch: 1.0.20 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9) fast-xml-parser: 5.8.0 @@ -11982,6 +12576,12 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/core@1.11.2': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 @@ -11992,6 +12592,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 @@ -13193,6 +13798,12 @@ snapshots: '@libsql/win32-x64-msvc@0.5.29': optional: true + '@lukeed/csprng@1.1.0': {} + + '@lukeed/uuid@2.0.1': + dependencies: + '@lukeed/csprng': 1.1.0 + '@malept/cross-spawn-promise@2.0.0': dependencies: cross-spawn: 7.0.6 @@ -13206,7 +13817,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)': + '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3)': dependencies: '@hono/node-server': 1.19.14(hono@4.12.27) ajv: 8.20.0 @@ -13225,6 +13836,8 @@ snapshots: raw-body: 3.0.2 zod: 4.4.3 zod-to-json-schema: 3.25.2(zod@4.4.3) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 transitivePeerDependencies: - supports-color @@ -13273,6 +13886,13 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + '@neon-rs/load@0.0.4': {} '@noble/curves@1.9.1': @@ -13385,6 +14005,9 @@ snapshots: dependencies: cross-spawn: 7.0.6 + '@opentelemetry/api@1.9.1': + optional: true + '@oslojs/encoding@1.1.0': {} '@oxc-project/runtime@0.138.0': {} @@ -13396,6 +14019,9 @@ snapshots: '@oxc-project/types@0.139.0': {} + '@oxc-project/types@0.140.0': + optional: true + '@oxfmt/binding-android-arm-eabi@0.57.0': optional: true @@ -13616,6 +14242,8 @@ snapshots: '@preact/signals-core@1.14.2': {} + '@protobuf-ts/protoc@2.11.1': {} + '@radix-ui/primitive@1.1.3': {} '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': @@ -14278,72 +14906,108 @@ snapshots: '@rolldown/binding-android-arm64@1.1.5': optional: true + '@rolldown/binding-android-arm64@1.2.0': + optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': optional: true '@rolldown/binding-darwin-arm64@1.1.5': optional: true + '@rolldown/binding-darwin-arm64@1.2.0': + optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.17': optional: true '@rolldown/binding-darwin-x64@1.1.5': optional: true + '@rolldown/binding-darwin-x64@1.2.0': + optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': optional: true '@rolldown/binding-freebsd-x64@1.1.5': optional: true + '@rolldown/binding-freebsd-x64@1.2.0': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': optional: true '@rolldown/binding-linux-arm-gnueabihf@1.1.5': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.2.0': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': optional: true '@rolldown/binding-linux-arm64-gnu@1.1.5': optional: true + '@rolldown/binding-linux-arm64-gnu@1.2.0': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': optional: true '@rolldown/binding-linux-arm64-musl@1.1.5': optional: true + '@rolldown/binding-linux-arm64-musl@1.2.0': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': optional: true '@rolldown/binding-linux-ppc64-gnu@1.1.5': optional: true + '@rolldown/binding-linux-ppc64-gnu@1.2.0': + optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': optional: true '@rolldown/binding-linux-s390x-gnu@1.1.5': optional: true + '@rolldown/binding-linux-s390x-gnu@1.2.0': + optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': optional: true '@rolldown/binding-linux-x64-gnu@1.1.5': optional: true + '@rolldown/binding-linux-x64-gnu@1.2.0': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': optional: true '@rolldown/binding-linux-x64-musl@1.1.5': optional: true + '@rolldown/binding-linux-x64-musl@1.2.0': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': optional: true '@rolldown/binding-openharmony-arm64@1.1.5': optional: true + '@rolldown/binding-openharmony-arm64@1.2.0': + optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': dependencies: '@emnapi/core': 1.10.0 @@ -14358,18 +15022,31 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true + '@rolldown/binding-wasm32-wasi@1.2.0': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': optional: true '@rolldown/binding-win32-arm64-msvc@1.1.5': optional: true + '@rolldown/binding-win32-arm64-msvc@1.2.0': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': optional: true '@rolldown/binding-win32-x64-msvc@1.1.5': optional: true + '@rolldown/binding-win32-x64-msvc@1.2.0': + optional: true + '@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)': dependencies: '@babel/core': 7.29.7 @@ -14468,6 +15145,38 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.61.0': optional: true + '@sapphire/async-queue@1.5.5': {} + + '@sapphire/shapeshift@4.0.0': + dependencies: + fast-deep-equal: 3.1.3 + lodash: 4.18.1 + + '@sapphire/snowflake@3.5.5': {} + + '@segment/analytics-core@1.8.2': + dependencies: + '@lukeed/uuid': 2.0.1 + '@segment/analytics-generic-utils': 1.2.0 + dset: 3.1.4 + tslib: 2.8.1 + + '@segment/analytics-generic-utils@1.2.0': + dependencies: + tslib: 2.8.1 + + '@segment/analytics-node@2.3.0': + dependencies: + '@lukeed/uuid': 2.0.1 + '@segment/analytics-core': 1.8.2 + '@segment/analytics-generic-utils': 1.2.0 + buffer: 6.0.3 + jose: 5.10.0 + node-fetch: 2.7.0 + tslib: 2.8.1 + transitivePeerDependencies: + - encoding + '@shikijs/core@4.2.0': dependencies: '@shikijs/primitive': 4.2.0 @@ -14764,6 +15473,11 @@ snapshots: '@tanstack/devtools-event-client': 0.4.3 '@tanstack/store': 0.8.1 + '@tanstack/pacer@0.20.1': + dependencies: + '@tanstack/devtools-event-client': 0.4.3 + '@tanstack/store': 0.9.3 + '@tanstack/query-core@5.100.14': {} '@tanstack/react-pacer@0.19.4(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': @@ -15010,6 +15724,8 @@ snapshots: '@types/unist@3.0.3': {} + '@types/uuid@10.0.0': {} + '@types/webidl-conversions@7.0.3': {} '@types/whatwg-url@11.0.5': @@ -15090,12 +15806,25 @@ snapshots: '@testing-library/dom': 10.4.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) '@vitest/browser': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) - vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser-preview@4.1.9(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.9)': + dependencies: + '@testing-library/dom': 10.4.1 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + '@vitest/browser': 4.1.9(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.9) + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite + optional: true '@vitest/browser@4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9)': dependencies: @@ -15106,13 +15835,31 @@ snapshots: pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.1.9(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.9)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.9(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + '@vitest/utils': 4.1.9 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite + optional: true '@vitest/expect@4.1.9': dependencies: @@ -15132,6 +15879,16 @@ snapshots: msw: 2.12.11(@types/node@24.12.4)(typescript@6.0.3) vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + '@vitest/mocker@4.1.9(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))': + dependencies: + '@vitest/spy': 4.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + msw: 2.12.11(@types/node@24.12.4)(typescript@6.0.3) + vite: 8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + optional: true + '@vitest/pretty-format@4.1.9': dependencies: tinyrainbow: 3.1.0 @@ -15156,6 +15913,8 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 + '@vladfrangu/async_event_emitter@2.4.7': {} + '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)': dependencies: '@oxc-project/runtime': 0.138.0 @@ -15350,7 +16109,7 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - alchemy@2.0.0-beta.65(a455401069e1fee89f31a277c51247f6): + alchemy@2.0.0-beta.65(cca023e78b21aab9077f3185bc54be18): dependencies: '@alchemy.run/node-utils': 0.0.5 '@aws-sdk/credential-providers': 3.1062.0 @@ -15395,7 +16154,7 @@ snapshots: '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(ioredis@5.11.0)(utf-8-validate@6.0.6) '@effect/sql-pg': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) drizzle-kit: 1.0.0-rc.4 - drizzle-orm: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3) + drizzle-orm: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@opentelemetry/api@1.9.1)(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3) vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: @@ -15911,6 +16670,11 @@ snapshots: buffer-from@1.1.2: {} + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + bufferutil@4.1.0: dependencies: node-gyp-build: 4.8.4 @@ -16150,6 +16914,8 @@ snapshots: compare-version@0.1.2: {} + compare-versions@6.1.1: {} + compressible@2.0.18: dependencies: mime-db: 1.54.0 @@ -16365,6 +17131,27 @@ snapshots: minimatch: 3.1.5 p-limit: 3.1.0 + discord-api-types@0.38.52: {} + + discord.js@14.27.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + dependencies: + '@discordjs/builders': 1.14.1 + '@discordjs/collection': 1.5.3 + '@discordjs/formatters': 0.6.2 + '@discordjs/rest': 2.6.3 + '@discordjs/util': 1.2.0 + '@discordjs/ws': 1.2.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@sapphire/snowflake': 3.5.5 + discord-api-types: 0.38.52 + fast-deep-equal: 3.1.3 + lodash.snakecase: 4.1.1 + magic-bytes.js: 1.13.1 + tslib: 2.8.1 + undici: 6.28.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dmg-builder@26.15.6(electron-builder-squirrel-windows@26.15.6): dependencies: app-builder-lib: 26.15.6(dmg-builder@26.15.6)(electron-builder-squirrel-windows@26.15.6) @@ -16418,13 +17205,14 @@ snapshots: get-tsconfig: 4.14.0 jiti: 2.7.0 - drizzle-orm@1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3): + drizzle-orm@1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@opentelemetry/api@1.9.1)(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9))(expo-sqlite@56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3): optionalDependencies: '@cloudflare/workers-types': 4.20260604.1 '@effect/sql-d1': 4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) '@effect/sql-pg': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) '@effect/sql-sqlite-bun': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9)) '@libsql/client': 0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@opentelemetry/api': 1.9.1 bun-types: 1.3.14 effect: 4.0.0-beta.103(patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9) expo-sqlite: 56.0.5(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6) @@ -16495,7 +17283,7 @@ snapshots: builder-util: 26.15.3 builder-util-runtime: 9.7.0 chalk: 4.1.2 - form-data: 4.0.5 + form-data: 4.0.6 fs-extra: 10.1.0 lazy-val: 1.0.5 mime: 2.6.0 @@ -17011,7 +17799,7 @@ snapshots: expo-symbols: 56.0.6(expo-font@56.0.7)(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) fast-deep-equal: 3.1.3 invariant: 2.2.4 - nanoid: 3.3.12 + nanoid: 3.3.17 query-string: 7.1.3 react: 19.2.3 react-fast-compare: 3.2.2 @@ -17062,7 +17850,7 @@ snapshots: expo-symbols: 56.0.6(expo-font@56.0.7)(expo@56.0.12)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6) fast-deep-equal: 3.1.3 invariant: 2.2.4 - nanoid: 3.3.12 + nanoid: 3.3.17 query-string: 7.1.3 react: 19.2.6 react-fast-compare: 3.2.2 @@ -17354,6 +18142,8 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 + fast-json-patch@3.1.1: {} + fast-json-stable-stringify@2.1.0: optional: true @@ -17482,7 +18272,7 @@ snapshots: dependencies: tiny-inflate: 1.0.3 - form-data@4.0.5: + form-data@4.0.6: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -17863,6 +18653,8 @@ snapshots: idb-keyval@6.2.1: optional: true + ieee754@1.2.1: {} + ignore@5.3.2: {} ignore@7.0.5: {} @@ -18064,6 +18856,8 @@ snapshots: jiti@2.7.0: {} + jose@5.10.0: {} + jose@6.2.2: {} jose@6.2.3: {} @@ -18188,6 +18982,9 @@ snapshots: lightningcss-android-arm64@1.32.0: optional: true + lightningcss-android-arm64@1.33.0: + optional: true + lightningcss-darwin-arm64@1.30.1: optional: true @@ -18197,6 +18994,9 @@ snapshots: lightningcss-darwin-arm64@1.32.0: optional: true + lightningcss-darwin-arm64@1.33.0: + optional: true + lightningcss-darwin-x64@1.30.1: optional: true @@ -18206,6 +19006,9 @@ snapshots: lightningcss-darwin-x64@1.32.0: optional: true + lightningcss-darwin-x64@1.33.0: + optional: true + lightningcss-freebsd-x64@1.30.1: optional: true @@ -18215,6 +19018,9 @@ snapshots: lightningcss-freebsd-x64@1.32.0: optional: true + lightningcss-freebsd-x64@1.33.0: + optional: true + lightningcss-linux-arm-gnueabihf@1.30.1: optional: true @@ -18224,6 +19030,9 @@ snapshots: lightningcss-linux-arm-gnueabihf@1.32.0: optional: true + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + lightningcss-linux-arm64-gnu@1.30.1: optional: true @@ -18233,6 +19042,9 @@ snapshots: lightningcss-linux-arm64-gnu@1.32.0: optional: true + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + lightningcss-linux-arm64-musl@1.30.1: optional: true @@ -18242,6 +19054,9 @@ snapshots: lightningcss-linux-arm64-musl@1.32.0: optional: true + lightningcss-linux-arm64-musl@1.33.0: + optional: true + lightningcss-linux-x64-gnu@1.30.1: optional: true @@ -18251,6 +19066,9 @@ snapshots: lightningcss-linux-x64-gnu@1.32.0: optional: true + lightningcss-linux-x64-gnu@1.33.0: + optional: true + lightningcss-linux-x64-musl@1.30.1: optional: true @@ -18260,6 +19078,9 @@ snapshots: lightningcss-linux-x64-musl@1.32.0: optional: true + lightningcss-linux-x64-musl@1.33.0: + optional: true + lightningcss-win32-arm64-msvc@1.30.1: optional: true @@ -18269,6 +19090,9 @@ snapshots: lightningcss-win32-arm64-msvc@1.32.0: optional: true + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + lightningcss-win32-x64-msvc@1.30.1: optional: true @@ -18278,6 +19102,9 @@ snapshots: lightningcss-win32-x64-msvc@1.32.0: optional: true + lightningcss-win32-x64-msvc@1.33.0: + optional: true + lightningcss@1.30.1: dependencies: detect-libc: 2.1.2 @@ -18325,6 +19152,23 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + optional: true + locate-path@3.0.0: dependencies: p-locate: 3.0.0 @@ -18336,6 +19180,8 @@ snapshots: lodash.isequal@4.5.0: {} + lodash.snakecase@4.1.1: {} + lodash.throttle@4.1.1: {} lodash@4.18.1: {} @@ -18381,6 +19227,8 @@ snapshots: lz-string@1.5.0: {} + magic-bytes.js@1.13.1: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -19108,6 +19956,9 @@ snapshots: nanoid@3.3.12: {} + nanoid@3.3.17: + optional: true + negotiator@0.6.3: {} negotiator@0.6.4: {} @@ -19160,7 +20011,7 @@ snapshots: semver: 7.8.5 tar: 7.5.16 tinyglobby: 0.2.17 - undici: 6.26.0 + undici: 6.28.0 which: 6.0.1 node-int64@0.4.0: {} @@ -19313,7 +20164,7 @@ snapshots: outvariant@1.4.3: {} - oxfmt@0.57.0(vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): + oxfmt@0.57.0(vite-plus@0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): dependencies: tinypool: 2.1.0 optionalDependencies: @@ -19336,7 +20187,7 @@ snapshots: '@oxfmt/binding-win32-arm64-msvc': 0.57.0 '@oxfmt/binding-win32-ia32-msvc': 0.57.0 '@oxfmt/binding-win32-x64-msvc': 0.57.0 - vite-plus: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + vite-plus: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) oxlint-tsgolint@0.24.0: optionalDependencies: @@ -19347,7 +20198,7 @@ snapshots: '@oxlint-tsgolint/win32-arm64': 0.24.0 '@oxlint-tsgolint/win32-x64': 0.24.0 - oxlint@1.72.0(oxlint-tsgolint@0.24.0)(vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): + oxlint@1.72.0(oxlint-tsgolint@0.24.0)(vite-plus@0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): optionalDependencies: '@oxlint/binding-android-arm-eabi': 1.72.0 '@oxlint/binding-android-arm64': 1.72.0 @@ -19369,7 +20220,7 @@ snapshots: '@oxlint/binding-win32-ia32-msvc': 1.72.0 '@oxlint/binding-win32-x64-msvc': 1.72.0 oxlint-tsgolint: 0.24.0 - vite-plus: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + vite-plus: 0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) p-cancelable@2.1.1: {} @@ -19432,6 +20283,8 @@ snapshots: parseurl@1.3.3: {} + partial-json@0.1.7: {} + patch-console@2.0.0: {} path-browserify@1.0.1: {} @@ -19530,6 +20383,8 @@ snapshots: dependencies: split2: 4.2.0 + phoenix@1.8.9: {} + piccolore@0.1.3: {} picocolors@1.1.1: {} @@ -19538,6 +20393,8 @@ snapshots: picomatch@4.0.4: {} + picomatch@4.0.5: {} + pkce-challenge@5.0.1: {} pkg-up@3.1.0: @@ -19577,6 +20434,13 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.25: + dependencies: + nanoid: 3.3.17 + picocolors: 1.1.1 + source-map-js: 1.2.1 + optional: true + postgres-array@2.0.0: {} postgres-array@3.0.4: {} @@ -20418,6 +21282,28 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.1.5 '@rolldown/binding-win32-x64-msvc': 1.1.5 + rolldown@1.2.0: + dependencies: + '@oxc-project/types': 0.140.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.2.0 + '@rolldown/binding-darwin-arm64': 1.2.0 + '@rolldown/binding-darwin-x64': 1.2.0 + '@rolldown/binding-freebsd-x64': 1.2.0 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.0 + '@rolldown/binding-linux-arm64-gnu': 1.2.0 + '@rolldown/binding-linux-arm64-musl': 1.2.0 + '@rolldown/binding-linux-ppc64-gnu': 1.2.0 + '@rolldown/binding-linux-s390x-gnu': 1.2.0 + '@rolldown/binding-linux-x64-gnu': 1.2.0 + '@rolldown/binding-linux-x64-musl': 1.2.0 + '@rolldown/binding-openharmony-arm64': 1.2.0 + '@rolldown/binding-wasm32-wasi': 1.2.0 + '@rolldown/binding-win32-arm64-msvc': 1.2.0 + '@rolldown/binding-win32-x64-msvc': 1.2.0 + optional: true + rollup@4.61.0: dependencies: '@types/estree': 1.0.9 @@ -20464,6 +21350,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 + rxjs@7.8.1: + dependencies: + tslib: 2.8.1 + safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} @@ -21021,6 +21911,8 @@ snapshots: ts-algebra@2.0.0: {} + ts-mixer@6.0.4: {} + tslib@2.8.1: {} type-fest@0.13.1: @@ -21058,7 +21950,7 @@ snapshots: undici-types@7.16.0: {} - undici@6.26.0: {} + undici@6.28.0: {} undici@7.27.1: {} @@ -21187,6 +22079,8 @@ snapshots: until-async@3.0.2: {} + untruncate-json@0.0.1: {} + unzipper@0.12.5: dependencies: bluebird: 3.7.2 @@ -21266,6 +22160,8 @@ snapshots: utils-merge@1.0.1: {} + uuid@11.1.1: {} + uuid@14.0.1: {} uuid@7.0.3: {} @@ -21308,7 +22204,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0): + vite-plus@0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0): dependencies: '@oxc-project/types': 0.138.0 '@oxlint/plugins': 1.68.0 @@ -21322,11 +22218,11 @@ snapshots: '@vitest/spy': 4.1.9 '@vitest/utils': 4.1.9 '@voidzero-dev/vite-plus-core': 0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0) - oxfmt: 0.57.0(vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) - oxlint: 1.72.0(oxlint-tsgolint@0.24.0)(vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) + oxfmt: 0.57.0(vite-plus@0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) + oxlint: 1.72.0(oxlint-tsgolint@0.24.0)(vite-plus@0.2.2(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) oxlint-tsgolint: 0.24.0 vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' - vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) optionalDependencies: '@voidzero-dev/vite-plus-darwin-arm64': 0.2.2 '@voidzero-dev/vite-plus-darwin-x64': 0.2.2 @@ -21366,11 +22262,27 @@ snapshots: - utf-8-validate - yaml + vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.5 + postcss: 8.5.25 + rolldown: 1.2.0 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.12.4 + esbuild: 0.28.1 + fsevents: 2.3.3 + jiti: 2.7.0 + terser: 5.48.0 + yaml: 2.9.0 + optional: true + vitefu@1.1.3(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)): optionalDependencies: vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' - vitest@4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)): + vitest@4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)): dependencies: '@vitest/expect': 4.1.9 '@vitest/mocker': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) @@ -21384,7 +22296,7 @@ snapshots: magic-string: 0.30.21 obug: 2.1.3 pathe: 2.0.3 - picomatch: 4.0.4 + picomatch: 4.0.5 std-env: 4.1.0 tinybench: 2.9.0 tinyexec: 1.2.4 @@ -21393,11 +22305,42 @@ snapshots: vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' why-is-node-running: 2.3.0 optionalDependencies: + '@opentelemetry/api': 1.9.1 '@types/node': 24.12.4 '@vitest/browser-preview': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) transitivePeerDependencies: - msw + vitest@4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)): + dependencies: + '@vitest/expect': 4.1.9 + '@vitest/mocker': 4.1.9(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.9 + '@vitest/runner': 4.1.9 + '@vitest/snapshot': 4.1.9 + '@vitest/spy': 4.1.9 + '@vitest/utils': 4.1.9 + es-module-lexer: 2.1.0 + expect-type: 1.4.0 + magic-string: 0.30.21 + obug: 2.1.3 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@opentelemetry/api': 1.9.1 + '@types/node': 24.12.4 + '@vitest/browser-preview': 4.1.9(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vite@8.2.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.9) + transitivePeerDependencies: + - msw + optional: true + vlq@1.0.1: {} volar-service-css@0.0.70(@volar/language-service@2.4.28): @@ -21675,6 +22618,10 @@ snapshots: yoga-layout@3.2.1: {} + zod-to-json-schema@3.25.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + zod-to-json-schema@3.25.2(zod@4.4.3): dependencies: zod: 4.4.3