diff --git a/.env.example b/.env.example index aa5c7da..d895fdb 100644 --- a/.env.example +++ b/.env.example @@ -11,16 +11,12 @@ VITE_CONVEX_URL=https://example.convex.cloud EXPO_PUBLIC_CONVEX_URL=https://example.convex.cloud EXPO_PUBLIC_CONVEX_SITE_URL=https://example.convex.site -# Daemon identity and control plane -DAEMON_ID=local-macbook -DAEMON_NAME=Local MacBook -DAEMON_VERSION=0.0.0 -DAEMON_HEARTBEAT_MS=15000 -DAEMON_COMMAND_LEASE_MS=60000 +# AgentOS / Rivet runtime +# RIVET_ENDPOINT is the private Engine control plane. RIVET_SERVERLESS_ENDPOINT +# is the callback path where that Engine reaches the registry inside Flue. RIVET_ENDPOINT=http://localhost:6420 -RIVET_PUBLIC_ENDPOINT=http://localhost:6420 +RIVET_SERVERLESS_ENDPOINT=http://127.0.0.1:3000/internal/rivet RIVET_WORKSPACE_TOKEN=replace-with-a-long-random-workspace-token -ZOPU_SOURCE_REPOSITORY=/absolute/path/to/zopu-code AGENT_WORKSPACE_ROOT=/absolute/path/to/zopu-agent-workspaces # Flue persistence adapter diff --git a/.gitignore b/.gitignore index 6f1379a..d49515f 100644 --- a/.gitignore +++ b/.gitignore @@ -56,23 +56,8 @@ tmp temp .env.* .env* -infra/ansible/.gitignore -infra/ansible/ansible.cfg -infra/ansible/README.md -infra/ansible/requirements.yml -infra/ansible/group_vars/staging_vds.example/main.yml -infra/ansible/group_vars/staging_vds.example/vault.yml -infra/ansible/inventory/hosts.example.yml -infra/ansible/playbooks/converge.yml -infra/ansible/roles/backup/handlers/main.yml -infra/ansible/roles/backup/tasks/main.yml -infra/ansible/roles/backup/templates/zopu-backup.service.j2 -infra/ansible/roles/backup/templates/zopu-backup.sh.j2 -infra/ansible/roles/backup/templates/zopu-backup.timer.j2 -infra/ansible/roles/common/tasks/main.yml -infra/ansible/roles/directories/tasks/main.yml -infra/ansible/roles/docker/handlers/main.yml -infra/ansible/roles/docker/tasks/main.yml -infra/ansible/roles/docker/vars/main.yml -infra/ansible/roles/firewall/handlers/main.yml -infra/ansible/roles/firewall/tasks/main.yml +infra + +# Local issue-tracker drafts and agent memory state. +.scratch/ +banks/ \ No newline at end of file diff --git a/.vercelignore b/.vercelignore index ffc39e1..bd570a8 100644 --- a/.vercelignore +++ b/.vercelignore @@ -15,3 +15,5 @@ coverage/ .env.* packages/backend/.convex/ .vercel/output/ +banks/ +.scratch/ diff --git a/AGENTS.md b/AGENTS.md index 1becc14..5d32da0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1 +1,15 @@ This Bun/TypeScript monorepo uses Bun/Vite+, Convex, Effect v4, and Flue; use `@code/*` exports, validate env in `packages/env`, never edit generated files or `repos/` (archived reference code — dormant apps, superseded web components, and prior implementations kept for reference), and keep UI presentational by moving UI state to reusable hooks and business/services/pure logic to dedicated modules. Treat `docs/PRODUCT.md`, `docs/DESIGN.md`, and `docs/TECH.md` as the canonical product, experience, and architecture specifications; read the relevant files before decisions or changes in those domains. Before Flue work, MUST read `.agents/skills/flue/SKILL.md` and use installed-version `flue docs`; after every change, MUST run `bunx ultracite check` on every changed source, script, and agent file (apply `bunx ultracite fix` first when needed), run the affected package's `bun run check-types`, exercise the changed behavior with its targeted runtime or smoke test, then run root `bun run check` and report unrelated pre-existing failures separately. Keep each individual instruction in any `AGENTS.md` to 1–2 dense sentences, replacing stale guidance rather than appending; this limit applies per instruction, not to the whole file. + +## Agent skills + +### Issue tracker + +Hybrid: local markdown drafts in `.scratch/`, final polished issues published to Gitea. See `docs/agents/issue-tracker.md`. + +### Triage labels + +Five canonical roles using default label strings. See `docs/agents/triage-labels.md`. + +### Domain docs + +Single-context: root `CONTEXT.md` plus `docs/adr/`. See `docs/agents/domain.md`. diff --git a/apps/web/src/components/projects/project-setup-panel.tsx b/apps/web/src/components/projects/project-setup-panel.tsx new file mode 100644 index 0000000..d918c16 --- /dev/null +++ b/apps/web/src/components/projects/project-setup-panel.tsx @@ -0,0 +1,103 @@ +import type { Id } from "@code/backend/convex/_generated/dataModel"; +import { Button } from "@code/ui/components/button"; +import { ArrowRight, LoaderCircle, X } from "lucide-react"; +import { useEffect, useRef } from "react"; +import { createPortal } from "react-dom"; + +import { useProjectSetup } from "@/hooks/use-project-setup"; + +import { ProjectSetupStatus } from "./project-setup-status"; + +const handleRetry = () => { + // The setup query is reactive — a retry on the backend will append new + // events and the phase derivation updates automatically. No client-side + // refetch is needed; this is a no-op signal for assistive tech. +}; + +export interface ProjectSetupPanelProps { + readonly onClose: () => void; + readonly onEnterProject: () => void; + readonly projectId: Id<"projects">; + readonly projectName: string; +} + +/** + * Modal surface shown after a project is created. Subscribes to the project + * setup lifecycle and renders thin progress states. On "ready" it offers a CTA + * to the global timeline / project home. Never surfaces raw runtime logs. + */ +export const ProjectSetupPanel = ({ + onClose, + onEnterProject, + projectId, + projectName, +}: ProjectSetupPanelProps) => { + const dialogRef = useRef(null); + const setup = useProjectSetup(projectId); + + useEffect(() => { + const dialog = dialogRef.current; + dialog?.showModal(); + return () => dialog?.close(); + }, []); + + return createPortal( + { + event.preventDefault(); + onClose(); + }} + ref={dialogRef} + > +
+
+
+

+ Project setup +

+

+ {projectName} +

+
+ +
+ +
+ {setup.kind === "loading" ? ( +
+ +
+ ) : ( + + )} + + {setup.kind === "ready" && setup.phase === "ready" ? ( +
+ +
+ ) : null} +
+
+
, + document.body + ); +}; diff --git a/apps/web/src/components/projects/project-setup-status.tsx b/apps/web/src/components/projects/project-setup-status.tsx new file mode 100644 index 0000000..610bcb7 --- /dev/null +++ b/apps/web/src/components/projects/project-setup-status.tsx @@ -0,0 +1,157 @@ +import { Button } from "@code/ui/components/button"; +import { + CheckCircle2, + FolderGit2, + LoaderCircle, + PackageOpen, + ShieldCheck, + TriangleAlert, + XCircle, +} from "lucide-react"; + +import type { ProjectSetupPhase } from "@/hooks/use-project-setup"; + +interface PhaseConfig { + readonly description: string; + readonly icon: typeof FolderGit2; + readonly label: string; +} + +const PHASE_CONFIG: Record = { + blocked: { + description: "Setup could not complete.", + icon: XCircle, + label: "Setup blocked", + }, + checking_repository: { + description: "Verifying the repository is readable.", + icon: ShieldCheck, + label: "Checking repository", + }, + cloning_repository: { + description: "Cloning the repository into the workspace.", + icon: PackageOpen, + label: "Cloning repository", + }, + creating_workspace: { + description: "Spinning up an isolated workspace for this project.", + icon: FolderGit2, + label: "Creating workspace", + }, + ready: { + description: "Project is set up and ready to explore.", + icon: CheckCircle2, + label: "Ready", + }, +}; + +const ORDER: readonly ProjectSetupPhase[] = [ + "creating_workspace", + "cloning_repository", + "checking_repository", + "ready", +]; + +export interface ProjectSetupStatusProps { + readonly onRetry?: () => void; + readonly phase: ProjectSetupPhase; +} + +const resolveStepClassName = ( + isComplete: boolean, + isActive: boolean +): string => { + if (isComplete) { + return "grid size-7 shrink-0 place-items-center rounded-full bg-[#20201d] text-[#fffefa]"; + } + + if (isActive) { + return "grid size-7 shrink-0 place-items-center rounded-full border border-[#20201d] text-[#20201d]"; + } + + return "grid size-7 shrink-0 place-items-center rounded-full border border-[#c9c5b9] text-[#858277]"; +}; + +/** + * Presentational rendering of the project setup lifecycle. Renders thin, + * user-meaningful states with no raw runtime logs. The `blocked` phase renders + * an actionable retry control when a handler is supplied. + */ +export const ProjectSetupStatus = ({ + onRetry, + phase, +}: ProjectSetupStatusProps) => { + if (phase === "blocked") { + return ( +
+ +
+

+ Setup hit a problem +

+

+ We could not finish preparing this project. You can retry now or + close and try again later. +

+ {onRetry ? ( + + ) : null} +
+
+ ); + } + + const activeIndex = ORDER.indexOf(phase); + + return ( +
    + {ORDER.map((stepPhase, index) => { + const config = PHASE_CONFIG[stepPhase]; + const isComplete = activeIndex > index; + const isActive = stepPhase === phase; + const Icon = isComplete ? CheckCircle2 : config.icon; + const stepClassName = resolveStepClassName(isComplete, isActive); + + return ( +
  1. + + {isActive ? ( + + ) : ( + + )} + +
    +

    + {config.label} +

    + {isActive ? ( +

    + {config.description} +

    + ) : null} +
    +
  2. + ); + })} +
+ ); +}; diff --git a/apps/web/src/hooks/use-project-setup.ts b/apps/web/src/hooks/use-project-setup.ts new file mode 100644 index 0000000..79918ae --- /dev/null +++ b/apps/web/src/hooks/use-project-setup.ts @@ -0,0 +1,168 @@ +import type { Id } from "@code/backend/convex/_generated/dataModel"; +import { useQuery } from "convex/react"; +import { makeFunctionReference } from "convex/server"; + +/** + * Setup event types emitted by the backend project-setup coordinator. The + * lifecycle types (`project.setup.*`, `project.ready`, `project.setup.failed`) + * are emitted by `projectSetup.runSetup`; the remaining types mirror the + * literals accepted by `projects.appendSetupEvent` and returned by + * `projects.getSetup`. + */ +export type ProjectSetupEventType = + // Lifecycle event types emitted by the project-setup coordinator. + | "project.setup.creating_vm" + | "project.setup.cloning" + | "project.setup.checking_repository" + | "project.ready" + | "project.setup.failed" + // Legacy / environment / preview event types (compatible). + | "project.setup.started" + | "project.setup.environment_required" + | "project.setup.environment_updated" + | "project.setup.ready" + | "project.setup.blocked" + | "project.preview.ready" + | "project.preview.blocked"; + +/** + * User-facing lifecycle phases derived from the raw setup event stream. The + * component layer never renders raw event types — it renders these phases. + */ +export type ProjectSetupPhase = + | "creating_workspace" + | "cloning_repository" + | "checking_repository" + | "ready" + | "blocked"; + +export interface ProjectSetupEvent { + readonly occurredAt: number; + readonly payload: unknown; + readonly type: ProjectSetupEventType; +} + +export interface ProjectSetupState { + readonly events: readonly ProjectSetupEvent[]; + readonly phase: ProjectSetupPhase; +} + +export type ProjectSetupResult = + | { readonly kind: "loading" } + | ({ readonly kind: "ready" } & ProjectSetupState); + +/** + * Minimal structural shape of the `projects.getSetup` return value. We define + * this locally rather than importing from generated code so the hook compiles + * before the backend regenerates its API manifest. + */ +interface SetupQueryResult { + readonly events: readonly { + readonly occurredAt: number; + readonly payload: unknown; + readonly type: ProjectSetupEventType; + }[]; +} + +const getSetupRef = makeFunctionReference< + "query", + { projectId: Id<"projects"> }, + SetupQueryResult +>("projects:getSetup"); + +const ORDERED_PHASES: readonly ProjectSetupPhase[] = [ + "creating_workspace", + "cloning_repository", + "checking_repository", + "ready", +]; + +const typeToPhase = (type: ProjectSetupEventType): ProjectSetupPhase => { + switch (type) { + case "project.setup.creating_vm": + case "project.setup.started": { + return "creating_workspace"; + } + case "project.setup.cloning": { + return "cloning_repository"; + } + case "project.setup.checking_repository": + case "project.setup.environment_required": + case "project.setup.environment_updated": { + return "checking_repository"; + } + default: { + return "creating_workspace"; + } + } +}; + +/** + * Derive the user-facing phase from the raw event stream. + * + * - A `blocked` event always wins (terminal error state). + * - A `ready` event wins over any in-progress phase. + * - Otherwise we map observed events to the furthest in-progress phase. + */ +const derivePhase = ( + events: readonly ProjectSetupEvent[] +): ProjectSetupPhase => { + if (events.length === 0) { + return "creating_workspace"; + } + + const hasBlocked = events.some( + (event) => + event.type === "project.setup.failed" || + event.type === "project.setup.blocked" || + event.type === "project.preview.blocked" + ); + if (hasBlocked) { + return "blocked"; + } + + const hasReady = events.some( + (event) => + event.type === "project.ready" || + event.type === "project.setup.ready" || + event.type === "project.preview.ready" + ); + if (hasReady) { + return "ready"; + } + + let furthestIndex = 0; + for (const event of events) { + const index = ORDERED_PHASES.indexOf(typeToPhase(event.type)); + if (index > furthestIndex) { + furthestIndex = index; + } + } + return ORDERED_PHASES[furthestIndex] ?? "creating_workspace"; +}; + +/** + * Subscribe to a project's setup lifecycle via the `projects.getSetup` query. + * Returns a loading sentinel while the first fetch is in flight, then a + * derived `{ phase, events }` state that components can render directly. + */ +export const useProjectSetup = ( + projectId: Id<"projects"> | undefined +): ProjectSetupResult => { + const setup = useQuery( + getSetupRef, + projectId === undefined ? "skip" : { projectId } + ); + + if (setup === undefined) { + return { kind: "loading" }; + } + + const events: readonly ProjectSetupEvent[] = setup.events.map((event) => ({ + occurredAt: event.occurredAt, + payload: event.payload, + type: event.type, + })); + const phase = derivePhase(events); + return { events, kind: "ready", phase }; +}; diff --git a/apps/web/src/routes/app/projects/page.tsx b/apps/web/src/routes/app/projects/page.tsx index d68498a..4612264 100644 --- a/apps/web/src/routes/app/projects/page.tsx +++ b/apps/web/src/routes/app/projects/page.tsx @@ -3,16 +3,22 @@ import type { Id } from "@code/backend/convex/_generated/dataModel"; import { useAction, useQuery } from "convex/react"; import { makeFunctionReference } from "convex/server"; import { useEffect, useState } from "react"; -import { useSearchParams } from "react-router"; +import { useNavigate, useSearchParams } from "react-router"; import { AddProjectPanel } from "@/components/projects/add-project-panel"; import { LoadingState } from "@/components/projects/loading-state"; +import { ProjectSetupPanel } from "@/components/projects/project-setup-panel"; import { ProjectsGrid } from "@/components/projects/projects-grid"; import { ProjectsHeader } from "@/components/projects/projects-header"; import type { GitProviderAccountOption } from "@/components/projects/provider-chips"; import { useFilteredProjects } from "@/hooks/use-filtered-projects"; import { useProjectsPageState } from "@/hooks/use-projects-page-state"; +interface SetupTarget { + readonly id: Id<"projects">; + readonly name: string; +} + const connectGithubRef = makeFunctionReference< "action", Record, @@ -20,6 +26,7 @@ const connectGithubRef = makeFunctionReference< >("gitConnections:connectGithub"); export default function ProjectsRoute() { + const navigate = useNavigate(); const [searchParams, setSearchParams] = useSearchParams(); const projects = useQuery(api.projects.list, {}); const providerAccounts = useQuery( @@ -28,6 +35,7 @@ export default function ProjectsRoute() { ) as readonly GitProviderAccountOption[] | undefined; const connectGithubAction = useAction(connectGithubRef); const [resumeError, setResumeError] = useState(); + const [setupTarget, setSetupTarget] = useState(); const pageState = useProjectsPageState({ hasProjects: projects === undefined ? undefined : projects.length > 0, }); @@ -67,8 +75,13 @@ export default function ProjectsRoute() { project.sources.map((source) => source.url) ); const hasProjects = projects.length > 0; - const handleProjectCreated = () => { + const handleProjectCreated = (projectId: string) => { pageState.closeAddProject(); + const project = projects.find((item) => item.id === projectId); + setSetupTarget({ + id: projectId as Id<"projects">, + name: project?.name ?? "Project", + }); }; const handleCloseAddProject = () => { pageState.closeAddProject(); @@ -115,6 +128,17 @@ export default function ProjectsRoute() { onProjectCreated={handleProjectCreated} /> ) : null} + {setupTarget ? ( + setSetupTarget(undefined)} + onEnterProject={() => { + setSetupTarget(undefined); + navigate("/"); + }} + projectId={setupTarget.id} + projectName={setupTarget.name} + /> + ) : null} ); } diff --git a/deploy/vds/Caddyfile b/deploy/vds/Caddyfile new file mode 100644 index 0000000..1f3e355 --- /dev/null +++ b/deploy/vds/Caddyfile @@ -0,0 +1,60 @@ +# Caddy reverse proxy for the Zopu VDS staging agent stack. +# +# This is the ONLY public ingress to the single agents Node process (see +# docs/DEPLOYMENT_PLAN.md §"Public surface"). It terminates TLS for +# agents.zopu.puter.wtf — the Flue callback hostname Convex reaches — then +# forwards ONLY the documented worker paths to the internal `agents` service at +# 127.0.0.1:3000. +# +# Hard rules this file enforces: +# - No generic /api/* proxy and no browser-to-Flue traffic (DEPLOYMENT_PLAN.md +# line 86). Browsers talk only to Convex. +# - Only the paths the Convex backend actually calls are routed: +# /health liveness probe +# /internal/project-setup single-call project setup coordinator +# /internal/agents//events agent event dispatch callback +# - The RivetKit serverless registry at /internal/rivet/* is NOT proxied. It +# is a private loopback callback the Engine reaches directly at +# http://127.0.0.1:3000/internal/rivet; exposing it publicly would widen the +# private worker protocol. +# - Former routes (/agents/zopu/*, /internal/work-attempts/*, /workflows/*, +# /api/rivet/*) are intentionally absent: they are stale and not part of the +# current Convex→agents contract. +# - Everything else returns 404. The private worker protocol stays narrow. +# +# TLS certs persist in Caddy's data directory. Caddy serves its own ACME +# HTTP-01 challenge responses on :80 automatically, so the :80 block only +# redirects everything else to HTTPS — worker traffic is never served over +# plain HTTP. +# +# Install/update: see the "Caddy" section of deploy/vds/README.md. In short, +# copy this file to /etc/caddy/Caddyfile, then: +# sudo caddy validate --config /etc/caddy/Caddyfile +# sudo systemctl reload caddy + +agents.zopu.puter.wtf { + encode zstd gzip + + # Explicit route block pins directive order: path-matched proxies run + # first, then the terminal 404 fallback. No directive is left to the + # default sort. + route { + # Liveness probe (CI healthcheck). Routed to the real worker so a failed + # process is not masked by a synthetic success. + reverse_proxy /health 127.0.0.1:3000 + + # Single-call project setup coordinator. Requires the internalRoute bearer. + reverse_proxy /internal/project-setup 127.0.0.1:3000 + + # Agent event dispatch callback. Requires the internalRoute bearer. + reverse_proxy /internal/agents/* 127.0.0.1:3000 + + # Everything else is not part of the private worker protocol. + respond 404 + } +} + +# HTTP → HTTPS redirect (Caddy still answers ACME challenges on :80). +:80 { + redir https://{host}{uri} permanent +} diff --git a/deploy/vds/README.md b/deploy/vds/README.md new file mode 100644 index 0000000..ceaf142 --- /dev/null +++ b/deploy/vds/README.md @@ -0,0 +1,121 @@ +# Zopu VDS agents deployment + +This directory holds the systemd unit, environment template, and Caddy reverse-proxy config that run the single Zopu agents Node process on the VDS. It supersedes the former container deployment for the agents process. + +## Runtime topology + +One Node process (`zopu-agents.service`) runs the whole intelligence runtime: + +``` +zopu-agents.service + └─ node /srv/zopu/current/packages/agents/dist/server.mjs + ├─ Hono server 127.0.0.1:3000 + ├─ Flue 2.0 agents SQLite at /srv/zopu/data/flue/flue.db + └─ AgentOS registry in-process, serverless, at /internal/rivet/* +``` + +The **Rivet Engine is a separate private service** on `127.0.0.1:6420`, managed by its own unit/compose. This unit does not start it. There is **no standalone AgentOS runner**: the registry handler runs inside the agents process. + +### The two Rivet endpoints (not interchangeable) + +| Variable | Role | Value on this host | +| --- | --- | --- | +| `RIVET_ENDPOINT` | Engine **control plane** this process connects _to_ for actor metadata | `http://127.0.0.1:6420` | +| `RIVET_SERVERLESS_ENDPOINT` | Address the engine calls **back into** this process's `/internal/rivet` handler | `http://127.0.0.1:3000/internal/rivet` | + +Pointing both at the engine, or dropping the `/internal/rivet` path, breaks the registry. See `agents.env.example` for the authoritative comments. + +## Files + +- `zopu-agents.service` — systemd unit. Runs `/srv/zopu/current/.../server.mjs` as user `zopu`, waits for engine health before binding, hardens the service, and restarts on failure. +- `agents.env.example` — template for `/etc/zopu/agents.env`. Contains the full validated env schema with no secrets. +- `../../scripts/release-agents.sh` — local build, upload, and atomic release promotion command. Each release includes this directory so the unit's `Documentation=` target remains valid. +- `Caddyfile` — source-controlled public ingress for `agents.zopu.puter.wtf`. Terminates TLS and forwards only `/health`, `/internal/project-setup`, and `/internal/agents/*` to `127.0.0.1:3000`; the private `/internal/rivet/*` registry handler is never proxied. + +## Prerequisites on the VDS + +1. **Node 24** installed at `/opt/zopu/node/bin/node` (the verified VDS Node; the unit's `ExecStart` and `PATH` are anchored on this path). The release bundle ships its own `node_modules`; only the Node binary is expected from the host. +2. **`curl`** and **`bash`** on `PATH` (used by the `ExecStartPre` engine health probe). +3. A dedicated service user and group: + ```sh + sudo useradd --system --no-create-home --shell /usr/sbin/nologin zopu + ``` +4. The two writable state trees, owned by `zopu`: + ```sh + sudo mkdir -p /srv/zopu/data/flue /srv/zopu/workspaces + sudo chown -R zopu:zopu /srv/zopu/data /srv/zopu/workspaces + ``` +5. The **Rivet Engine** running and answering `http://127.0.0.1:6420/health`. +6. A release promoted by `scripts/release-agents.sh` to `/srv/zopu/releases/`, with `/srv/zopu/current` symlinked to it. The release must contain `packages/agents/dist/server.mjs` and `deploy/vds/`. + +## Install + +```sh +# 1. Secrets +sudo install -d -m 0750 -o root -g zopu /etc/zopu +sudo cp agents.env.example /etc/zopu/agents.env +sudo chown root:zopu /etc/zopu/agents.env +sudo chmod 0600 /etc/zopu/agents.env +sudo "$EDITOR" /etc/zopu/agents.env # fill in every REPLACE-WITH-... + +# 2. Unit +sudo install -m 0644 zopu-agents.service /etc/systemd/system/zopu-agents.service +sudo systemctl daemon-reload +sudo systemctl enable --now zopu-agents.service +``` + +## Verify + +```sh +systemctl status zopu-agents.service +curl -fsS http://127.0.0.1:3000/health # {"service":"zopu-agents","status":"ok"} +``` + +### Public ingress (Caddy) + +Caddy terminates TLS for `agents.zopu.puter.wtf` and forwards only the three paths the Convex backend calls to the internal agents worker (`127.0.0.1:3000`). The in-process serverless registry at `/internal/rivet/*` is reachable only over loopback (the Engine's `RIVET_SERVERLESS_ENDPOINT` callback), never through Caddy. All other paths return `404`. + +Install or update from this checked-in artifact: + +```sh +# 1. Materialize the config +sudo install -m 0644 Caddyfile /etc/caddy/Caddyfile + +# 2. Validate before applying +sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile + +# 3. Reload the running Caddy (no restart needed) +sudo systemctl reload caddy +``` + +Verify the narrow public surface: + +```sh +curl -fsS https://agents.zopu.puter.wtf/health # {"service":"zopu-agents","status":"ok"} +curl -i https://agents.zopu.puter.wtf/internal/rivet/anything # 404 — registry stays private +``` + +## Release switch + +From the repository root on the build host, create and promote a release: + +```sh +scripts/release-agents.sh +``` + +The script atomically swaps `/srv/zopu/current`; it deliberately does **not** restart the service. After the upload succeeds, restart the single agents unit: + +```sh +sudo systemctl restart zopu-agents.service +``` + +Roll back by atomically replacing `current` with a symlink to a prior release, then restarting the same service. + +## Optional: explicit engine ordering + +The unit already gates startup on the engine health endpoint via `ExecStartPre`. If the engine is itself a named systemd unit on this host, you may add a hard ordering by uncommenting/adding in the `[Unit]` section: + +```ini +After=rivet-engine.service +Wants=rivet-engine.service +``` diff --git a/deploy/vds/agents.env.example b/deploy/vds/agents.env.example new file mode 100644 index 0000000..0bf4bb4 --- /dev/null +++ b/deploy/vds/agents.env.example @@ -0,0 +1,55 @@ +# /etc/zopu/agents.env — runtime environment for zopu-agents.service +# +# Install at /etc/zopu/agents.env, owner root:zopu, mode 0600. Fill in every +# REPLACE-WITH-... value; the process validates the full schema at start and +# will refuse to boot if a required key is missing or malformed. This file is +# the single source of secrets for the VDS agents process — never commit a +# filled-in copy. + +# --- Process listener -------------------------------------------------------- +# Binds the private loopback only. Caddy (or an equivalent reverse proxy) +# terminates TLS upstream and forwards to 127.0.0.1:3000. +HOST=127.0.0.1 +PORT=3000 +NODE_ENV=production + +# --- Rivet Engine + in-process registry (two distinct endpoints) ------------- +# +# RIVET_ENDPOINT is the Engine CONTROL PLANE this process connects TO for actor +# metadata/management. The engine is a separate private service on this host. +RIVET_ENDPOINT=http://127.0.0.1:6420 +# +# RIVET_SERVERLESS_ENDPOINT is the address the Engine calls BACK INTO this same +# process to reach the in-process serverless AgentOS registry handler, which is +# mounted at /internal/rivet/*. It must resolve to this process's own listener +# plus that base path. Do NOT point this at the engine; do NOT drop the path. +RIVET_SERVERLESS_ENDPOINT=http://127.0.0.1:3000/internal/rivet +# +# Shared secret authenticating actor connections between the engine and this +# registry's onBeforeConnect. Must match the value configured on the engine. +RIVET_WORKSPACE_TOKEN=REPLACE-WITH-LONG-RANDOM-WORKSPACE-TOKEN + +# --- Flue SQLite persistence ------------------------------------------------- +# Canonical conversation state. Parent dir must be one of the unit's +# ReadWritePaths (/srv/zopu/data). +FLUE_DB_PATH=/srv/zopu/data/flue/flue.db +# Bearer token shared with Convex for /internal/* service calls. +FLUE_DB_TOKEN=REPLACE-WITH-LONG-RANDOM-SERVICE-TOKEN + +# --- Project workspaces ------------------------------------------------------ +# Root for project-bound AgentOS VMs and generated artifacts. Must be one of +# the unit's ReadWritePaths (/srv/zopu/workspaces). +AGENT_WORKSPACE_ROOT=/srv/zopu/workspaces + +# --- Convex control plane ---------------------------------------------------- +CONVEX_URL=REPLACE-WITH-DEPLOYMENT.convex.cloud +CONVEX_SITE_URL=REPLACE-WITH-DEPLOYMENT.convex.site + +# --- Agent model provider (OpenAI-compatible) -------------------------------- +AGENT_MODEL_PROVIDER=cheaptricks +AGENT_MODEL_API=openai-completions +AGENT_MODEL_NAME=mimo-v2.5 +AGENT_MODEL_BASE_URL=https://ai.example.com/v1 +AGENT_MODEL_API_KEY=REPLACE-WITH-PROVIDER-API-KEY +AGENT_MODEL_CONTEXT_WINDOW=1048576 +AGENT_MODEL_MAX_TOKENS=131072 diff --git a/deploy/vds/zopu-agents.service b/deploy/vds/zopu-agents.service new file mode 100644 index 0000000..c639f94 --- /dev/null +++ b/deploy/vds/zopu-agents.service @@ -0,0 +1,76 @@ +# zopu-agents.service — single Node intelligence runtime for the Zopu VDS. +# +# Runtime shape (one process, no separate runner): +# +# zopu-agents (this unit) +# └─ node /srv/zopu/current/packages/agents/dist/server.mjs +# ├─ Hono HTTP server on 127.0.0.1:3000 +# ├─ Flue 2.0 conversation agents + SQLite at /srv/zopu/data/flue +# └─ AgentOS registry in serverless mode, served in-process at +# /internal/rivet/* (registry.handler drives the per-request +# runtime; there is no standalone AgentOS runner process). +# +# The Rivet Engine is a SEPARATE private service on 127.0.0.1:6420, managed +# by its own unit/compose. This unit does not start or own it; it only waits +# for the engine health endpoint before binding (ExecStartPre below). +# +# Two distinct Rivet endpoints (see agents.env): +# RIVET_ENDPOINT — engine control plane the registry connects to +# (http://127.0.0.1:6420). Used for actor metadata. +# RIVET_SERVERLESS_ENDPOINT — address the engine calls BACK into this same +# process's /internal/rivet handler +# (http://127.0.0.1:3000/internal/rivet). +# These are NOT interchangeable; do not point both at the engine. +# +# The release is a self-contained bundle under /srv/zopu/releases/ with +# /srv/zopu/current as the live symlink. This unit always runs `current`; the +# release script swaps it atomically, then the operator restarts this service. + +[Unit] +Description=Zopu agents intelligence runtime (Flue + in-process AgentOS registry) +# Soft network ordering. The real gate on the separate Engine is the health +# probe in ExecStartPre. If the engine is itself a named systemd unit on this +# host, add an explicit ordering here, e.g.: +# After=rivet-engine.service +# Wants=rivet-engine.service +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=zopu +Group=zopu +WorkingDirectory=/srv/zopu/current + +# Secrets and runtime config live in /etc/zopu/agents.env (chmod 600, owner +# root:zopu). See agents.env.example for the full schema; never commit real +# values. NODE_ENV is pinned here so a release can never accidentally start in +# development mode. +Environment=NODE_ENV=production +EnvironmentFile=/etc/zopu/agents.env + +# Wait for the separate Rivet Engine control plane to report healthy before +# binding. The engine is NOT managed by this unit; this probe is the startup +# dependency on its health. Bounded to ~60s. +ExecStartPre=/usr/bin/env bash -c 'i=0; until curl -fsS -o /dev/null http://127.0.0.1:6420/health; do i=$$((i+1)); [ "$$i" -ge 60 ] && { echo "rivet engine not healthy at http://127.0.0.1:6420/health" >&2; exit 1; }; sleep 1; done' + +# Built release artifact. Node is the verified VDS install at +# /opt/zopu/node/bin/node (Node 24). PATH is anchored on that directory so the +# Node binary and its bundled toolchain (corepack/pnpm) resolve deterministically. +Environment=PATH=/opt/zopu/node/bin:/usr/local/bin:/usr/bin:/bin +ExecStart=/opt/zopu/node/bin/node /srv/zopu/current/packages/agents/dist/server.mjs + +Restart=always +RestartSec=5 + +# --- Hardening --------------------------------------------------------------- +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=full +ProtectHome=true +# Writable state: Flue SQLite + project workspaces. The release tree under +# /srv/zopu/current is treated read-only at runtime. +ReadWritePaths=/srv/zopu/workspaces /srv/zopu/data + +[Install] +WantedBy=multi-user.target diff --git a/docs/DEPLOYMENT_PLAN.md b/docs/DEPLOYMENT_PLAN.md index fa9c354..eef4c5d 100644 --- a/docs/DEPLOYMENT_PLAN.md +++ b/docs/DEPLOYMENT_PLAN.md @@ -1,6 +1,6 @@ # Deployment Architecture Recommendation -> **Status:** Proposed — research completed 2026-07-31. This supersedes the shared-Convex-environment approach in `docs/deployment.md` once implemented. +> **Status:** Partially implemented — staging environment is live as of 2026-08-03. The public Vercel/Convex endpoints and VDS services are operational; the declarative Pulumi/Ansible/CI backlog remains. > > **Goal:** retain an instant local iteration loop while operating one stable public staging environment with reproducible, declarative infrastructure. @@ -12,18 +12,18 @@ Use a deliberately split stack: Fast iteration (private development) Stable staging (public) ──────────────────────────────────── ──────────────────────── Mac + Tailscale Vercel + Contabo VDS -Web / Flue / Rivet / runner Web SSR Agents VDS +Web / Flue + in-process registry / Rivet Web SSR Agents VDS │ │ │ personal Convex dev deployment staging Convex deployment ``` | Concern | Iteration | Staging | | --- | --- | --- | -| User-visible URL | Existing Tailscale URL on the Mac | `https://staging.` on Vercel | +| User-visible URL | Existing Tailscale URL on the Mac | `https://zopu-staging.vercel.app` on Vercel | | Product backend | Personal Convex **dev** deployment | Dedicated long-lived Convex deployment | | Web | Vite HMR on the Mac | Vercel React Router SSR | -| Agent worker | Local Flue, engine, and runner | Contabo VDS: Flue, Rivet Engine, AgentOS runner | -| Delivery | Run local `pnpm dev:tailscale` | CI applies IaC then updates immutable images | +| Agent worker | Local Flue + in-process AgentOS registry and Engine | Contabo VDS: one Flue/registry Node process + Rivet Engine | +| Delivery | Run local `pnpm dev:tailscale` | Locally built release bundle promoted on the VDS | | State/credentials | Development-only | Independent staging secrets, OAuth app, and volumes | **Do not create a second remote “fast iteration” stack.** It duplicates the slowest part of the loop—building and replacing container images—while the existing Mac/Tailscale stack already exercises the complete topology from a phone. Staging is the public link and integration gate; local development is the fast environment. @@ -33,21 +33,21 @@ personal Convex dev deployment staging Convex deployment The repository has three materially different runtime needs: 1. **Web** is a React Router SSR Node application. Its current production artifact is `react-router build` plus `react-router-serve`, and `apps/web/Dockerfile` already serves it on Node. Vercel supports React Router SSR and streaming, and is the appropriate managed host for this stateless application. [Vercel React Router guide](https://vercel.com/docs/frameworks/frontend/react-router) -2. **Convex** owns authentication, durable product data, workflows, and reactive client projections. It is not an application container to run on the VDS. The architecture explicitly requires clients to communicate only with Convex. (`docs/TECH.md`, §1.) -3. **Flue + Rivet Engine + AgentOS runner** are persistent worker processes. The runner creates Git worktrees, installs dependencies, and host-mounts those directories into AgentOS; they require a long-lived filesystem and must stay co-located with their workspace volume. They are not appropriate for Vercel or Cloudflare Workers. [Flue Node Docker deployment](https://flueframework.com/docs/ecosystem/deploy/docker) · [Rivet runtime modes](https://rivet.dev/docs/general/runtime-modes) +2. **Convex** owns authentication, durable product data, workflows, and reactive client projections. It is not an application container to run on the VDS. The architecture explicitly requires clients to communicate only with Convex. +3. **Flue + in-process AgentOS registry + Rivet Engine** are the worker topology. Flue owns the registry request handler in the same Node process; the Engine remains a separate private service with durable state. Their filesystem-backed workspaces require a long-lived volume, so they are not appropriate for Vercel or Cloudflare Workers. [Flue Node deployment](https://flueframework.com/docs/ecosystem/deploy/node) · [Rivet runtime modes](https://rivet.dev/docs/general/runtime-modes) Cloudflare remains valuable for authoritative DNS, TLS/DDoS controls, and optionally a later public-edge layer. It is **not** the first frontend runtime choice: moving the current Node SSR artifact to Workers requires a Cloudflare-specific React Router/workerd build and `nodejs_compat`; it does not host the private worker stack. [Cloudflare React Router guide](https://developers.cloudflare.com/workers/framework-guides/web-apps/react-router/) ## Environment isolation — required, not optional -The present shared Convex deployment is incompatible with two simultaneously operating environments. `SITE_URL` is a single deployment-scoped Better Auth base/trusted origin and GitHub OAuth callback origin; switching it between hosts breaks the other host (`docs/deployment.md`, lines 19–47). +The present shared Convex deployment is incompatible with two simultaneously operating environments. `SITE_URL` is a single deployment-scoped Better Auth base/trusted origin and GitHub OAuth callback origin; switching it between hosts breaks the other host. Create these independent Convex deployments: | Deployment | Type | Purpose | | --- | --- | --- | | `dev:` | Convex dev | Local loop only; each developer owns one | -| `staging` | Long-lived production-type deployment | Public integration/staging; never reused for local testing | +| `staging` (`joyous-cat-297`) | Long-lived production-type deployment | Public integration/staging; never reused for local testing | | Branch previews | Ephemeral preview deployment | Optional later, only for frontend/backend changes that do not need OAuth | Convex supports a named long-lived production-type deployment (`convex deployment create staging --type prod`), per-deployment environment variables, and branch preview deployments. [Convex multiple deployments](https://docs.convex.dev/production/multiple-deployments) · [Convex environment variables](https://docs.convex.dev/production/environment-variables) @@ -55,61 +55,62 @@ Convex supports a named long-lived production-type deployment (`convex deploymen Every environment gets its own: - `SITE_URL`, exact browser origin; -- `FLUE_URL` / `AGENT_BACKEND_URL`, pointing at only that environment’s Flue worker; +- `FLUE_URL` / `AGENT_BACKEND_URL`, pointing at only that environment’s Flue worker (e.g. `https://agents.zopu.puter.wtf`); - `FLUE_DB_TOKEN` shared only with that environment’s agent service; - model and Git provider credentials; - GitHub OAuth application/client credentials where GitHub login is enabled. -A GitHub OAuth App permits one callback URL. Use a staging OAuth App with `https://staging./api/auth/callback/github`; keep local development on its own OAuth app or login mechanism. Do not promise OAuth on throwaway Vercel preview domains. [GitHub OAuth Apps](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) +A GitHub OAuth App permits one callback URL. Use a staging OAuth App with `https://zopu-staging.vercel.app/api/auth/callback/github`; keep local development on its own OAuth app or login mechanism. Do not promise OAuth on throwaway Vercel preview domains. [GitHub OAuth Apps](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) ## Staging topology ```mermaid flowchart LR - Browser[Browser] -->|HTTPS| Vercel[Vercel: staging web SSR] - Browser -->|queries & mutations| Convex[Convex: staging] - Vercel -->|/api/auth rewrite| ConvexSite[Convex Site auth routes] - Convex -->|service-authenticated HTTPS| Flue[Contabo: Flue Node service] - Flue --> Engine[Rivet Engine: private Docker network] - Runner[AgentOS runner: private Docker network] --> Engine - Runner --> Volumes[Persistent source mirror + workspaces] + Browser[Browser] -->|HTTPS| Vercel[Vercel: zopu-staging.vercel.app] + Browser -->|queries & mutations| Convex[Convex: joyous-cat-297] + Vercel -->|/api/auth rewrite| ConvexSite[Convex Site: joyous-cat-297.convex.site] + Convex -->|FLUE_DB_TOKEN + org header| Flue[Contabo: Flue + AgentOS registry] + Flue -->|control plane| Engine[Rivet Engine: 127.0.0.1:6420] + Engine -->|serverless callback| Flue + Engine --> Volumes[/srv/zopu/data/rivet] + Flue --> Workspaces[/srv/zopu/workspaces + /srv/zopu/data/flue] CF[Cloudflare DNS] --> Vercel CF --> Flue ``` ### Public surface -- `staging.` → Vercel. -- `agents-staging.` → Contabo Caddy/Traefik → Flue only. -- Only ports 80/443 (and Tailscale/managed SSH) enter the VDS. Do **not** publish Rivet ports `6420` or `6421`, the AgentOS runner, workspace directories, or any engine dashboard. +- `zopu-staging.vercel.app` → Vercel. +- `agents.zopu.puter.wtf` → Contabo VDS (`zopu-staging-1`, `158.220.110.74`) Caddy → Flue only. +- Only ports 80/443 (and Tailscale/managed SSH) enter the VDS. Do **not** publish Rivet ports `6420` or `6421`, registry internals, workspace directories, or any engine dashboard. - The Flue route is reachable from Convex, but its middleware must continue to require the per-environment bearer `FLUE_DB_TOKEN` and organization/turn correlation headers. This is a private worker protocol exposed narrowly for Convex callbacks—not a browser API. - Browser clients continue to talk only to Convex. Do not restore browser-to-Flue traffic or a generic `/api/*` agent proxy. ### Private VDS services -The checked-in Compose topology should contain exactly these services: +The current VDS (`zopu-staging-1`, `158.220.110.74`) runs a deliberately small private topology: -| Service | Network exposure | Persistent data | Notes | -| --- | --- | --- | --- | -| `engine` | Internal only | `/data` bind mount | Single-node RocksDB is suitable for staging. Set an admin token; probe `:6420/health`. | -| `agents` | Caddy upstream only | Shared workspace bind mount | Runs the existing Flue Node build and owns worktree preparation; `/health` is a liveness endpoint. | -| `runner` | Internal only | Shared workspace bind mount | Separate from `agents`; needs Bun, Git, and the same worktree paths prepared by `agents`. | -| `caddy` | 80/443 only | Caddy certificate/config bind mounts | TLS for the Flue callback hostname. | +| Service | Runtime | Network exposure | Persistent data | Notes | +| --- | --- | --- | --- | --- | +| `engine` | Existing Docker Compose (`/srv/zopu/compose/docker-compose.yml`) | private loopback `127.0.0.1:6420` | `/srv/zopu/data/rivet` bind mount | Single-node RocksDB backend. Health: `http://127.0.0.1:6420/health`. | +| `agents` | systemd (`/etc/systemd/system/zopu-agents.service`) | Caddy upstream only (`127.0.0.1:3000`) | `/srv/zopu/workspaces` + `/srv/zopu/data/flue` | One Node process runs Flue and its serverless AgentOS registry. `RIVET_ENDPOINT` is the Engine control plane; `RIVET_SERVERLESS_ENDPOINT` is Engine's private callback to `http://127.0.0.1:3000/internal/rivet`. | +| `caddy` | systemd (`/etc/systemd/system/caddy.service`) | 80/443 only | Caddy certificate/config volumes | `/etc/caddy/Caddyfile` terminates TLS for `agents.zopu.puter.wtf` and forwards only the documented Flue paths to `127.0.0.1:3000`. | + +Release artifacts are source controlled: `scripts/release-agents.sh` builds a curated bundle locally and atomically promotes `/srv/zopu/current`; `deploy/vds/` contains the systemd unit and secret-free environment template. The VDS materializes Linux production dependencies from the frozen lockfile, so macOS-native binaries are never uploaded. Rivet’s filesystem backend is explicitly appropriate for single-node deployments; multi-node/HA later requires PostgreSQL and NATS. Configure the engine with a persistent `/data` bind mount, admin token, resource limits, and a `:6420/health` probe. [Rivet Docker Compose](https://rivet.dev/docs/self-hosting/docker-compose) · [Rivet production checklist](https://rivet.dev/docs/self-hosting/production-checklist) -The runner must receive a **build-time** `RIVET_RUNNER_VERSION` derived from the CI run or immutable release revision. Rivet uses it to route new actors to the new runner and drain old actors; without it, existing actors can continue on old code. - -## IaC model: Pulumi + Ansible + Compose, each at the right seam +## IaC model: Pulumi + Ansible + systemd/Compose, each at the right seam Dokploy is intentionally excluded: it has already proved too slow and imperative for this stack. One tool should not be forced to manage three different concerns poorly. | Layer | Source of truth | Tool | Reason | | --- | --- | --- | --- | -| SaaS control plane | `infra/pulumi` | **Pulumi TypeScript** | Declarative Cloudflare DNS and Vercel project/domain/environment configuration; one `staging` stack now, later `production`; encrypted stack secrets and `preview`/`refresh` drift workflows. | | VDS baseline | `infra/ansible` | **Ansible** | Idempotent OS convergence: service user, Docker, firewall, Tailscale, directories, Caddy prerequisites, and backup timer. No Pulumi SSH-command pseudo-provider. | -| VDS application topology | `deploy/compose` | **Docker Compose** | Explicit services, networks, volumes, healthchecks, images, and restart policy in the repository. This is the deployable unit. | -| Release execution | CI | **Gitea Actions or an equivalent CI runner** | Builds tagged images, pushes them to a registry, runs `ansible-playbook`, then applies a pinned Compose release and checks health. | +| VDS application topology | `deploy/vds` + `/srv/zopu/compose` | **systemd + Docker Compose** | Engine stays in its existing private Compose service; the checked-in systemd unit runs the single Node agents/registry process. | +| Release execution | `scripts/release-agents.sh` now; CI later | **Local release bundle promotion** | Builds a curated cross-platform bundle, installs Linux dependencies on the VDS, atomically swaps `current`, then restarts `zopu-agents`. | + +> **Current state (2026-08-03):** the Engine and Caddy retain their manually bootstrapped VDS services. The Node agents process is now represented by source-controlled `deploy/vds` artifacts and `scripts/release-agents.sh`; Pulumi/Ansible and CI are still future work. Pulumi state is meaningful only with a shared backend—use Pulumi Cloud or a managed/self-hosted state backend, **not** a developer-local `file://` state file. Pulumi’s state is what enables previews, refreshes, encrypted secret tracking, and drift detection. [Pulumi state and backends](https://www.pulumi.com/docs/iac/concepts/state-and-backends/) · [Pulumi secrets](https://www.pulumi.com/docs/iac/concepts/secrets/) @@ -126,43 +127,39 @@ Ansible is not redundant: it makes the Contabo host reproducible without pretend ### Staging release -1. A merge to the staging branch (initially `master` if that is the stable branch) starts CI. -2. CI runs type checks and targeted tests. -3. CI builds the web for the **staging Convex deployment** and deploys it to the dedicated staging Vercel project. Build-time `VITE_CONVEX_URL` and `VITE_AUTH_URL` must be staging values. -4. CI builds immutable `agents` and `runner` images tagged with commit SHA; it sets `RIVET_RUNNER_VERSION` from the release identity. -5. CI runs Ansible convergence, updates the Compose release to those exact image digests, and executes `docker compose up -d`. -6. CI verifies: Vercel URL returns 200, Convex auth origin is accepted, agents health endpoint returns 200, engine health returns 200 inside the private network, and a real signed-in staging conversation receives an agent response. -7. Rollback means redeploying the previous image digests and restoring the corresponding Vercel deployment—not rebuilding mutable `latest` images. +1. Run repository validation and build the staging web artifact for the staging Convex deployment (`joyous-cat-297`, `https://joyous-cat-297.convex.cloud`), then deploy it to `zopu-staging` (`https://zopu-staging.vercel.app`). +2. From the repository root, create and promote the agents release with `scripts/release-agents.sh `; it installs Linux production dependencies on the VDS, atomically swaps `/srv/zopu/current`, and leaves the running process untouched until restart. +3. Restart `zopu-agents.service` on the VDS. The unit waits for Engine health, then starts the one Node process that exposes Flue and the serverless registry. +4. Verify: `https://zopu-staging.vercel.app` returns 200, Convex auth origin `https://zopu-staging.vercel.app` is accepted, `https://agents.zopu.puter.wtf/health` returns 200, Engine health returns 200 at `http://127.0.0.1:6420/health` inside the private network, and a real signed-in staging conversation receives an agent response. +5. Roll back by atomically repointing `/srv/zopu/current` at the prior release then restarting `zopu-agents.service`. Do not couple the Vercel deployment to Gitea-native Git integration assumptions. The repository is hosted on Gitea, so start with CI invoking the Vercel CLI/API. If a Git mirror is later introduced, Vercel previews can be enabled separately. ## Required implementation backlog -This research does **not** deploy anything. Before the first staging release, complete these changes in order: +The staging environment is live. Remaining work is to close the gap between the manual, on-host configuration and the declarative, CI-driven target described above: -1. Create the separate `staging` Convex deployment and its deploy key; configure deployment-scoped secrets and `SITE_URL`. -2. Correct the auth/webhook origin seams: - - Add Vercel production rewrites for `/api/auth/*` to the staging Convex Site URL; Vite’s current proxy only applies to local development. - - Make the Puter webhook target the staging Convex Site HTTP action directly, rather than the web origin. -3. Add Vercel React Router support and a dedicated staging deployment configuration. -4. Create the four-service Compose topology and a runner-capable image. The current agents Dockerfile starts only Flue and does not provide the dedicated Bun/Git runner service. -5. Add health routes/checks, resource limits, volume backup, image-digest deployments, and `RIVET_RUNNER_VERSION`. -6. Add `infra/pulumi` and `infra/ansible`, then CI environments with protected staging secrets. -7. Execute an end-to-end staging smoke: sign in, create/connect a project, send a conversation, and complete a disposable issue-to-PR job. +1. **Convex staging deployment** — ✅ Done as `joyous-cat-297`. `SITE_URL` is set to `https://zopu-staging.vercel.app`, `FLUE_URL`/`AGENT_BACKEND_URL` to `https://agents.zopu.puter.wtf`, and `FLUE_DB_TOKEN` to the VDS agents token. +2. **Auth/webhook origin seams** — ✅ Vercel rewrites `/api/auth/*` to `https://joyous-cat-297.convex.site/api/auth/*` in `vercel.json`. Verify that Puter/Gitea webhooks are configured to post directly to the Convex Site HTTP action URL (`https://joyous-cat-297.convex.site/api/git/webhooks/...`) rather than the web origin. +3. **Vercel React Router staging project** — ✅ Done as `zopu-staging` (`https://zopu-staging.vercel.app`). +4. **VDS agent topology** — ✅ Source-controlled VDS unit, env template, and atomic release bundle now model the single Flue + in-process registry process. Apply them to the VDS and retire the former runner service from its Compose file. +5. **Engine deployment, backups, and CI** — 🔄 Engine health and VDS backups exist. Move the existing Engine Compose service and Caddy configuration into source-controlled provisioning; add CI to run validation, promote release bundles, and deploy the web. +6. **Declarative IaC** — ⏳ Create `infra/pulumi` (Cloudflare DNS + Vercel project) and `infra/ansible` (host convergence). +7. **End-to-end staging smoke** — ⏳ Execute: sign in via GitHub OAuth, create/connect a project, send a conversation, and complete a disposable issue-to-PR job against the live `zopu-staging` + `agents.zopu.puter.wtf` stack. ## Security and operations guardrails - Keep environment secrets in CI environment secret stores, Pulumi encrypted configuration/ESC where appropriate, Convex deployment variables, and Vercel environment variables. Never commit `.env` files or place secrets in image layers. - Use unique `FLUE_DB_TOKEN`, Rivet admin token, workspace token, model credential, and Git token per environment. -- The VDS runs code-writing agents. Use a dedicated service user; do not mount the host home directory; expose only scoped repository credentials to individual attempts; and keep staging separate from any production host. This follows the repository-isolation policy in `docs/TECH.md` §11. +- The VDS runs code-writing agents. Use a dedicated service user; do not mount the host home directory; expose only scoped repository credentials to individual attempts; and keep staging separate from any production host. - Back up Rivet engine state and Caddy configuration. Treat workspaces as reproducible/ephemeral unless an active job requires retention; prune completed worktrees deliberately. - A single Flue Node instance is the correct initial staging shape. Its durable Convex adapter survives restarts, but each conversation still requires one live owner—do not add replicas until ownership routing is designed. [Flue database guide](https://flueframework.com/docs/guide/database) ## Sources -- Repository architecture: `docs/TECH.md` §§1, 10–11; `docs/LOCAL_SETUP.md`; `apps/web/Dockerfile`; `packages/agents/Dockerfile`; `packages/agents/src/runtime/repository-workspace.ts`; `packages/agents/src/runtime/attempt-runner.ts`. +- Repository architecture: `docs/LOCAL_SETUP.md`; `docs/auth-proxy.md`; `vercel.json`; `apps/web/Dockerfile`; `deploy/vds/`; `scripts/release-agents.sh`. - [Convex environments and deployments](https://docs.convex.dev/production/multiple-deployments), [hosting on Vercel](https://docs.convex.dev/production/hosting/vercel), and [HTTP actions](https://docs.convex.dev/functions/http-actions). - [Vercel React Router](https://vercel.com/docs/frameworks/frontend/react-router) and [Vercel environments](https://vercel.com/docs/deployments/environments). -- [Rivet self-hosted Docker Compose](https://rivet.dev/docs/self-hosting/docker-compose), [production checklist](https://rivet.dev/docs/self-hosting/production-checklist), and [version upgrades](https://rivet.dev/docs/actors/versions). -- [Flue Node/Docker deployment](https://flueframework.com/docs/ecosystem/deploy/docker) and [durable database ownership](https://flueframework.com/docs/guide/database). +- [Rivet self-hosted Docker Compose](https://rivet.dev/docs/self-hosting/docker-compose), [production checklist](https://rivet.dev/docs/self-hosting/production-checklist), and [runtime modes](https://rivet.dev/docs/general/runtime-modes). +- [Flue Node deployment](https://flueframework.com/docs/ecosystem/deploy/node) and [durable database ownership](https://flueframework.com/docs/guide/database). - [Pulumi state](https://www.pulumi.com/docs/iac/concepts/state-and-backends/), [Pulumi secrets](https://www.pulumi.com/docs/iac/concepts/secrets/), and [Ansible](https://docs.ansible.com/projects/ansible/latest/getting_started/). diff --git a/docs/LOCAL_SETUP.md b/docs/LOCAL_SETUP.md index cf7cd6d..49ae531 100644 --- a/docs/LOCAL_SETUP.md +++ b/docs/LOCAL_SETUP.md @@ -7,10 +7,9 @@ This guide runs the active Zopu stack locally, including the browser chat and th ```text Browser (React Router/Vite, :5173) -> Convex Cloud (durable product state, auth, workflows) - -> Flue agent server (:3585) - -> Rivet Engine guard endpoint (:6420) - -> AgentOS registry runner - -> isolated Pi workspace mounted from the local repository + -> Flue agent server + in-process AgentOS registry (:3585) + -> Rivet Engine control plane (:6420) + -> AgentOS workspace actor (Git + repo clone mounted from the local checkout) -> Gitea branch and pull request ``` @@ -83,16 +82,15 @@ AGENT_MODEL_MAX_TOKENS= ### Rivet and AgentOS ```env +# The private Engine control plane this process connects to. RIVET_ENDPOINT=http://127.0.0.1:6420 -RIVET_PUBLIC_ENDPOINT=http://127.0.0.1:6420 -RIVET_WORKSPACE_TOKEN= -ZOPU_SOURCE_REPOSITORY=/absolute/path/to/zopu-code +# The path where the Engine calls the registry co-hosted in Flue. +RIVET_SERVERLESS_ENDPOINT=http://127.0.0.1:3585/internal/rivet +RIVET_WORKSPACE_TOKEN= AGENT_WORKSPACE_ROOT=/absolute/path/to/zopu-agent-workspaces ``` -Use the same repository checkout for `ZOPU_SOURCE_REPOSITORY`. The harness creates Git worktrees beneath `AGENT_WORKSPACE_ROOT`, copies the source checkout's `.env`, installs dependencies, and mounts the isolated checkout into AgentOS. - -Port `6420` is the Rivet Engine guard endpoint used by the application. Port `6421` is an internal engine API-peer port and must not be used as `RIVET_ENDPOINT`. +The registry runs in the Flue process; there is no standalone AgentOS runner. `RIVET_ENDPOINT` and `RIVET_SERVERLESS_ENDPOINT` have opposite directions and are not interchangeable. Port `6421` is an internal Engine API-peer port and must not be used as `RIVET_ENDPOINT`. ### Gitea @@ -138,7 +136,7 @@ If work execution uses a separate agent URL, set `AGENT_BACKEND_URL`; otherwise ## Start the stack -Run each process in its own terminal. The order matters for the AgentOS path. +Run each process in its own terminal. The Engine must be healthy before Flue starts because Flue serves the in-process registry that uses it. ### 1. Start Convex development @@ -152,65 +150,26 @@ pnpm dev:server Both commands run from `packages/backend` and explicitly load the repository-root `.env` with `--env-file=../../.env`. `packages/backend/.env.local` remains Convex CLI metadata for the selected deployment; keep the shared runtime settings in the root `.env`. -### 2. Start the whole stack +### 2. Start the Rivet Engine -The root `dev` script starts Rivet Engine, the AgentOS registry runner, Convex, Flue agents, and the web app in one terminal: +Start exactly one Engine listening on `127.0.0.1:6420` using the local Engine deployment mechanism. Do not use port `6421` as the application endpoint. + +### 3. Start Flue and the in-process registry ```bash -pnpm dev -``` +# Laptop-only access +pnpm --filter @code/agents dev -- --port 3585 -For phone or Tailscale-device access, start the stack with the web server bound to all interfaces: - -```bash -pnpm dev:tailscale -``` - -### 3. Start Rivet Engine - -If you prefer separate terminals, start the engine from the agents package: - -```bash -cd packages/agents -bun run dev:engine -``` - -There must be exactly one local engine listening on `127.0.0.1:6420`. Do not start a second engine, and do not use `npx rivetkit dev`; that command is unavailable in the installed version. - -### 4. Start the AgentOS registry runner - -```bash -cd packages/agents -bun run runner -``` - -The runner registers the AgentOS workspace actor with Rivet Engine. Keep it running whenever a coding attempt or issue-to-PR request may execute. - -### 5. Start Flue agents - -For laptop-only access: - -```bash -pnpm dev:agents -``` - -For Convex callbacks or access from another device, bind Flue to all interfaces: - -```bash -pnpm dev:tailscale:agents -``` - -The dev scripts already use port `3585`; the Flue CLI defaults to `3583`, but the current Zopu configuration and Convex environment use `3585`. - -If the shell already exports remote Rivet values, shell values override `.env`. Start Flue with explicit local values: - -```bash +# Convex callbacks or access from another device +HOST=0.0.0.0 \ RIVET_ENDPOINT=http://127.0.0.1:6420 \ -RIVET_PUBLIC_ENDPOINT=http://127.0.0.1:6420 \ -bun run dev:tailscale:agents -- --port 3585 +RIVET_SERVERLESS_ENDPOINT=http://127.0.0.1:3585/internal/rivet \ +pnpm --filter @code/agents dev -- --port 3585 ``` -### 6. Start the web application +The Flue development server serves both agent routes and the AgentOS registry at `/internal/rivet/*`; never start a separate registry runner. If shell exports override `.env`, set both endpoints explicitly as shown. + +### 4. Start the web application If you are not using the root `dev` script, start the web app separately. @@ -233,12 +192,12 @@ Open `http://localhost:5173`, or `http://:5173` when using the Tai Check the listeners: ```bash -curl -I http://127.0.0.1:6420 -curl -I http://127.0.0.1:3585 +curl -fsS http://127.0.0.1:6420/health +curl -fsS http://127.0.0.1:3585/health curl -I http://127.0.0.1:5173 ``` -Any HTTP response confirms the process is reachable; these roots may redirect or return `404` because their functional routes live elsewhere. +The first two commands must return a successful health response; the web root may redirect or return `404` if its functional routes live elsewhere. Then verify behavior in order: @@ -285,21 +244,21 @@ Set Convex `SITE_URL` to the exact browser origin. The shared development deploy ### AgentOS fails while mounting the repository -- Confirm both Rivet endpoints use port `6420`. -- Confirm the engine and `bun run runner` are both running. -- Confirm `ZOPU_SOURCE_REPOSITORY` contains `.git`. +- Confirm the Engine is healthy at `http://127.0.0.1:6420/health`. +- Confirm Flue is running with `RIVET_ENDPOINT=http://127.0.0.1:6420`. +- Confirm `RIVET_SERVERLESS_ENDPOINT` points back to the active Flue listener with `/internal/rivet` appended. - Confirm `AGENT_WORKSPACE_ROOT` is writable. -- Restart the runner after changing AgentOS registry configuration; Flue hot reload is not enough. +- Restart Flue after changing registry configuration; its development server owns the in-process registry. -The harness clients require CBOR encoding for host-directory mount descriptors. Do not remove the `encoding: "cbor"` configuration in `packages/agents/src/runtime/agent-os.ts`. +The harness clients require CBOR encoding for actor RPC. Do not remove the `encoding: "cbor"` configuration in `packages/agents/src/adapters/agentos.ts`. ### AgentOS reports an ACP completed-message resource limit -The workspace registry raises `limits.acp.maxCompletedMessageBytes` for long Pi coding runs. Restart the runner so the updated registry configuration is registered with Rivet Engine. +Restart Flue so the in-process registry picks up its updated actor configuration. ### Flue connects to a remote Rivet deployment unexpectedly -Environment variables exported by the shell override values loaded from `.env`. Start Flue and the runner with explicit `RIVET_ENDPOINT` and `RIVET_PUBLIC_ENDPOINT` values pointing to `127.0.0.1:6420`. +Environment variables exported by the shell override values loaded from `.env`. Start Flue with explicit `RIVET_ENDPOINT=http://127.0.0.1:6420` and `RIVET_SERVERLESS_ENDPOINT=http://127.0.0.1:3585/internal/rivet`. ### Gitea issue or PR commands fail @@ -327,7 +286,6 @@ For agent-only changes, run `bun run check-types` from `packages/agents` before See also: -- [`TECH.md`](TECH.md) for architecture and ownership boundaries -- [`deployment.md`](deployment.md) for the shared staging deployment +- [`DEPLOYMENT_PLAN.md`](DEPLOYMENT_PLAN.md) for the staging topology and VDS release path - [Rivet AgentOS quickstart](https://rivet.dev/docs/agent-os/quickstart) -- [Flue local development](https://flue.dev/docs/cli/dev) +- [Flue Node deployment](https://flueframework.com/docs/ecosystem/deploy/node) diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 5f90edc..0000000 --- a/docs/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Zopu Work OS — Documentation Map - -Dense context set for product development and coding agents. - -## Read order - -```text -1. agent-context.md — bootstrap and non-negotiables -2. product.md — product model and quality doctrine -3. glossary.md — canonical terminology -4. dev-loop.md — normative software delivery process -5. tech.md — architecture, actors, ports, runtimes -6. design.md — user experience -7. slices.md — sequential vertical product increments -8. dev-plan.md — repository execution plan/backlog -9. evaluation.md — quality measurement and improvement -``` - -For a runnable development environment, see [`LOCAL_SETUP.md`](LOCAL_SETUP.md). - -## Use by role - -| Role | Minimum context | -| --- | --- | -| Product/definition agent | agent-context, product, glossary, dev-loop | -| Architecture/design agent | agent-context, tech, dev-loop, current Work Definition | -| Coding agent | agent-context, current Design Packet/Slice, tech sections, repository rules | -| Verifier | agent-context, dev-loop, evaluation, Verification Plan | -| Frontend agent | agent-context, design, product, current slice | -| Lead/orchestrator | all documents, current repository state, active decisions | - -## Document boundaries - -```text -product.md what/why -tech.md system architecture -design.md interaction behavior -dev-loop.md how software Work is delivered -slices.md how Zopu product is incrementally built -dev-plan.md engineering order and release gates -evaluation.md how quality and improvements are measured -glossary.md exact term definitions -agent-context compact instructions for execution agents -``` - -## First build target - -```text -message -→ Signal -→ approved Work Definition -→ approved Design Packet -→ one isolated implementation slice -→ independent verification -→ exact verified PR -→ human question/resume -``` - -Start at `dev-plan.md` backlog item 01. Do not begin dynamic Kit Builder or fleets before Slices 1–7 work reliably. diff --git a/docs/TECH.md b/docs/TECH.md deleted file mode 100644 index afb546f..0000000 --- a/docs/TECH.md +++ /dev/null @@ -1,676 +0,0 @@ -# Zopu Work OS — Technical Architecture - -> **Related:** `agent-context.md` defines agent rules; `dev-loop.md` defines orchestration; `glossary.md` defines terms. - -> **Status:** Working technical source of truth -> **Audience:** engineers and implementation agents -> **Read after:** `product.md` -> **Principle:** durable intent/state is separate from disposable execution. - -## 1. System topology - -```text -Web / desktop / mobile - │ Convex queries, mutations, storage - ▼ -Convex application backend -├── authentication and tenancy -├── normalized product data -├── conversation turn queue -└── reactive client projections - │ durable Workflow steps + service-authenticated dispatch - ▼ -Private agent backend -├── FLUE product agents and typed tools -├── AgentOS execution environments -├── Codex implementation harness -└── canonical events/results returned to Convex - │ optional attached full sandbox - ▼ -Cube/E2B-compatible runtime (later) -``` - -Clients MUST communicate only with Convex. FLUE and future Rivet/AgentOS services are private workers: Convex admits durable commands, invokes the worker, and stores the product-facing result before clients observe it. - -### Ownership - -| Layer | Owns | -| --- | --- | -| Convex | authentication, normalized product records, command admission, reactive reads | -| Convex Workflow | durable sequencing, retries, cancellation, scheduling, and completion callbacks | -| Agent backend | private programmable agents and execution adapters | -| Rivet Engine + runners | placement, routing, sleep/wake, and execution ownership for AgentOS workspaces | -| Harness | bounded coding/tool loop | -| Sandbox/runtime | filesystem, processes, network, isolation | -| Git | source revision history | -| Artifact store | durable outputs/evidence | -| External systems | collaboration, delivery, monitoring | - -No client, harness, sandbox, or FLUE process owns product state. - -### Slice 1 relational core - -```text -organizations ──< organizationMembers -organizations ──< projects ──< projectContextDocuments -organizations ──1 conversations ──< conversationTurns -conversationTurns ──< conversationMessages ──< conversationAttachments -projects ──< signals ──< signalConstraints -signals ──< signalSources >── conversationMessages -projects ──< works -signals ──< signalWorkAttachments >── works -works ──< workEvents -``` - -Convex mutations provide atomic transactions and optimistic serializability. Foreign-key integrity and uniqueness are enforced in the owning mutations; composite indexes back every identity and relation lookup. Flue's adapter tables remain isolated infrastructure persistence and are not product-domain relations. - -## 2. Domain boundaries - -Recommended packages: - -```text -packages/ -├── signals/ -├── work/ -├── design/ -├── planning/ -├── kits/ -├── resolver/ -├── verification/ -├── artifacts/ -├── results/ -├── knowledge/ -├── runtimes/ -├── harnesses/ -└── integrations/ -``` - -Each domain SHOULD separate: - -```text -domain/ pure state, schemas, invariants -application/ use cases and orchestration -ports/ Effect services -adapters/ infrastructure implementations -``` - -Avoid package proliferation in v0; logical boundaries may begin as folders. - -## 3. Core records - -Minimal durable model: - -```ts -type Id = string; - -interface Message { - id: Id; - projectId: Id; - content: string; - createdAt: number; -} - -interface Signal { - id: Id; - projectId: Id; - sourceType: string; - sourceId: string; - sourcePayloadRef?: string; - summary: string; - fingerprint: string; - status: "candidate" | "accepted" | "dismissed"; -} - -interface Work { - id: Id; - projectId: Id; - title: string; - objective: string; - risk: "low" | "medium" | "high"; - status: WorkStatus; - definitionVersion?: number; - designVersion?: number; - createdAt: number; - updatedAt: number; -} - -interface Step { - id: Id; - workId: Id; - sliceId?: Id; - kind: "design" | "implement" | "verify" | "integrate" | "publish" | "observe"; - objective: string; - dependsOn: readonly Id[]; - status: StepStatus; -} - -interface Run { - id: Id; - workId: Id; - stepId: Id; - kitVersion: string; - status: RunStatus; -} - -interface Attempt { - id: Id; - runId: Id; - number: number; - harness: string; - runtime: string; - sourceRevision: string; - status: AttemptStatus; - startedAt?: number; - endedAt?: number; -} - -interface Artifact { - id: Id; - workId: Id; - stepId?: Id; - runId?: Id; - attemptId?: Id; - type: string; - uri?: string; - contentHash?: string; - sourceRevision?: string; - environmentId?: string; - metadata: unknown; -} - -interface Question { - id: Id; - workId: Id; - stepId?: Id; - attemptId?: Id; - prompt: string; - recommendation?: string; - alternatives: readonly string[]; - status: "open" | "answered" | "withdrawn"; - answer?: string; -} -``` - -All external/model payloads MUST be decoded with schemas at boundaries. - -## 4. Work state machine - -```text -Proposed -→ Defining -→ Designing -→ Ready -→ ExecutingSlice -→ VerifyingSlice -→ AwaitingSliceReview -→ IntegratedVerification -→ Review -→ Releasing -→ Observing -→ Completed -``` - -Side/terminal states: - -```text -NeedsInput | Blocked | Replanning | Failed | Cancelled -``` - -Transitions require explicit commands plus evidence. State MUST NOT be inferred from the latest text message. - -## 5. Actor model - -Start small. - -### ProjectActor - -Owns: - -- project configuration; -- repository/runtime policies; -- active Work index; -- integration endpoints; -- project-level Signal routing. - -### WorkActor - -Initial central aggregate: - -- Work Definition and versions; -- Design Packet and versions; -- slice/step graph; -- Resolver state; -- questions; -- artifact references; -- result. - -It serializes lifecycle transitions and commands. - -### AttemptActor - -Owns one execution attempt: - -- runtime lease/sandbox ID; -- harness session; -- scoped credentials; -- event stream/checkpoints; -- cancellation; -- attempt timeout; -- normalized outcome. - -### VerificationActor - -Split from WorkActor after v0 verification is stable. Owns plan, checks, evidence, verdict. - -### IntegrationActor - -Added when multiple slices/branches exist. Owns branch composition, conflicts, integrated revision, integrated checks. - -### ResultActor - -Added after delivery observation exists. Owns rollout observation, original success signals, final outcome, learning proposals. - -Do not create an actor per document or tool call. Create actors for durable identity, serialized ownership, independent failure/recovery, or timers. - -## 6. Commands, events, and idempotency - -Use command/event vocabulary rather than mutable agent prose. - -Example commands: - -```text -ProcessMessage -AcceptSignal -CreateWork -ApproveDefinition -ApproveDesign -StartNextSlice -RecordHarnessEvent -CompleteAttempt -StartVerification -RecordVerificationCheck -CreateRepairAttempt -PublishPullRequest -RecordHumanDecision -CompleteWork -``` - -Example events: - -```text -SignalCreated -SignalAttached -WorkProposed -DefinitionGenerated -DefinitionApproved -DesignGenerated -DesignApproved -SliceStarted -AttemptStarted -AttemptCompleted -VerificationPassed -VerificationFailed -QuestionOpened -QuestionAnswered -PullRequestCreated -WorkCompleted -``` - -Every side-effecting command MUST include an idempotency key. Suggested key: - -```text -:: -``` - -External artifact creation stores provider ID before transition completion to prevent duplicate PRs/deployments. - -## 7. Effect service boundaries - -Keep domain/application code provider-neutral. - -```ts -interface HarnessRuntime { - open(input: OpenHarnessInput): Effect.Effect; - prompt(id: string, content: string): Effect.Effect; - events(id: string): Stream.Stream; - approve(input: PermissionDecision): Effect.Effect; - abort(id: string): Effect.Effect; - close(id: string): Effect.Effect; -} - -interface SandboxRuntime { - create(spec: SandboxSpec): Effect.Effect; - exec( - lease: SandboxLease, - cmd: Command - ): Effect.Effect; - readFile( - lease: SandboxLease, - path: string - ): Effect.Effect; - writeFile( - lease: SandboxLease, - path: string, - body: Uint8Array - ): Effect.Effect; - pause(lease: SandboxLease): Effect.Effect; - resume(id: string): Effect.Effect; - terminate(lease: SandboxLease): Effect.Effect; -} - -interface SourceControl { - prepareWorktree(input: WorktreeInput): Effect.Effect; - diff(worktree: Worktree): Effect.Effect; - commit(input: CommitInput): Effect.Effect; - push(input: PushInput): Effect.Effect; - createPullRequest( - input: PullRequestInput - ): Effect.Effect; -} - -interface VerificationRuntime { - execute( - plan: VerificationPlan, - env: EnvironmentRef - ): Effect.Effect; -} -``` - -Also define: - -```text -ArtifactStore | SecretBroker | EventJournal | PreviewRuntime | RuntimePolicy -``` - -Use `Layer` for adapters, `Scope` for leases/processes, `Stream` for events, `Schedule` for bounded retries, and supervised fibers for long-running consumers. Pin Effect version and isolate beta API churn. - -## 8. FLUE responsibilities - -Use FLUE for domain-specific agents/workflows: - -- conversation response and Signal proposal; -- Work Definition compiler; -- impact analysis; -- architecture/program design; -- vertical-slice planning; -- Resolver decision support; -- verification-plan generation; -- maintainability review; -- result/learning synthesis. - -FLUE output MUST be typed proposals/commands, validated by application policy. - -FLUE MUST NOT directly: - -- mutate arbitrary database tables; -- bypass actor lifecycle; -- grant itself tools; -- merge/deploy outside policy; -- mark Work complete without evidence. - -## 9. Harness strategy - -Harness is replaceable: - -```text -HarnessRuntime -├── OmpHarnessLive -├── OpenCodeHarnessLive -├── CodexHarnessLive -├── PiHarnessLive -└── FlueHarnessLive -``` - -v0 selects one harness. Prefer mature coding harnesses for repository exploration/edit/test loops; use custom FLUE agents for product-specific reasoning. - -Zopu owns Work, branches, worktrees, budgets, artifacts, and completion. Harness owns one bounded implementation loop. - -## 10. Runtime strategy - -### Convex orchestration - -Slice 5 uses the Convex Workflow component as the durable product orchestration layer. Workflow steps call private agent-backend actions, while all user-visible state, events, artifacts, idempotency keys, and cancellation remain canonical in Convex. - -### CubeSandbox - -Best for full Linux execution: - -- native binaries; -- Bun/Node/Python; -- browsers; -- databases/services; -- project builds/tests; -- pause/resume; -- strong isolation. - -Use E2B-compatible SDK behind `SandboxRuntime`. OMP runs as a process inside the Cube microVM. - -### AgentOS - -Best for: - -- lightweight durable agent environments; -- ACP-integrated software; -- actor-adjacent orchestration; -- context/files/networking that fit runtime limits. - -Slice 5 starts here with one Codex-backed AgentOS actor and one authenticated repository checkout per project. Convex Workflow owns product orchestration; Rivet Engine coordinates placement while a normal runner executes the actor. Use an attached full sandbox through the E2B-compatible boundary when native/heavy tooling is needed. - -### Persistent project machine - -Later optimization for long-lived caches, large repositories, and developer-customized environments. Use Git worktrees per active Work. Do not make it the only isolation boundary. - -### Runtime selection - -The Resolver requests capabilities: - -```text -writable repo, Bun, browser, PostgreSQL, 8 GB RAM, network policy -``` - -`RuntimePolicy` chooses provider. Product logic never branches on Cube/AgentOS directly. - -## 11. Repository isolation - -Initial safe model: - -```text -one project repository mirror -one Git worktree per active Work/slice -one mutating attempt per worktree -``` - -Rules: - -- attempts receive scoped worktrees; -- parallel mutating attempts use separate branches; -- credentials are short-lived and repository-scoped; -- host home directories are never mounted; -- model credentials are run-scoped; -- untrusted code runs in sandbox; -- output commits record base and candidate SHA. - -## 12. Planning and design artifacts - -Required for standard work: - -```text -WorkDefinition -ImpactMap -DesignPacket -VerticalSlicePlan -VerificationPlan -``` - -Program design SHOULD include: - -- expected file-tree delta; -- expected call-flow delta; -- key types/signatures; -- dependency direction; -- invariants; -- security/data boundaries; -- known deviations. - -The verifier compares candidate code against this design, but metrics are evidence, not absolute truth. - -## 13. Verification architecture - -Verification layers: - -```text -Static -├── format/lint/typecheck -├── dependency policy -├── secret scan -└── static security - -Behavior -├── unit -├── integration -├── contract -└── property tests where useful - -Product -├── browser/user flow -├── screenshots/video -├── accessibility -└── visual checks - -Operational -├── build/start/health -├── migration/rollback -├── logs -└── resource limits - -Design -├── expected vs actual files/interfaces -├── dependency graph delta -├── design deviations -└── maintainability review -``` - -A `VerificationResult` MUST bind checks to candidate commit and environment. - -Repair loop: - -```text -failure evidence → bounded repair attempt → clean verification rerun -``` - -Tests added by the implementation SHOULD fail on the base revision and pass on the candidate when practical. - -## 14. Delivery and integration - -Publishing order: - -```text -slice checks pass -→ integrated candidate created -→ impacted checks on integrated SHA -→ commit/push -→ PR -→ review package -``` - -Never create a “verified PR” from a different SHA than the verified candidate. - -Review package: - -- original intent; -- current definition/design; -- slice narrative; -- meaningful diffs; -- screenshots/video; -- verification evidence; -- deviations/risks; -- exact commit/PR. - -Manual merge remains policy in v0. - -## 15. Preview and release - -Preview is an artifact, not an open random port. `PreviewRuntime` may use: - -- sandbox-exposed app; -- agentOS Apps for compatible generated HTTP apps; -- external staging/deployment. - -Production release requires explicit policy, rollout plan, health signals, and rollback trigger. - -## 16. Security baseline - -- private control-plane endpoints; -- authenticated Cube/Rivet APIs; -- scoped runtime tokens; -- no long-lived model/Git secrets in workspace files; -- network egress policy; -- artifact access authorization; -- immutable audit trail for all Work events; -- tool allowlist per Kit; -- destructive tools denied by default; -- merge/deploy human-gated initially; -- cleanup of terminated sandboxes and credentials. - -## 17. Observability - -Record product-level events, not only infrastructure logs. - -Required dimensions: - -```text -projectId workId sliceId runId attemptId actorId -kitVersion harness runtime model baseSha candidateSha -``` - -Track: - -- state-transition latency; -- attempt duration/outcome; -- retries/replans; -- verification checks; -- human wait time; -- token/compute cost; -- duplicate side effects; -- abandoned/stale Work; -- post-release failures. - -Raw harness logs are retained as artifacts; UI consumes normalized events. - -## 18. Initial deployment shape - -```text -Web + API + Convex - │ - ▼ -Bun/Effect daemon - │ - ▼ -Rivet cluster/actors - │ - ├── FLUE agents/workflows - └── SandboxRuntime - └── CubeSandbox on dedicated/VDS host - └── OMP + repo + tests -``` - -Keep Cube control APIs private; expose only authorized preview paths. Rivet and execution daemon may share the VPS initially but remain separate deployable processes. - -## 19. Technical acceptance for v0 - -The architecture is proven when one real repository supports: - -```text -message → Signal → proposed Work → ready Work -→ one slice → isolated harness run → independent verification -→ verified commit → real PR → human response/resume -``` - -With: - -- durable recovery; -- no duplicate Work/PR; -- bounded retries; -- exact evidence; -- cancellation; -- explicit terminal states. diff --git a/docs/agent-context.md b/docs/agent-context.md deleted file mode 100644 index d77904e..0000000 --- a/docs/agent-context.md +++ /dev/null @@ -1,334 +0,0 @@ -# Zopu Work OS — Agent Context - -> **Purpose:** compact bootstrap context for Codex/OMP/OpenCode/FLUE workers contributing to Zopu. -> **Usage:** read this first, then load only task-relevant documents and repository files. - -## 1. Mission - -Build Zopu: a Work OS that turns conversation and external Signals into durable, verified outcomes. - -```text -Signal → Work → Definition → Design → Vertical Slices -→ Resolver → Attempts → Verification → Delivery → Result → Learning -``` - -The product is not chat threads, an issue tracker, a harness UI, or an autonomous PR factory. - -## 2. Source-of-truth order - -```text -1. current accepted Work/Question/Decision -2. approved Work Definition -3. approved Design Packet + current Slice -4. repository tests/types/code -5. product.md -6. tech.md -7. design.md -8. dev-loop.md -9. slices.md -10. dev-plan.md -11. glossary.md -12. evaluation.md -``` - -When sources conflict, report the conflict. Do not silently choose a convenient interpretation. - -## 3. Current product target - -Initial user: - -```text -technical founder / small engineering team -one project + one Git repository -web chat + Work cards -manual merge -``` - -Initial complete loop: - -```text -message -→ Signal -→ approved Work -→ approved Design Packet -→ one bounded coding slice -→ independent verification -→ exact verified commit -→ real PR -→ human intervention/resume -``` - -## 4. Non-negotiable invariants - -1. Work is a durable outcome, not a chat/session/issue/PR. -2. Exact Signal provenance is preserved. -3. State transitions are explicit commands/events. -4. FLUE/model output is validated proposal data, not authority. -5. Rivet actors own serialized lifecycle/recovery. -6. Harnesses and runtimes are replaceable adapters. -7. One mutating Attempt owns one isolated worktree. -8. Every Attempt is bounded and terminally classified. -9. Builder output remains candidate output until independent verification. -10. Evidence binds to exact revision and environment. -11. Published PR head equals verified integrated SHA. -12. Human questions/approvals are durable objects. -13. Retry/restart must not duplicate Work, commits, PRs, or deployments. -14. Merge/deploy remain human-gated initially. -15. Completion requires outcome evidence, not an agent’s “done.” - -## 5. System ownership - -```text -Work OS durable intent/state/evidence/policy -Rivet actors identity, serialization, timers, recovery -FLUE domain agents/workflows and typed proposals -Harness bounded coding/tool loop -Sandbox filesystem/process/network isolation -Git source history -ArtifactStore durable output/evidence -UI/Buzz interaction surfaces, not workflow truth -``` - -## 6. Initial actor shape - -```text -ProjectActor -├── project config + active Work index - -WorkActor -├── definition/design/slices -├── resolver state -├── questions/approvals -├── artifacts/result - -AttemptActor -├── runtime lease -├── harness session -├── normalized events -├── timeout/cancellation/outcome -``` - -Add Verification/Integration/Result actors only when their lifecycles justify separation. - -## 7. Initial adapters - -Preferred first implementation: - -```text -FLUE definition/design/resolver support -Rivet actors -CubeSandbox full Linux runtime -OMP first coding harness, replaceable -Git forge branch/commit/PR -Convex durable application data/projections where used -Effect application ports/layers/errors/scopes/streams -``` - -Do not import provider-specific types into domain modules. - -## 8. Working protocol for every code task - -### Before editing - -1. Identify current vertical slice and acceptance criteria. -2. Read relevant docs and repository rules. -3. Inspect current architecture, tests, and existing abstractions. -4. State impacted modules and risks. -5. Produce/confirm a small implementation plan. -6. Ask a Question only when ambiguity changes behavior, security, data, or architecture. - -### During implementation - -1. Stay within the current slice. -2. Preserve dependency direction. -3. Prefer existing patterns over parallel frameworks. -4. Add typed boundaries and tagged errors. -5. Make external effects idempotent. -6. Add cancellation/timeouts for long-running operations. -7. Record exact revisions/provider identifiers. -8. Add tests with the implementation. -9. Do not weaken unrelated tests or hide failures. -10. Explain intentional Design Packet deviations. - -### Before declaring candidate ready - -Run task-relevant checks: - -```text -format/lint/typecheck -focused unit/integration tests -behavioral/live check -security/secret check where relevant -design-conformance review -``` - -Report: - -```text -files changed -behavior implemented -checks run + results -known risks/deviations -artifacts/revision -remaining blockers -``` - -Never claim verified unless the independent verification path ran. - -## 9. Code organization rule - -Use logical separation: - -```text -domain/ pure types/state/invariants -application/ use cases/commands -ports/ Effect services -adapters/ FLUE/Rivet/Cube/OMP/Git implementations -``` - -Keep the initial package count practical. A folder boundary is enough until independent reuse/lifecycle exists. - -## 10. State modeling rule - -Prefer explicit state machines over booleans. - -Bad: - -```ts -isRunning: boolean; -isDone: boolean; -hasError: boolean; -``` - -Good: - -```ts -type AttemptStatus = - | "queued" - | "running" - | "succeeded" - | "retryable_failure" - | "needs_input" - | "blocked" - | "verification_failed" - | "budget_exhausted" - | "cancelled" - | "permanent_failure"; -``` - -Transitions must validate current version/state. - -## 11. Model/agent output rule - -Agents return schemas such as: - -```text -SignalProposal -WorkDefinitionProposal -DesignPacketProposal -ResolverDecisionProposal -VerificationAssessment -LearningProposal -``` - -Application code decodes, authorizes, and executes commands. Agents do not directly mutate arbitrary state. - -## 12. Quality rule - -For every behavior, identify: - -```text -acceptance criterion -implementation evidence -independent check -exact candidate revision -review requirement -``` - -Tests prove immediate behavior. Design review protects maintainability and future change cost. Both matter. - -## 13. UI rule - -Expose: - -```text -outcome -phase -latest meaningful update -next action/blocker -slice progress -evidence -delivery/result -``` - -Hide low-level harness noise by default. Preserve raw logs in diagnostics. - -## 14. Scope control - -Do not implement unless required by the current slice: - -- dynamic Kit Builder; -- multiple harness providers; -- large fleets; -- autonomous merge/deploy; -- universal workflows; -- automatic canonical-memory mutation; -- sophisticated multi-tenancy. - -Design replaceable boundaries, then ship one path. - -## 15. Task completion template - -```md -## Implemented - -- ... - -## Behavior - -- ... - -## Verification run - -- `command` — pass/fail -- ... - -## Evidence - -- candidate SHA/artifacts -- ... - -## Design deviations - -- none / ... - -## Remaining risks or blockers - -- none / ... -``` - -## 16. Required reading by task type - -| Task | Read | -| ------------------ | ---------------------------------------- | -| product/domain | product.md, glossary.md | -| UI | design.md, product.md | -| actors/state | tech.md, glossary.md | -| orchestration | dev-loop.md, tech.md | -| current sequencing | slices.md, dev-plan.md | -| verification/evals | evaluation.md, dev-loop.md | -| provider adapter | tech.md plus provider docs | -| broad feature | agent-context.md + all relevant sections | - -## 17. Stop and escalate when - -- accepted definition/design is missing or contradictory; -- required permission is unavailable; -- worktree/revision identity is uncertain; -- a destructive action is outside policy; -- verification cannot bind to exact candidate; -- implementation requires expanding scope materially; -- a retry would repeat a non-transient failure; -- repository state suggests another active mutating owner. - -Return a precise Question or blocker, not a guess. diff --git a/docs/agents/domain.md b/docs/agents/domain.md new file mode 100644 index 0000000..b7e7e5d --- /dev/null +++ b/docs/agents/domain.md @@ -0,0 +1,35 @@ +# Domain Docs + +How the engineering skills should consume this repo's domain documentation when exploring the codebase. + +## Before exploring, read these + +- **`CONTEXT.md`** at the repo root +- **`docs/adr/`** — read ADRs that touch the area you're about to work in + +If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill creates them lazily when terms or decisions actually get resolved. + +## File structure + +Single-context repo: + +``` +/ +├── CONTEXT.md +├── docs/adr/ +│ ├── 0001-event-sourced-orders.md +│ └── 0002-postgres-for-write-model.md +└── src/ +``` + +## Use the glossary's vocabulary + +When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids. + +If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`). + +## Flag ADR conflicts + +If your output contradicts an existing ADR, surface it explicitly rather than silently overriding: + +> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_ diff --git a/docs/agents/issue-tracker.md b/docs/agents/issue-tracker.md new file mode 100644 index 0000000..c6585d9 --- /dev/null +++ b/docs/agents/issue-tracker.md @@ -0,0 +1,43 @@ +# Issue tracker: Gitea + local markdown + +This repo uses a hybrid workflow: issues are drafted and triaged locally as markdown files under `.scratch/`, then published as polished issues to Gitea (`git.openputer.com:2222/puter/zopu-code`) when they are ready for the public tracker. + +## Local markdown conventions + +- One feature per directory: `.scratch//` +- The spec/PRD is `.scratch//spec.md` +- Implementation issues are one file per ticket at `.scratch//issues/-.md`, numbered from `01` — never a single combined tickets file +- Triage state is recorded as a `Status:` line near the top of each issue file (see `triage-labels.md` for the role strings) +- Comments and conversation history append to the bottom of the file under a `## Comments` heading + +## Gitea conventions + +Use the Gitea web UI or API at `https://git.openputer.com/puter/zopu-code/issues`. + +- Create a polished issue from a local draft: copy the title and body from the final local file, then create the issue in Gitea. +- Read an issue: open the issue in the Gitea UI or fetch it via the API. +- List issues: use the Gitea UI or API with label/state filters. +- Comment on an issue: add a comment through the Gitea UI or API. +- Apply / remove labels: edit labels through the Gitea UI or API. +- Close an issue: close through the Gitea UI or API. + +## When a skill says "publish to the issue tracker" + +1. If the output is a draft, spec, or work-in-progress, write it under `.scratch//`. +2. If the output is a final, polished issue, create it in Gitea and, if helpful, archive the local draft with a link to the Gitea issue number. + +## When a skill says "fetch the relevant ticket" + +- For local drafts: read the file at the referenced path. +- For Gitea issues: open or fetch the issue by its Gitea number. + +## Wayfinding operations + +Used by `/wayfinder`. The **map** is a file with one **child** file per ticket. + +- **Map**: `.scratch//map.md` — the Notes / Decisions-so-far / Fog body. +- **Child ticket**: `.scratch//issues/NN-.md`, numbered from `01`, with the question in the body. A `Type:` line records the ticket type (`research`/`prototype`/`grilling`/`task`); a `Status:` line records `claimed`/`resolved`. +- **Blocking**: a `Blocked by: NN, NN` line near the top. A ticket is unblocked when every file it lists is `resolved`. +- **Frontier**: scan `.scratch//issues/` for files that are open, unblocked, and unclaimed; first by number wins. +- **Claim**: set `Status: claimed` and save before any work. +- **Resolve**: append the answer under an `## Answer` heading, set `Status: resolved`, then append a context pointer (gist + link) to the map's Decisions-so-far in `map.md`. diff --git a/docs/agents/triage-labels.md b/docs/agents/triage-labels.md new file mode 100644 index 0000000..6c96ee1 --- /dev/null +++ b/docs/agents/triage-labels.md @@ -0,0 +1,15 @@ +# Triage Labels + +The skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker. + +| Label in mattpocock/skills | Label in our tracker | Meaning | +| --- | --- | --- | +| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue | +| `needs-info` | `needs-info` | Waiting on reporter for more information | +| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent | +| `ready-for-human` | `ready-for-human` | Requires human implementation | +| `wontfix` | `wontfix` | Will not be actioned | + +When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding label string from this table. + +Edit the right-hand column to match whatever vocabulary you actually use. diff --git a/docs/auth-proxy.md b/docs/auth-proxy.md index 4f4ef83..c1f30d5 100644 --- a/docs/auth-proxy.md +++ b/docs/auth-proxy.md @@ -16,8 +16,8 @@ At the public application domain, route: ```caddy zopu.example.com { handle /api/auth/* { - reverse_proxy https://befitting-dalmatian-161.convex.site { - header_up Host befitting-dalmatian-161.convex.site + reverse_proxy https://joyous-cat-297.convex.site { + header_up Host joyous-cat-297.convex.site } } @@ -51,7 +51,7 @@ npx convex env set SITE_URL 'https://zopu.example.com' npx convex env set SITE_URL 'http://100.101.157.28:5173' # Staging -npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf' +npx convex env set SITE_URL 'https://zopu-staging.vercel.app' ``` This value is Better Auth's public `baseURL` and `trustedOrigins`. It must be the browser origin because Better Auth writes OAuth state cookies and receives provider callbacks through the same-origin proxy. `CONVEX_SITE_URL` remains the internal Convex HTTP site URL. diff --git a/docs/deployment.md b/docs/deployment.md deleted file mode 100644 index 9230a38..0000000 --- a/docs/deployment.md +++ /dev/null @@ -1,233 +0,0 @@ -# Deployment Notes - -Two active environments share one Convex deployment (`dev:befitting-dalmatian-161`). Each runs its own web server, Flue agents process, and `.env` file. - -## Environments - -| | Local Mac Dev | Cheaptricks Staging | -| --- | --- | --- | -| SSH alias | (local) | `cheaptricks` | -| Repo path | `/Users/puter/Workspace/zopu/code` | `/workspace/code` | -| Tailscale IPv4 | `100.101.157.28` | `100.122.185.111` | -| Web URL | `http://100.101.157.28:5173` | `https://zopu.cheaptricks.puter.wtf` | -| Flue URL (internal) | `http://100.101.157.28:3585` | `http://127.0.0.1:3585` | -| Flue URL (browser-facing) | `http://100.101.157.28:3585` | `https://zopu.cheaptricks.puter.wtf/api` | -| Caddy | none (direct Tailscale) | `zopu.cheaptricks.puter.wtf` HTTPS termination | -| Bun | installed directly | symlink at `/workspace/.bun` | -| Process manager | manual `bun run dev:tailscale:*` | `nohup` into `/tmp/zopu-*.log` | - -## Shared Convex deployment - -Deployment name: `dev:befitting-dalmatian-161` Convex URL: `https://befitting-dalmatian-161.convex.cloud` Convex Site URL: `https://befitting-dalmatian-161.convex.site` - -Convex env vars are deployment-scoped, not per-machine. Authenticate from any machine with `npx convex dev` inside `packages/backend`. - -Key Convex env var: - -``` -SITE_URL = -``` - -This controls `trustedOrigins` in the Better Auth config (`packages/backend/convex/auth.ts`). It must match the URL the browser actually visits, or sign-in fails silently with a CORS rejection. - -When switching between environments: - -```bash -cd packages/backend - -# For local Mac testing: -npx convex env set SITE_URL 'http://100.101.157.28:5173' - -# For Cheaptricks staging: -npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf' -``` - -### OAuth consequence - -`SITE_URL` drives both Better Auth's public callback origin and the single GitHub OAuth App callback. When switching the shared deployment between the local and staging origins, also update the GitHub OAuth App's **Authorization callback URL** to `/api/auth/callback/github` before attempting a GitHub connection. GitHub OAuth Apps allow one callback URL; use distinct Convex deployments and OAuth Apps if both environments must operate concurrently. - -## Local Mac Dev `.env` - -```env -CONVEX_DEPLOYMENT=dev:befitting-dalmatian-161 -CONVEX_URL=https://befitting-dalmatian-161.convex.cloud -CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site -SITE_URL=http://100.101.157.28:5173 -NATIVE_APP_URL=code:// - -VITE_CONVEX_URL=https://befitting-dalmatian-161.convex.cloud -VITE_CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site -VITE_FLUE_URL=http://100.101.157.28:3585 - -DAEMON_ID=local-macbook -DAEMON_NAME=Local MacBook -DAEMON_VERSION=0.0.0 -DAEMON_HEARTBEAT_MS=15000 -DAEMON_COMMAND_LEASE_MS=60000 - -FLUE_DB_TOKEN= - -AGENT_MODEL_PROVIDER=xiaomi -AGENT_MODEL_NAME=mimo-v2.5 -AGENT_MODEL_API=openai-completions -AGENT_MODEL_BASE_URL= -AGENT_MODEL_API_KEY= -AGENT_MODEL_CONTEXT_WINDOW=1048576 -AGENT_MODEL_MAX_TOKENS=131072 - -GITEA_URL=https://git.openputer.com -GITEA_TOKEN= -``` - -### Start local dev - -```bash -bun run dev:tailscale:agents -- --port 3585 & -bun run dev:tailscale:web & -``` - -Both bind `0.0.0.0` so they are reachable over Tailscale from a phone. - -Before testing locally, flip the Convex `SITE_URL`: - -```bash -cd packages/backend && npx convex env set SITE_URL 'http://100.101.157.28:5173' -``` - -## Cheaptricks Staging `.env` - -Located at `/workspace/code/.env` on the `cheaptricks` host. - -```env -CONVEX_DEPLOYMENT=dev:befitting-dalmatian-161 -CONVEX_URL=https://befitting-dalmatian-161.convex.cloud -CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site -SITE_URL=https://zopu.cheaptricks.puter.wtf -NATIVE_APP_URL=code:// - -VITE_CONVEX_URL=https://befitting-dalmatian-161.convex.cloud -VITE_CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site -VITE_FLUE_URL=https://zopu.cheaptricks.puter.wtf/api - -VITE_ZOPU_SERVER_URL=https://zopu.cheaptricks.puter.wtf/api -PORT=3590 - -DAEMON_ID=local-macbook -DAEMON_NAME=Local MacBook -DAEMON_VERSION=0.0.0 -DAEMON_HEARTBEAT_MS=15000 -DAEMON_COMMAND_LEASE_MS=60000 - -FLUE_DB_TOKEN= - -AGENT_MODEL_PROVIDER=xiaomi -AGENT_MODEL_NAME=mimo-v2.5 -AGENT_MODEL_API=openai-completions -AGENT_MODEL_BASE_URL=https://ai.cheaptricks.puter.wtf/v1 -AGENT_MODEL_API_KEY= -AGENT_MODEL_CONTEXT_WINDOW=1048576 -AGENT_MODEL_MAX_TOKENS=131072 - -GITEA_URL=https://git.openputer.com -GITEA_TOKEN= -``` - -### Caddy config - -File: `/etc/caddy/Caddyfile` on `cheaptricks` - -``` -zopu.cheaptricks.puter.wtf { - bind 135.181.82.179 2a01:4f9:c013:4a64::1 - encode zstd gzip - - # Must precede the generic /api route: preserves /api/auth/* and cookies. - handle /api/auth/* { - reverse_proxy https://befitting-dalmatian-161.convex.site { - header_up Host befitting-dalmatian-161.convex.site - } - } - - handle_path /api/* { - reverse_proxy 127.0.0.1:3585 - } - - handle { - reverse_proxy 127.0.0.1:5173 - } -} -``` - -`/api/auth/*` is the same-origin Better Auth proxy to Convex. The generic `/api/*` route serves Flue at port `3585`; it must be evaluated only after the authentication route. - -Reload after changes: - -```bash -sudo systemctl reload caddy -``` - -### Vite allowedHosts - -`apps/web/vite.config.ts` must include `server: { allowedHosts: true }` or Vite rejects requests arriving through the Caddy domain. - -### Start staging dev - -```bash -ssh cheaptricks -export PATH=$PATH:/workspace/.bun/bin -cd /workspace/code - -# Pull latest -git pull origin feat/web-integrarion -bun install - -# Start both processes with nohup so they survive SSH disconnect -nohup bun run dev:tailscale:agents -- --port 3585 > /tmp/zopu-agents.log 2>&1 & -nohup bun run dev:tailscale:web > /tmp/zopu-web.log 2>&1 & -``` - -Before testing on staging, flip the Convex `SITE_URL`: - -```bash -cd packages/backend && npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf' -``` - -### Verify staging - -```bash -curl -sS -o /dev/null -w '%{http_code}\n' https://zopu.cheaptricks.puter.wtf/ -# expect: 200 - -curl -sS -D - -o /dev/null \ - 'https://befitting-dalmatian-161.convex.site/api/auth/get-session' \ - -H 'Origin: https://zopu.cheaptricks.puter.wtf' | grep access-control-allow-origin -# expect: access-control-allow-origin: https://zopu.cheaptricks.puter.wtf -``` - -## Model configuration - -Both environments use the same model via the Cheaptricks AI gateway: - -- Provider identity: `xiaomi` (Flue catalog maps this to MiMo multimodal metadata) -- Model: `mimo-v2.5` -- API protocol: `openai-completions` -- Context window: `1048576` -- Max output tokens: `131072` -- Multimodal: text + image input - -The `AGENT_MODEL_BASE_URL` differs: - -- Local Mac: uses the external gateway URL -- Cheaptricks: uses `https://ai.cheaptricks.puter.wtf/v1` (local to the box) - -## Known gotchas - -1. **Convex `SITE_URL` is single-valued and is the OAuth callback origin.** Switch it together with the GitHub OAuth App's single callback URL when moving between local and staging. Running both origins concurrently requires separate Convex deployments and OAuth Apps. - -2. **Vite blocks unknown hosts by default.** Caddy domain must be allowed via `server.allowedHosts` in `apps/web/vite.config.ts`. - -3. **Flue port changed from 3583 to 3585.** The old Caddy config pointed at 3583/13100. Current ports are 3585 (Flue) and 5173 (web). - -4. **`.env` is gitignored.** Each machine maintains its own copy. The repo ships `.env.example` as the template. - -5. **Convex CLI auth is per-machine.** Run `npx convex dev` once inside `packages/backend` on each new machine to authenticate the CLI. diff --git a/docs/dev-plan.md b/docs/dev-plan.md deleted file mode 100644 index 96dcae9..0000000 --- a/docs/dev-plan.md +++ /dev/null @@ -1,445 +0,0 @@ -# Zopu Work OS — Development Plan - -> **Related:** `slices.md` defines product increments; `dev-loop.md` defines the normative delivery loop; `evaluation.md` defines promotion gates. - -> **Purpose:** concrete implementation order for the repository. -> **Strategy:** one vertical product loop, contracts first, provider adapters second, generalization last. - -## 1. Target demonstration - -Use one real repository and one deterministic Work: - -> Add `GET /health` returning `{ status: "ok", commit: "" }`, with automated and live HTTP verification, then create a verified PR. - -The first release is successful only when the full path works from chat to exact PR evidence. - -## 2. Engineering rules - -1. Land domain contracts before parallel adapter/UI work. -2. Keep FLUE, Rivet, Cube, AgentOS, and harness types behind ports. -3. One side effect has one idempotency key. -4. One mutating attempt owns one worktree. -5. Every state transition has a command, event, actor, timestamp, and evidence reference. -6. Every async process has timeout, cancellation, retry policy, and terminal classification. -7. Builder output is candidate output until independent verification passes. -8. Do not generalize until two real use cases require it. -9. Do not add an agent role without an evaluation showing quality gain. -10. Keep manual merge/deploy gates initially. - -## 3. Repository workstreams - -Recommended logical ownership: - -```text -A. Domain/actors -B. FLUE definition/design agents -C. Resolver/runtime/harness -D. Verification/Git -E. Web experience -F. Deployment/operations -``` - -Only parallelize after shared schemas and event contracts are merged. - -## 4. Phase 0 — Baseline and contracts - -### Deliverables - -- repository architecture inventory; -- one canonical glossary; -- schemas for Message, Signal, Work, WorkDefinition, DesignPacket, VerticalSlice, Run, Attempt, Artifact, Question; -- Work/Attempt state machines; -- command/event list; -- port interfaces; -- static `CodingKitV0`; -- deterministic fixture project/task. - -### Tests - -- schema round trips; -- state transition property/table tests; -- idempotency tests; -- fake adapters; -- actor restart/replay tests. - -### Exit gate - -A fake end-to-end test can create Work, approve definition/design, run fake slices, verify, and produce a fake PR artifact. - -## 5. Milestone A — Work exists (Slices 1–2) - -### Issue order - -1. Persist project messages. -2. Implement `ProcessMessage`. -3. FLUE structured Signal/Work proposal. -4. Signal fingerprinting and attach/create rules. -5. WorkActor/projection. -6. Reactive Work card. -7. Work Definition schema/versioning. -8. Definition compiler agent. -9. definition edit/approval/questions UI. -10. approval invalidation tests. - -### Release gate - -```text -message → exact Signal → proposed card → approved Work Definition -``` - -No runtime integration. - -## 6. Milestone B — Work is executable (Slices 3–5) - -### Issue order - -1. ImpactMap/DesignPacket schemas. -2. design compiler and slice planner. -3. design review/version UI. -4. Resolver decision function as pure domain logic. -5. WorkActor resolver commands/events. -6. FakeHarness/FakeSandbox adapters. -7. AttemptActor lifecycle. -8. CubeSandbox adapter. -9. selected harness adapter (OMP first unless spike rejects it). -10. Git worktree preparation. -11. normalized activity stream. -12. cancellation/timeout/cleanup. - -### Contract freeze before adapter work - -```text -HarnessEvent -SandboxLease -AttemptInput/Outcome -Artifact metadata -``` - -### Release gate - -```text -approved design → one real slice → isolated repository changes -``` - -No PR claim yet. - -## 7. Milestone C — Work is trustworthy (Slices 6–7) - -### Issue order - -1. VerificationPlan schema. -2. command-check runner. -3. HTTP-check runner. -4. revision/environment binding. -5. verifier role/process. -6. repair-attempt loop. -7. design-conformance evidence. -8. Git commit/push adapter. -9. PR creation adapter with idempotency. -10. review-package generator/UI. -11. exact-SHA invariant tests. - -### Required quality fixture - -For the health task, prove: - -```text -new test fails on base -candidate passes focused tests -service starts -GET /health returns expected body -candidate SHA equals PR head SHA -``` - -### Release gate - -A human can review and merge a real verified PR without reading raw agent logs. - -## 8. Milestone D — Work is steerable (Slice 8) - -### Issue order - -1. Question/Decision lifecycle. -2. harness permission/question normalization. -3. attention UI. -4. contextual answer routing. -5. same-session resume and restarted-session recovery. -6. stale-question/version protections. - -### Release gate - -A deliberate ambiguity blocks Work, receives an answer, and resumes without duplicate execution. - -## 9. Milestone E — Work survives complexity (Slices 9–10) - -### Issue order - -1. multi-slice commit model. -2. IntegrationActor/use case. -3. conflict/overlap analysis. -4. integrated verification. -5. preview adapter. -6. release/rollback policy. -7. observation and WorkResult. -8. incident/result-to-Signal loop. - -### Release gate - -Two slices pass independently, integrate on one SHA, publish preview, and produce an observed result. - -## 10. Milestone F — System improvement (Slices 11–12) - -### Issue order - -1. post-run evaluation schema. -2. learning synthesis. -3. knowledge proposal/diff workflow. -4. Kit registry/versioning. -5. Kit compiler. -6. tool/skill registry. -7. role evaluation harness. -8. controlled parallel fleet. -9. policy fallback to static Kit. - -### Release gate - -A completed run proposes a reviewable Kit/knowledge improvement, and a second run demonstrably benefits. - -## 11. Actor rollout - -### Initial - -```text -ProjectActor -WorkActor -AttemptActor -``` - -WorkActor contains Resolver state and verification orchestration initially. - -### Split only when justified - -```text -VerificationActor — independent check lifecycle becomes complex -IntegrationActor — multi-branch/slice composition exists -ResultActor — deployment observation exists -ResolverActor — scheduling lifecycle needs independent ownership -``` - -Avoid actor-per-record designs. - -## 12. Test architecture - -### Domain - -- transition tables; -- invariants; -- retry/budget logic; -- dependency graph readiness; -- approval/version invalidation; -- completion rules. - -### Application - -- command → event → projection; -- idempotent side effects; -- crash/restart recovery; -- timeout/cancellation; -- stale command rejection. - -### Adapter contract tests - -Run same suite against fake and live adapters: - -```text -HarnessRuntime -SandboxRuntime -SourceControl -ArtifactStore -``` - -### End-to-end - -Maintain fixtures: - -```text -happy path -casual message/no Work -duplicate message -definition revision -design rejection -harness transient failure -human question/resume -verification repair -retry exhaustion -PR duplicate callback -actor restart mid-attempt -cancellation -``` - -### Quality evaluation - -Before adding a new model/role/Kit, compare: - -- success rate; -- escaped defect rate; -- review changes requested; -- retries; -- human attention; -- cost/time; -- design deviation. - -## 13. Operational rollout - -### Local - -- fake adapters; -- local Rivet/AgentOS; -- one local repository fixture. - -### Internal VPS - -- deployed Rivet actors; -- Bun/Effect daemon; -- private Cube API; -- one OMP template; -- test forge repository. - -### Dogfood repository - -- real branch/PR; -- manual review; -- no production deploy; -- collect every failure. - -### Controlled release - -- one project/user; -- quotas; -- kill switch; -- audit trail; -- explicit external side-effect gates. - -## 14. Security checklist before real repositories - -```text -private control-plane networking -Cube/Rivet authentication -short-lived Git/model credentials -sandbox egress policy -no host HOME mounts -tool allowlist -artifact authorization -secret redaction -attempt timeout/cleanup -manual merge/deploy -audit approvals -``` - -## 15. Branch/PR sequencing - -Suggested integration branch: - -```text -dogfood/v0 -``` - -Per-slice branches: - -```text -dogfood/s01-work -dogfood/s02-definition -... -``` - -Within a slice, parallel branches may cover: - -```text -contracts/domain -backend/actor -frontend -adapter -tests -``` - -Merge order: - -```text -contracts → domain/actor → adapters/UI → integration tests -``` - -Every branch must target the current slice integration branch, not independently invent shared schemas. - -## 16. First backlog - -Execute exactly in this order: - -```text -01 glossary + schemas -02 Work/Attempt state machines -03 commands/events/idempotency -04 fake E2E harness -05 message persistence -06 Signal extraction -07 Work card -08 Work Definition -09 definition approval -10 Design Packet -11 vertical-slice planner -12 design approval -13 Resolver with fake harness -14 AttemptActor -15 CubeSandbox adapter -16 OMP adapter/spike -17 real repository mutation -18 VerificationRuntime -19 repair loop -20 Git commit/push/PR -21 review package -22 contextual question/resume -23 integration verification -24 preview/release/result -25 learning proposals -26 dynamic Kit Builder -``` - -## 17. First production-quality acceptance test - -```text -Given: -- one configured project/repository; -- one actionable user message; -- no pre-existing Work. - -When: -- Zopu processes the message; -- the user approves definition/design; -- the Resolver executes all slices; -- verification passes; -- publication is requested. - -Then: -- one Signal and one Work exist; -- exact provenance is preserved; -- every attempt has a terminal outcome; -- one verified candidate SHA exists; -- all required checks bind to that SHA; -- one PR exists at that SHA; -- the Work card explains intent, design, changes, evidence, and next action; -- actor/process restarts produce no duplicate Work, attempts, commits, or PRs. -``` - -## 18. Stop conditions - -Pause feature expansion when any is true: - -- stale “running” Work exists; -- duplicate external side effects occur; -- verification cannot identify exact SHA/environment; -- human cannot understand why a Work is “done”; -- retries are unbounded; -- agents bypass actor/application commands; -- provider-specific assumptions leak into domain; -- new roles add cost without measured quality improvement. - -Fix the completion system before adding more autonomy. diff --git a/docs/dogfood-plan.md b/docs/dogfood-plan.md deleted file mode 100644 index 7810af4..0000000 --- a/docs/dogfood-plan.md +++ /dev/null @@ -1,1241 +0,0 @@ -You are the lead engineering agent responsible for shipping the first working Zopu dogfooding loop today. - -You are not here to merely produce a plan. You must inspect the repository, create isolated Paseo workspaces, spawn parallel GLM 5.2 coding agents, supervise them, review their work, request corrections, integrate their branches, run the complete system, and leave the repository in a demonstrably working state. - -You have shell access and may use the Paseo CLI to create and manage other Codex agents. - -All child agents must use: - ---provider codex/glm-5.2 - -The current repository is the Zopu monorepo. It already contains product documentation, design documentation, technical documentation, Effect primitives, Convex backend code, web/mobile/desktop applications, agent code, project-management primitives, Signals, and partial AgentOS/Rivet integration. - -The starting branch is expected to be: - -feat/projects-backend - -Verify this rather than blindly assuming it. - -The final integration branch should be: - -dogfood/v0 - -Your job is to manage the entire implementation through parallel isolated worktrees. - -====================================================================== - -1. PRODUCT OBJECTIVE ====================================================================== - -Ship the smallest complete Zopu dogfooding loop for the Zopu repository itself: - -1. The user opens the Zopu web application. -2. The user selects the Zopu project. -3. The project has access to: - - product.md / PRODUCT.md - - design.md / DESIGN.md - - tech.md / TECH.md - - AGENTS.md - - repository source and Git history -4. The user sends a message through project chat. -5. Zopu stores the exact message as evidence and extracts a Signal. -6. The Signal either: - - attaches to an existing related work unit; or - - creates a new work unit. -7. For this version, an existing ProjectIssue may serve as the work-unit implementation. -8. Starting the work unit creates or resumes an execution run. -9. The Zopu orchestration agent delegates coding to an Orb. -10. The Orb consists of: - - AgentOS - - OpenCode - - an attached Docker sandbox - - repository checkout/worktree - - project context - - runtime tools - - model-gateway configuration -11. OpenCode: - - reads the issue and project context; - - edits the repository; - - runs tests; - - iterates on failures; - - asks questions when blocked; - - commits and pushes a branch; - - opens a pull request. -12. Events, Signals, steps, questions, artifacts, commits and the PR are shown in the work-unit card. -13. The user can send a contextual follow-up to the same work unit. -14. The same orchestration context and OpenCode run should continue when possible. -15. The user manually reviews and merges the PR. - -The completed proof should be something like: - -User: “Add a health endpoint that exposes the current build commit.” - -Result: ✓ exact message evidence stored ✓ Signal created ✓ Work Unit created or updated ✓ work started ✓ Orb provisioned ✓ OpenCode session started ✓ repository changed ✓ tests executed ✓ branch committed and pushed ✓ pull request opened ✓ work card updated ✓ contextual follow-up reaches the active work - -====================================================================== 2. HARD SCOPE -====================================================================== - -This is a narrow dogfooding implementation. - -Implement only: - -- one user; -- one organization; -- one project; -- one repository: zopu-code; -- web application only; -- one primary mutating execution at a time; -- OpenCode as the coding harness; -- GLM 5.2 as the inference model; -- Docker as the full execution sandbox; -- AgentOS as the harness/orchestration environment; -- Convex as the existing control-plane backend; -- self-hosted Git/Gitea as source control; -- manual pull-request merge. - -Do not build: - -- general multitenancy; -- arbitrary repository onboarding; -- customer-facing billing; -- mobile UI; -- desktop UI; -- TUI changes; -- stable production deployment of generated applications; -- multiple sandbox providers; -- agent swarms; -- elaborate prioritization systems; -- complex work-unit status taxonomy; -- Slack, Telegram or email ingestion; -- broad refactors unrelated to the dogfooding loop; -- speculative frameworks that are not needed by the loop. - -ProjectIssue may remain the backend representation of a Work Unit for this version. - -Project events may represent execution steps and activity. - -Project artifacts may represent: - -- work.md; -- steps.md; -- agent reports; -- test output; -- diffs; -- commits; -- pull requests. - -====================================================================== 3. OPERATING RULES -====================================================================== - -Before changing anything: - -1. Run: - - pwd - - git status - - git branch --show-current - - git remote -v -2. Read: - - root AGENTS.md - - product documentation - - design documentation - - technical documentation - - smoke/testing documentation -3. Inspect existing packages and flows before creating replacements. -4. Confirm whether the current orchestration framework is Flue rather than Flask. Treat speech-to-text references to “Flask agent” as untrusted until confirmed in the code. -5. Inspect: - - Signals primitive - - ProjectIssue primitive - - project workspace hooks - - project-manager agent - - Zopu agent - - daemon - - AgentOS registry - - Git/Gitea actions - - existing smoke tests -6. Search for current TODOs and unfinished contracts. -7. Reuse existing abstractions when they are sound. -8. Do not redesign the entire repository. - -Engineering requirements: - -- Follow existing Effect v4 conventions. -- Preserve dependency direction. -- Use tagged domain errors rather than generic thrown strings. -- Validate external data with schemas. -- Preserve exact provenance for user messages and agent events. -- Keep infrastructure implementation out of pure domain packages. -- Do not expose model, Git, Convex or infrastructure credentials in generated repository files. -- Never let generated model text become trusted evidence without provenance. -- Do not auto-merge pull requests. -- Do not run multiple mutating agents in the same Git checkout. -- Keep every child agent inside an isolated Paseo worktree. -- Every child agent must commit its work. -- Prefer that every child agent pushes its branch and opens a PR targeting dogfood/v0. -- If the Git CLI cannot open a PR automatically, require the agent to leave exact commands and a complete PR description. -- Do not let child agents merge their own branches. -- The lead agent reviews and integrates them. - -When an agent is blocked: - -- inspect its logs; -- send a focused follow-up using `paseo send`; -- do not restart from scratch unless the workspace is broken; -- continue supervising other lanes in parallel. - -Do not stop after spawning agents. You must monitor and integrate them. - -====================================================================== 4. INITIAL BRANCH PREPARATION -====================================================================== - -Inspect the current branch. - -If currently on feat/projects-backend: - -git pull --ff-only git switch -c dogfood/v0 git push -u origin dogfood/v0 - -If dogfood/v0 already exists: - -git switch dogfood/v0 git pull --ff-only - -If the expected branch is different, inspect the repository history and choose the branch containing the current projects backend work. Do not discard existing uncommitted work. - -Run the baseline checks before spawning agents. Record failures but do not spend the entire session fixing unrelated pre-existing problems. - -Suggested baseline: - -bun install bun run check - -Also inspect package-specific scripts and use the actual commands defined by the repository. - -====================================================================== 5. PASEO ORCHESTRATION -====================================================================== - -Verify Paseo first: - -paseo status paseo ls - -If the daemon is unavailable, inspect: - -tail -n 200 ~/.paseo/daemon.log - -Do not continue spawning until Paseo works. - -For every child lane: - -1. Create a worktree workspace: - - paseo workspace create \ - --isolation worktree \ - --mode branch-off \ - --new-branch \ - --base dogfood/v0 \ - --title "" \ - --json - -2. Read the returned workspaceId. - -3. Start the child agent: - - paseo run \ - --provider codex/glm-5.2 \ - --workspace <workspaceId> \ - --title "<title>" \ - --background \ - --json \ - "<full lane prompt>" - -4. Save: - - branch; - - workspaceId; - - agentId; - - task; - - current status. - -Maintain an orchestration note in a temporary file outside committed product code, for example: - -/tmp/zopu-dogfood-orchestration.md - -Track: - -| Lane | Branch | Workspace ID | Agent ID | Status | PR | -| ---- | ------ | ------------ | -------- | ------ | --- | - -Use: - -paseo ls paseo inspect <agentId> paseo logs <agentId> paseo send <agentId> "<focused instruction>" paseo wait <agentId> - -Do not block waiting on one child while others are still running. Poll all first-wave agents periodically. - -====================================================================== 6. SHARED CHILD-AGENT PREFIX -====================================================================== - -Prepend the following instructions to every child prompt: - -You are implementing one isolated lane of the Zopu dogfood v0 loop. - -Repository base branch: dogfood/v0 - -Your branch is already isolated in a Paseo Git worktree. - -Before changing code: - -1. Read root AGENTS.md. -2. Read the product, design and technical Markdown files. -3. Read smoke/testing documentation. -4. Inspect the current implementation before proposing replacements. -5. Preserve the existing Effect v4, Convex, Flue, AgentOS and repository boundaries. -6. Do not edit generated Convex output manually. -7. Do not edit vendored repositories. -8. Do not modify mobile, desktop or TUI code unless this task explicitly requires it. -9. Do not build general multitenancy, arbitrary repository support or speculative abstractions. -10. Keep the implementation focused on the one-repository Zopu dogfooding loop. - -While working: - -- Make incremental changes. -- Preserve existing behavior outside your lane. -- Add focused tests. -- Use tagged errors and schema validation at boundaries. -- Do not store credentials in source code. -- Do not merge branches. -- Do not alter another lane’s primary ownership unless required to fix a compile contract. When cross-lane changes are unavoidable, keep them minimal and document them. - -Before finishing: - -1. Run formatting/linting for every changed file. -2. Run targeted tests. -3. Run package type checks. -4. Run the root check. -5. Clearly separate pre-existing unrelated failures from failures caused by your changes. -6. Review `git diff`. -7. Commit all intended changes. -8. Push your branch. -9. Open a pull request targeting dogfood/v0 when tooling permits. -10. Return: - - summary; - - changed files; - - architecture decisions; - - tests run; - - exact failures; - - environment variables; - - PR URL or exact PR creation instructions; - - remaining limitations. - -====================================================================== 7. FIRST-WAVE PARALLEL LANES -====================================================================== - -Spawn all four first-wave agents immediately. - ---- - -LANE A — PROJECT CHAT, SIGNALS AND WORK ROUTING ----------------------------------------------------------------------- - -Branch: - -dogfood/zopu-orchestrator - -Title: - -Zopu Signals Orchestrator - -Prompt: - -Implement the project-scoped Zopu chat, Signal extraction and work-routing loop. - -Inspect the existing: - -- Zopu agent; -- Signals primitive; -- ProjectIssue primitive; -- Convex Signal functions; -- project-issue functions; -- current Flue routes and authenticated agent transport; -- project workspace hooks. - -Goal: - -A user sends a message in the selected project context. - -The system must: - -1. store the exact user message as evidence; -2. create a Signal only when the message contains an actionable problem, request, opportunity, blocker or decision; -3. inspect related open ProjectIssues; -4. choose one of: - - attach the Signal to a related existing ProjectIssue; - - create a new ProjectIssue from the Signal; -5. return a clear user-facing explanation of what happened; -6. optionally allow the issue to be started; -7. preserve project and organization scope; -8. be idempotent under retries. - -Required tools or application capabilities: - -- read selected project; -- read project context documents; -- list recent project Signals; -- list active ProjectIssues; -- create Signal from exact stored evidence; -- attach Signal to an existing ProjectIssue; -- create ProjectIssue from Signal; -- optionally begin the ProjectIssue. - -Rules: - -- The model must not supply or rewrite the raw source message. -- Store a reference to the exact persisted message. -- Do not create work from casual chat. -- Ask one focused clarification when genuinely ambiguous. -- Repeated delivery of the same message must not create duplicate Signals or duplicate attachments. -- Reject cross-project and cross-organization access. -- Use a proper relation if multiple Signals need to attach to one ProjectIssue. -- Do not create generic WorkUnit architecture in this lane unless the repository already has it and it is required. -- Do not implement background ingestion. -- Do not touch Orb runtime implementation. - -Acceptance examples: - -Message: “The work-unit card should expose the generated PR.” - -Expected: - -- exact message persisted; -- Signal created; -- attached to an existing UI/workspace issue if relevant; -- otherwise a new ProjectIssue is created. - -Tests: - -- authentication; -- project scoping; -- idempotency; -- attach versus create; -- exact-message provenance; -- casual conversation does not create work; -- cross-project rejection. - -Likely ownership: - -- packages/agents/src/agents/zopu* -- packages/agents/src/tools/* -- packages/backend/convex/signals* -- packages/backend/convex/projectIssues* -- packages/backend/convex/schema* -- Signal/project-issue primitives only as required. - ---- - -LANE B — ORB RUNTIME FOUNDATION ----------------------------------------------------------------------- - -Branch: - -dogfood/orb-runtime - -Title: - -AgentOS OpenCode Orb Runtime - -Prompt: - -Build the first real Zopu Orb runtime as a focused infrastructure/application package. - -Do not wire it into the existing project-manager agent yet. Provide the runtime contract, implementation and a bounded proof. - -Definition: - -An Orb is one logical execution workspace for one ProjectIssue run. - -For this version it contains: - -- AgentOS actor; -- OpenCode harness; -- Docker sandbox; -- mounted repository workspace; -- project context; -- model-gateway configuration; -- process/log handling; -- normalized execution events; -- cleanup lifecycle. - -Required stack: - -- existing Effect v4 conventions; -- @rivet-dev/agentos; -- @agentos-software/opencode; -- @rivet-dev/agentos-sandbox or the current supported equivalent; -- Docker sandbox provider; -- existing repository preparation primitives; -- existing model-gateway conventions. - -Do not use `opencode serve` unless the repository already requires it for a proven reason. Prefer native AgentOS/OpenCode ACP integration. - -Define a narrow domain and application contract: - -- OrbId; -- OrbRunId; -- OrbSessionId; -- Orb state; -- run state; -- normalized OrbEvent; -- tagged failures. - -Suggested operations: - -- create or resolve Orb; -- prepare repository; -- attach Docker sandbox; -- open OpenCode session; -- send initial task; -- send follow-up; -- stream normalized events; -- execute commands; -- read process logs; -- cancel; -- collect results; -- dispose or suspend. - -Keep product-domain concepts separate from infrastructure leases. - -Do not make AgentOS VM state equal the work-unit state. - -Actor identity must include: - -- project; -- issue/work unit; -- run. - -Runtime behavior: - -1. Create AgentOS actor. -2. Create one Docker sandbox for the Orb. -3. Prepare a project checkout or worktree. -4. Mount the sandbox project directory into AgentOS at a stable path. -5. Configure OpenCode under its expected configuration location. -6. Run OpenCode inside AgentOS. -7. Execute Bun, package-manager, test and build commands through Docker. -8. Stream meaningful events without exposing secrets. -9. Support bounded cancellation and cleanup. -10. Preserve enough session identity to send a later follow-up. - -Security: - -- no permanent provider credentials in project files; -- no global Git credential; -- use run-scoped runtime credentials when possible; -- redact secrets from logs; -- restrict writable mounts; -- no production deployment capability; -- no automatic merge capability. - -Proof fixture: - -Provide one local command or opt-in integration test that: - -1. creates an Orb; -2. starts a Docker sandbox; -3. writes or prepares a tiny TypeScript project; -4. opens OpenCode; -5. sends a bounded task; -6. executes one command in Docker; -7. streams events; -8. cancels or completes; -9. cleans up. - -Document: - -- environment variables; -- local startup; -- Docker requirements; -- AgentOS endpoint; -- model gateway; -- filesystem layout; -- current limitations. - -Do not modify: - -- Zopu chat behavior; -- project-manager delegation; -- web UI. - ---- - -LANE C — WEB WORKSPACE AND WORK CARDS ----------------------------------------------------------------------- - -Branch: - -dogfood/web-workspace - -Title: - -Zopu Web Work OS - -Prompt: - -Turn the current project workspace into the minimal web Work OS required for dogfooding. - -Use the existing Convex backend, project Signals, ProjectIssues, project events, artifacts and Flue agent transport. - -Do not make backend schema changes unless a tiny compatibility fix is absolutely required. Coordinate through existing contracts. - -Product projection: - -- ProjectIssue appears to the user as a Work Unit. -- Signals are source evidence and inputs. -- Project events are the step/activity timeline. -- Project artifacts include plans, logs, diffs, commits and PRs. -- A selected Work Unit has contextual chat. -- Project chat is global within the selected project. - -Required interface: - -Header: - -- Zopu; -- current project; -- project/runtime connection status; -- basic project switcher if already supported. - -Main surface: - -- global project conversation; -- active Work Unit cards; -- lightweight Signals display; -- persistent composer. - -Collapsed Work Unit card: - -- title; -- latest summary; -- linked Signal count; -- current activity; -- step count; -- artifact count; -- PR indicator; -- needs-input indicator when available. - -Expanded Work Unit: - -- objective; -- linked Signals and provenance; -- current plan or steps; -- event/activity timeline; -- questions/blockers; -- artifacts; -- commit or PR information; -- contextual chat composer; -- start or continue action. - -Composer modes: - -- Project -- Selected Work Unit - -Project mode sends messages to the Zopu/global project agent. - -Work Unit mode sends messages to the existing issue-scoped project-manager agent identity. - -Do not create visible chat threads or session history navigation. - -A follow-up to a selected Work Unit should use the same issue identity and continue the existing agent context. - -Visual direction: - -- dark; -- calm; -- Apple-like; -- large rounded surfaces; -- readable dense information; -- minimal borders; -- restrained accent; -- mobile-responsive web, but do not build native apps; -- no Kanban board; -- no model selector; -- no thinking-level selector; -- no raw infrastructure debug UI in the main experience. - -Implementation guidance: - -- Refactor oversized workspace components into focused components when useful. -- Keep queries/mutations in hooks. -- Keep presentation components mostly pure. -- Preserve Convex reactivity. -- Do not duplicate native/mobile abstractions. -- Make loading, empty, error and needs-input states clear. -- PR links must be directly usable. - -Acceptance: - -A signed-in user can: - -1. open the Zopu project; -2. chat globally; -3. see a resulting Work Unit; -4. start it; -5. select it; -6. inspect Signals, events and artifacts; -7. send a contextual follow-up; -8. open a resulting PR. - -Tests: - -- event-to-card projection; -- artifact display; -- composer scope switching; -- selected issue identity; -- empty state; -- needs-input display. - ---- - -LANE D — SINGLE-NODE EXECUTION DEPLOYMENT ----------------------------------------------------------------------- - -Branch: - -dogfood/runtime-deploy - -Title: - -Zopu Dedicated Runtime Deployment - -Prompt: - -Create the smallest reproducible deployment for the Zopu execution plane on a fresh Debian dedicated server. - -Context: - -- Convex is already deployed. -- The dedicated server has approximately 12 CPU cores and 40 GB RAM. -- Debian is freshly installed. -- The execution plane should initially be single-node. -- Docker sandboxes will execute repository workloads. -- The web app does not need to be deployed in this lane. - -Deploy or document: - -1. Docker Engine. -2. Bun. -3. single-node Rivet Engine / current required AgentOS runtime. -4. Zopu agent service. -5. Bun/Effect daemon. -6. Docker access required for Orb sandboxes. -7. persistent logs. -8. health checks. -9. restart behavior. -10. repository update workflow. - -Prefer: - -- Docker Compose for infrastructure where appropriate; -- systemd for long-running application services where useful; -- private networking; -- Tailscale when available; -- Caddy only for endpoints that genuinely need HTTP exposure; -- single-node persistent filesystem storage; -- non-root services where practical. - -Do not introduce: - -- Kubernetes; -- PostgreSQL solely for Rivet; -- multi-node coordination; -- public administration endpoints; -- secrets committed to the repository; -- web-app deployment; -- production generated-app hosting. - -Deliverables: - -- install/bootstrap script; -- Compose file or equivalent; -- systemd service files where useful; -- environment template; -- deployment documentation; -- health-check script; -- start/stop/restart commands; -- log inspection commands; -- update-to-commit procedure; -- rollback procedure; -- Docker cleanup guidance; -- disk-space monitoring; -- firewall/private-network notes. - -Required environment groups: - -- Convex; -- self-hosted Git/Gitea; -- model gateway; -- AgentOS/Rivet; -- Zopu agent; -- daemon; -- Docker sandbox; -- service authentication. - -The deployment must be reproducible on a clean Debian host. - -Do not require the developer’s MacBook to remain online after deployment. - -====================================================================== 8. FIRST-WAVE MONITORING -====================================================================== - -After spawning all four first-wave agents: - -1. Record all agent and workspace IDs. -2. Run `paseo ls`. -3. Inspect each agent after a few minutes. -4. Read logs for stalled or questioning agents. -5. Send corrections when needed. -6. Ensure agents are not editing each other’s lanes unnecessarily. -7. Prevent lane B from wiring into project-manager prematurely. -8. Prevent lane C from inventing a new backend schema. -9. Prevent lane D from overengineering deployment. -10. Prevent lane A from creating a second competing work-unit model. - -Use concise interventions. - -Examples: - -paseo send <agentId> "Keep ProjectIssue as the v0 Work Unit. Do not introduce a second generic work-unit schema." - -paseo send <agentId> "Do not wire project-manager yet. Finish the Orb port, adapter and proof fixture only." - -paseo send <agentId> "Use existing Convex contracts. Avoid backend schema changes in the UI lane." - -Wait until each first-wave agent is idle, then inspect: - -paseo inspect <agentId> paseo logs <agentId> - -Review each branch yourself. - -For every lane: - -- inspect commit history; -- inspect diff; -- run targeted tests; -- run package checks; -- verify no secrets; -- verify no unrelated broad refactors; -- verify documentation; -- verify branch was pushed; -- verify PR targets dogfood/v0. - -Do not merge a failing lane merely because the child says it works. - -====================================================================== 9. FIRST-WAVE MERGE PROCESS -====================================================================== - -Recommended merge order: - -1. dogfood/zopu-orchestrator -2. dogfood/orb-runtime -3. dogfood/web-workspace -4. dogfood/runtime-deploy - -Before every merge: - -git switch dogfood/v0 git pull --ff-only git fetch origin git log --oneline --decorate --max-count=10 origin/<branch> git diff dogfood/v0...origin/<branch> - -Run lane-specific checks. - -Merge using the repository’s normal PR workflow when possible. - -If merging locally: - -git merge --no-ff origin/<branch> - -Resolve conflicts conservatively. - -After each merge: - -bun install run targeted checks git push origin dogfood/v0 - -Do not squash away useful commits unless repository policy requires squashing. - -====================================================================== 10. SECOND-WAVE LANE — WIRE PROJECT MANAGER TO ORBS -====================================================================== - -Only spawn this lane after the Orb runtime branch is integrated into dogfood/v0. - -Branch: - -dogfood/orb-wiring - -Title: - -Project Manager Orb Wiring - -Create its Paseo workspace from the updated dogfood/v0 branch. - -Prompt: - -Wire the existing ProjectIssue execution flow to the merged Orb runtime. - -Goal: - -The issue-scoped project-manager becomes a thin orchestration agent. - -OpenCode inside the Orb performs repository implementation. - -Required flow: - -1. User starts a ProjectIssue. -2. The project-manager creates or resumes its Orb run. -3. The project-manager assembles a concise context pack from: - - ProjectIssue; - - exact Signal evidence; - - project context files; - - AGENTS.md; - - relevant repository metadata; - - previous work artifacts. -4. The project-manager sends the implementation objective to OpenCode. -5. OpenCode edits and verifies in the Docker sandbox. -6. Orb events are normalized into durable project events. -7. Meaningful updates refresh the issue summary. -8. OpenCode questions create a needs-input condition visible to the user. -9. A later contextual user message is forwarded to the same OpenCode session when the session remains valid. -10. A resumable replacement session may be created only when required by runtime loss, with previous context restored. -11. Verification runs in Docker. -12. Once verification passes: - - commit; - - push branch; - - create PR using the existing Git/Gitea lifecycle. -13. Store: - - branch; - - commit; - - diff; - - verification report; - - PR metadata; - - agent summary. -14. Mark completed only when: - - a PR exists; or - - a verified no-change result is explicitly recorded. -15. Never merge automatically. - -Refactor the current Git lifecycle so it can be invoked from the Orb/application layer without requiring a particular interactive Flue shell, while preserving compatible existing adapters. - -Failure mapping: - -- runtime unavailable: infrastructure failure with clear reason; -- missing user context: needs input; -- failed tests that can be repaired: agent continues; -- unrecoverable repeated failure: failed with logs and evidence; -- cancellation: terminate OpenCode and sandbox processes; -- Git rejection: preserve commit and expose exact failure; -- PR creation failure: retain pushed branch and retry safely. - -Idempotency: - -- starting the same active issue must not create duplicate active runs; -- repeated completion events must not create duplicate commits or PRs; -- follow-up messages must not accidentally create a separate unrelated issue; -- retries must reuse stable run identity where safe. - -Tests: - -- fake Orb adapter; -- fake Git adapter; -- first-message start; -- follow-up forwarding; -- needs-input handling; -- cancellation; -- duplicate-start prevention; -- successful PR completion; -- failed PR creation recovery; -- one opt-in live local integration test. - -Do not add multi-agent parallel execution. - -====================================================================== 11. SECOND-WAVE REVIEW AND MERGE -====================================================================== - -Monitor the orb-wiring agent closely. - -This lane crosses several boundaries and is the most likely to overreach. - -Intervene if it: - -- edits repository code directly from project-manager; -- bypasses the Orb abstraction; -- creates a new source-control system; -- duplicates the existing project issue lifecycle; -- exposes raw OpenCode event noise directly to the UI; -- auto-merges; -- starts several mutating runs for one issue. - -Review and merge it into dogfood/v0 only after: - -- fake integration tests pass; -- affected packages type-check; -- cancellation works; -- idempotency is demonstrated; -- no secrets appear in logs or artifacts. - -====================================================================== 12. FINAL LANE — END-TO-END DOGFOOD INTEGRATION -====================================================================== - -After all implementation lanes are merged, spawn the final integration agent. - -Branch: - -dogfood/e2e-integration - -Title: - -Zopu Dogfood End-to-End - -Prompt: - -Integrate and prove the complete Zopu dogfood v0 loop. - -Do not add new product scope. Fix integration defects and missing glue only. - -Required live scenario: - -1. Authenticate. -2. Select or bootstrap the Zopu project. -3. Confirm project context files are available. -4. Send this or an equivalently tiny deterministic request through project chat: - - “Add a health endpoint that exposes the current build commit.” - -5. Confirm the exact user message is durably stored. -6. Confirm a Signal is created. -7. Confirm the Signal creates or attaches to a ProjectIssue. -8. Confirm a Work Unit card appears. -9. Start the Work Unit. -10. Confirm project-manager delegates to an Orb. -11. Confirm AgentOS starts. -12. Confirm Docker sandbox starts. -13. Confirm repository checkout/worktree is prepared. -14. Confirm OpenCode session starts with the correct context. -15. Confirm OpenCode modifies the branch. -16. Confirm tests or verification run. -17. Confirm progress events update the work card. -18. Confirm artifacts are generated. -19. Confirm commit and push succeed. -20. Confirm a Gitea PR is created. -21. Confirm the web UI exposes the PR link. -22. Send a contextual follow-up to the same Work Unit. -23. Confirm the follow-up reaches the same active or resumably restored work context. - -Extend the existing smoke/test infrastructure rather than creating a disconnected framework. - -The smoke harness must support: - -- preflight-only; -- one complete run; -- sanitized JSON report; -- bounded timeout; -- stable success marker; -- stable blocked marker; -- cleanup instructions. - -Preflight checks: - -- Convex reachable; -- authentication valid; -- project exists; -- Git repository reachable; -- Git credentials valid; -- daemon healthy; -- Zopu agent healthy; -- Rivet/AgentOS healthy; -- Docker healthy; -- OpenCode package available; -- model gateway reachable; -- GLM model usable; -- repository writable; -- Gitea PR creation available. - -Verification matrix: - -- primitive tests; -- backend tests; -- agents type check; -- daemon type check/build; -- Orb tests; -- web tests; -- web build; -- root check; -- smoke preflight; -- live dogfood scenario. - -Produce: - -docs/DOGFOOD_V0.md - -It must contain: - -- architecture summary; -- exact service startup order; -- required environment variables; -- local MacBook development flow; -- dedicated-server runtime flow; -- exact demo procedure; -- health checks; -- logs; -- failure recovery; -- cleanup; -- known limitations; -- next incremental milestones. - -Commit, push and open a PR targeting dogfood/v0. - -====================================================================== 13. FINAL INTEGRATION RESPONSIBILITIES -====================================================================== - -After the final agent completes: - -1. Review its branch. -2. Run the full verification matrix yourself. -3. Merge it into dogfood/v0. -4. Push dogfood/v0. -5. Deploy or start the execution plane using the runtime runbook. -6. Run the real smoke flow. -7. Open the web application. -8. Verify the Work Unit card and contextual chat manually. -9. Verify the PR exists in the self-hosted Git system. -10. Capture exact remaining failures. - -If the full live path cannot complete: - -- identify the first broken boundary; -- fix that boundary; -- do not mask it with fake success data; -- rerun from a clean Signal or deterministic test issue; -- preserve logs and artifacts. - -The final system must not claim that a PR exists unless it exists in Git. - -====================================================================== 14. QUALITY GATES -====================================================================== - -A lane is not done merely because code was generated. - -Every merged lane must satisfy: - -- no uncommitted intended changes; -- no secrets committed; -- no generated Convex files manually edited; -- no unrelated mobile/desktop/TUI changes; -- no second conflicting work-unit abstraction; -- no automatic PR merge; -- tagged errors for infrastructure failures; -- schema validation at external boundaries; -- idempotent retry behavior where relevant; -- focused tests; -- clear documentation; -- branch pushed; -- PR or merge record available. - -The complete v0 must satisfy: - -- project chat works; -- exact evidence is retained; -- Signal appears; -- work appears; -- work starts; -- Orb starts; -- OpenCode runs; -- Docker executes commands; -- events update; -- user can answer a question; -- changes are committed; -- PR is created; -- PR is visible in the UI. - -====================================================================== 15. RESOURCE AND CONCURRENCY LIMITS -====================================================================== - -For this v0: - -- maximum one mutating Orb per project; -- maximum two child coding agents changing adjacent integration code at the same time; -- no parallel mutation inside one worktree; -- no agent may work directly in the lead agent’s checkout; -- heavy build and browser work stays in Docker; -- use bounded model and execution timeouts; -- terminate abandoned Docker containers; -- archive finished Paseo agents after all work is integrated. - -When agents are no longer needed: - -paseo archive <agentId> - -Do not archive them until their logs and work have been reviewed. - -====================================================================== 16. COMMUNICATION WITH THE USER -====================================================================== - -Do not repeatedly ask the user to choose between reasonable implementation details. - -Make grounded decisions from the repository. - -Ask the user only when blocked by something that cannot be inferred, such as: - -- unavailable server credentials; -- unavailable Git token; -- missing model-gateway key; -- a required destructive infrastructure action; -- an irreversible product decision outside v0 scope. - -When requesting input, provide: - -- the exact blocker; -- the exact command or credential needed; -- what work continues without it; -- the safest default. - -Continue supervising all unblocked lanes while waiting. - -====================================================================== 17. FINAL REPORT -====================================================================== - -When finished, provide a concise but complete report: - -## Dogfood status - -- Project chat: -- Signal extraction: -- Work routing: -- Web cards: -- Contextual chat: -- Orb runtime: -- Docker execution: -- OpenCode: -- Git commit/push: -- PR creation: -- Dedicated runtime: -- End-to-end smoke: - -## Integrated branches - -For each branch: - -- purpose; -- final commit; -- PR; -- tests. - -## Running services - -- service; -- machine; -- port or endpoint; -- health status. - -## Demo instructions - -Exact steps to reproduce the loop. - -## Known limitations - -Only real limitations, not speculative roadmap items. - -## Next three increments - -Choose the three highest-leverage improvements after the dogfooding loop works. - -Your mission is complete only when the dogfooding loop is either demonstrably working or reduced to one clearly identified external blocker with all other implementation complete. diff --git a/docs/manifest.json b/docs/manifest.json deleted file mode 100644 index c241ab9..0000000 --- a/docs/manifest.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "read_order": [ - "agent-context.md", - "product.md", - "glossary.md", - "dev-loop.md", - "tech.md", - "design.md", - "slices.md", - "dev-plan.md", - "evaluation.md" - ], - "files": { - "README.md": { - "bytes": 1957, - "lines": 57, - "sha256": "9f732b8c40e1714767bbf31ef8ea6263c64b572775555f00527d775c6204f9c2" - }, - "agent-context.md": { - "bytes": 7930, - "lines": 328, - "sha256": "6f2e97bc7e2606e84792391beb2d5bb8f4c23a720c277e4b22976cab2cfaf730" - }, - "design.md": { - "bytes": 8470, - "lines": 469, - "sha256": "4d42edbcf6f723b2e845350b5b99925b78fc2fa09783d726f02fec5389bf0a9c" - }, - "dev-loop.md": { - "bytes": 15737, - "lines": 705, - "sha256": "3fe99dcbf05cecfd2403b289fd9d0545372309e41c02973875739ace5822eb04" - }, - "dev-plan.md": { - "bytes": 10138, - "lines": 445, - "sha256": "4e1e68fe91a9f442c1f662d133a27efb9c74223ed92f2f2634cff2aa36d8e429" - }, - "evaluation.md": { - "bytes": 8310, - "lines": 405, - "sha256": "22037e62ae0b7abd1b639c3bd0b6e1a19328b919dd6a7c3fc4a1b7a62c9cac7e" - }, - "glossary.md": { - "bytes": 3800, - "lines": 44, - "sha256": "79abd47b212d3b3c160238f703360a841090da6c9787b9c9f8871e14588aef74" - }, - "product.md": { - "bytes": 10423, - "lines": 422, - "sha256": "020e1b7dd00be90aa1061f1ab2cd1a0416f48735c281a079b1e995dc333c5b75" - }, - "slices.md": { - "bytes": 10132, - "lines": 493, - "sha256": "7ee7500685e5789f2aebf29d6a3b7d14866edc7c0f85b2f2c727edb669e66b00" - }, - "tech.md": { - "bytes": 15349, - "lines": 663, - "sha256": "bcef9fdd0166ead4ff9f1c898016098871089680956de79e990e66d5d472e4d8" - } - } -} diff --git a/docs/slices.md b/docs/slices.md deleted file mode 100644 index 21992cd..0000000 --- a/docs/slices.md +++ /dev/null @@ -1,498 +0,0 @@ -# Zopu Work OS — Vertical Slices - -> **Related:** `dev-loop.md` defines the software-building process; `dev-plan.md` defines implementation sequencing. - -> **Purpose:** ordered product increments. Complete each slice end-to-end before starting the next. -> **Reference task:** “Add `GET /health` returning status and current build commit.” -> **Rule:** every slice must produce visible product behavior, durable state, and automated acceptance coverage. - -## Global definition of done - -For every slice: - -- schema/state migrations applied; -- commands/events are idempotent; -- actor restart does not corrupt state; -- frontend handles loading/error/empty states; -- important actions are audited; -- unit/integration tests cover invariants; -- no provider-specific types leak into domain; -- docs updated when contracts change. - -## Slice 1 — Conversation → Signal → Work card - -### User outcome - -A user message creates one actionable Signal and one proposed Work card with exact provenance. - -### Backend - -```text -Message -Signal -Work -WorkEvent -ProcessMessage → structured FLUE proposal → validated command -``` - -Implement: - -- persist exact message; -- Signal fingerprint/idempotency; -- create vs attach decision; -- proposed Work state; -- Work event feed. - -### Frontend - -- continuous chat; -- inline Work creation notice; -- collapsed reactive Work card; -- source-message link. - -### Acceptance - -- duplicate processing creates no duplicate Signal/Work; -- casual message creates no Work; -- actionable message creates one Work; -- card survives refresh/restart; -- exact source text is recoverable. - -### Explicitly exclude - -Planning, sandboxes, Git, verification. - ---- - -## Slice 2 — Work Definition and approval - -### User outcome - -The proposed Work becomes a testable outcome contract that can be edited and approved. - -### Backend - -Add: - -```text -WorkDefinition(versioned) -DefinitionApproval -Question -RiskClass -``` - -FLUE compiles: - -- problem; -- desired outcome; -- scope/non-goals; -- acceptance criteria; -- assumptions/questions; -- risk. - -Work state: - -```text -Proposed → Defining → AwaitingDefinitionApproval → Designing -``` - -### Frontend - -Expanded Outcome section; edit/approve/request revision; unresolved-question cards. - -### Acceptance - -- high-impact unresolved question blocks approval; -- approval binds exact version; -- revision invalidates stale approval; -- risk lane is visible; -- definition can be reconstructed from event history. - ---- - -## Slice 3 — Design Packet and vertical slices - -### User outcome - -The user can review expected architecture/code shape and approve a bounded slice plan before coding. - -### Backend - -Add versioned: - -```text -ImpactMap -DesignPacket -VerticalSlice -VerificationPlan -DesignApproval -``` - -Required Design Packet fields: - -- affected systems/files; -- architecture summary; -- expected file-tree/call-flow changes; -- key types/invariants; -- risks/trade-offs; -- 1–4 vertical slices; -- evidence requirements per slice. - -### Frontend - -Design section with diagram, file tree, call flow, slices, version diff, approval. - -### Acceptance - -- horizontal “backend/frontend/test later” plan rejected; -- each slice is independently observable/verifiable; -- approval binds definition+design versions; -- changed definition invalidates dependent design; -- Work reaches `Ready`. - ---- - -## Slice 4 — Resolver state machine with fake harness - -### User outcome - -Starting Work visibly advances slices, retries bounded failures, and surfaces blockers without real code execution. - -### Backend - -Add: - -```text -Run -Attempt -ResolverDecision -KitVersion -HarnessRuntime port -FakeHarnessLive -``` - -Static `CodingKitV0`. - -Implement durable loop: - -```text -Ready → ExecutingSlice → VerifyingSlice → NextSlice -``` - -Attempt outcomes: - -```text -Succeeded | RetryableFailure | NeedsInput | Blocked -| VerificationFailed | BudgetExhausted | Cancelled | PermanentFailure -``` - -### Frontend - -Slice progress, meaningful activity, retry count, stop/retry controls, question state. - -### Acceptance - -- injected transient failure retries up to policy; -- restart resumes from durable state; -- no executable step produces explicit failure; -- cancellation terminates attempt; -- no Work remains permanently “running.” - ---- - -## Slice 5 — Real sandbox + implementation harness - -### User outcome - -Zopu implements one approved slice in an isolated repository environment and streams useful progress. - -### Backend - -Initial adapter choice: - -```text -SandboxRuntime = AgentOsSandboxLive -HarnessRuntime = CodexHarnessLive -Durable orchestration = Convex Workflow -``` - -Flow: - -```text -load the project's authenticated Git connection -→ start durable Convex workflow -→ create AgentOS execution environment -→ clone the single configured repo -→ inject context -→ run one slice -→ normalize events -→ collect diff/artifacts -→ pause/terminate -``` - -Security: - -- GitHub OAuth or self-hosted Gitea PAT, scoped to one project; -- scoped Git/model tokens passed only to private execution; -- isolated HOME/worktree; -- one mutating attempt per worktree; -- timeout/cancel cleanup. - -### Frontend - -Project selector/settings, Git connection status, current activity, changed files, artifact links, expandable raw logs, cancel/retry, and manual Git delivery controls. - -### Acceptance - -- real repository file changes occur; -- another Work cannot see/modify checkout; -- cancellation stops process; -- provider failure becomes classified attempt outcome; -- exact base/candidate revision recorded. - -Rivet Engine coordinates AgentOS actor placement through a normal runner, but does not own product orchestration; Convex Workflow remains canonical for the Run lifecycle. Cube/Kubernetes sandbox support remains behind `SandboxRuntime` and can be mounted through AgentOS incrementally. - ---- - -## Slice 6 — Independent verification and repair - -### User outcome - -The card shows objective evidence; failed checks trigger a bounded repair loop. - -### Backend - -Implement `VerificationRuntime` and verifier role. - -Initial checks: - -```text -format/lint/typecheck -focused tests -service start -HTTP behavior -secret scan -expected vs actual files/interfaces -test weakening/deletion detection -``` - -Bind result to candidate SHA/environment. - -Repair: - -```text -failure evidence → repair attempt → clean rerun -``` - -### Frontend - -Evidence checklist, exact failures, candidate SHA, repair status. - -### Acceptance - -- implementer cannot self-mark passed; -- failed check stores output/exit code; -- repair receives exact evidence; -- max attempts enforced; -- final verdict is Passed/Failed/Inconclusive. - ---- - -## Slice 7 — Git publication and review package - -### User outcome - -A verified candidate becomes a real branch/commit/PR with an understandable review package. - -### Backend - -`SourceControl` adapter: - -```text -commit → push → create PR -``` - -Idempotent artifact creation; verify PR head SHA equals verified SHA. - -Generate review package: - -- intent/definition/design; -- slice narrative; -- important diffs; -- screenshots/API evidence; -- checks; -- deviations/risks. - -### Frontend - -Delivery section, PR action, narrative review package. - -### Acceptance - -- no duplicate PR after retry; -- exact verified SHA published; -- PR link survives restart; -- merge remains human-controlled; -- request-changes action returns Work to appropriate state. - -**Milestone:** first useful product. - ---- - -## Slice 8 — Contextual human intervention - -### User outcome - -A blocked agent asks one precise question; the user answers from the Work card; the same Work resumes. - -### Backend - -Durable `Question`/`Decision`; map response to Work/slice/attempt/harness session. - -### Frontend - -Attention card with recommendation, alternatives, consequences; contextual composer. - -### Acceptance - -- answer persists before resume; -- harness restart does not lose decision; -- stale questions cannot mutate newer plan; -- response never creates unrelated thread; -- attention queue orders blockers correctly. - ---- - -## Slice 9 — Multi-slice integration verification - -### User outcome - -Several passing slices are combined and tested as one exact candidate before PR readiness. - -### Backend - -Add `IntegrationActor`/use case: - -```text -compose commits -detect overlap/conflict -rebase/resolve policy -run impacted checks on integrated SHA -``` - -### Frontend - -Integration state, conflict blocker, combined evidence. - -### Acceptance - -- individually passing slices cannot skip combined checks; -- conflicts become explicit blockers; -- integrated SHA is the published SHA; -- failed integration can replan/repair. - ---- - -## Slice 10 — Preview, release, and observation - -### User outcome - -The user can inspect a preview, approve delivery, and see whether the released behavior works. - -### Backend - -Provider-neutral `PreviewRuntime`/release adapter. Add: - -```text -RolloutPlan -RollbackPlan -HealthSignal -ObservationWindow -WorkResult -``` - -### Frontend - -Preview link, release gate, health state, expected-vs-actual result. - -### Acceptance - -- preview binds candidate SHA; -- release requires policy-defined approval; -- observation records actual behavior; -- rollback trigger is explicit for critical work; -- merged PR alone does not mark outcome achieved. - ---- - -## Slice 11 — Learning and knowledge proposals - -### User outcome - -Completed Work produces reviewable improvements to project knowledge and execution policy. - -### Backend - -Synthesize: - -- planning errors; -- missing context; -- useful/failing tools; -- escaped defects; -- Kit/test recommendations. - -Create proposal artifacts, never direct canonical mutation. - -### Frontend - -Diffable learning cards: accept/edit/reject. - -### Acceptance - -- every proposal cites run/evidence; -- rejection is retained; -- accepted update is versioned; -- no autonomous rewrite of canonical docs. - ---- - -## Slice 12 — Dynamic Kit Builder and controlled fleet - -### User outcome - -Zopu selects/composes the right roles, tools, runtime, and checks for different software Work while preserving policy. - -### Backend - -Kit compiler inputs: - -```text -Work Definition + risk + Design Packet + project policy -+ runtime/tool registry + previous results -``` - -Outputs immutable/versioned `ExecutionKit`. - -Add roles only with measurable value: - -```text -investigator implementer verifier security-reviewer -browser-tester integration-coordinator -``` - -### Acceptance - -- Kit is explainable/versioned; -- tool grants are least privilege; -- budgets enforced; -- role addition has evaluation evidence; -- dynamic tools are proposed/reviewed before trust; -- fallback static Kit remains available. - -## Dependency graph - -```text -1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11 → 12 -``` - -Parallel engineering is allowed _within_ a slice after contracts land, but product release order remains sequential. diff --git a/docs/zopu-intelligence-runtime-handoff.md b/docs/zopu-intelligence-runtime-handoff.md index c8c2d4c..5a43720 100644 --- a/docs/zopu-intelligence-runtime-handoff.md +++ b/docs/zopu-intelligence-runtime-handoff.md @@ -205,24 +205,24 @@ Represents the Project-to-AgentOS binding. ```ts interface ProjectRuntime { - projectId: ProjectId - organizationId: OrganizationId - provider: "agentos" - runtimeId?: string - vmId?: string - workspacePath: string - repositoryPath: string + projectId: ProjectId; + organizationId: OrganizationId; + provider: "agentos"; + runtimeId?: string; + vmId?: string; + workspacePath: string; + repositoryPath: string; status: | "requested" | "creating_vm" | "cloning" | "checking_repository" | "ready" - | "failed" - repositoryCommit?: string - lastError?: RuntimeError - createdAt: number - updatedAt: number + | "failed"; + repositoryCommit?: string; + lastError?: RuntimeError; + createdAt: number; + updatedAt: number; } ``` @@ -246,17 +246,17 @@ Maps one Project to one Flue agent instance. ```ts interface ConversationAgentBinding { - id: AgentId - organizationId: OrganizationId - userId: string - projectId: ProjectId - runtimeId: string - globalTimelineId: TimelineId - status: "creating" | "ready" | "busy" | "error" | "disabled" - flueConversationId?: string - lastEventId?: EventId - createdAt: number - updatedAt: number + id: AgentId; + organizationId: OrganizationId; + userId: string; + projectId: ProjectId; + runtimeId: string; + globalTimelineId: TimelineId; + status: "creating" | "ready" | "busy" | "error" | "disabled"; + flueConversationId?: string; + lastEventId?: EventId; + createdAt: number; + updatedAt: number; } ``` @@ -268,20 +268,20 @@ One request to deliver one Event to one agent. ```ts interface AgentDispatch { - id: DispatchId - sourceEventId: EventId - organizationId: OrganizationId - projectId: ProjectId - agentId: AgentId - workId?: WorkId - threadId?: ThreadId - status: "queued" | "sending" | "accepted" | "completed" | "failed" - attempt: number - handlerVersion: number - idempotencyKey: string - lastError?: string - createdAt: number - updatedAt: number + id: DispatchId; + sourceEventId: EventId; + organizationId: OrganizationId; + projectId: ProjectId; + agentId: AgentId; + workId?: WorkId; + threadId?: ThreadId; + status: "queued" | "sending" | "accepted" | "completed" | "failed"; + attempt: number; + handlerVersion: number; + idempotencyKey: string; + lastError?: string; + createdAt: number; + updatedAt: number; } ``` @@ -291,14 +291,14 @@ Represents an execution of a Flue specialist flow beneath a Thread. ```ts interface FlowRun { - id: FlowRunId - flowType: "onboarding_explore" | "explore" | "issue" - flowVersion: number - projectId: ProjectId - workId?: WorkId - threadId?: ThreadId - sourceEventId: EventId - agentId: AgentId + id: FlowRunId; + flowType: "onboarding_explore" | "explore" | "issue"; + flowVersion: number; + projectId: ProjectId; + workId?: WorkId; + threadId?: ThreadId; + sourceEventId: EventId; + agentId: AgentId; status: | "queued" | "running" @@ -306,12 +306,12 @@ interface FlowRun { | "generating_artifact" | "completed" | "failed" - | "cancelled" - state?: unknown - attempt: number - startedAt?: number - finishedAt?: number - updatedAt: number + | "cancelled"; + state?: unknown; + attempt: number; + startedAt?: number; + finishedAt?: number; + updatedAt: number; } ``` @@ -327,17 +327,17 @@ summary.md ```ts interface ProjectContextDocument { - id: ContextDocumentId - projectId: ProjectId - kind: "repository_summary" | "environment_manifest" | "other" - title: string - contentType: "text/markdown" | "application/json" - body?: string - storageId?: string - sourceFlowRunId?: FlowRunId - revision: number - status: "current" | "superseded" | "failed" - createdAt: number + id: ContextDocumentId; + projectId: ProjectId; + kind: "repository_summary" | "environment_manifest" | "other"; + title: string; + contentType: "text/markdown" | "application/json"; + body?: string; + storageId?: string; + sourceFlowRunId?: FlowRunId; + revision: number; + status: "current" | "superseded" | "failed"; + createdAt: number; } ``` @@ -347,20 +347,26 @@ Tracks the generation and publication of a static artifact. ```ts interface ArtifactBuild { - id: ArtifactBuildId - projectId: ProjectId - workId?: WorkId - threadId?: ThreadId - flowRunId: FlowRunId - artifactKind: "project_setup" | "exploration" | "issue" - status: "drafting" | "rendering" | "validating" | "uploading" | "published" | "failed" - sourceManifest?: unknown - outputStorageId?: string - artifactId?: ArtifactId - attempt: number - lastError?: string - createdAt: number - updatedAt: number + id: ArtifactBuildId; + projectId: ProjectId; + workId?: WorkId; + threadId?: ThreadId; + flowRunId: FlowRunId; + artifactKind: "project_setup" | "exploration" | "issue"; + status: + | "drafting" + | "rendering" + | "validating" + | "uploading" + | "published" + | "failed"; + sourceManifest?: unknown; + outputStorageId?: string; + artifactId?: ArtifactId; + attempt: number; + lastError?: string; + createdAt: number; + updatedAt: number; } ``` @@ -382,11 +388,11 @@ Input: ```ts interface CreateProjectInput { - repositoryConnectionId: string - repositoryOwner: string - repositoryName: string - repositoryUrl: string - defaultBranch: string + repositoryConnectionId: string; + repositoryOwner: string; + repositoryName: string; + repositoryUrl: string; + defaultBranch: string; } ``` @@ -418,9 +424,9 @@ Required result: ```ts { - runtimeId: string - vmId: string - workspacePath: string + runtimeId: string; + vmId: string; + workspacePath: string; } ``` @@ -609,14 +615,14 @@ load_source_event ```ts interface ConversationEventInput { - dispatchId: DispatchId - sourceEvent: EventEnvelope - agentId: AgentId - organizationId: OrganizationId - projectId: ProjectId - globalTimelineId: TimelineId - workId?: WorkId - threadId?: ThreadId + dispatchId: DispatchId; + sourceEvent: EventEnvelope; + agentId: AgentId; + organizationId: OrganizationId; + projectId: ProjectId; + globalTimelineId: TimelineId; + workId?: WorkId; + threadId?: ThreadId; } ``` @@ -645,28 +651,28 @@ Suggested tool surface: ```ts interface TimelineTool { postMessage(input: { - text: string - replyToEventId?: EventId - workId?: WorkId - importance?: "normal" | "high" - idempotencyKey: string - }): Promise<{ eventId: EventId }> + text: string; + replyToEventId?: EventId; + workId?: WorkId; + importance?: "normal" | "high"; + idempotencyKey: string; + }): Promise<{ eventId: EventId }>; postUpdate(input: { - text: string - workId: WorkId - threadId?: ThreadId - status?: "working" | "blocked" | "waiting" | "done" - idempotencyKey: string - }): Promise<{ eventId: EventId }> + text: string; + workId: WorkId; + threadId?: ThreadId; + status?: "working" | "blocked" | "waiting" | "done"; + idempotencyKey: string; + }): Promise<{ eventId: EventId }>; publishArtifact(input: { - artifactId: ArtifactId - workId?: WorkId - threadId?: ThreadId - text?: string - idempotencyKey: string - }): Promise<{ eventId: EventId }> + artifactId: ArtifactId; + workId?: WorkId; + threadId?: ThreadId; + text?: string; + idempotencyKey: string; + }): Promise<{ eventId: EventId }>; } ``` @@ -884,12 +890,12 @@ Purpose: ```ts interface OnboardingExploreInput { - projectId: ProjectId - runtimeId: string - repositoryPath: string - repositoryCommit: string - environmentVariableNames: string[] - sourceEventId: EventId + projectId: ProjectId; + runtimeId: string; + repositoryPath: string; + repositoryCommit: string; + environmentVariableNames: string[]; + sourceEventId: EventId; } ``` @@ -964,26 +970,26 @@ frame_question ```ts interface ExplorationResult { - question: string - summary: string + question: string; + summary: string; findings: Array<{ - title: string - detail: string + title: string; + detail: string; evidence: Array<{ - path: string - lineRange?: string - note: string - }> - }> + path: string; + lineRange?: string; + note: string; + }>; + }>; systemMap?: Array<{ - from: string - to: string - relationship: string - }> - risks: string[] - unknowns: string[] - suggestedNextActions: string[] - generatedFiles: string[] + from: string; + to: string; + relationship: string; + }>; + risks: string[]; + unknowns: string[]; + suggestedNextActions: string[]; + generatedFiles: string[]; } ``` @@ -1030,21 +1036,21 @@ understand_request ```ts interface IssueResult { - title: string - summary: string - currentWorld: string - desiredWorld: string - scope: string[] - nonGoals: string[] - acceptanceCriteria: string[] + title: string; + summary: string; + currentWorld: string; + desiredWorld: string; + scope: string[]; + nonGoals: string[]; + acceptanceCriteria: string[]; evidence: Array<{ - path?: string - note: string - }> - risks: string[] - openQuestions: string[] - suggestedImplementationShape?: string[] - generatedFiles: string[] + path?: string; + note: string; + }>; + risks: string[]; + openQuestions: string[]; + suggestedImplementationShape?: string[]; + generatedFiles: string[]; } ``` @@ -1098,30 +1104,30 @@ Every specialist must produce a typed manifest before HTML generation. ```ts interface ArtifactManifest { - kind: "project_setup" | "exploration" | "issue" - title: string - summary: string - projectId: ProjectId - workId?: WorkId - threadId?: ThreadId - flowRunId: FlowRunId - sourceEventIds: EventId[] + kind: "project_setup" | "exploration" | "issue"; + title: string; + summary: string; + projectId: ProjectId; + workId?: WorkId; + threadId?: ThreadId; + flowRunId: FlowRunId; + sourceEventIds: EventId[]; card: { - label: string - facts: Array<{ label: string; value: string }> + label: string; + facts: Array<{ label: string; value: string }>; actions?: Array<{ - id: string - label: string - eventType: "client.action" - style?: "primary" | "secondary" - }> - } - sections: unknown[] + id: string; + label: string; + eventType: "client.action"; + style?: "primary" | "secondary"; + }>; + }; + sections: unknown[]; evidence: Array<{ - path?: string - note: string - }> - generatedFiles: string[] + path?: string; + note: string; + }>; + generatedFiles: string[]; } ``` @@ -1860,4 +1866,3 @@ Repository selected → every meaningful result becomes a polished artifact → Convex publishes the result back into the timeline ``` - diff --git a/docs/zopu-system-handoff-v2.md b/docs/zopu-system-handoff-v2.md index 2dfc633..b62b1f8 100644 --- a/docs/zopu-system-handoff-v2.md +++ b/docs/zopu-system-handoff-v2.md @@ -557,7 +557,7 @@ Use one shared envelope for every event. ```ts export type TimelineScope = | { kind: "global"; organizationId: Id<"organizations"> } - | { kind: "work"; organizationId: Id<"organizations">; workId: Id<"works"> } + | { kind: "work"; organizationId: Id<"organizations">; workId: Id<"works"> }; export type Actor = | { kind: "user"; userId: string } @@ -565,26 +565,26 @@ export type Actor = | { kind: "work"; workId: Id<"works"> } | { kind: "thread"; threadId: Id<"threads"> } | { kind: "tool"; tool: string } - | { kind: "integration"; integration: string } + | { kind: "integration"; integration: string }; export interface EventEnvelope<TType extends string, TPayload> { - type: TType - actor: Actor - scope: TimelineScope - payload: TPayload + type: TType; + actor: Actor; + scope: TimelineScope; + payload: TPayload; - projectId?: Id<"projects"> - workId?: Id<"works"> - threadId?: Id<"threads"> - runId?: string + projectId?: Id<"projects">; + workId?: Id<"works">; + threadId?: Id<"threads">; + runId?: string; - causationId?: Id<"events"> - correlationId: string - replyToEventId?: Id<"events"> - artifactIds?: Id<"artifacts">[] + causationId?: Id<"events">; + correlationId: string; + replyToEventId?: Id<"events">; + artifactIds?: Id<"artifacts">[]; - idempotencyKey?: string - occurredAt: number + idempotencyKey?: string; + occurredAt: number; } ``` @@ -643,10 +643,7 @@ artifact.failed Every event should have a visibility classification: ```ts -type EventVisibility = - | "timeline" - | "compact" - | "internal" +type EventVisibility = "timeline" | "compact" | "internal"; ``` - `timeline`: render as a full timeline item @@ -682,22 +679,22 @@ export type ArtifactKind = | "review" | "verification" | "blocker" - | "report" + | "report"; export interface ArtifactCard { - component: "summary" | "setup" | "plan" | "preview" | "blocker" - label: string - title: string - summary: string - status: "working" | "ready" | "blocked" | "failed" | "superseded" - facts?: Array<{ label: string; value: string }> + component: "summary" | "setup" | "plan" | "preview" | "blocker"; + label: string; + title: string; + summary: string; + status: "working" | "ready" | "blocked" | "failed" | "superseded"; + facts?: Array<{ label: string; value: string }>; actions?: Array<{ - id: string - label: string - style?: "primary" | "secondary" | "danger" - emits: "client.action" - payload?: unknown - }> + id: string; + label: string; + style?: "primary" | "secondary" | "danger"; + emits: "client.action"; + payload?: unknown; + }>; } export type ArtifactContent = @@ -705,7 +702,7 @@ export type ArtifactContent = | { type: "html"; storageId: Id<"_storage">; sandboxed: true } | { type: "file"; storageId: Id<"_storage">; mimeType: string } | { type: "external"; url: string } - | { type: "structured"; schema: string; data: unknown } + | { type: "structured"; schema: string; data: unknown }; ``` Do not initially allow arbitrary generated JavaScript inside timeline cards. @@ -1201,7 +1198,7 @@ const eventRenderers = { "thread.started": CompactSystemEvent, "thread.completed": CompactSystemEvent, "artifact.published": ArtifactMessage, -} +}; ``` Unknown event types must degrade safely to a generic system event during development. @@ -1472,7 +1469,6 @@ Events preserve history. Artifacts communicate results. ``` - --- # CONTINUATION — Intelligence & Delivery Runtime @@ -1681,24 +1677,24 @@ Represents the Project-to-AgentOS binding. ```ts interface ProjectRuntime { - projectId: ProjectId - organizationId: OrganizationId - provider: "agentos" - runtimeId?: string - vmId?: string - workspacePath: string - repositoryPath: string + projectId: ProjectId; + organizationId: OrganizationId; + provider: "agentos"; + runtimeId?: string; + vmId?: string; + workspacePath: string; + repositoryPath: string; status: | "requested" | "creating_vm" | "cloning" | "checking_repository" | "ready" - | "failed" - repositoryCommit?: string - lastError?: RuntimeError - createdAt: number - updatedAt: number + | "failed"; + repositoryCommit?: string; + lastError?: RuntimeError; + createdAt: number; + updatedAt: number; } ``` @@ -1722,17 +1718,17 @@ Maps one Project to one Flue agent instance. ```ts interface ConversationAgentBinding { - id: AgentId - organizationId: OrganizationId - userId: string - projectId: ProjectId - runtimeId: string - globalTimelineId: TimelineId - status: "creating" | "ready" | "busy" | "error" | "disabled" - flueConversationId?: string - lastEventId?: EventId - createdAt: number - updatedAt: number + id: AgentId; + organizationId: OrganizationId; + userId: string; + projectId: ProjectId; + runtimeId: string; + globalTimelineId: TimelineId; + status: "creating" | "ready" | "busy" | "error" | "disabled"; + flueConversationId?: string; + lastEventId?: EventId; + createdAt: number; + updatedAt: number; } ``` @@ -1744,20 +1740,20 @@ One request to deliver one Event to one agent. ```ts interface AgentDispatch { - id: DispatchId - sourceEventId: EventId - organizationId: OrganizationId - projectId: ProjectId - agentId: AgentId - workId?: WorkId - threadId?: ThreadId - status: "queued" | "sending" | "accepted" | "completed" | "failed" - attempt: number - handlerVersion: number - idempotencyKey: string - lastError?: string - createdAt: number - updatedAt: number + id: DispatchId; + sourceEventId: EventId; + organizationId: OrganizationId; + projectId: ProjectId; + agentId: AgentId; + workId?: WorkId; + threadId?: ThreadId; + status: "queued" | "sending" | "accepted" | "completed" | "failed"; + attempt: number; + handlerVersion: number; + idempotencyKey: string; + lastError?: string; + createdAt: number; + updatedAt: number; } ``` @@ -1767,14 +1763,14 @@ Represents an execution of a Flue specialist flow beneath a Thread. ```ts interface FlowRun { - id: FlowRunId - flowType: "onboarding_explore" | "explore" | "issue" - flowVersion: number - projectId: ProjectId - workId?: WorkId - threadId?: ThreadId - sourceEventId: EventId - agentId: AgentId + id: FlowRunId; + flowType: "onboarding_explore" | "explore" | "issue"; + flowVersion: number; + projectId: ProjectId; + workId?: WorkId; + threadId?: ThreadId; + sourceEventId: EventId; + agentId: AgentId; status: | "queued" | "running" @@ -1782,12 +1778,12 @@ interface FlowRun { | "generating_artifact" | "completed" | "failed" - | "cancelled" - state?: unknown - attempt: number - startedAt?: number - finishedAt?: number - updatedAt: number + | "cancelled"; + state?: unknown; + attempt: number; + startedAt?: number; + finishedAt?: number; + updatedAt: number; } ``` @@ -1803,17 +1799,17 @@ summary.md ```ts interface ProjectContextDocument { - id: ContextDocumentId - projectId: ProjectId - kind: "repository_summary" | "environment_manifest" | "other" - title: string - contentType: "text/markdown" | "application/json" - body?: string - storageId?: string - sourceFlowRunId?: FlowRunId - revision: number - status: "current" | "superseded" | "failed" - createdAt: number + id: ContextDocumentId; + projectId: ProjectId; + kind: "repository_summary" | "environment_manifest" | "other"; + title: string; + contentType: "text/markdown" | "application/json"; + body?: string; + storageId?: string; + sourceFlowRunId?: FlowRunId; + revision: number; + status: "current" | "superseded" | "failed"; + createdAt: number; } ``` @@ -1823,20 +1819,26 @@ Tracks the generation and publication of a static artifact. ```ts interface ArtifactBuild { - id: ArtifactBuildId - projectId: ProjectId - workId?: WorkId - threadId?: ThreadId - flowRunId: FlowRunId - artifactKind: "project_setup" | "exploration" | "issue" - status: "drafting" | "rendering" | "validating" | "uploading" | "published" | "failed" - sourceManifest?: unknown - outputStorageId?: string - artifactId?: ArtifactId - attempt: number - lastError?: string - createdAt: number - updatedAt: number + id: ArtifactBuildId; + projectId: ProjectId; + workId?: WorkId; + threadId?: ThreadId; + flowRunId: FlowRunId; + artifactKind: "project_setup" | "exploration" | "issue"; + status: + | "drafting" + | "rendering" + | "validating" + | "uploading" + | "published" + | "failed"; + sourceManifest?: unknown; + outputStorageId?: string; + artifactId?: ArtifactId; + attempt: number; + lastError?: string; + createdAt: number; + updatedAt: number; } ``` @@ -1858,11 +1860,11 @@ Input: ```ts interface CreateProjectInput { - repositoryConnectionId: string - repositoryOwner: string - repositoryName: string - repositoryUrl: string - defaultBranch: string + repositoryConnectionId: string; + repositoryOwner: string; + repositoryName: string; + repositoryUrl: string; + defaultBranch: string; } ``` @@ -1894,9 +1896,9 @@ Required result: ```ts { - runtimeId: string - vmId: string - workspacePath: string + runtimeId: string; + vmId: string; + workspacePath: string; } ``` @@ -2085,14 +2087,14 @@ load_source_event ```ts interface ConversationEventInput { - dispatchId: DispatchId - sourceEvent: EventEnvelope - agentId: AgentId - organizationId: OrganizationId - projectId: ProjectId - globalTimelineId: TimelineId - workId?: WorkId - threadId?: ThreadId + dispatchId: DispatchId; + sourceEvent: EventEnvelope; + agentId: AgentId; + organizationId: OrganizationId; + projectId: ProjectId; + globalTimelineId: TimelineId; + workId?: WorkId; + threadId?: ThreadId; } ``` @@ -2121,28 +2123,28 @@ Suggested tool surface: ```ts interface TimelineTool { postMessage(input: { - text: string - replyToEventId?: EventId - workId?: WorkId - importance?: "normal" | "high" - idempotencyKey: string - }): Promise<{ eventId: EventId }> + text: string; + replyToEventId?: EventId; + workId?: WorkId; + importance?: "normal" | "high"; + idempotencyKey: string; + }): Promise<{ eventId: EventId }>; postUpdate(input: { - text: string - workId: WorkId - threadId?: ThreadId - status?: "working" | "blocked" | "waiting" | "done" - idempotencyKey: string - }): Promise<{ eventId: EventId }> + text: string; + workId: WorkId; + threadId?: ThreadId; + status?: "working" | "blocked" | "waiting" | "done"; + idempotencyKey: string; + }): Promise<{ eventId: EventId }>; publishArtifact(input: { - artifactId: ArtifactId - workId?: WorkId - threadId?: ThreadId - text?: string - idempotencyKey: string - }): Promise<{ eventId: EventId }> + artifactId: ArtifactId; + workId?: WorkId; + threadId?: ThreadId; + text?: string; + idempotencyKey: string; + }): Promise<{ eventId: EventId }>; } ``` @@ -2360,12 +2362,12 @@ Purpose: ```ts interface OnboardingExploreInput { - projectId: ProjectId - runtimeId: string - repositoryPath: string - repositoryCommit: string - environmentVariableNames: string[] - sourceEventId: EventId + projectId: ProjectId; + runtimeId: string; + repositoryPath: string; + repositoryCommit: string; + environmentVariableNames: string[]; + sourceEventId: EventId; } ``` @@ -2440,26 +2442,26 @@ frame_question ```ts interface ExplorationResult { - question: string - summary: string + question: string; + summary: string; findings: Array<{ - title: string - detail: string + title: string; + detail: string; evidence: Array<{ - path: string - lineRange?: string - note: string - }> - }> + path: string; + lineRange?: string; + note: string; + }>; + }>; systemMap?: Array<{ - from: string - to: string - relationship: string - }> - risks: string[] - unknowns: string[] - suggestedNextActions: string[] - generatedFiles: string[] + from: string; + to: string; + relationship: string; + }>; + risks: string[]; + unknowns: string[]; + suggestedNextActions: string[]; + generatedFiles: string[]; } ``` @@ -2506,21 +2508,21 @@ understand_request ```ts interface IssueResult { - title: string - summary: string - currentWorld: string - desiredWorld: string - scope: string[] - nonGoals: string[] - acceptanceCriteria: string[] + title: string; + summary: string; + currentWorld: string; + desiredWorld: string; + scope: string[]; + nonGoals: string[]; + acceptanceCriteria: string[]; evidence: Array<{ - path?: string - note: string - }> - risks: string[] - openQuestions: string[] - suggestedImplementationShape?: string[] - generatedFiles: string[] + path?: string; + note: string; + }>; + risks: string[]; + openQuestions: string[]; + suggestedImplementationShape?: string[]; + generatedFiles: string[]; } ``` @@ -2574,30 +2576,30 @@ Every specialist must produce a typed manifest before HTML generation. ```ts interface ArtifactManifest { - kind: "project_setup" | "exploration" | "issue" - title: string - summary: string - projectId: ProjectId - workId?: WorkId - threadId?: ThreadId - flowRunId: FlowRunId - sourceEventIds: EventId[] + kind: "project_setup" | "exploration" | "issue"; + title: string; + summary: string; + projectId: ProjectId; + workId?: WorkId; + threadId?: ThreadId; + flowRunId: FlowRunId; + sourceEventIds: EventId[]; card: { - label: string - facts: Array<{ label: string; value: string }> + label: string; + facts: Array<{ label: string; value: string }>; actions?: Array<{ - id: string - label: string - eventType: "client.action" - style?: "primary" | "secondary" - }> - } - sections: unknown[] + id: string; + label: string; + eventType: "client.action"; + style?: "primary" | "secondary"; + }>; + }; + sections: unknown[]; evidence: Array<{ - path?: string - note: string - }> - generatedFiles: string[] + path?: string; + note: string; + }>; + generatedFiles: string[]; } ``` @@ -3336,4 +3338,3 @@ Repository selected → every meaningful result becomes a polished artifact → Convex publishes the result back into the timeline ``` - diff --git a/package.json b/package.json index 6742be7..a51b50d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,21 @@ "@types/react": "19.2.17", "@types/node": "22.20.1", "@tailwindcss/postcss": "4.3.3", - "@tailwindcss/vite": "4.3.3" + "@tailwindcss/vite": "4.3.3", + "@flue/runtime": "2.0.1", + "@flue/cli": "2.0.1", + "@flue/vite": "2.0.1", + "@flue/sdk": "2.0.1", + "hono": "4.12.34", + "@hono/node-server": "2.0.3", + "@rivet-dev/agentos": "0.2.15", + "@rivet-dev/agentos-core": "0.2.15", + "@rivet-dev/agentos-flue": "0.2.15", + "rivetkit": "2.3.10", + "@rivetkit/engine-cli": "2.3.10", + "@earendil-works/pi-ai": "0.83.0", + "@agentos-software/common": "0.2.15", + "@agentos-software/git": "0.3.3" } }, "type": "module", diff --git a/packages/agents/flue.config.ts b/packages/agents/flue.config.ts new file mode 100644 index 0000000..ce250a4 --- /dev/null +++ b/packages/agents/flue.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from "@flue/runtime/config"; + +// Flue 2.0 project configuration. +// - target: 'node' builds a long-running Node HTTP server. +// - app: the route map (src/app.ts) — health + private internal routes + agent router. +// - db: file-backed SQLite persistence (src/db.ts) for canonical conversation state. +// - agents: scoped to src/agents/ for the 'use agent' scan. +export default defineConfig({ + agents: "agents/**/*.ts", + app: "src/app.ts", + db: "src/db.ts", + // Custom providers are registered at runtime via setProvider() in app.ts. + // Empty list = register none from the built-in catalog; the Cheaptricks + // provider is wired programmatically. + providers: [], + target: "node", +}); diff --git a/packages/agents/package.json b/packages/agents/package.json new file mode 100644 index 0000000..9afac94 --- /dev/null +++ b/packages/agents/package.json @@ -0,0 +1,39 @@ +{ + "name": "@code/agents", + "version": "0.0.0", + "private": true, + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "check-types": "tsc --noEmit", + "start": "node dist/server.mjs" + }, + "dependencies": { + "@agentos-software/common": "catalog:", + "@agentos-software/git": "catalog:", + "@code/env": "workspace:*", + "@earendil-works/pi-ai": "catalog:", + "@flue/runtime": "catalog:", + "@flue/sdk": "catalog:", + "@hono/node-server": "catalog:", + "@rivet-dev/agentos": "catalog:", + "convex": "catalog:", + "hono": "catalog:", + "rivetkit": "catalog:", + "valibot": "^1.0.0", + "zod": "catalog:" + }, + "devDependencies": { + "@code/config": "workspace:*", + "@flue/cli": "catalog:", + "@flue/vite": "catalog:", + "@types/node": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" + } +} diff --git a/packages/agents/src/adapters/agentos.ts b/packages/agents/src/adapters/agentos.ts new file mode 100644 index 0000000..80eb03e --- /dev/null +++ b/packages/agents/src/adapters/agentos.ts @@ -0,0 +1,469 @@ +import path from "node:path"; + +import { env } from "@code/env/agent"; +import type { CodeExecutionResult } from "@rivet-dev/agentos"; +import { createClient } from "@rivet-dev/agentos/client"; + +import type { registry } from "../runner"; + +// AgentOS adapter: resolves one project workspace actor keyed structurally +// by projectId, and exposes only safe read-oriented operations for the +// onboarding runtime endpoint and the conversation agent's tools. +// +// The adapter talks to the durable AgentOS RivetKit actor registered in this +// same process (src/runner.ts, served in serverless mode via the Hono app). +// It caches only the lightweight actor client, never VM handles — so it +// survives engine restarts and process recycling. Each operation re-resolves +// the actor handle via getOrCreate + resolve, which is stateless and safe +// across lifecycle boundaries. +// +// It does NOT use Pi for onboarding — Pi capability is preserved only for +// later GLM-5.2 work, and this module never invokes it. + +/** + * Repository path inside a project VM. + * All repos clone to /workspace/repo inside the VM. + */ +export const REPO_PATH = "/workspace/repo"; + +export interface ProjectVm { + vmId: string; + workspacePath: string; + repositoryPath: string; +} + +export interface DirListEntry { + name: string; + kind: "file" | "directory" | "symlink"; + size: number; +} + +export interface RepoDescription { + commit: string; + rootEntries: DirListEntry[]; +} + +export interface SearchResult { + path: string; + snippet: string; +} + +// --------------------------------------------------------------------------- +// Safe-command policy for execSafe. +// Only static inspected command names are permitted; shell strings are +// rejected. Arguments are passed as an array (no shell interpolation). +// --------------------------------------------------------------------------- + +const ALLOWED_COMMANDS: ReadonlyMap<string, readonly string[]> = new Map([ + // Git read-only. + [ + "git", + [ + "rev-parse", + "log", + "status", + "ls-files", + "remote", + "branch", + "describe", + "show", + ], + ], + // Text inspection. + ["grep", ["-r", "-rn", "-i", "--include", "-l"]], + ["find", ["-name", "-type", "-maxdepth", "-mindepth"]], + ["wc", ["-l", "-w", "-c"]], + ["head", ["-n", "-c"]], + ["tail", ["-n", "-c"]], + ["cat", []], + ["ls", ["-la", "-l", "-a"]], +]); + +/** + * Validate that a command is statically permitted and that its args are a + * safe list (no shell metacharacters, no strings). This is the only gate + * between the model and process execution. + */ +export const validateSafeCommand = ( + command: string, + args: readonly string[] +): void => { + if (typeof command !== "string" || command.length === 0) { + throw new Error("execSafe requires a non-empty command name"); + } + // Reject anything that looks like a shell string (spaces, pipes, redirects). + if (/\s|[;&|<>`$()]/u.test(command)) { + throw new Error(`execSafe rejects shell expression: ${command}`); + } + // Resolve the command to its base name (no path traversal through /bin/...). + const base = path.basename(command); + const allowedFlags = ALLOWED_COMMANDS.get(base); + if (!allowedFlags) { + throw new Error(`execSafe command not permitted: ${base}`); + } + for (const arg of args) { + if (typeof arg !== "string") { + throw new TypeError("execSafe args must all be strings"); + } + // Reject shell metacharacters in arguments. + if (/[;&|<>`$()]/u.test(arg)) { + throw new Error(`execSafe arg contains shell metacharacters: ${arg}`); + } + // Flags must be in the allowlist (starts with -). Non-flag args (paths, + // patterns, numbers) pass through — they cannot invoke a shell. + if ( + arg.startsWith("-") && + !allowedFlags.includes(arg) && + !arg.startsWith("--include=") + ) { + throw new Error(`execSafe flag not permitted for ${base}: ${arg}`); + } + } +}; + +/** + * Prevent path traversal: resolve a path against the repository root and + * ensure the result stays inside it. Rejects absolute paths escaping the + * root and ../ sequences. + */ +export const safeRepoPath = ( + repoRoot: string, + relativePath: string +): string => { + // Normalize and strip leading slashes so "/etc/passwd" can't escape. + const cleaned = relativePath.replace(/^\/+/u, ""); + const resolved = path.resolve(repoRoot, cleaned); + const normalizedRoot = path.resolve(repoRoot); + if ( + resolved !== normalizedRoot && + !resolved.startsWith(normalizedRoot + path.sep) + ) { + throw new Error( + `Path traversal rejected: ${relativePath} escapes repository root` + ); + } + return resolved; +}; + +// --------------------------------------------------------------------------- +// Actor client. +// +// The client is the only durable handle the adapter caches. Actor (VM) +// handles are resolved per-operation through getOrCreate + resolve, so the +// adapter is stateless with respect to VM lifecycle and survives process +// recycling. +// --------------------------------------------------------------------------- + +/** + * The public actor client surface used by this adapter. The actor handle is + * stateless: every action resolves it against the engine as needed. + */ +interface ProjectWorkspaceClient { + projectWorkspace: { + getOrCreate: ( + key: readonly [projectId: string], + options: { params: { token: string } } + ) => { + resolve: () => Promise<string>; + process: { + execFile: ( + command: string, + args?: readonly string[] + ) => Promise<CodeExecutionResult>; + }; + filesystem: { + exists: (target: string) => Promise<boolean>; + readdirEntries: (target: string) => Promise<readonly DirStatEntry[]>; + readFile: (target: string) => Promise<Uint8Array>; + mkdir: ( + target: string, + options?: { recursive?: boolean } + ) => Promise<void>; + writeFile: ( + target: string, + content: string | Uint8Array + ) => Promise<void>; + }; + }; + }; +} + +/** Entry returned by filesystem.readdirEntries. */ +interface DirStatEntry { + name: string; + isDirectory: boolean; + isSymbolicLink: boolean; + size: number; +} + +/** + * Lazily-created actor client. Cached for the process lifetime; the client + * object is safe to reuse, unlike VM handles which are lifecycle-bound. + */ +let clientCache: ProjectWorkspaceClient | undefined; + +const getClient = (): ProjectWorkspaceClient => { + if (!clientCache) { + clientCache = createClient<typeof registry>({ + disableMetadataLookup: true, + encoding: "cbor", + endpoint: env.RIVET_ENDPOINT, + }) as unknown as ProjectWorkspaceClient; + } + return clientCache; +}; + +/** + * Resolve the durable actor handle for a project. The actor is keyed + * structurally by [projectId] (project ids are globally unique). The handle + * is stateless — it re-resolves across lifecycle boundaries — so it is never + * cached. + */ +const getProjectHandle = (projectId: string) => + getClient().projectWorkspace.getOrCreate([projectId], { + params: { token: env.RIVET_WORKSPACE_TOKEN }, + }); + +/** + * Throw a descriptive Error when an execFile result did not succeed. + * Surfaces the operation, outcome, and available stdout/stderr/error. + */ +const requireExecSuccess = ( + result: CodeExecutionResult, + operation: string +): void => { + if (result.outcome !== "succeeded") { + const detail = [result.stderr, result.stdout, result.error.message] + .filter( + (part): part is string => typeof part === "string" && part.length > 0 + ) + .join(" | "); + throw new Error( + `${operation} failed (outcome=${result.outcome})${detail ? `: ${detail}` : ""}` + ); + } +}; + +/** + * AgentOS owns the actor filesystem. The repository has no host workspace + * projection, so persist its actual in-VM path rather than an invented path. + */ +const workspacePath = (): string => REPO_PATH; + +/** + * Get or create a project workspace VM. Idempotent by projectId — the actor + * is keyed structurally by [projectId] and resolved on demand. + * + * The vmId/runtimeId is the actor's resolved id, which remains stable across + * re-resolution. + */ +export const getOrCreateProjectVm = async ( + projectId: string +): Promise<ProjectVm> => { + const handle = getProjectHandle(projectId); + const vmId = await handle.resolve(); + return { + repositoryPath: REPO_PATH, + vmId, + workspacePath: workspacePath(), + }; +}; + +/** + * Read the current HEAD commit. Used for readability verification and + * ProjectRuntime.repositoryCommit. + */ +export const readRepositoryHead = async ( + projectId: string +): Promise<{ commit: string }> => { + const handle = getProjectHandle(projectId); + const result = await handle.process.execFile("git", [ + "-C", + REPO_PATH, + "rev-parse", + "HEAD", + ]); + requireExecSuccess(result, "git rev-parse HEAD"); + return { commit: (result.stdout ?? "").trim() }; +}; + +/** + * Depth-1 branch clone into the project VM. Idempotent: if the repository + * directory already exists, the clone is skipped (assuming a prior successful + * clone). Credentials are never exposed to the model. + */ +export const cloneRepository = async (input: { + projectId: string; + repositoryUrl: string; + branch: string; +}): Promise<{ commit: string }> => { + const handle = getProjectHandle(input.projectId); + + // Idempotent: skip if repo dir already exists. + const exists = await handle.filesystem.exists(REPO_PATH).catch(() => false); + if (!exists) { + const result = await handle.process.execFile("git", [ + "clone", + "--depth=1", + "--single-branch", + "--branch", + input.branch, + input.repositoryUrl, + REPO_PATH, + ]); + requireExecSuccess(result, "git clone"); + } + + return readRepositoryHead(input.projectId); +}; + +/** + * List files in a directory relative to the repository root. + * Path traversal is prevented by safeRepoPath(). + */ +export const listFiles = async ( + projectId: string, + relativePath: string +): Promise<DirListEntry[]> => { + const handle = getProjectHandle(projectId); + const target = safeRepoPath(REPO_PATH, relativePath); + const entries = await handle.filesystem.readdirEntries(target); + return entries.map((e) => { + let kind: DirListEntry["kind"] = "file"; + if (e.isDirectory) { + kind = "directory"; + } else if (e.isSymbolicLink) { + kind = "symlink"; + } + return { kind, name: e.name, size: e.size }; + }); +}; + +/** + * Verify repository readability: HEAD commit + root listing + read one file. + */ +export const describeRepository = async ( + projectId: string +): Promise<RepoDescription> => { + const { commit } = await readRepositoryHead(projectId); + const entries = await listFiles(projectId, ""); + return { commit, rootEntries: entries }; +}; + +/** + * Read a file relative to the repository root. Path traversal prevented. + */ +export const readFile = async ( + projectId: string, + relativePath: string +): Promise<{ content: string }> => { + const handle = getProjectHandle(projectId); + const target = safeRepoPath(REPO_PATH, relativePath); + const bytes = await handle.filesystem.readFile(target); + return { content: Buffer.from(bytes).toString("utf-8") }; +}; + +/** + * Search repository files using grep. Returns path + snippet matches. + * Zero matches return an empty array rather than throwing. + */ +export const searchRepository = async ( + projectId: string, + query: string +): Promise<{ matches: SearchResult[] }> => { + if (typeof query !== "string" || query.length === 0) { + throw new Error("searchRepository requires a non-empty query string"); + } + // Validate exactly the args we execute. + const args = ["-rn", "--include=*", query, REPO_PATH]; + validateSafeCommand("grep", args); + + const handle = getProjectHandle(projectId); + const result = await handle.process.execFile("grep", args); + if (result.outcome !== "succeeded") { + if (result.exitCode === 1) { + return { matches: [] }; + } + requireExecSuccess(result, "grep repository"); + } + const lines = (result.stdout ?? "").split("\n").filter(Boolean).slice(0, 50); + return { + matches: lines.map((line) => { + const colonIdx = line.indexOf(":"); + const secondColon = line.indexOf(":", colonIdx + 1); + return { + path: line.slice(0, colonIdx), + snippet: line.slice(secondColon + 1, secondColon + 1 + 200), + }; + }), + }; +}; + +/** + * Execute a validated safe command in the project VM. Only statically + * inspected commands / safe argument lists are permitted. + */ +export const execSafe = async ( + projectId: string, + command: string, + args: readonly string[] +): Promise<{ stdout: string; stderr: string }> => { + validateSafeCommand(command, args); + const handle = getProjectHandle(projectId); + const result = await handle.process.execFile(command, [...args]); + requireExecSuccess(result, `execSafe ${command}`); + return { stderr: result.stderr ?? "", stdout: result.stdout ?? "" }; +}; + +/** + * Scan root .env.example for variable names only (values are never stored + * or displayed). Non-blocking: returns empty array if absent. + */ +export const scanEnvExample = async ( + projectId: string +): Promise<{ names: string[] }> => { + const handle = getProjectHandle(projectId); + const envPath = safeRepoPath(REPO_PATH, ".env.example"); + const exists = await handle.filesystem.exists(envPath).catch(() => false); + if (!exists) { + return { names: [] }; + } + const bytes = await handle.filesystem + .readFile(envPath) + .catch(() => new Uint8Array()); + const content = Buffer.from(bytes).toString("utf-8"); + const names: string[] = []; + for (const line of content.split("\n")) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) { + continue; + } + const [rawName] = trimmed.split("="); + const name = rawName?.trim() ?? ""; + if (name && /^[A-Z_][A-Z0-9_]*$/iu.test(name)) { + names.push(name); + } + } + return { names }; +}; + +/** + * Write a generated file under .zopu/artifacts/. This is the only write path + * exposed — it is constrained to the .zopu output directory and never touches + * repository source files. + */ +export const writeArtifactFile = async ( + projectId: string, + buildId: string, + filename: string, + content: string +): Promise<{ path: string }> => { + const handle = getProjectHandle(projectId); + const artifactPath = `/workspace/.zopu/artifacts/${buildId}/${filename}`; + // Ensure parent directory exists. + await handle.filesystem.mkdir(`/workspace/.zopu/artifacts/${buildId}`, { + recursive: true, + }); + await handle.filesystem.writeFile(artifactPath, content); + return { path: artifactPath }; +}; diff --git a/packages/agents/src/adapters/artifact-renderer.ts b/packages/agents/src/adapters/artifact-renderer.ts new file mode 100644 index 0000000..7eaaf64 --- /dev/null +++ b/packages/agents/src/adapters/artifact-renderer.ts @@ -0,0 +1,103 @@ +// Static HTML artifact renderer. +// Takes a typed ArtifactManifest and produces a safe, static HTML page. +// No user-supplied HTML is passed through — all content is escaped and +// rendered through the kit's component templates. + +export interface ArtifactManifestSection { + title: string; + body: string; + items?: string[]; +} + +export interface ArtifactManifest { + kind: string; + title: string; + subtitle?: string; + sections: ArtifactManifestSection[]; + generatedAt: string; + projectName?: string; + repositoryCommit?: string; +} + +/** Escape HTML special characters to prevent injection. */ +const escapeHtml = (text: string): string => + text + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); + +const renderSection = (section: ArtifactManifestSection): string => { + const items = section.items + ? `<ul class="items">${section.items.map((i) => `<li>${escapeHtml(i)}</li>`).join("")}</ul>` + : ""; + return ` <section> + <h2>${escapeHtml(section.title)}</h2> + <p>${escapeHtml(section.body)}</p> + ${items} + </section>`; +}; + +/** + * Render a typed manifest to a polished, static HTML page. + * All content is escaped — the renderer supplies visual quality and safety. + */ +export const renderStaticHtml = (manifest: ArtifactManifest): string => { + const sections = manifest.sections.map(renderSection).join("\n"); + const subtitle = manifest.subtitle + ? `<p class="subtitle">${escapeHtml(manifest.subtitle)}</p>` + : ""; + const meta: string[] = []; + if (manifest.projectName) { + meta.push(`<span>Project: ${escapeHtml(manifest.projectName)}</span>`); + } + if (manifest.repositoryCommit) { + meta.push( + `<span>Commit: <code>${escapeHtml(manifest.repositoryCommit)}</code></span>` + ); + } + const metaHtml = meta.length + ? `<div class="meta">${meta.join(" ")}</div>` + : ""; + + return `<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>${escapeHtml(manifest.title)} + + + +
+
+

${escapeHtml(manifest.title)}

+ ${subtitle} + ${metaHtml} +
+
+${sections} +
+
Generated by Zopu at ${escapeHtml(manifest.generatedAt)}
+
+ +`; +}; diff --git a/packages/agents/src/adapters/convex-service-client.ts b/packages/agents/src/adapters/convex-service-client.ts new file mode 100644 index 0000000..ecb7d10 --- /dev/null +++ b/packages/agents/src/adapters/convex-service-client.ts @@ -0,0 +1,259 @@ +import { env } from "@code/env/agent"; + +/* eslint-disable max-classes-per-file -- service client and its error type form one domain module. */ + +/** + * Service-authenticated Convex client for runtime → Convex callbacks. + * + * The agent's timeline/context tools call through this client to persist agent + * messages, summaries, artifacts, and timeline cards. It POSTs to the + * service-authenticated Convex Site HTTP actions exposed in + * `packages/backend/convex/agentHttp.ts`: + * + * POST /api/agents/events/message + * POST /api/agents/events/artifact + * POST /api/agents/storage/generate-upload-url + * + * These actions carry the FLUE_DB_TOKEN bearer so Convex authenticates the call + * as the intelligence runtime service (not a browser session) and enforce the + * agent→project→organization boundary server-side. The runtime never holds + * database credentials and never calls Convex mutations directly. + */ + +/** + * Shared error type for non-OK responses from Convex service actions. + * The Convex httpActions return `{ error }` with a status of 400/401 on + * validation/auth failures. + */ +class ConvexServiceError extends Error { + readonly status: number; + + constructor(message: string, status: number) { + super(message); + this.name = "ConvexServiceError"; + this.status = status; + } +} + +/** + * Boundary context carried in every runtime → Convex callback. The Convex + * `resolveBoundary` helper validates these against the conversationAgents row. + */ +interface BoundaryInput { + agentId: string; + organizationId: string; + projectId: string; +} + +export class ConvexServiceClient { + private readonly baseUrl: string; + private readonly token: string; + + constructor() { + this.baseUrl = env.CONVEX_SITE_URL.replace(/\/$/u, ""); + this.token = env.FLUE_DB_TOKEN; + } + + /** + * POST an agent-authored message to the global timeline. + * Maps to the Convex `events:appendToolEvent` mutation via the + * `/api/agents/events/message` Site action. Idempotent by idempotencyKey. + */ + async postAgentMessage(input: { + organizationId: string; + projectId: string; + agentId: string; + text: string; + idempotencyKey: string; + correlationId: string; + type: string; + visibility: string; + replyToEventId?: string; + workId?: string; + threadId?: string; + }): Promise<{ eventId: string }> { + const result = await this.postJson("/api/agents/events/message", { + agentId: input.agentId, + correlationId: input.correlationId, + idempotencyKey: input.idempotencyKey, + organizationId: input.organizationId, + projectId: input.projectId, + replyToEventId: input.replyToEventId, + text: input.text, + threadId: input.threadId, + type: input.type, + visibility: input.visibility, + workId: input.workId, + }); + return { eventId: result.eventId as string }; + } + + /** + * Upload rendered HTML (or other bytes) to Convex Storage and return the + * storageId. The flow is: + * 1. POST /api/agents/storage/generate-upload-url → one-time upload URL. + * 2. PUT the bytes as a Blob to the upload URL. + * 3. The Convex-generated storageId is the UUID in the upload URL path. + * + * Returns undefined if the upload could not be completed so the caller can + * still publish an inline-only artifact. + */ + async uploadHtml( + boundary: BoundaryInput, + html: string + ): Promise<{ storageId: string } | undefined> { + // 1. Obtain a one-time upload URL. + const urlResult = await this.postJson( + "/api/agents/storage/generate-upload-url", + { + agentId: boundary.agentId, + organizationId: boundary.organizationId, + projectId: boundary.projectId, + } + ); + const uploadUrl = urlResult.url as string | undefined; + if (!uploadUrl) { + return undefined; + } + + // 2. PUT the bytes as a Blob to the upload URL. + const blob = new Blob([html], { type: "text/html" }); + const uploadResponse = await fetch(uploadUrl, { + body: blob, + method: "POST", + }); + if (!uploadResponse.ok) { + return undefined; + } + + // 3. The Convex-generated storageId is in the upload URL's path + // (/upload/) and is echoed back in the JSON body of the PUT. + const storageId = await uploadResponse + .json() + .then((body) => (body as { storageId?: string }).storageId) + .catch(() => { + /* malformed upload response body — fall through to URL fallback */ + }); + if (storageId) { + return { storageId }; + } + // Fallback: extract the UUID from the upload URL path. + const match = /\/upload\/(?[A-Za-z0-9_-]+)/u.exec(uploadUrl); + return match?.groups?.id ? { storageId: match.groups.id } : undefined; + } + + /** + * Publish a typed artifact revision (with an optional Convex Storage id for + * rendered HTML) and emit the `artifact.published` timeline event. Maps to + * the Convex `artifacts:publishRevision` mutation + `events:appendToolEvent` + * via the `/api/agents/events/artifact` Site action. + * + * Note: the artifact revision requires a `createdByEventId` (the timeline + * event that produced it). The onboarding slice publishes the message event + * first, then uses its eventId here. + */ + async publishArtifact(input: { + organizationId: string; + projectId: string; + agentId: string; + createdByEventId: string; + kind: string; + logicalKey: string; + title: string; + summary: string; + status: string; + card: unknown; + content: unknown; + storageId?: string; + idempotencyKey: string; + correlationId: string; + workId?: string; + threadId?: string; + }): Promise<{ eventId: string; artifactId: string }> { + const result = await this.postJson("/api/agents/events/artifact", { + agentId: input.agentId, + card: input.card, + content: input.content, + correlationId: input.correlationId, + createdByEventId: input.createdByEventId, + idempotencyKey: input.idempotencyKey, + kind: input.kind, + logicalKey: input.logicalKey, + organizationId: input.organizationId, + projectId: input.projectId, + status: input.status, + storageId: input.storageId, + summary: input.summary, + threadId: input.threadId, + title: input.title, + workId: input.workId, + }); + return { + artifactId: result.artifactId as string, + eventId: result.eventId as string, + }; + } + + /** + * Store a project context document (e.g. the onboarding summary). + * Published as an inline artifact revision of kind "summary" so it persists + * durably and is recoverable across agent restarts. + */ + upsertProjectSummary(input: { + organizationId: string; + projectId: string; + agentId: string; + kind: string; + content: string; + correlationId: string; + createdByEventId: string; + idempotencyKey: string; + }): Promise<{ eventId: string; artifactId: string }> { + return this.publishArtifact({ + agentId: input.agentId, + card: { kind: input.kind }, + content: { markdown: input.content }, + correlationId: input.correlationId, + createdByEventId: input.createdByEventId, + idempotencyKey: input.idempotencyKey, + kind: "summary", + logicalKey: `project:${input.projectId}:summary`, + organizationId: input.organizationId, + projectId: input.projectId, + status: "ready", + summary: input.content.slice(0, 160), + title: "Project summary", + }); + } + + /** + * POST JSON to a Convex Site action with the service bearer token. + * Returns the parsed JSON body. Throws ConvexServiceError on non-2xx. + */ + private async postJson( + path: string, + body: Record + ): Promise> { + const response = await fetch(`${this.baseUrl}${path}`, { + body: JSON.stringify(body), + headers: { + authorization: `Bearer ${this.token}`, + "content-type": "application/json", + }, + method: "POST", + }); + if (!response.ok) { + const detail = await response + .json() + .then((b) => (b as { error?: string }).error) + .catch(() => { + /* non-JSON error body — fall through to status fallback */ + }); + throw new ConvexServiceError( + detail ?? `Convex action ${path} returned ${response.status}`, + response.status + ); + } + return (await response.json()) as Record; + } +} diff --git a/packages/agents/src/agents/project-agent.ts b/packages/agents/src/agents/project-agent.ts new file mode 100644 index 0000000..0b18171 --- /dev/null +++ b/packages/agents/src/agents/project-agent.ts @@ -0,0 +1,77 @@ +"use agent"; + +import { useModel, useTool } from "@flue/runtime"; + +import { modelSpecifier } from "../model-config.ts"; +import { projectContextUpdate } from "../tools/project-context.ts"; +import { + sandboxDescribe, + sandboxListFiles, + sandboxReadFile, + sandboxSearch, +} from "../tools/sandbox.ts"; +import { + timelinePostMessage, + timelinePublishArtifact, +} from "../tools/timeline.ts"; + +/** + * ProjectConversationAgent — one project-bound Flue 2.0 conversation agent. + * + * Identity is stable and structural: `conversation:::v1`. + * The agent instance id passed to dispatch() encodes these facts: + * conversation:: + * + * On a `project.ready` signal it: + * 1. Posts one idempotent short acknowledgement. + * 2. Explores the repository via VM read-only tools. + * 3. Stores a concise summary via projectContextUpdate. + * 4. Renders a static setup artifact and publishes it to the timeline. + * + * The agent is read-oriented for the first slice — no autonomous code mutation. + */ +export const ProjectConversationAgent = () => { + useModel(modelSpecifier()); + + // Timeline tools — constrained write surface to Convex (not arbitrary mutations). + useTool(timelinePostMessage); + useTool(timelinePublishArtifact); + + // Project context tools — store durable project knowledge. + useTool(projectContextUpdate); + + // Sandbox tools — read-only repository access through the project VM. + useTool(sandboxDescribe); + useTool(sandboxListFiles); + useTool(sandboxReadFile); + useTool(sandboxSearch); + + return `You are Zopu's project conversation agent — an effective coworker who already understands this project. + +You are bound to exactly one project and its repository workspace VM. You have read-only access to the repository through your tools. + +## Onboarding (project.ready) +When you receive a \`project.ready\` signal: +1. Acknowledge briefly (1-2 sentences) using timelinePostMessage with idempotencyKey "dispatch::message:acknowledge". +2. Use sandboxDescribe to understand the repository structure. +3. Use sandboxListFiles on the root to see the layout. +4. Read key files: README.md, package.json, or equivalent entry documentation. +5. Synthesize a concise summary and store it via projectContextUpdate (kind "summary"). +6. Render a polished setup artifact via timelinePublishArtifact with idempotencyKey "dispatch::message:onboarding-artifact". + +## Style +- Default to 1-3 short sentences per response. +- Be specific and evidence-backed — cite file paths. +- Do not claim code was changed, tested, or shipped when it was not. +- For writing requests: inspect, scope, and explain — do not falsely claim completion. +- Keep internal exploration invisible; post only meaningful results to the timeline. + +## Constraints +- You may NOT mutate repository source files. Output only goes under .zopu/. +- You must NOT expose API keys, credentials, or secrets. +- You must NOT access paths outside the repository root.`; +}; + +// Durable identity — decoupled from the source-level function name so +// minification or renames cannot corrupt conversation storage. +ProjectConversationAgent.agentName = "project-conversation"; diff --git a/packages/agents/src/app.ts b/packages/agents/src/app.ts new file mode 100644 index 0000000..3b6bbaa --- /dev/null +++ b/packages/agents/src/app.ts @@ -0,0 +1,253 @@ +import { env } from "@code/env/agent"; +import { dispatch } from "@flue/runtime"; +import { createAgentRouter } from "@flue/runtime/routing"; +import { Hono } from "hono"; + +import { + cloneRepository, + getOrCreateProjectVm, + describeRepository, + scanEnvExample, +} from "./adapters/agentos.ts"; +import { ProjectConversationAgent } from "./agents/project-agent.ts"; +import { registerModelProvider } from "./model-config.ts"; +import { registry } from "./runner.ts"; + +// Register the Cheaptricks OpenAI-compatible provider before the server +// starts handling requests. The API key is resolved per-request inside the +// provider's auth resolver and is never exposed to model tools. +registerModelProvider(); + +const app = new Hono(); + +// --- Health (unauthenticated liveness) -------------------------------------- +app.get("/health", (c) => c.json({ service: "zopu-agents", status: "ok" })); + +// --- Auth ------------------------------------------------------------------- + +/** Validate the bearer token against FLUE_DB_TOKEN. */ +const requireServiceAuth = (authHeader: string | undefined): boolean => { + if (!authHeader) { + return false; + } + const match = /^Bearer\s+(?.+)$/u.exec(authHeader); + if (!match) { + return false; + } + return match.groups?.token === env.FLUE_DB_TOKEN; +}; + +// --- Internal project-setup endpoint ---------------------------------------- +// +// Called by the Convex `projectSetup.runSetup` coordinator to perform the +// AgentOS VM get-or-create, shallow clone, readability verification, and root +// `.env.example` name-only scan. Returns exactly the coordinator contract. +// +// Convex request body (callSetupEndpoint in projectSetup.ts): +// { branch, projectId, repositoryUrl } +// +// Coordinator-expected response (SetupRuntimeResult): +// { runtimeId?, vmId?, workspacePath?, repositoryPath?, +// repositoryCommit?, environmentVariableNames? } +interface ProjectSetupRequest { + branch: string; + projectId: string; + repositoryUrl: string; +} + +export interface ProjectSetupResult { + runtimeId?: string; + vmId?: string; + workspacePath?: string; + repositoryPath?: string; + repositoryCommit?: string; + environmentVariableNames?: string[]; +} + +/** + * POST /internal/project-setup + * + * Single-call setup coordinator target. Performs: + * 1. Get-or-create the project workspace VM (idempotent by projectId). + * 2. Shallow single-branch clone (idempotent — skips if repo dir exists). + * 3. Verify readability: HEAD commit + root listing + read one file. + * 4. Scan root `.env.example` for variable names only (values never stored). + * + * Never mutates repository source files. The returned object matches the + * Convex `SetupRuntimeResult` wire shape exactly. + */ +app.post("/internal/project-setup", async (c) => { + if (!requireServiceAuth(c.req.header("authorization"))) { + return c.json({ error: "unauthorized" }, 401); + } + + let body: ProjectSetupRequest; + try { + body = (await c.req.json()) as ProjectSetupRequest; + } catch { + return c.json({ error: "invalid JSON body" }, 400); + } + + if ( + typeof body.projectId !== "string" || + body.projectId.length === 0 || + typeof body.repositoryUrl !== "string" || + body.repositoryUrl.length === 0 || + typeof body.branch !== "string" || + body.branch.length === 0 + ) { + return c.json({ error: "invalid project-setup request" }, 400); + } + + try { + const vm = await getOrCreateProjectVm(body.projectId); + + // Shallow clone (idempotent). Credentials are never exposed. + const { commit } = await cloneRepository({ + branch: body.branch, + projectId: body.projectId, + repositoryUrl: body.repositoryUrl, + }); + + // Verify readability: HEAD commit + root listing (throws on failure). + await describeRepository(body.projectId); + + // Scan root .env.example names-only. + const { names } = await scanEnvExample(body.projectId); + + const result: ProjectSetupResult = { + environmentVariableNames: names, + repositoryCommit: commit, + repositoryPath: vm.repositoryPath, + runtimeId: vm.vmId, + vmId: vm.vmId, + workspacePath: vm.workspacePath, + }; + return c.json(result, 200); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return c.json({ detail: message, error: "project-setup failed" }, 500); + } +}); + +// --- Private dispatch endpoint ----------------------------------------------- +// +// Convex calls this with a bearer FLUE_DB_TOKEN to deliver an event to a +// project-bound conversation agent. The endpoint validates the envelope, +// calls Flue dispatch(), and returns 202 Accepted. +// +// Idempotency: the dispatchId is encoded in the signal's idempotencyKey so +// a retried Convex workflow step converges on the original submission. + +export interface DispatchEnvelope { + dispatchId: string; + // The triggering event. Convex sends sourceEventId separately for + // correlation; sourceEvent carries the event type + payload the agent acts on. + sourceEvent: { + type: string; + payload?: unknown; + }; + // The Convex events row id of the source event (e.g. the project.ready id). + // Used for reply correlation; optional because some dispatches may be + // ad-hoc. + sourceEventId?: string; + agentId: string; + organizationId: string; + projectId: string; + // Correlation id tying all setup/dispatch events together. + correlationId?: string; + workId?: string; + threadId?: string; +} + +app.post("/internal/agents/:agentId/events", async (c) => { + // Bearer auth. + if (!requireServiceAuth(c.req.header("authorization"))) { + return c.json({ error: "unauthorized" }, 401); + } + + const routeAgentId = c.req.param("agentId"); + let body: DispatchEnvelope; + try { + body = (await c.req.json()) as DispatchEnvelope; + } catch { + return c.json({ error: "invalid JSON body" }, 400); + } + + // Validate the dispatch envelope. + if ( + typeof body.dispatchId !== "string" || + typeof body.agentId !== "string" || + typeof body.organizationId !== "string" || + typeof body.projectId !== "string" || + !body.sourceEvent || + typeof body.sourceEvent.type !== "string" + ) { + return c.json({ error: "invalid dispatch envelope" }, 400); + } + + // The route agentId must match the envelope agentId. + if (routeAgentId !== body.agentId) { + return c.json({ error: "agentId mismatch" }, 400); + } + + // Build the stable conversation instance id. Must match + // conversationAgents.register: `conversation:::v1`. + // The envelope agentId is already in that form. + const conversationId = body.agentId; + + // Dispatch into Flue as a signal carrying the source event. + // The signal's attributes carry dispatch metadata so the agent's tools + // can resolve project/org/dispatch context during the turn. + try { + await dispatch(ProjectConversationAgent, { + id: conversationId, + idempotencyKey: `event:${body.dispatchId}:agent:${body.agentId}:handler:v1`, + message: { + attributes: { + agentId: body.agentId, + correlationId: body.correlationId ?? "", + dispatchId: body.dispatchId, + organizationId: body.organizationId, + projectId: body.projectId, + sourceEventId: body.sourceEventId ?? "", + threadId: body.threadId ?? "", + workId: body.workId ?? "", + }, + body: JSON.stringify(body.sourceEvent), + kind: "signal", + type: body.sourceEvent.type, + }, + }); + return c.json( + { accepted: true, conversationId, dispatchId: body.dispatchId }, + 202 + ); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return c.json({ detail: message, error: "dispatch failed" }, 500); + } +}); + +// --- Public agent router (protected, optional) ------------------------------- +// Mounted for direct conversation access. Protected by the same bearer auth. +// The dispatch-only path above is the primary entry for Convex → agent. +const agentSubApp = createAgentRouter(ProjectConversationAgent); +const protectedAgent = new Hono(); +protectedAgent.use("*", async (c, next) => { + if (!requireServiceAuth(c.req.header("authorization"))) { + return c.json({ error: "unauthorized" }, 401); + } + return await next(); +}); +protectedAgent.route("/", agentSubApp as unknown as Hono); +app.route("/agents/project-conversation", protectedAgent); + +// --- In-process RivetKit registry (serverless handler) ----------------------- +// +// The AgentOS registry runs in serverless mode inside this same process. +// Mounted on a private path so only internal callers (and the Engine via +// configurePool.url) reach it. registry.handler drives the per-request +// serverless runtime; importing the registry object performs no start. +app.all("/internal/rivet/*", (c) => registry.handler(c.req.raw)); +export default app; diff --git a/packages/agents/src/db.ts b/packages/agents/src/db.ts new file mode 100644 index 0000000..8ef87f0 --- /dev/null +++ b/packages/agents/src/db.ts @@ -0,0 +1,10 @@ +import { sqlite } from "@flue/runtime/node"; + +// Flue 2.0 file-backed SQLite persistence adapter. +// Stores canonical conversation state and accepted submissions for the +// project-bound conversation agent. Application product truth remains Convex. +// +// Default path: /srv/zopu/data/flue/flue.db (overridable via FLUE_DB_PATH). +export default sqlite( + process.env.FLUE_DB_PATH ?? "/srv/zopu/data/flue/flue.db" +); diff --git a/packages/agents/src/index.ts b/packages/agents/src/index.ts new file mode 100644 index 0000000..80e2d5d --- /dev/null +++ b/packages/agents/src/index.ts @@ -0,0 +1,16 @@ +// @code/agents — Zopu Flue 2.0 + Hono + AgentOS intelligence runtime. +// +// The Flue 2.0 Node target generates dist/server.mjs via @flue/vite. That +// generated entry calls startFlueNodeServer(), which loads src/app.ts (the +// Hono route map) and src/db.ts (SQLite persistence) internally. +// +// This package's public exports are the reusable pieces: the conversation +// agent definition and the model configuration utilities. The server entry +// is dist/server.mjs (generated, not hand-authored). +export { ProjectConversationAgent } from "./agents/project-agent.ts"; +export { registerModelProvider, modelSpecifier } from "./model-config.ts"; +export type { + ArtifactManifest, + ArtifactManifestSection, +} from "./adapters/artifact-renderer.ts"; +export type { DispatchEnvelope, ProjectSetupResult } from "./app.ts"; diff --git a/packages/agents/src/model-config.ts b/packages/agents/src/model-config.ts new file mode 100644 index 0000000..1220185 --- /dev/null +++ b/packages/agents/src/model-config.ts @@ -0,0 +1,58 @@ +import { env } from "@code/env/agent"; +import { createProvider } from "@earendil-works/pi-ai"; +import type { Provider } from "@earendil-works/pi-ai"; +import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy"; +import { setProvider } from "@flue/runtime"; + +/** + * Register the Cheaptricks OpenAI-compatible provider with the Flue runtime. + * + * The provider is keyed by env.AGENT_MODEL_PROVIDER (default "cheaptricks"), + * exposing the model named by env.AGENT_MODEL_NAME (default "mimo-v2.5") over + * the OpenAI Completions API against env.AGENT_MODEL_BASE_URL. + * + * The API key is resolved at request time from env.AGENT_MODEL_API_KEY and is + * never exposed to model-facing tools — it lives only in the provider's auth + * resolver, not in agent instructions, tool inputs, or conversation state. + */ +export const registerModelProvider = (): Provider<"openai-completions"> => { + const provider = createProvider({ + api: openAICompletionsApi(), + auth: { + apiKey: { + name: "Cheaptricks API key", + resolve: () => + Promise.resolve({ + auth: { + apiKey: env.AGENT_MODEL_API_KEY, + baseUrl: env.AGENT_MODEL_BASE_URL, + }, + }), + }, + }, + baseUrl: env.AGENT_MODEL_BASE_URL, + id: env.AGENT_MODEL_PROVIDER, + models: [ + { + api: "openai-completions", + baseUrl: env.AGENT_MODEL_BASE_URL, + contextWindow: env.AGENT_MODEL_CONTEXT_WINDOW, + cost: { cacheRead: 0, cacheWrite: 0, input: 0, output: 0 }, + id: env.AGENT_MODEL_NAME, + input: ["text"], + maxTokens: env.AGENT_MODEL_MAX_TOKENS, + name: env.AGENT_MODEL_NAME, + provider: env.AGENT_MODEL_PROVIDER, + reasoning: false, + }, + ], + name: "Cheaptricks", + }); + + setProvider(provider); + return provider; +}; + +/** Full model specifier string for useModel(): provider-id/model-id. */ +export const modelSpecifier = (): string => + `${env.AGENT_MODEL_PROVIDER}/${env.AGENT_MODEL_NAME}`; diff --git a/packages/agents/src/runner.ts b/packages/agents/src/runner.ts new file mode 100644 index 0000000..de16bb3 --- /dev/null +++ b/packages/agents/src/runner.ts @@ -0,0 +1,65 @@ +import git from "@agentos-software/git"; +import { env } from "@code/env/agent"; +import { agentOS, setup } from "@rivet-dev/agentos"; + +/** + * AgentOS registry — owns the durable project workspace actor. + * + * The actor is keyed structurally by [projectId] (project ids are globally + * unique), so each project resolves to one dedicated VM across the process's + * lifetime. The registry runs in serverless runtime mode and is served + * in-process by the Hono app (see app.ts), which mounts + * `registry.handler(c.req.raw)` at `/internal/rivet/*`. There is no + * standalone runner process and no `startAndWait` entry point. + * + * `configurePool.url` is the distinct endpoint the Engine invokes to reach + * this registry handler; it is NOT the Engine control-plane URL (that stays + * `endpoint: env.RIVET_ENDPOINT`). The actor still authenticates every + * connection via `onBeforeConnect` against RIVET_WORKSPACE_TOKEN, so only + * this deployment's adapter can drive the actor. + * + * Software: the actor bundles Git (@agentos-software/git) alongside the + * AgentOS default utilities. defaultSoftware alone is common utilities, not + * Git — without the explicit git entry, clone/rev-parse/grep would fail. + * + * Import-safe: this module exports a pure registry object and performs no + * top-level process start. Importing it (including `import type`) does not + * start a registry. + */ + +// Project workspace actor — one VM per project, with Git + default utilities. +const projectWorkspace = agentOS({ + defaultSoftware: true, + onBeforeConnect: (_context, params) => { + if (params.token !== env.RIVET_WORKSPACE_TOKEN) { + throw new Error("Unauthorized workspace connection"); + } + }, + // Git is required for clone, rev-parse, and read-only repository inspection. + // defaultSoftware provides sh/coreutils/common utilities only. + software: [git], +}); + +// Internal mount path shared by the Hono app route and the registry's +// serverless base path. Both MUST agree — the handler uses this base path to +// route actor/metadata requests, and the app must mount it at the same path. +export const RIVET_SERVERLESS_BASE_PATH = "/internal/rivet"; + +// Registry: the single actor type served by this process, in serverless mode. +// `serverless.basePath` matches the app route mount point; `configurePool.url` +// is the address the Engine calls back into this handler. Importing this +// module does not start the registry — the handler is driven per-request by +// the Hono app. +export const registry = setup({ + configurePool: { + url: env.RIVET_SERVERLESS_ENDPOINT, + }, + endpoint: env.RIVET_ENDPOINT, + logging: { level: "info" }, + serverless: { + basePath: RIVET_SERVERLESS_BASE_PATH, + }, + use: { + projectWorkspace, + }, +}); diff --git a/packages/agents/src/tools/project-context.ts b/packages/agents/src/tools/project-context.ts new file mode 100644 index 0000000..c9c655c --- /dev/null +++ b/packages/agents/src/tools/project-context.ts @@ -0,0 +1,63 @@ +import { defineTool, useDelivery } from "@flue/runtime"; +import * as v from "valibot"; + +import { ConvexServiceClient } from "../adapters/convex-service-client.ts"; + +let client: ConvexServiceClient | null = null; +const getClient = (): ConvexServiceClient => { + if (!client) { + client = new ConvexServiceClient(); + } + return client; +}; + +/** + * projectContextUpdate — store durable project knowledge (summary documents). + * + * Published as an inline artifact revision of kind "summary" via the Convex + * `/api/agents/events/artifact` Site action, so it persists durably in Convex + * and is recoverable across agent restarts. Requires a creation event (the + * current dispatch message) as the `createdByEventId`. + */ +export const projectContextUpdate = defineTool({ + description: + "Store or update a project context document (e.g. the onboarding summary). The document persists in Convex and is recoverable across agent restarts.", + input: v.object({ + content: v.pipe( + v.string(), + v.description("Markdown content of the document") + ), + kind: v.pipe(v.string(), v.description("Document kind, e.g. 'summary'")), + }), + name: "projectContextUpdate", + run: async (ctx) => { + // eslint-disable-next-line react-hooks/rules-of-hooks -- useDelivery is a Flue runtime hook, not a React hook; called inside the tool's run callback per Flue tool contract. + const delivery = useDelivery(); + if (delivery.kind !== "signal") { + throw new Error("projectContextUpdate requires a signal delivery"); + } + const attrs = delivery.attributes ?? {}; + const { organizationId, projectId, agentId, correlationId, sourceEventId } = + attrs; + if ( + !organizationId || + !projectId || + !agentId || + !correlationId || + !sourceEventId + ) { + throw new Error("Delivery context missing source event metadata"); + } + await getClient().upsertProjectSummary({ + agentId, + content: ctx.data.content, + correlationId, + createdByEventId: sourceEventId, + idempotencyKey: `project:${projectId}:summary:${ctx.data.kind}`, + kind: ctx.data.kind, + organizationId, + projectId, + }); + return { output: { stored: true } }; + }, +}); diff --git a/packages/agents/src/tools/sandbox.ts b/packages/agents/src/tools/sandbox.ts new file mode 100644 index 0000000..ad26d5f --- /dev/null +++ b/packages/agents/src/tools/sandbox.ts @@ -0,0 +1,141 @@ +import { defineTool, useDelivery } from "@flue/runtime"; +import * as v from "valibot"; + +import { + describeRepository, + listFiles, + readFile, + searchRepository, +} from "../adapters/agentos.ts"; + +/** + * Sandbox tools — read-only repository access through the project VM. + * These are model-callable Flue tools that operate inside the agent's turn. + * + * Tool input schemas use Valibot (Flue 2.0's schema standard), not Typebox. + * + * The project context (projectId) is extracted from the delivery signal's + * attributes, which carry the dispatch metadata. + */ + +/** Extract dispatch metadata from the current delivery signal. */ +const getDispatchMeta = (): { + projectId: string; + organizationId: string; + agentId: string; + dispatchId: string; + correlationId: string; +} => { + // eslint-disable-next-line react-hooks/rules-of-hooks -- useDelivery is a Flue runtime hook, not a React hook; called inside a tool helper per Flue tool contract. + const delivery = useDelivery(); + if (delivery.kind !== "signal") { + throw new Error("Sandbox tools require a signal delivery"); + } + const attrs = delivery.attributes ?? {}; + const { projectId } = attrs; + const { organizationId } = attrs; + const { agentId } = attrs; + const { dispatchId } = attrs; + const { correlationId } = attrs; + if ( + !projectId || + !organizationId || + !agentId || + !dispatchId || + !correlationId + ) { + throw new Error("No projectId in delivery context"); + } + return { agentId, correlationId, dispatchId, organizationId, projectId }; +}; + +/** sandboxDescribe: report workspace/repo paths and current HEAD commit. */ +export const sandboxDescribe = defineTool({ + description: + "Describe the project repository workspace: paths and current HEAD commit. Call this first when exploring a repository.", + input: v.object({}), + name: "sandboxDescribe", + run: async () => { + const { projectId } = getDispatchMeta(); + const desc = await describeRepository(projectId); + const rootEntries = desc.rootEntries.map((e) => ({ + kind: e.kind, + name: e.name, + size: e.size, + })); + return { + output: { + commit: desc.commit, + repositoryPath: "/workspace/repo", + rootEntries, + }, + }; + }, +}); + +/** sandboxListFiles: list directory entries relative to repo root. */ +export const sandboxListFiles = defineTool({ + description: + "List files and directories at a path relative to the repository root.", + input: v.object({ + path: v.pipe( + v.string(), + v.description( + "Directory path relative to repository root (use '' for root)" + ) + ), + }), + name: "sandboxListFiles", + run: async (ctx) => { + const { projectId } = getDispatchMeta(); + const result = await listFiles(projectId, ctx.data.path); + const entries = result.map((e) => ({ + kind: e.kind, + name: e.name, + size: e.size, + })); + return { output: { entries } }; + }, +}); + +/** sandboxReadFile: read a file's content relative to repo root. */ +export const sandboxReadFile = defineTool({ + description: + "Read the text content of a file at a path relative to the repository root.", + input: v.object({ + path: v.pipe( + v.string(), + v.description("File path relative to repository root") + ), + }), + name: "sandboxReadFile", + run: async (ctx) => { + const { projectId } = getDispatchMeta(); + const result = await readFile(projectId, ctx.data.path); + // Truncate very large files to keep context bounded. + const content = + result.content.length > 50_000 + ? `${result.content.slice(0, 50_000)}\n...[truncated]` + : result.content; + return { output: { content } }; + }, +}); + +/** sandboxSearch: search repository for a text query. */ +export const sandboxSearch = defineTool({ + description: + "Search the repository for a text query. Returns matching file paths and snippets.", + input: v.object({ + query: v.pipe(v.string(), v.description("Search query (text or pattern)")), + }), + name: "sandboxSearch", + run: async (ctx) => { + const { projectId } = getDispatchMeta(); + const result = await searchRepository(projectId, ctx.data.query); + const matches = result.matches.map((m) => ({ + path: m.path, + snippet: m.snippet, + })); + return { output: { matches } }; + }, +}); diff --git a/packages/agents/src/tools/timeline.ts b/packages/agents/src/tools/timeline.ts new file mode 100644 index 0000000..d1778dc --- /dev/null +++ b/packages/agents/src/tools/timeline.ts @@ -0,0 +1,185 @@ +import { defineTool, useDelivery } from "@flue/runtime"; +import * as v from "valibot"; + +import { renderStaticHtml } from "../adapters/artifact-renderer.ts"; +import { ConvexServiceClient } from "../adapters/convex-service-client.ts"; + +let client: ConvexServiceClient | null = null; +const getClient = (): ConvexServiceClient => { + if (!client) { + client = new ConvexServiceClient(); + } + return client; +}; + +/** Extract dispatch/project context from the current delivery signal. */ +const getDispatchContext = (): { + dispatchId: string; + correlationId: string; + organizationId: string; + projectId: string; + agentId: string; + sourceEventId: string; +} => { + // eslint-disable-next-line react-hooks/rules-of-hooks -- useDelivery is a Flue runtime hook, not a React hook; called inside a tool helper per Flue tool contract. + const delivery = useDelivery(); + if (delivery.kind !== "signal") { + throw new Error("Timeline tools require a signal delivery"); + } + const attrs = delivery.attributes ?? {}; + const { dispatchId } = attrs; + const { correlationId } = attrs; + const { organizationId } = attrs; + const { projectId } = attrs; + const { agentId } = attrs; + const { sourceEventId } = attrs; + if ( + !dispatchId || + !correlationId || + !organizationId || + !projectId || + !agentId || + !sourceEventId + ) { + throw new Error("Delivery context missing source event metadata"); + } + return { + agentId, + correlationId, + dispatchId, + organizationId, + projectId, + sourceEventId, + }; +}; + +/** + * timelinePostMessage — post an agent-authored message to the global timeline. + * The message is idempotent by the provided idempotencyKey; a retry with the + * same key converges on the original event. + * + * Posts through the Convex `/api/agents/events/message` Site action, which + * enforces the agent→project→organization boundary and exact-once semantics. + */ +export const timelinePostMessage = defineTool({ + description: + "Post a short message to the project timeline. Use for acknowledgements and brief responses (1-3 sentences). Provide a unique idempotencyKey.", + input: v.object({ + idempotencyKey: v.pipe( + v.string(), + v.description("Stable idempotency key for this message") + ), + importance: v.optional( + v.pipe( + v.union([v.literal("normal"), v.literal("high")]), + v.description("Message importance level (default: normal)") + ) + ), + text: v.pipe( + v.string(), + v.description("The message text to post (1-3 sentences)") + ), + }), + name: "timelinePostMessage", + run: async (ctx) => { + const { correlationId, organizationId, projectId, agentId, sourceEventId } = + getDispatchContext(); + const result = await getClient().postAgentMessage({ + agentId, + correlationId, + idempotencyKey: ctx.data.idempotencyKey, + organizationId, + projectId, + replyToEventId: sourceEventId, + text: ctx.data.text, + type: "agent.message", + visibility: "timeline", + }); + return { output: { eventId: result.eventId } }; + }, +}); + +/** + * timelinePublishArtifact — render and publish a static setup artifact. + * + * Two-step flow matching the Convex artifact contract: + * 1. Post an acknowledgement/creation message (the `createdByEventId`) so the + * artifact revision is tied to a timeline event. + * 2. Render safe static HTML, upload it to Convex Storage, and publish the + * artifact revision referencing the uploaded storageId. + * + * The artifact is idempotent by logicalKey + version (server-side) and the + * event is exact-once by idempotencyKey. + */ +export const timelinePublishArtifact = defineTool({ + description: + "Render a project setup artifact from structured sections and publish it to the timeline. Provide title, subtitle, and content sections.", + input: v.object({ + idempotencyKey: v.pipe( + v.string(), + v.description("Stable idempotency key for this artifact") + ), + sections: v.array( + v.object({ + body: v.string(), + items: v.optional(v.array(v.string())), + title: v.string(), + }) + ), + subtitle: v.optional( + v.pipe(v.string(), v.description("Artifact subtitle")) + ), + title: v.pipe(v.string(), v.description("Artifact title")), + }), + name: "timelinePublishArtifact", + run: async (ctx) => { + const { correlationId, organizationId, projectId, agentId } = + getDispatchContext(); + + // Step 1: create the timeline event that the artifact revision is tied to. + const createdBy = await getClient().postAgentMessage({ + agentId, + correlationId, + idempotencyKey: `${ctx.data.idempotencyKey}:create`, + organizationId, + projectId, + text: `Published artifact: ${ctx.data.title}`, + type: "artifact.created", + visibility: "compact", + }); + + // Step 2: render + upload + publish the artifact revision. + const manifest = { + generatedAt: new Date().toISOString(), + kind: "project_setup", + sections: ctx.data.sections, + subtitle: ctx.data.subtitle, + title: ctx.data.title, + }; + const html = renderStaticHtml(manifest); + const boundary = { agentId, organizationId, projectId }; + const uploaded = await getClient().uploadHtml(boundary, html); + const result = await getClient().publishArtifact({ + agentId, + card: { + sections: ctx.data.sections, + subtitle: ctx.data.subtitle, + }, + content: { manifest }, + correlationId, + createdByEventId: createdBy.eventId, + idempotencyKey: ctx.data.idempotencyKey, + kind: "project_setup", + logicalKey: `project:${projectId}:setup`, + organizationId, + projectId, + status: "ready", + storageId: uploaded?.storageId, + summary: ctx.data.subtitle ?? ctx.data.title, + title: ctx.data.title, + }); + return { + output: { artifactId: result.artifactId, eventId: result.eventId }, + }; + }, +}); diff --git a/packages/agents/tsconfig.json b/packages/agents/tsconfig.json new file mode 100644 index 0000000..dab03bd --- /dev/null +++ b/packages/agents/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@code/config/tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "allowImportingTsExtensions": true, + "noEmit": true, + "types": ["node"] + }, + "include": ["src/**/*.ts", "*.d.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/agents/vite.config.ts b/packages/agents/vite.config.ts new file mode 100644 index 0000000..fe928f2 --- /dev/null +++ b/packages/agents/vite.config.ts @@ -0,0 +1,22 @@ +import { flue } from "@flue/vite"; +import { defineConfig } from "vite"; + +// Flue 2.0 Node target. @flue/vite auto-discovers flue.config.ts, scans +// 'use agent' modules, and builds dist/server.mjs. The built server listens +// on 127.0.0.1:3000 (Caddy terminates TLS upstream at agents.zopu.puter.wtf). +export default defineConfig({ + plugins: [ + ...flue({ + providers: [], + target: "node", + }), + ], + preview: { + host: process.env.HOST ?? "127.0.0.1", + port: Number(process.env.PORT ?? 3000), + }, + server: { + host: process.env.HOST ?? "127.0.0.1", + port: Number(process.env.PORT ?? 3000), + }, +}); diff --git a/packages/backend/convex/_generated/api.d.ts b/packages/backend/convex/_generated/api.d.ts index 1a8357e..1c3840f 100644 --- a/packages/backend/convex/_generated/api.d.ts +++ b/packages/backend/convex/_generated/api.d.ts @@ -8,10 +8,17 @@ * @module */ +import type * as agentDispatches from "../agentDispatches.js"; +import type * as agentHttp from "../agentHttp.js"; +import type * as artifactBuilds from "../artifactBuilds.js"; +import type * as artifacts from "../artifacts.js"; import type * as auth from "../auth.js"; import type * as authz from "../authz.js"; import type * as cleanup from "../cleanup.js"; +import type * as conversationAgents from "../conversationAgents.js"; import type * as crons from "../crons.js"; +import type * as events from "../events.js"; +import type * as flowRuns from "../flowRuns.js"; import type * as gitConnectionData from "../gitConnectionData.js"; import type * as gitConnectionHealth from "../gitConnectionHealth.js"; import type * as gitConnections from "../gitConnections.js"; @@ -21,8 +28,14 @@ import type * as healthCheck from "../healthCheck.js"; import type * as http from "../http.js"; import type * as organizations from "../organizations.js"; import type * as privateData from "../privateData.js"; +import type * as projectEnvironmentVariables from "../projectEnvironmentVariables.js"; +import type * as projectRuntimes from "../projectRuntimes.js"; +import type * as projectSetup from "../projectSetup.js"; +import type * as projectSetupQueries from "../projectSetupQueries.js"; import type * as projects from "../projects.js"; import type * as publicGit from "../publicGit.js"; +import type * as timeline from "../timeline.js"; +import type * as works from "../works.js"; import type { ApiFromModules, @@ -31,10 +44,17 @@ import type { } from "convex/server"; declare const fullApi: ApiFromModules<{ + agentDispatches: typeof agentDispatches; + agentHttp: typeof agentHttp; + artifactBuilds: typeof artifactBuilds; + artifacts: typeof artifacts; auth: typeof auth; authz: typeof authz; cleanup: typeof cleanup; + conversationAgents: typeof conversationAgents; crons: typeof crons; + events: typeof events; + flowRuns: typeof flowRuns; gitConnectionData: typeof gitConnectionData; gitConnectionHealth: typeof gitConnectionHealth; gitConnections: typeof gitConnections; @@ -44,8 +64,14 @@ declare const fullApi: ApiFromModules<{ http: typeof http; organizations: typeof organizations; privateData: typeof privateData; + projectEnvironmentVariables: typeof projectEnvironmentVariables; + projectRuntimes: typeof projectRuntimes; + projectSetup: typeof projectSetup; + projectSetupQueries: typeof projectSetupQueries; projects: typeof projects; publicGit: typeof publicGit; + timeline: typeof timeline; + works: typeof works; }>; /** diff --git a/packages/backend/convex/_generated/server.d.ts b/packages/backend/convex/_generated/server.d.ts index bc6ac21..3e784d6 100644 --- a/packages/backend/convex/_generated/server.d.ts +++ b/packages/backend/convex/_generated/server.d.ts @@ -25,6 +25,9 @@ import type { DataModel } from "./dataModel.js"; * Typesafe environment variables declared in `convex.config.ts`. */ type Env = { + readonly AGENT_BACKEND_URL: string | undefined; + readonly FLUE_DB_TOKEN: string | undefined; + readonly FLUE_URL: string | undefined; readonly GITEA_TOKEN: string | undefined; readonly GITEA_URL: string | undefined; readonly GITEA_WEBHOOK_SECRET: string | undefined; diff --git a/packages/backend/convex/agentDispatches.ts b/packages/backend/convex/agentDispatches.ts new file mode 100644 index 0000000..db400dc --- /dev/null +++ b/packages/backend/convex/agentDispatches.ts @@ -0,0 +1,184 @@ +import { ConvexError, v } from "convex/values"; + +import type { Doc } from "./_generated/dataModel"; +import { internalMutation, internalQuery } from "./_generated/server"; + +const dispatchStatus = v.union( + v.literal("pending"), + v.literal("sending"), + v.literal("accepted"), + v.literal("completed"), + v.literal("failed") +); + +/** + * The handler-version stamp every dispatch carries. Bumped only when the + * handler contract changes; encoded into the idempotency key so a new version + * is a fresh dispatch rather than a duplicate of the old one. + */ +export const HANDLER_VERSION = "v1"; + +/** + * Create an AgentDispatch row keyed idempotently by + * `event::agent::handler:`. Retries reuse the + * existing pending/sending dispatch rather than duplicating deliveries. + * Returns `{ dispatchId, created }` so callers can decide whether to send. + */ +export const create = internalMutation({ + args: { + agentId: v.string(), + idempotencyKey: v.string(), + organizationId: v.id("organizations"), + projectId: v.optional(v.id("projects")), + sourceEventId: v.id("events"), + threadId: v.optional(v.id("threads")), + workId: v.optional(v.id("works")), + }, + handler: async ( + ctx, + args + ): Promise<{ created: boolean; dispatch: Doc<"agentDispatches"> }> => { + const existing = await ctx.db + .query("agentDispatches") + .withIndex("by_organizationId_and_source_event_handler", (q) => + q + .eq("organizationId", args.organizationId) + .eq("sourceEventId", args.sourceEventId) + .eq("agentId", args.agentId) + .eq("handlerVersion", HANDLER_VERSION) + ) + .unique(); + if (existing) { + return { created: false, dispatch: existing }; + } + const timestamp = Date.now(); + const dispatchId = await ctx.db.insert("agentDispatches", { + agentId: args.agentId, + attempt: 1, + createdAt: timestamp, + handlerVersion: HANDLER_VERSION, + idempotencyKey: args.idempotencyKey, + organizationId: args.organizationId, + projectId: args.projectId, + sourceEventId: args.sourceEventId, + status: "pending", + threadId: args.threadId, + updatedAt: timestamp, + workId: args.workId, + }); + const dispatch = await ctx.db.get(dispatchId); + if (!dispatch) { + throw new ConvexError("Agent dispatch could not be read after insert"); + } + return { created: true, dispatch }; + }, +}); + +/** + * Transition a dispatch toward sending. Idempotent: a dispatch already accepted + * or completed is not rewound back to sending on retry. + */ +export const markSending = internalMutation({ + args: { dispatchId: v.id("agentDispatches") }, + handler: async (ctx, args): Promise> => { + const dispatch = await ctx.db.get(args.dispatchId); + if (!dispatch) { + throw new ConvexError("Agent dispatch not found"); + } + if (dispatch.status === "accepted" || dispatch.status === "completed") { + return dispatch; + } + await ctx.db.patch(args.dispatchId, { + status: "sending", + updatedAt: Date.now(), + }); + const updated = await ctx.db.get(args.dispatchId); + if (!updated) { + throw new ConvexError("Agent dispatch could not be read after update"); + } + return updated; + }, +}); + +export const markAccepted = internalMutation({ + args: { dispatchId: v.id("agentDispatches") }, + handler: async (ctx, args): Promise> => { + const dispatch = await ctx.db.get(args.dispatchId); + if (!dispatch) { + throw new ConvexError("Agent dispatch not found"); + } + // Completed is terminal; do not rewind to accepted. + if (dispatch.status === "completed") { + return dispatch; + } + await ctx.db.patch(args.dispatchId, { + status: "accepted", + updatedAt: Date.now(), + }); + const updated = await ctx.db.get(args.dispatchId); + if (!updated) { + throw new ConvexError("Agent dispatch could not be read after update"); + } + return updated; + }, +}); + +export const markCompleted = internalMutation({ + args: { dispatchId: v.id("agentDispatches") }, + handler: async (ctx, args): Promise> => { + const dispatch = await ctx.db.get(args.dispatchId); + if (!dispatch) { + throw new ConvexError("Agent dispatch not found"); + } + if (dispatch.status === "completed") { + return dispatch; + } + await ctx.db.patch(args.dispatchId, { + status: "completed", + updatedAt: Date.now(), + }); + const updated = await ctx.db.get(args.dispatchId); + if (!updated) { + throw new ConvexError("Agent dispatch could not be read after update"); + } + return updated; + }, +}); + +export const markFailed = internalMutation({ + args: { + dispatchId: v.id("agentDispatches"), + error: v.string(), + retry: v.boolean(), + }, + handler: async (ctx, args): Promise> => { + const dispatch = await ctx.db.get(args.dispatchId); + if (!dispatch) { + throw new ConvexError("Agent dispatch not found"); + } + // Completed is terminal; a late failure after completion is ignored. + if (dispatch.status === "completed") { + return dispatch; + } + const nextAttempt = args.retry ? dispatch.attempt + 1 : dispatch.attempt; + await ctx.db.patch(args.dispatchId, { + attempt: nextAttempt, + lastError: args.error, + status: args.retry ? "pending" : "failed", + updatedAt: Date.now(), + }); + const updated = await ctx.db.get(args.dispatchId); + if (!updated) { + throw new ConvexError("Agent dispatch could not be read after update"); + } + return updated; + }, +}); + +export const get = internalQuery({ + args: { dispatchId: v.id("agentDispatches") }, + handler: async (ctx, args): Promise | null> => + await ctx.db.get(args.dispatchId), +}); + +export { dispatchStatus }; diff --git a/packages/backend/convex/agentHttp.ts b/packages/backend/convex/agentHttp.ts new file mode 100644 index 0000000..35c78b6 --- /dev/null +++ b/packages/backend/convex/agentHttp.ts @@ -0,0 +1,291 @@ +import { env } from "@code/env/convex"; +import { makeFunctionReference } from "convex/server"; +import { ConvexError } from "convex/values"; + +import type { Id } from "./_generated/dataModel"; +import { httpAction } from "./_generated/server"; +import type { ActionCtx } from "./_generated/server"; +// never call Convex mutations directly; they POST to these HTTP endpoints and +// we run the validated mutations server-side. +const appendToolEventRef = makeFunctionReference< + "mutation", + { + actorTool: string; + artifactIds?: Id<"artifacts">[]; + correlationId: string; + idempotencyKey: string; + organizationId: Id<"organizations">; + payload: unknown; + projectId?: Id<"projects">; + replyToEventId?: Id<"events">; + scopeKind: "global" | "work"; + threadId?: Id<"threads">; + type: string; + visibility: "timeline" | "compact" | "internal"; + workId?: Id<"works">; + }, + Id<"events"> +>("events:appendToolEvent"); +const publishRevisionRef = makeFunctionReference< + "mutation", + { + card: unknown; + content: unknown; + createdByEventId: Id<"events">; + kind: string; + logicalKey: string; + organizationId: Id<"organizations">; + projectId?: Id<"projects">; + status: string; + storageId?: Id<"_storage">; + summary: string; + threadId?: Id<"threads">; + title: string; + workId?: Id<"works">; + }, + { _id: Id<"artifacts">; _creationTime: number } +>("artifacts:publishRevision"); +const getAgentForProjectRef = makeFunctionReference< + "query", + { projectId: Id<"projects"> }, + { + _id: Id<"conversationAgents">; + id: string; + organizationId: Id<"organizations">; + projectId: Id<"projects">; + } | null +>("conversationAgents:getForProject"); + +/** + * Validate the `Authorization: Bearer ` header. Returns the + * token on success; throws a ConvexError (mapped to 401 by the httpAction). + */ +const requireServiceToken = (request: Request): string => { + if (!env.FLUE_DB_TOKEN) { + throw new ConvexError("FLUE_DB_TOKEN is not configured"); + } + const header = request.headers.get("authorization") ?? ""; + if (!header.startsWith("Bearer ")) { + throw new ConvexError("Missing bearer token"); + } + const token = header.slice("Bearer ".length).trim(); + if (token.length === 0 || token !== env.FLUE_DB_TOKEN) { + throw new ConvexError("Invalid service token"); + } + return token; +}; + +interface BoundaryContext { + agentId: string; + organizationId: Id<"organizations">; + projectId: Id<"projects">; +} + +/** Shape returned by the conversationAgents:getForProject internal query. */ +interface AgentRow { + _id: Id<"conversationAgents">; + id: string; + organizationId: Id<"organizations">; + projectId: Id<"projects">; +} + +/** + * Enforce the agent -> project -> organization boundary. The caller asserts an + * `agentId` of the form `conversation:::v1`; we verify the + * conversationAgents row exists for that project and belongs to the claimed + * organization. This prevents a project-A agent from writing into project-B. + */ +const resolveBoundary = async ( + ctx: ActionCtx, + body: { agentId?: unknown; organizationId?: unknown; projectId?: unknown } +): Promise => { + if (typeof body.agentId !== "string" || body.agentId.length === 0) { + throw new ConvexError("agentId is required"); + } + if (typeof body.projectId !== "string") { + throw new ConvexError("projectId is required"); + } + if (typeof body.organizationId !== "string") { + throw new ConvexError("organizationId is required"); + } + const projectId = body.projectId as Id<"projects">; + const organizationId = body.organizationId as Id<"organizations">; + const agent = (await ctx.runQuery(getAgentForProjectRef, { + projectId, + })) as AgentRow | null; + if ( + !agent || + agent.id !== body.agentId || + agent.organizationId !== organizationId + ) { + throw new ConvexError("Agent is not bound to this project/organization"); + } + return { agentId: body.agentId, organizationId, projectId }; +}; + +const json = (status: number, payload: unknown): Response => + Response.json(payload, { status }); + +const asString = (value: unknown, field: string): string => { + if (typeof value !== "string" || value.length === 0) { + throw new ConvexError(`${field} is required`); + } + return value; +}; + +const asOptionalId = (value: unknown): string | undefined => { + if (typeof value !== "string" || value.length === 0) { + return undefined; + } + return value; +}; + +/** + * POST /api/agents/events/message + * + * Service-authenticated endpoint for a project conversation agent to append a + * timeline event (an assistant message, acknowledgement, etc.). Enforces the + * agent->project->organization boundary and exact-once semantics via the + * supplied idempotency key. + * + * Body: { + * agentId, organizationId, projectId, + * text, type, visibility, idempotencyKey, correlationId, + * replyToEventId?, workId?, threadId? + * } + */ +export const postAgentMessage = httpAction(async (ctx, request) => { + try { + requireServiceToken(request); + const body = (await request.json()) as Record; + const boundary = await resolveBoundary(ctx, body); + const text = asString(body.text, "text"); + const type = asString(body.type, "type"); + const visibility = asString(body.visibility, "visibility"); + const idempotencyKey = asString(body.idempotencyKey, "idempotencyKey"); + const correlationId = asString(body.correlationId, "correlationId"); + if (!["timeline", "compact", "internal"].includes(visibility)) { + return json(400, { error: "Invalid visibility" }); + } + const eventId = (await ctx.runMutation(appendToolEventRef, { + actorTool: boundary.agentId, + artifactIds: undefined, + correlationId, + idempotencyKey, + organizationId: boundary.organizationId, + payload: { text }, + projectId: boundary.projectId, + replyToEventId: asOptionalId(body.replyToEventId) as + | Id<"events"> + | undefined, + scopeKind: "global", + threadId: asOptionalId(body.threadId) as Id<"threads"> | undefined, + type, + visibility: visibility as "timeline" | "compact" | "internal", + workId: asOptionalId(body.workId) as Id<"works"> | undefined, + })) as Id<"events">; + return json(200, { eventId }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + const status = message.startsWith("Unauthorized") ? 401 : 400; + return json(status, { error: message }); + } +}); + +/** + * POST /api/agents/events/artifact + * + * Service-authenticated endpoint for a project conversation agent to publish a + * typed artifact revision (with an optional Convex Storage id) and emit the + * `artifact.published` event referencing it. Enforces the boundary and is + * idempotent through the artifact's logicalKey+version and the event key. + * + * Body: { + * agentId, organizationId, projectId, + * createdByEventId, kind, logicalKey, title, summary, status, + * card, content, storageId?, idempotencyKey, correlationId, + * workId?, threadId? + * } + */ +export const publishAgentArtifact = httpAction(async (ctx, request) => { + try { + requireServiceToken(request); + const body = (await request.json()) as Record; + const boundary = await resolveBoundary(ctx, body); + const createdByEventId = asString( + body.createdByEventId, + "createdByEventId" + ) as Id<"events">; + const kind = asString(body.kind, "kind"); + const logicalKey = asString(body.logicalKey, "logicalKey"); + const title = asString(body.title, "title"); + const summary = asString(body.summary, "summary"); + const status = asString(body.status, "status"); + const idempotencyKey = asString(body.idempotencyKey, "idempotencyKey"); + const correlationId = asString(body.correlationId, "correlationId"); + const card = body.card ?? {}; + const content = body.content ?? {}; + + const artifact = (await ctx.runMutation(publishRevisionRef, { + card, + content, + createdByEventId, + kind, + logicalKey, + organizationId: boundary.organizationId, + projectId: boundary.projectId, + status, + storageId: asOptionalId(body.storageId) as Id<"_storage"> | undefined, + summary, + threadId: asOptionalId(body.threadId) as Id<"threads"> | undefined, + title, + workId: asOptionalId(body.workId) as Id<"works"> | undefined, + })) as { _id: Id<"artifacts"> }; + + // Emit the artifact.published timeline event (exact-once). + const eventId = (await ctx.runMutation(appendToolEventRef, { + actorTool: boundary.agentId, + artifactIds: [artifact._id], + correlationId, + idempotencyKey: `${idempotencyKey}:event`, + organizationId: boundary.organizationId, + payload: { artifactId: artifact._id, title }, + projectId: boundary.projectId, + scopeKind: "global", + threadId: asOptionalId(body.threadId) as Id<"threads"> | undefined, + type: "artifact.published", + visibility: "timeline", + workId: asOptionalId(body.workId) as Id<"works"> | undefined, + })) as Id<"events">; + + return json(200, { artifactId: artifact._id, eventId }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + const status = message.startsWith("Unauthorized") ? 401 : 400; + return json(status, { error: message }); + } +}); + +/** + * POST /api/agents/storage/generate-upload-url + * + * Service-authenticated endpoint for an agent to obtain a one-time Convex + * Storage upload URL for a binary artifact (e.g. rendered HTML). The agent + * uploads the bytes to the returned URL and then references the resulting + * storageId in {@link publishAgentArtifact}. + * + * Body: { agentId, organizationId, projectId } + */ +export const generateAgentUploadUrl = httpAction(async (ctx, request) => { + try { + requireServiceToken(request); + const body = (await request.json()) as Record; + await resolveBoundary(ctx, body); + const url = await ctx.storage.generateUploadUrl(); + return json(200, { url }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + const status = message.startsWith("Unauthorized") ? 401 : 400; + return json(status, { error: message }); + } +}); diff --git a/packages/backend/convex/artifactBuilds.ts b/packages/backend/convex/artifactBuilds.ts new file mode 100644 index 0000000..cc296b3 --- /dev/null +++ b/packages/backend/convex/artifactBuilds.ts @@ -0,0 +1,141 @@ +import { ConvexError, v } from "convex/values"; + +import type { Doc } from "./_generated/dataModel"; +import { internalMutation, internalQuery } from "./_generated/server"; + +const artifactKind = v.union( + v.literal("project_setup"), + v.literal("summary"), + v.literal("plan"), + v.literal("preview"), + v.literal("blocker"), + v.literal("report") +); + +const buildStatus = v.union( + v.literal("pending"), + v.literal("building"), + v.literal("ready"), + v.literal("failed") +); + +/** + * Create an ArtifactBuild keyed idempotently by + * `flow::artifact::revision:` (per contract). The + * build records the typed source manifest; the rendered artifact + storage + * upload are linked via {@link markReady}. + */ +export const create = internalMutation({ + args: { + artifactKind, + flowRunId: v.optional(v.id("flowRuns")), + idempotencyKey: v.string(), + organizationId: v.id("organizations"), + projectId: v.optional(v.id("projects")), + sourceManifest: v.any(), + threadId: v.optional(v.id("threads")), + workId: v.optional(v.id("works")), + }, + handler: async (ctx, args): Promise> => { + // Idempotency: reuse an existing build for the same flow run + kind. + if (args.flowRunId) { + const existing = await ctx.db + .query("artifactBuilds") + .withIndex("by_organizationId_and_flow_run", (q) => + q + .eq("organizationId", args.organizationId) + .eq("flowRunId", args.flowRunId) + ) + .filter((q) => q.eq(q.field("artifactKind"), args.artifactKind)) + .unique(); + if (existing) { + return existing; + } + } + const timestamp = Date.now(); + const buildId = await ctx.db.insert("artifactBuilds", { + artifactKind: args.artifactKind, + createdAt: timestamp, + flowRunId: args.flowRunId, + idempotencyKey: args.idempotencyKey, + organizationId: args.organizationId, + projectId: args.projectId, + sourceManifest: args.sourceManifest, + status: "pending", + threadId: args.threadId, + updatedAt: timestamp, + workId: args.workId, + }); + const build = await ctx.db.get(buildId); + if (!build) { + throw new ConvexError("Artifact build could not be read after insert"); + } + return build; + }, +}); + +/** + * Link a finished artifact build to its rendered Convex Storage id and the + * created artifact row. A ready build is terminal. + */ +export const markReady = internalMutation({ + args: { + artifactId: v.id("artifacts"), + buildId: v.id("artifactBuilds"), + outputStorageId: v.optional(v.id("_storage")), + }, + handler: async (ctx, args): Promise> => { + const build = await ctx.db.get(args.buildId); + if (!build) { + throw new ConvexError("Artifact build not found"); + } + if (build.status === "ready") { + return build; + } + await ctx.db.patch(args.buildId, { + artifactId: args.artifactId, + outputStorageId: args.outputStorageId, + status: "ready", + updatedAt: Date.now(), + }); + const updated = await ctx.db.get(args.buildId); + if (!updated) { + throw new ConvexError("Artifact build could not be read after update"); + } + return updated; + }, +}); + +export const markFailed = internalMutation({ + args: { + buildId: v.id("artifactBuilds"), + error: v.string(), + }, + handler: async (ctx, args): Promise> => { + const build = await ctx.db.get(args.buildId); + if (!build) { + throw new ConvexError("Artifact build not found"); + } + if (build.status === "ready") { + return build; + } + await ctx.db.patch(args.buildId, { + lastError: args.error, + status: "failed", + updatedAt: Date.now(), + }); + const updated = await ctx.db.get(args.buildId); + if (!updated) { + throw new ConvexError("Artifact build could not be read after update"); + } + return updated; + }, +}); + +export const get = internalQuery({ + args: { buildId: v.id("artifactBuilds") }, + handler: async (ctx, args): Promise | null> => + await ctx.db.get(args.buildId), +}); + +export { buildStatus }; diff --git a/packages/backend/convex/artifacts.ts b/packages/backend/convex/artifacts.ts index dbf2518..557cf4a 100644 --- a/packages/backend/convex/artifacts.ts +++ b/packages/backend/convex/artifacts.ts @@ -1,7 +1,7 @@ -import { v } from "convex/values"; +import { ConvexError, v } from "convex/values"; import type { Doc } from "./_generated/dataModel"; -import { query } from "./_generated/server"; +import { internalMutation, query } from "./_generated/server"; import { requireArtifactMember, requireWorkMember } from "./authz"; export const get = query({ @@ -25,3 +25,90 @@ export const listForWork = query({ .take(limit); }, }); + +/** + * Publish (or supersede) a typed artifact revision for a project/work/thread. + * + * Versioning: the new artifact's `version` is one greater than the latest + * existing artifact sharing the same `logicalKey` within the org. The previous + * latest artifact (if any) is marked `superseded` and linked via + * `supersedesArtifactId` on the new row. + * + * The optional `storageId` links the rendered static HTML (or other binary) in + * Convex Storage to the artifact row, keeping the card/manifest inline for the + * timeline. + * + * Idempotent by `logicalKey` + `version`: a re-publish of the same version + * returns the existing artifact. `createdByEventId` ties the artifact to the + * event that produced it (exact-once via the event's idempotency key). + */ +export const publishRevision = internalMutation({ + args: { + card: v.any(), + content: v.any(), + createdByEventId: v.id("events"), + kind: v.union( + v.literal("project_setup"), + v.literal("summary"), + v.literal("plan"), + v.literal("preview"), + v.literal("blocker"), + v.literal("report") + ), + logicalKey: v.string(), + organizationId: v.id("organizations"), + projectId: v.optional(v.id("projects")), + status: v.union( + v.literal("working"), + v.literal("ready"), + v.literal("blocked"), + v.literal("failed"), + v.literal("superseded") + ), + storageId: v.optional(v.id("_storage")), + summary: v.string(), + threadId: v.optional(v.id("threads")), + title: v.string(), + workId: v.optional(v.id("works")), + }, + handler: async (ctx, args): Promise> => { + const previous = await ctx.db + .query("artifacts") + .withIndex("by_organizationId_and_logicalKey_and_version", (q) => + q + .eq("organizationId", args.organizationId) + .eq("logicalKey", args.logicalKey) + ) + .order("desc") + .first(); + const version = (previous?.version ?? 0) + 1; + const now = Date.now(); + const artifactId = await ctx.db.insert("artifacts", { + card: args.card, + content: args.content, + createdAt: now, + createdByEventId: args.createdByEventId, + kind: args.kind, + logicalKey: args.logicalKey, + organizationId: args.organizationId, + projectId: args.projectId, + status: args.status, + storageId: args.storageId, + summary: args.summary, + supersedesArtifactId: previous?._id, + threadId: args.threadId, + title: args.title, + version, + workId: args.workId, + }); + // Mark the prior revision superseded so only the latest is "ready". + if (previous && previous.status !== "superseded") { + await ctx.db.patch(previous._id, { status: "superseded" }); + } + const artifact = await ctx.db.get(artifactId); + if (!artifact) { + throw new ConvexError("Artifact could not be read after publish"); + } + return artifact; + }, +}); diff --git a/packages/backend/convex/conversationAgents.ts b/packages/backend/convex/conversationAgents.ts new file mode 100644 index 0000000..5fbef2d --- /dev/null +++ b/packages/backend/convex/conversationAgents.ts @@ -0,0 +1,104 @@ +import { ConvexError, v } from "convex/values"; + +import type { Doc, Id } from "./_generated/dataModel"; +import { internalMutation, internalQuery } from "./_generated/server"; + +const agentStatus = v.union( + v.literal("registered"), + v.literal("active"), + v.literal("idle"), + v.literal("disabled") +); + +/** + * The stable conversation id used as the Flue `dispatch` conversation id and + * the `conversationAgents.id` uniqueness key. + * Shape: `conversation:::v1` + */ +export const conversationAgentId = ( + organizationId: Id<"organizations">, + projectId: Id<"projects"> +): string => `conversation:${organizationId}:${projectId}:v1`; + +/** + * Register one project-bound conversation agent per Project. Idempotent by the + * stable `conversation:::v1` key; retries reuse the existing row. + */ +export const register = internalMutation({ + args: { + agentType: v.string(), + organizationId: v.id("organizations"), + projectId: v.id("projects"), + runtimeId: v.optional(v.id("projectRuntimes")), + }, + handler: async (ctx, args): Promise> => { + const id = conversationAgentId(args.organizationId, args.projectId); + const existing = await ctx.db + .query("conversationAgents") + .withIndex("by_projectId", (q) => q.eq("projectId", args.projectId)) + .unique(); + if (existing) { + return existing; + } + const timestamp = Date.now(); + const rowId = await ctx.db.insert("conversationAgents", { + agentType: args.agentType, + createdAt: timestamp, + id, + organizationId: args.organizationId, + projectId: args.projectId, + runtimeId: args.runtimeId, + status: "registered", + updatedAt: timestamp, + }); + const saved = await ctx.db.get(rowId); + if (!saved) { + throw new ConvexError( + "Conversation agent could not be read after insert" + ); + } + return saved; + }, +}); + +export const markStatus = internalMutation({ + args: { + agentRowId: v.id("conversationAgents"), + flueConversationId: v.optional(v.string()), + lastEventId: v.optional(v.id("events")), + status: agentStatus, + }, + handler: async (ctx, args): Promise> => { + const agent = await ctx.db.get(args.agentRowId); + if (!agent) { + throw new ConvexError("Conversation agent not found"); + } + const patch: Record = { + status: args.status, + updatedAt: Date.now(), + }; + if (args.flueConversationId !== undefined) { + patch.flueConversationId = args.flueConversationId; + } + if (args.lastEventId !== undefined) { + patch.lastEventId = args.lastEventId; + } + await ctx.db.patch(args.agentRowId, patch); + const updated = await ctx.db.get(args.agentRowId); + if (!updated) { + throw new ConvexError( + "Conversation agent could not be read after update" + ); + } + return updated; + }, +}); + +export const getForProject = internalQuery({ + args: { projectId: v.id("projects") }, + handler: async (ctx, args): Promise | null> => + await ctx.db + .query("conversationAgents") + .withIndex("by_projectId", (q) => q.eq("projectId", args.projectId)) + .unique(), +}); diff --git a/packages/backend/convex/convex.config.ts b/packages/backend/convex/convex.config.ts index 8a828fc..69d0999 100644 --- a/packages/backend/convex/convex.config.ts +++ b/packages/backend/convex/convex.config.ts @@ -4,6 +4,9 @@ import { v } from "convex/values"; const app = defineApp({ env: { + AGENT_BACKEND_URL: v.optional(v.string()), + FLUE_DB_TOKEN: v.optional(v.string()), + FLUE_URL: v.optional(v.string()), GITEA_TOKEN: v.optional(v.string()), GITEA_URL: v.optional(v.string()), GITEA_WEBHOOK_SECRET: v.optional(v.string()), diff --git a/packages/backend/convex/events.ts b/packages/backend/convex/events.ts new file mode 100644 index 0000000..cb2fb73 --- /dev/null +++ b/packages/backend/convex/events.ts @@ -0,0 +1,156 @@ +import { v } from "convex/values"; + +import type { Id } from "./_generated/dataModel"; +import type { MutationCtx } from "./_generated/server"; +import { internalMutation } from "./_generated/server"; + +/** + * The system actors used by the coordinator and agent tooling. The existing + * `events.actor` union already permits `{ kind: "system", service }` and + * `{ kind: "tool", tool }`; these constants name the canonical services. + */ +export const SYSTEM_SERVICE_PROJECT_SETUP = "project-setup"; +export const SYSTEM_SERVICE_AGENT_GATEWAY = "agent-gateway"; + +interface AppendInput { + readonly actor: + | { readonly kind: "system"; readonly service: string } + | { readonly kind: "tool"; readonly tool: string }; + readonly artifactIds?: readonly Id<"artifacts">[]; + readonly causationId?: Id<"events">; + readonly correlationId: string; + readonly idempotencyKey: string; + readonly organizationId: Id<"organizations">; + readonly payload: unknown; + readonly projectId?: Id<"projects">; + readonly replyToEventId?: Id<"events">; + readonly scopeKind: "global" | "work"; + readonly threadId?: Id<"threads">; + readonly type: string; + readonly visibility: "timeline" | "compact" | "internal"; + readonly workId?: Id<"works">; +} + +/** + * Append an immutable system/tool event with exact-once semantics: an event + * with the same `(organizationId, idempotencyKey)` is returned unchanged on + * retry. This is the shared primitive every coordinator phase and agent tool + * writes through. + */ +const appendEventOnce = async ( + ctx: MutationCtx, + input: AppendInput +): Promise> => { + const existing = await ctx.db + .query("events") + .withIndex("by_organizationId_and_idempotencyKey", (q) => + q + .eq("organizationId", input.organizationId) + .eq("idempotencyKey", input.idempotencyKey) + ) + .unique(); + if (existing) { + return existing._id; + } + const now = Date.now(); + return await ctx.db.insert("events", { + actor: input.actor, + artifactIds: input.artifactIds ? [...input.artifactIds] : undefined, + causationId: input.causationId, + correlationId: input.correlationId, + idempotencyKey: input.idempotencyKey, + occurredAt: now, + organizationId: input.organizationId, + payload: input.payload, + projectId: input.projectId, + recordedAt: now, + replyToEventId: input.replyToEventId, + scopeKind: input.scopeKind, + threadId: input.threadId, + type: input.type, + visibility: input.visibility, + workId: input.workId, + }); +}; + +export const appendSystemEvent = internalMutation({ + args: { + actorService: v.string(), + artifactIds: v.optional(v.array(v.id("artifacts"))), + causationId: v.optional(v.id("events")), + correlationId: v.string(), + idempotencyKey: v.string(), + organizationId: v.id("organizations"), + payload: v.any(), + projectId: v.optional(v.id("projects")), + replyToEventId: v.optional(v.id("events")), + scopeKind: v.union(v.literal("global"), v.literal("work")), + threadId: v.optional(v.id("threads")), + type: v.string(), + visibility: v.union( + v.literal("timeline"), + v.literal("compact"), + v.literal("internal") + ), + workId: v.optional(v.id("works")), + }, + handler: (ctx, args): Promise> => + appendEventOnce(ctx, { + actor: { kind: "system", service: args.actorService }, + artifactIds: args.artifactIds, + causationId: args.causationId, + correlationId: args.correlationId, + idempotencyKey: args.idempotencyKey, + organizationId: args.organizationId, + payload: args.payload, + projectId: args.projectId, + replyToEventId: args.replyToEventId, + scopeKind: args.scopeKind, + threadId: args.threadId, + type: args.type, + visibility: args.visibility, + workId: args.workId, + }), +}); + +export const appendToolEvent = internalMutation({ + args: { + actorTool: v.string(), + artifactIds: v.optional(v.array(v.id("artifacts"))), + causationId: v.optional(v.id("events")), + correlationId: v.string(), + idempotencyKey: v.string(), + organizationId: v.id("organizations"), + payload: v.any(), + projectId: v.optional(v.id("projects")), + replyToEventId: v.optional(v.id("events")), + scopeKind: v.union(v.literal("global"), v.literal("work")), + threadId: v.optional(v.id("threads")), + type: v.string(), + visibility: v.union( + v.literal("timeline"), + v.literal("compact"), + v.literal("internal") + ), + workId: v.optional(v.id("works")), + }, + handler: (ctx, args): Promise> => + appendEventOnce(ctx, { + actor: { kind: "tool", tool: args.actorTool }, + artifactIds: args.artifactIds, + causationId: args.causationId, + correlationId: args.correlationId, + idempotencyKey: args.idempotencyKey, + organizationId: args.organizationId, + payload: args.payload, + projectId: args.projectId, + replyToEventId: args.replyToEventId, + scopeKind: args.scopeKind, + threadId: args.threadId, + type: args.type, + visibility: args.visibility, + workId: args.workId, + }), +}); + +export { appendEventOnce }; diff --git a/packages/backend/convex/flowRuns.ts b/packages/backend/convex/flowRuns.ts new file mode 100644 index 0000000..30fac2d --- /dev/null +++ b/packages/backend/convex/flowRuns.ts @@ -0,0 +1,121 @@ +import { ConvexError, v } from "convex/values"; + +import type { Doc } from "./_generated/dataModel"; +import { internalMutation, internalQuery } from "./_generated/server"; + +const flowRunStatus = v.union( + v.literal("running"), + v.literal("completed"), + v.literal("failed"), + v.literal("cancelled") +); + +/** + * Create a FlowRun keyed idempotently by its idempotencyKey + * (`event::flow::`). Retries reuse the existing + * run rather than creating duplicate specialist executions. + */ +export const create = internalMutation({ + args: { + agentId: v.optional(v.string()), + flowType: v.string(), + flowVersion: v.string(), + idempotencyKey: v.string(), + organizationId: v.id("organizations"), + projectId: v.optional(v.id("projects")), + sourceEventId: v.id("events"), + threadId: v.optional(v.id("threads")), + workId: v.optional(v.id("works")), + }, + handler: async (ctx, args): Promise> => { + // Idempotency: look up an existing run for the same source event + flow type. + const existing = await ctx.db + .query("flowRuns") + .withIndex("by_organizationId_and_source_event", (q) => + q + .eq("organizationId", args.organizationId) + .eq("sourceEventId", args.sourceEventId) + ) + .filter((q) => q.eq(q.field("flowType"), args.flowType)) + .unique(); + if (existing) { + return existing; + } + const timestamp = Date.now(); + const runId = await ctx.db.insert("flowRuns", { + agentId: args.agentId, + attempt: 1, + flowType: args.flowType, + flowVersion: args.flowVersion, + idempotencyKey: args.idempotencyKey, + organizationId: args.organizationId, + projectId: args.projectId, + sourceEventId: args.sourceEventId, + startedAt: timestamp, + state: {}, + status: "running", + threadId: args.threadId, + updatedAt: timestamp, + workId: args.workId, + }); + const run = await ctx.db.get(runId); + if (!run) { + throw new ConvexError("Flow run could not be read after insert"); + } + return run; + }, +}); + +/** + * Patch a FlowRun's state/status. A terminal run cannot be revived by update. + */ +export const update = internalMutation({ + args: { + finishedAt: v.optional(v.number()), + flowRunId: v.id("flowRuns"), + lastError: v.optional(v.string()), + state: v.optional(v.any()), + status: v.optional(flowRunStatus), + }, + handler: async (ctx, args): Promise> => { + const run = await ctx.db.get(args.flowRunId); + if (!run) { + throw new ConvexError("Flow run not found"); + } + // Terminal runs are immutable. + if ( + run.status === "completed" || + run.status === "cancelled" || + run.status === "failed" + ) { + return run; + } + const patch: Record = { updatedAt: Date.now() }; + if (args.state !== undefined) { + patch.state = args.state; + } + if (args.status !== undefined) { + patch.status = args.status; + } + if (args.finishedAt !== undefined) { + patch.finishedAt = args.finishedAt; + } + if (args.lastError !== undefined) { + patch.lastError = args.lastError; + } + await ctx.db.patch(args.flowRunId, patch); + const updated = await ctx.db.get(args.flowRunId); + if (!updated) { + throw new ConvexError("Flow run could not be read after update"); + } + return updated; + }, +}); + +export const get = internalQuery({ + args: { flowRunId: v.id("flowRuns") }, + handler: async (ctx, args): Promise | null> => + await ctx.db.get(args.flowRunId), +}); + +export { flowRunStatus }; diff --git a/packages/backend/convex/http.ts b/packages/backend/convex/http.ts index 9e430bd..e851eaa 100644 --- a/packages/backend/convex/http.ts +++ b/packages/backend/convex/http.ts @@ -1,5 +1,10 @@ import { httpRouter } from "convex/server"; +import { + generateAgentUploadUrl, + postAgentMessage, + publishAgentArtifact, +} from "./agentHttp"; import { authComponent, createAuth } from "./auth"; import { githubWebhook, puterWebhook } from "./gitWebhooks"; @@ -19,4 +24,22 @@ http.route({ path: "/api/git/webhooks/puter", }); +http.route({ + handler: postAgentMessage, + method: "POST", + path: "/api/agents/events/message", +}); + +http.route({ + handler: publishAgentArtifact, + method: "POST", + path: "/api/agents/events/artifact", +}); + +http.route({ + handler: generateAgentUploadUrl, + method: "POST", + path: "/api/agents/storage/generate-upload-url", +}); + export default http; diff --git a/packages/backend/convex/projectEnvironmentVariables.ts b/packages/backend/convex/projectEnvironmentVariables.ts index 6b605ae..7f92ce9 100644 --- a/packages/backend/convex/projectEnvironmentVariables.ts +++ b/packages/backend/convex/projectEnvironmentVariables.ts @@ -1,7 +1,7 @@ import { ConvexError, v } from "convex/values"; import type { Doc, Id } from "./_generated/dataModel"; -import { mutation, query } from "./_generated/server"; +import { internalMutation, mutation, query } from "./_generated/server"; import { requireProjectMember } from "./authz"; const category = v.union( @@ -82,3 +82,52 @@ export const upsert = mutation({ return saved; }, }); + +/** + * Replace the entire detected environment-variable manifest for a Project in a + * single idempotent transaction. Called by the setup coordinator after it + * scans the root `.env.example` (names only — example/default text is never + * treated as a secret, stored, or displayed). + * + * Semantics: + * - All previously `detected` rows for the project are removed. + * - One new `detected` row is inserted per scanned name, category `optional`, + * status `missing` (configuration is not part of the readiness predicate). + * - `user`/`system` rows are untouched. + * + * Idempotency: re-running the coordinator with the same names produces the + * same final set of detected rows. No values are persisted. + */ +export const replaceDetectedManifest = internalMutation({ + args: { + names: v.array(v.string()), + organizationId: v.id("organizations"), + projectId: v.id("projects"), + }, + handler: async (ctx, args): Promise<{ count: number }> => { + const detected = await ctx.db + .query("projectEnvironmentVariables") + .withIndex("by_projectId", (q) => q.eq("projectId", args.projectId)) + .filter((q) => q.eq(q.field("source"), "detected")) + .collect(); + for (const row of detected) { + await ctx.db.delete(row._id); + } + const timestamp = Date.now(); + const deduped = [...new Set(args.names.map((name) => name.trim())).values()] + .filter((name) => name.length > 0) + .sort(); + for (const name of deduped) { + await ctx.db.insert("projectEnvironmentVariables", { + category: "optional", + name, + organizationId: args.organizationId, + projectId: args.projectId, + source: "detected", + status: "missing", + updatedAt: timestamp, + }); + } + return { count: deduped.length }; + }, +}); diff --git a/packages/backend/convex/projectRuntimes.ts b/packages/backend/convex/projectRuntimes.ts new file mode 100644 index 0000000..3fe7a5b --- /dev/null +++ b/packages/backend/convex/projectRuntimes.ts @@ -0,0 +1,133 @@ +import { ConvexError, v } from "convex/values"; + +import type { Doc, Id } from "./_generated/dataModel"; +import { internalMutation, internalQuery } from "./_generated/server"; + +const RUNTIME_STATUS = [ + "requested", + "creating_vm", + "cloning", + "checking_repository", + "ready", + "failed", +] as const; + +const runtimeStatus = v.union( + v.literal("requested"), + v.literal("creating_vm"), + v.literal("cloning"), + v.literal("checking_repository"), + v.literal("ready"), + v.literal("failed") +); + +/** + * Create or reuse a ProjectRuntime row, keyed idempotently by projectId. + * Idempotency key: `project::vm:v1` (per the shared contract). + * Re-runs (retries) return the existing row without duplicating it. + */ +export const requestRuntime = internalMutation({ + args: { + idempotencyKey: v.string(), + organizationId: v.id("organizations"), + projectId: v.id("projects"), + provider: v.string(), + }, + handler: async (ctx, args): Promise> => { + const existing = await ctx.db + .query("projectRuntimes") + .withIndex("by_projectId", (q) => q.eq("projectId", args.projectId)) + .unique(); + if (existing) { + return existing._id; + } + const timestamp = Date.now(); + return await ctx.db.insert("projectRuntimes", { + createdAt: timestamp, + idempotencyKey: args.idempotencyKey, + organizationId: args.organizationId, + projectId: args.projectId, + provider: args.provider, + status: "requested", + updatedAt: timestamp, + }); + }, +}); + +/** + * Advance a ProjectRuntime to a new phase. A terminal "ready" or "failed" + * status cannot be overwritten by an earlier phase on retry, so a completed + * setup is never partially rewound. Idempotent: re-applying the same status + * is a no-op. + */ +export const markStatus = internalMutation({ + args: { + lastError: v.optional(v.string()), + repositoryCommit: v.optional(v.string()), + repositoryPath: v.optional(v.string()), + runtimeId: v.optional(v.string()), + runtimeRowId: v.id("projectRuntimes"), + status: runtimeStatus, + vmId: v.optional(v.string()), + workspacePath: v.optional(v.string()), + }, + handler: async (ctx, args): Promise> => { + const runtime = await ctx.db.get(args.runtimeRowId); + if (!runtime) { + throw new ConvexError("Project runtime not found"); + } + // Never rewind a terminal state. A retry that re-enters the coordinator + // after success must observe readiness, not re-run phases. + if ( + (runtime.status === "ready" || runtime.status === "failed") && + args.status !== runtime.status + ) { + return runtime; + } + const patch: Record = { + status: args.status, + updatedAt: Date.now(), + }; + if (args.runtimeId !== undefined) { + patch.runtimeId = args.runtimeId; + } + if (args.vmId !== undefined) { + patch.vmId = args.vmId; + } + if (args.workspacePath !== undefined) { + patch.workspacePath = args.workspacePath; + } + if (args.repositoryPath !== undefined) { + patch.repositoryPath = args.repositoryPath; + } + if (args.repositoryCommit !== undefined) { + patch.repositoryCommit = args.repositoryCommit; + } + if (args.lastError !== undefined) { + patch.lastError = args.lastError; + } + await ctx.db.patch(args.runtimeRowId, patch); + const updated = await ctx.db.get(args.runtimeRowId); + if (!updated) { + throw new ConvexError("Project runtime could not be read after update"); + } + return updated; + }, +}); + +export const getForProject = internalQuery({ + args: { projectId: v.id("projects") }, + handler: async (ctx, args): Promise | null> => + await ctx.db + .query("projectRuntimes") + .withIndex("by_projectId", (q) => q.eq("projectId", args.projectId)) + .unique(), +}); + +export const get = internalQuery({ + args: { runtimeRowId: v.id("projectRuntimes") }, + handler: async (ctx, args): Promise | null> => + await ctx.db.get(args.runtimeRowId), +}); + +export { RUNTIME_STATUS }; diff --git a/packages/backend/convex/projectSetup.ts b/packages/backend/convex/projectSetup.ts new file mode 100644 index 0000000..bab6f9a --- /dev/null +++ b/packages/backend/convex/projectSetup.ts @@ -0,0 +1,528 @@ +"use node"; + +import { env } from "@code/env/convex"; +import { makeFunctionReference } from "convex/server"; +import { ConvexError, v } from "convex/values"; + +import type { Id } from "./_generated/dataModel"; +import { internalAction } from "./_generated/server"; +import type { ActionCtx } from "./_generated/server"; + +// Idempotency keys (shared contract): +const runtimeIdempotencyKey = (projectId: Id<"projects">) => + `project:${projectId}:vm:v1`; +const readyEventIdempotencyKey = (projectId: Id<"projects">) => + `project:${projectId}:ready:v1`; +const dispatchIdempotencyKey = (eventId: Id<"events">, agentId: string) => + `event:${eventId}:agent:${agentId}:handler:v1`; +const lifecycleEventIdempotencyKey = ( + projectId: Id<"projects">, + phase: string +) => `project:${projectId}:setup:${phase}:v1`; + +const PROJECT_AGENT_TYPE = "project"; + +const requestRuntimeRef = makeFunctionReference< + "mutation", + { + idempotencyKey: string; + organizationId: Id<"organizations">; + projectId: Id<"projects">; + provider: string; + }, + Id<"projectRuntimes"> +>("projectRuntimes:requestRuntime"); +const markRuntimeStatusRef = makeFunctionReference< + "mutation", + { + runtimeRowId: Id<"projectRuntimes">; + status: string; + runtimeId?: string; + vmId?: string; + workspacePath?: string; + repositoryPath?: string; + repositoryCommit?: string; + lastError?: string; + }, + unknown +>("projectRuntimes:markStatus"); +const getRuntimeRef = makeFunctionReference< + "query", + { projectId: Id<"projects"> }, + unknown +>("projectRuntimes:getForProject"); +const replaceDetectedManifestRef = makeFunctionReference< + "mutation", + { + names: string[]; + organizationId: Id<"organizations">; + projectId: Id<"projects">; + }, + { count: number } +>("projectEnvironmentVariables:replaceDetectedManifest"); +const registerAgentRef = makeFunctionReference< + "mutation", + { + agentType: string; + organizationId: Id<"organizations">; + projectId: Id<"projects">; + runtimeId?: Id<"projectRuntimes">; + }, + { _id: Id<"conversationAgents">; id: string } +>("conversationAgents:register"); +const markAgentStatusRef = makeFunctionReference< + "mutation", + { agentRowId: Id<"conversationAgents">; status: string }, + unknown +>("conversationAgents:markStatus"); +const appendSystemEventRef = makeFunctionReference< + "mutation", + { + actorService: string; + correlationId: string; + idempotencyKey: string; + organizationId: Id<"organizations">; + payload: unknown; + projectId: Id<"projects">; + scopeKind: "global" | "work"; + type: string; + visibility: "timeline" | "compact" | "internal"; + }, + Id<"events"> +>("events:appendSystemEvent"); +const createDispatchRef = makeFunctionReference< + "mutation", + { + agentId: string; + idempotencyKey: string; + organizationId: Id<"organizations">; + projectId: Id<"projects">; + sourceEventId: Id<"events">; + }, + { created: boolean; dispatch: { _id: Id<"agentDispatches">; status: string } } +>("agentDispatches:create"); +const markDispatchSendingRef = makeFunctionReference< + "mutation", + { dispatchId: Id<"agentDispatches"> }, + unknown +>("agentDispatches:markSending"); +const markDispatchAcceptedRef = makeFunctionReference< + "mutation", + { dispatchId: Id<"agentDispatches"> }, + unknown +>("agentDispatches:markAccepted"); +const markDispatchCompletedRef = makeFunctionReference< + "mutation", + { dispatchId: Id<"agentDispatches"> }, + unknown +>("agentDispatches:markCompleted"); +const markDispatchFailedRef = makeFunctionReference< + "mutation", + { dispatchId: Id<"agentDispatches">; error: string; retry: boolean }, + unknown +>("agentDispatches:markFailed"); +const getProjectSourceRef = makeFunctionReference< + "query", + { projectId: Id<"projects"> }, + { + organizationId: Id<"organizations">; + sourceUrl: string; + defaultBranch: string | null; + name: string; + } | null +>("projectSetupQueries:getProjectSource"); +/** Resolve the agent backend URL. AGENT_BACKEND_URL takes precedence over FLUE_URL. */ +const backendUrl = (): string => { + const url = env.AGENT_BACKEND_URL ?? env.FLUE_URL; + if (!url) { + throw new ConvexError( + "AGENT_BACKEND_URL or FLUE_URL must be configured for project setup" + ); + } + return url; +}; + +const authHeaders = (): Record => { + if (!env.FLUE_DB_TOKEN) { + throw new ConvexError("FLUE_DB_TOKEN must be configured for project setup"); + } + return { + authorization: `Bearer ${env.FLUE_DB_TOKEN}`, + "content-type": "application/json", + }; +}; + +/** Wire shape of the setup-coordinator result returned by the Hono endpoint. */ +interface SetupRuntimeResult { + runtimeId?: string; + vmId?: string; + workspacePath?: string; + repositoryPath?: string; + repositoryCommit?: string; + environmentVariableNames?: string[]; +} + +interface RuntimeRow { + _id: Id<"projectRuntimes">; + status: string; + organizationId: Id<"organizations">; +} + +const asRuntimeRow = (doc: unknown): RuntimeRow => { + const row = doc as Partial | null; + if (!row || !row._id || !row.organizationId) { + throw new ConvexError("Project runtime row is malformed"); + } + return { + _id: row._id, + organizationId: row.organizationId, + status: row.status ?? "requested", + }; +}; + +interface DispatchReadyArgs { + agentId: string; + correlationId: string; + organizationId: Id<"organizations">; + projectId: Id<"projects">; + readyEventId: Id<"events">; + sourceEvent: { type: string; payload: unknown }; +} + +const dispatchReadyWithEvent = async ( + ctx: ActionCtx, + args: DispatchReadyArgs +): Promise => { + const created = (await ctx.runMutation(createDispatchRef, { + agentId: args.agentId, + idempotencyKey: dispatchIdempotencyKey(args.readyEventId, args.agentId), + organizationId: args.organizationId, + projectId: args.projectId, + sourceEventId: args.readyEventId, + })) as { + created: boolean; + dispatch: { _id: Id<"agentDispatches">; status: string }; + }; + const dispatchId = created.dispatch._id; + + // An already-completed dispatch from a prior run must never be re-sent; the + // idempotency key guarantees this is the same logical delivery. + if (created.dispatch.status === "completed") { + return; + } + + await ctx.runMutation(markDispatchSendingRef, { dispatchId }); + + try { + const response = await fetch( + `${backendUrl()}/internal/agents/${encodeURIComponent(args.agentId)}/events`, + { + body: JSON.stringify({ + agentId: args.agentId, + correlationId: args.correlationId, + dispatchId, + organizationId: args.organizationId, + projectId: args.projectId, + sourceEvent: args.sourceEvent, + sourceEventId: args.readyEventId, + }), + headers: authHeaders(), + method: "POST", + } + ); + if (response.status === 202 || response.status === 200) { + await ctx.runMutation(markDispatchAcceptedRef, { dispatchId }); + await ctx.runMutation(markDispatchCompletedRef, { dispatchId }); + return; + } + const text = await response.text().catch(() => ""); + throw new Error( + `Agent dispatch failed: ${response.status} ${response.statusText}${text ? ` — ${text}` : ""}` + ); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + await ctx.runMutation(markDispatchFailedRef, { + dispatchId, + error: message, + retry: true, + }); + throw error; + } +}; + +const callSetupEndpoint = async (args: { + branch: string; + projectId: Id<"projects">; + repositoryUrl: string; +}): Promise => { + const response = await fetch(`${backendUrl()}/internal/project-setup`, { + body: JSON.stringify({ + branch: args.branch, + projectId: args.projectId, + repositoryUrl: args.repositoryUrl, + }), + headers: authHeaders(), + method: "POST", + }); + if (!response.ok) { + const text = await response.text().catch(() => ""); + throw new Error( + `Project setup endpoint returned ${response.status} ${response.statusText}${text ? ` — ${text}` : ""}` + ); + } + const payload = (await response.json()) as unknown; + if (typeof payload !== "object" || payload === null) { + throw new Error("Project setup endpoint returned a malformed response"); + } + return payload as SetupRuntimeResult; +}; + +/** + * The durable project setup coordinator. Drives one Project through: + * requested -> creating_vm -> cloning -> checking_repository -> ready + * (or -> failed). + * + * It calls a single Hono internal setup endpoint that performs the AgentOS VM + * get-or-create, shallow clone, readability verification, and `.env.example` + * scan, returning the runtime facts. Each Convex-visible phase transition is + * persisted to `projectRuntimes` so retries and the setup screen observe + * progress. On success it registers the conversation agent, appends the + * exact-once `project.ready` event, creates the `agentDispatches` row, and + * dispatches the ready event to the Hono `POST /internal/agents/:agentId/events` + * endpoint. + * + * This function never mutates the repository and never persists example/env + * values. Idempotency keys guarantee retries create no duplicate VMs, agents, + * events, or dispatches. + * + * `correlationId` ties all setup events together; `agentId` is the stable + * `conversation:::v1` agent identity. + */ +export const runSetup = internalAction({ + args: { + agentId: v.string(), + correlationId: v.string(), + organizationId: v.id("organizations"), + projectId: v.id("projects"), + }, + handler: async (ctx, args) => { + const source = await ctx.runQuery(getProjectSourceRef, { + projectId: args.projectId, + }); + if (!source || source.organizationId !== args.organizationId) { + throw new ConvexError("Project not found within organization"); + } + + // Request (or reuse) the runtime row. Terminal-safe: a ready/failed row is + // returned as-is by the mutation. + const runtimeRowId = await ctx.runMutation(requestRuntimeRef, { + idempotencyKey: runtimeIdempotencyKey(args.projectId), + organizationId: args.organizationId, + projectId: args.projectId, + provider: "agentos", + }); + + // Re-check terminal state: if already ready, just (re)dispatch ready. + const current = asRuntimeRow( + await ctx.runQuery(getRuntimeRef, { + projectId: args.projectId, + }) + ); + if (current.status === "ready") { + // Terminal `ready` is only reached after the exact-once `project.ready` + // event was appended AND its dispatch completed on a prior run, so a + // re-entry simply reports readiness without re-running phases or + // re-delivering (the dispatch idempotency key would no-op anyway). + return { + projectId: args.projectId, + runtimeId: runtimeRowId, + status: "ready", + }; + } + if (current.status === "failed") { + return { + projectId: args.projectId, + runtimeId: runtimeRowId, + status: "failed", + }; + } + + const branch = source.defaultBranch ?? "main"; + + // --- Phase: creating_vm --- + await ctx.runMutation(markRuntimeStatusRef, { + runtimeRowId, + status: "creating_vm", + }); + await ctx.runMutation(appendSystemEventRef, { + actorService: "project-setup", + correlationId: args.correlationId, + idempotencyKey: lifecycleEventIdempotencyKey( + args.projectId, + "creating_vm" + ), + organizationId: args.organizationId, + payload: {}, + projectId: args.projectId, + scopeKind: "global", + type: "project.setup.creating_vm", + visibility: "internal", + }); + + // --- Phase: cloning + checking_repository + env scan (single Hono call) --- + await ctx.runMutation(markRuntimeStatusRef, { + runtimeRowId, + status: "cloning", + }); + await ctx.runMutation(appendSystemEventRef, { + actorService: "project-setup", + correlationId: args.correlationId, + idempotencyKey: lifecycleEventIdempotencyKey(args.projectId, "cloning"), + organizationId: args.organizationId, + payload: { branch }, + projectId: args.projectId, + scopeKind: "global", + type: "project.setup.cloning", + visibility: "internal", + }); + + let result: SetupRuntimeResult; + try { + result = await callSetupEndpoint({ + branch, + projectId: args.projectId, + repositoryUrl: source.sourceUrl, + }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + await ctx.runMutation(markRuntimeStatusRef, { + lastError: message, + runtimeRowId, + status: "failed", + }); + await ctx.runMutation(appendSystemEventRef, { + actorService: "project-setup", + correlationId: args.correlationId, + idempotencyKey: `${readyEventIdempotencyKey(args.projectId)}:failed`, + organizationId: args.organizationId, + payload: { error: message }, + projectId: args.projectId, + scopeKind: "global", + type: "project.setup.failed", + visibility: "internal", + }); + return { + error: message, + projectId: args.projectId, + runtimeId: runtimeRowId, + status: "failed", + }; + } + + // --- Phase: checking_repository (persisted) --- + await ctx.runMutation(markRuntimeStatusRef, { + repositoryCommit: result.repositoryCommit, + repositoryPath: result.repositoryPath, + runtimeId: result.runtimeId, + runtimeRowId, + status: "checking_repository", + vmId: result.vmId, + workspacePath: result.workspacePath, + }); + await ctx.runMutation(appendSystemEventRef, { + actorService: "project-setup", + correlationId: args.correlationId, + idempotencyKey: lifecycleEventIdempotencyKey( + args.projectId, + "checking_repository" + ), + organizationId: args.organizationId, + payload: { + repositoryCommit: result.repositoryCommit ?? null, + runtimeId: result.runtimeId ?? null, + vmId: result.vmId ?? null, + }, + projectId: args.projectId, + scopeKind: "global", + type: "project.setup.checking_repository", + visibility: "internal", + }); + + // Persist the detected env-name manifest (names only; non-blocking). + const envNames = result.environmentVariableNames ?? []; + await ctx.runMutation(replaceDetectedManifestRef, { + names: envNames, + organizationId: args.organizationId, + projectId: args.projectId, + }); + + // Register the one project-bound conversation agent (idempotent). + const agent = (await ctx.runMutation(registerAgentRef, { + agentType: PROJECT_AGENT_TYPE, + organizationId: args.organizationId, + projectId: args.projectId, + runtimeId: runtimeRowId, + })) as { _id: Id<"conversationAgents">; id: string }; + await ctx.runMutation(markAgentStatusRef, { + agentRowId: agent._id, + status: "active", + }); + + // --- Phase: ready --- + // Append the exact-once `project.ready` event (the durable onboarding + // trigger) and deliver it BEFORE flipping the runtime terminal. A delivery + // failure must throw so Convex retries the coordinator; the runtime stays + // non-terminal, and the idempotency keys make the retry reuse the same + // event/dispatch rather than duplicating it. + const readyEventId = await ctx.runMutation(appendSystemEventRef, { + actorService: "project-setup", + correlationId: args.correlationId, + idempotencyKey: readyEventIdempotencyKey(args.projectId), + organizationId: args.organizationId, + payload: { + agentId: args.agentId, + environmentVariableNames: envNames, + repositoryCommit: result.repositoryCommit ?? null, + runtimeId: result.runtimeId ?? null, + }, + projectId: args.projectId, + scopeKind: "global", + type: "project.ready", + visibility: "timeline", + }); + + // Dispatch the ready event to the project conversation agent. Throws on + // delivery failure; only success returns, after which `ready` is durable. + await dispatchReadyWithEvent(ctx, { + agentId: args.agentId, + correlationId: args.correlationId, + organizationId: args.organizationId, + projectId: args.projectId, + readyEventId, + sourceEvent: { + payload: { + agentId: args.agentId, + environmentVariableNames: envNames, + repositoryCommit: result.repositoryCommit ?? null, + runtimeId: result.runtimeId ?? null, + }, + type: "project.ready", + }, + }); + + // Runtime becomes terminal only after the ready event is durably delivered. + await ctx.runMutation(markRuntimeStatusRef, { + runtimeRowId, + status: "ready", + }); + + return { + projectId: args.projectId, + readyEventId, + runtimeId: runtimeRowId, + status: "ready", + }; + }, +}); + +export { runtimeIdempotencyKey, readyEventIdempotencyKey }; diff --git a/packages/backend/convex/projectSetupQueries.ts b/packages/backend/convex/projectSetupQueries.ts new file mode 100644 index 0000000..d39c3e8 --- /dev/null +++ b/packages/backend/convex/projectSetupQueries.ts @@ -0,0 +1,64 @@ +import { v } from "convex/values"; + +import { internalQuery } from "./_generated/server"; + +/** + * Query the project source metadata the coordinator needs (clone URL, default + * branch, org). Internal so the Node action can read it without touching the DB. + * + * Lives outside the `"use node"` projectSetup module because Convex forbids + * query/mutation definitions in Node-runtime modules. + */ +export const getProjectSource = internalQuery({ + args: { projectId: v.id("projects") }, + handler: async (ctx, args) => { + const project = await ctx.db.get(args.projectId); + if (!project) { + return null; + } + return { + defaultBranch: project.defaultBranch ?? null, + name: project.name, + organizationId: project.organizationId, + sourceUrl: project.sourceUrl, + }; + }, +}); + +/** + * Read-only project setup status for the setup screen: latest runtime row plus + * the setup-scoped events. Auth-gated to project members. + */ +export const getStatus = internalQuery({ + args: { projectId: v.id("projects") }, + handler: async (ctx, args) => { + const project = await ctx.db.get(args.projectId); + if (!project) { + return { events: [], runtime: null }; + } + const runtime = await ctx.db + .query("projectRuntimes") + .withIndex("by_projectId", (q) => q.eq("projectId", args.projectId)) + .unique(); + const events = await ctx.db + .query("events") + .withIndex("by_organizationId_and_projectId_and_recordedAt", (q) => + q + .eq("organizationId", project.organizationId) + .eq("projectId", args.projectId) + ) + .order("desc") + .filter((q) => + q.or( + q.eq(q.field("type"), "project.setup.creating_vm"), + q.eq(q.field("type"), "project.setup.cloning"), + q.eq(q.field("type"), "project.setup.checking_repository"), + q.eq(q.field("type"), "project.ready"), + q.eq(q.field("type"), "project.setup.failed"), + q.eq(q.field("type"), "project.setup.started") + ) + ) + .take(50); + return { events, runtime }; + }, +}); diff --git a/packages/backend/convex/projects.ts b/packages/backend/convex/projects.ts index aad05df..b24ed15 100644 --- a/packages/backend/convex/projects.ts +++ b/packages/backend/convex/projects.ts @@ -7,6 +7,7 @@ import type { ProjectImportOutcome, ProjectView, } from "@code/primitives/project"; +import { makeFunctionReference } from "convex/server"; import { ConvexError, v } from "convex/values"; import { Effect } from "effect"; @@ -18,8 +19,20 @@ import { requireCurrentOrganization, requireProjectMember, } from "./authz"; +import { conversationAgentId } from "./conversationAgents"; import { inspectPublicGit } from "./publicGit"; +const runSetupRef = makeFunctionReference< + "action", + { + agentId: string; + correlationId: string; + organizationId: Id<"organizations">; + projectId: Id<"projects">; + }, + unknown +>("projectSetup:runSetup"); + const toProjectView = async ( ctx: Parameters[0], project: Doc<"projects"> @@ -197,6 +210,13 @@ export const getSetup = query({ .order("desc") .filter((q) => q.or( + // Lifecycle event types emitted by the project-setup coordinator. + q.eq(q.field("type"), "project.setup.creating_vm"), + q.eq(q.field("type"), "project.setup.cloning"), + q.eq(q.field("type"), "project.setup.checking_repository"), + q.eq(q.field("type"), "project.ready"), + q.eq(q.field("type"), "project.setup.failed"), + // Legacy / environment / preview event types (compatible). q.eq(q.field("type"), "project.setup.started"), q.eq(q.field("type"), "project.setup.environment_required"), q.eq(q.field("type"), "project.setup.environment_updated"), @@ -233,6 +253,13 @@ export const appendSetupEvent = internalMutation({ payload: v.any(), projectId: v.id("projects"), type: v.union( + // Lifecycle event types emitted by the project-setup coordinator. + v.literal("project.setup.creating_vm"), + v.literal("project.setup.cloning"), + v.literal("project.setup.checking_repository"), + v.literal("project.ready"), + v.literal("project.setup.failed"), + // Legacy / environment / preview event types (compatible). v.literal("project.setup.started"), v.literal("project.setup.environment_required"), v.literal("project.setup.environment_updated"), @@ -290,15 +317,32 @@ export const importPublicGit = action({ const remote = await Effect.runPromise( decodePublicGitImportResult(await inspectPublicGit(source)) ); - return await ctx.runMutation(internal.projects.persistPublicGitImport, { - remote: { - defaultBranch: remote.defaultBranch, - documents: remote.documents.map((document) => ({ ...document })), - warnings: remote.warnings.map((warning) => ({ ...warning })), - }, - source, - userId, + const outcome = await ctx.runMutation( + internal.projects.persistPublicGitImport, + { + remote: { + defaultBranch: remote.defaultBranch, + documents: remote.documents.map((document) => ({ ...document })), + warnings: remote.warnings.map((warning) => ({ ...warning })), + }, + source, + userId, + } + ); + // Kick off the idempotent project setup coordinator (AgentOS VM + clone + + // readiness + project.ready + agent dispatch). Scheduled as an internal + // action so retries are safe: every step is keyed idempotently. + const projectId = outcome.id as unknown as Id<"projects">; + const organizationId = + outcome.organizationId as unknown as Id<"organizations">; + const agentId = conversationAgentId(organizationId, projectId); + await ctx.scheduler.runAfter(0, runSetupRef, { + agentId, + correlationId: `import:${projectId}`, + organizationId, + projectId, }); + return outcome; }, }); diff --git a/packages/backend/convex/schema.ts b/packages/backend/convex/schema.ts index 5f8e1d5..0fa1c31 100644 --- a/packages/backend/convex/schema.ts +++ b/packages/backend/convex/schema.ts @@ -365,6 +365,7 @@ export default defineSchema({ threadId: v.optional(v.id("threads")), title: v.string(), version: v.number(), + storageId: v.optional(v.id("_storage")), workId: v.optional(v.id("works")), }) .index("by_projectId_and_createdAt", ["projectId", "createdAt"]) @@ -375,4 +376,158 @@ export default defineSchema({ "logicalKey", "version", ]), + projectRuntimes: defineTable({ + createdAt: v.number(), + idempotencyKey: v.string(), + lastError: v.optional(v.string()), + organizationId: v.id("organizations"), + projectId: v.id("projects"), + provider: v.string(), + repositoryCommit: v.optional(v.string()), + repositoryPath: v.optional(v.string()), + runtimeId: v.optional(v.string()), + status: v.union( + v.literal("requested"), + v.literal("creating_vm"), + v.literal("cloning"), + v.literal("checking_repository"), + v.literal("ready"), + v.literal("failed") + ), + updatedAt: v.number(), + vmId: v.optional(v.string()), + workspacePath: v.optional(v.string()), + }) + .index("by_projectId", ["projectId"]) + .index("by_organizationId_and_status", ["organizationId", "status"]) + .index("by_organizationId_and_runtime_id", ["organizationId", "runtimeId"]), + conversationAgents: defineTable({ + agentType: v.string(), + createdAt: v.number(), + flueConversationId: v.optional(v.string()), + id: v.string(), + lastEventId: v.optional(v.id("events")), + organizationId: v.id("organizations"), + projectId: v.id("projects"), + runtimeId: v.optional(v.id("projectRuntimes")), + status: v.union( + v.literal("registered"), + v.literal("active"), + v.literal("idle"), + v.literal("disabled") + ), + updatedAt: v.number(), + }) + .index("by_projectId", ["projectId"]) + .index("by_projectId_and_status", ["projectId", "status"]) + .index("by_organizationId_and_status", ["organizationId", "status"]), + agentDispatches: defineTable({ + agentId: v.string(), + attempt: v.number(), + createdAt: v.number(), + handlerVersion: v.string(), + idempotencyKey: v.string(), + lastError: v.optional(v.string()), + organizationId: v.id("organizations"), + projectId: v.optional(v.id("projects")), + sourceEventId: v.id("events"), + status: v.union( + v.literal("pending"), + v.literal("sending"), + v.literal("accepted"), + v.literal("completed"), + v.literal("failed") + ), + threadId: v.optional(v.id("threads")), + updatedAt: v.number(), + workId: v.optional(v.id("works")), + }) + .index("by_organizationId_and_source_event_handler", [ + "organizationId", + "sourceEventId", + "agentId", + "handlerVersion", + ]) + .index("by_organizationId_and_status", ["organizationId", "status"]) + .index("by_organizationId_and_status_and_updatedAt", [ + "organizationId", + "status", + "updatedAt", + ]), + flowRuns: defineTable({ + agentId: v.optional(v.string()), + attempt: v.number(), + finishedAt: v.optional(v.number()), + flowType: v.string(), + flowVersion: v.string(), + idempotencyKey: v.string(), + organizationId: v.id("organizations"), + projectId: v.optional(v.id("projects")), + sourceEventId: v.id("events"), + startedAt: v.number(), + state: v.any(), + status: v.union( + v.literal("running"), + v.literal("completed"), + v.literal("failed"), + v.literal("cancelled") + ), + threadId: v.optional(v.id("threads")), + updatedAt: v.number(), + workId: v.optional(v.id("works")), + }) + .index("by_organizationId_and_thread", ["organizationId", "threadId"]) + .index("by_organizationId_and_work_and_status", [ + "organizationId", + "workId", + "status", + ]) + .index("by_organizationId_and_agent_and_status", [ + "organizationId", + "agentId", + "status", + ]) + .index("by_organizationId_and_source_event", [ + "organizationId", + "sourceEventId", + ]), + artifactBuilds: defineTable({ + artifactId: v.optional(v.id("artifacts")), + artifactKind: v.union( + v.literal("project_setup"), + v.literal("summary"), + v.literal("plan"), + v.literal("preview"), + v.literal("blocker"), + v.literal("report") + ), + createdAt: v.number(), + flowRunId: v.optional(v.id("flowRuns")), + idempotencyKey: v.string(), + lastError: v.optional(v.string()), + organizationId: v.id("organizations"), + outputStorageId: v.optional(v.id("_storage")), + projectId: v.optional(v.id("projects")), + sourceManifest: v.any(), + status: v.union( + v.literal("pending"), + v.literal("building"), + v.literal("ready"), + v.literal("failed") + ), + threadId: v.optional(v.id("threads")), + updatedAt: v.number(), + workId: v.optional(v.id("works")), + }) + .index("by_organizationId_and_flow_run", ["organizationId", "flowRunId"]) + .index("by_organizationId_and_status_and_updatedAt", [ + "organizationId", + "status", + "updatedAt", + ]) + .index("by_organizationId_and_project_and_createdAt", [ + "organizationId", + "projectId", + "createdAt", + ]), }); diff --git a/packages/env/package.json b/packages/env/package.json index 6c0c4f5..5acdb6f 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -4,6 +4,7 @@ "private": true, "type": "module", "exports": { + "./agent": "./src/agent.ts", "./convex": "./src/convex.ts", "./native": "./src/native.ts", "./server": "./src/server.ts", diff --git a/packages/env/src/agent.ts b/packages/env/src/agent.ts new file mode 100644 index 0000000..2fa48fe --- /dev/null +++ b/packages/env/src/agent.ts @@ -0,0 +1,89 @@ +import { createEnv } from "@t3-oss/env-core"; +import { z } from "zod"; + +/** + * Runtime environment for the Flue 2.0 + Hono + AgentOS intelligence + * runtime (@code/agents). Validated once at process start. + * + * Convex remains the durable source of truth; these keys configure only the + * runtime process: model routing, persistence, service auth, and the + * AgentOS/Rivet host connection. + */ +export const env = createEnv({ + emptyStringAsUndefined: true, + runtimeEnv: process.env, + server: { + AGENT_MODEL_API: z.string().min(1).default("openai-completions"), + AGENT_MODEL_API_KEY: z.string().min(1), + AGENT_MODEL_BASE_URL: z.url(), + AGENT_MODEL_CONTEXT_WINDOW: z.coerce + .number() + .int() + .positive() + .default(1_048_576), + AGENT_MODEL_MAX_TOKENS: z.coerce.number().int().positive().default(131_072), + AGENT_MODEL_NAME: z.string().min(1).default("mimo-v2.5"), + // Model routing — Cheaptricks OpenAI-compatible provider. + AGENT_MODEL_PROVIDER: z.string().min(1).default("cheaptricks"), + // Local workspace root for project VMs and generated artifacts. + AGENT_WORKSPACE_ROOT: z.string().min(1), + // Convex Site base for service HTTP actions (the .convex.site host). + // Runtime → Convex callbacks POST bearer-authenticated calls here. + CONVEX_SITE_URL: z.url(), + // Convex control plane (the .convex.cloud deployment URL). + CONVEX_URL: z.url(), + // Flue SQLite canonical conversation state. + FLUE_DB_PATH: z.string().min(1).default("/srv/zopu/data/flue/flue.db"), + // Service auth between Convex and this runtime. + FLUE_DB_TOKEN: z.string().min(1), + HOST: z.string().min(1).default("127.0.0.1"), + // HTTP listen config. + PORT: z.coerce.number().int().positive().default(3000), + // AgentOS / Rivet host connection. Accepts a full URL + // (http://namespace:token@127.0.0.1:6420) or a bare host:port + // (127.0.0.1:6420), normalizing the latter to http://. + RIVET_ENDPOINT: z + .string() + .min(1) + .refine( + (val) => { + try { + const candidate = /^https?:\/\//u.test(val) ? val : `http://${val}`; + void new URL(candidate); + return true; + } catch { + return false; + } + }, + { message: "RIVET_ENDPOINT must be a valid URL or host:port" } + ) + .transform((val) => (/^https?:\/\//u.test(val) ? val : `http://${val}`)), + // Distinct endpoint the Rivet Engine invokes to reach this process's + // in-process serverless registry handler (mounted by the Hono app at + // RIVET_SERVERLESS_BASE_PATH). This is NOT the Engine control-plane URL + // (that is RIVET_ENDPOINT); it is how the Engine calls back into the + // registry handler co-hosted in this Node process. Defaults to the local + // app listener. + RIVET_SERVERLESS_ENDPOINT: z + .string() + .min(1) + .refine( + (val) => { + try { + const candidate = /^https?:\/\//u.test(val) ? val : `http://${val}`; + void new URL(candidate); + return true; + } catch { + return false; + } + }, + { + message: "RIVET_SERVERLESS_ENDPOINT must be a valid URL or host:port", + } + ) + .transform((val) => (/^https?:\/\//u.test(val) ? val : `http://${val}`)) + .default("http://127.0.0.1:3000/internal/rivet"), + RIVET_WORKSPACE_TOKEN: z.string().min(1), + }, + skipValidation: process.env.SKIP_ENV_VALIDATION === "true", +}); diff --git a/packages/env/src/convex.ts b/packages/env/src/convex.ts index 7ab0482..b2f6186 100644 --- a/packages/env/src/convex.ts +++ b/packages/env/src/convex.ts @@ -5,7 +5,10 @@ export const env = createEnv({ emptyStringAsUndefined: true, runtimeEnv: process.env, server: { + AGENT_BACKEND_URL: z.url().optional(), CONVEX_SITE_URL: z.url().optional(), + FLUE_DB_TOKEN: z.string().min(1).optional(), + FLUE_URL: z.url().optional(), GITEA_TOKEN: z.string().min(1).optional(), GITEA_URL: z.url().default("https://git.openputer.com"), GITEA_WEBHOOK_SECRET: z.string().min(1).optional(), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 372430d..fad9f60 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,12 +6,39 @@ settings: catalogs: default: + '@agentos-software/common': + specifier: 0.2.15 + version: 0.2.15 + '@agentos-software/git': + specifier: 0.3.3 + version: 0.3.3 '@better-auth/expo': specifier: 1.6.15 version: 1.6.15 '@convex-dev/better-auth': specifier: 0.12.5 version: 0.12.5 + '@earendil-works/pi-ai': + specifier: 0.83.0 + version: 0.83.0 + '@flue/cli': + specifier: 2.0.1 + version: 2.0.1 + '@flue/runtime': + specifier: 2.0.1 + version: 2.0.1 + '@flue/sdk': + specifier: 2.0.1 + version: 2.0.1 + '@flue/vite': + specifier: 2.0.1 + version: 2.0.1 + '@hono/node-server': + specifier: 2.0.3 + version: 2.0.3 + '@rivet-dev/agentos': + specifier: 0.2.15 + version: 0.2.15 '@tailwindcss/postcss': specifier: 4.3.3 version: 4.3.3 @@ -48,6 +75,9 @@ catalogs: heroui-native: specifier: 1.0.6 version: 1.0.6 + hono: + specifier: 4.12.34 + version: 4.12.34 lucide-react: specifier: 1.27.0 version: 1.27.0 @@ -57,6 +87,9 @@ catalogs: react-native: specifier: 0.86.0 version: 0.86.0 + rivetkit: + specifier: 2.3.10 + version: 2.3.10 sonner: specifier: 2.0.7 version: 2.0.7 @@ -234,6 +267,67 @@ importers: specifier: 'catalog:' version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0)) + packages/agents: + dependencies: + '@agentos-software/common': + specifier: 'catalog:' + version: 0.2.15 + '@agentos-software/git': + specifier: 'catalog:' + version: 0.3.3 + '@code/env': + specifier: workspace:* + version: link:../env + '@earendil-works/pi-ai': + specifier: 'catalog:' + version: 0.83.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + '@flue/runtime': + specifier: 'catalog:' + version: 2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(typescript@7.0.2)(ws@8.21.1)(zod@4.4.3) + '@flue/sdk': + specifier: 'catalog:' + version: 2.0.1 + '@hono/node-server': + specifier: 'catalog:' + version: 2.0.3(hono@4.12.34) + '@rivet-dev/agentos': + specifier: 'catalog:' + version: 0.2.15(@cfworker/json-schema@4.1.1)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)(ws@8.21.1) + convex: + specifier: 'catalog:' + version: 1.42.3(react@19.2.8) + hono: + specifier: 'catalog:' + version: 4.12.34 + rivetkit: + specifier: 'catalog:' + version: 2.3.10(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(ws@8.21.1) + valibot: + specifier: ^1.0.0 + version: 1.4.2(typescript@7.0.2) + zod: + specifier: 'catalog:' + version: 4.4.3 + devDependencies: + '@code/config': + specifier: workspace:* + version: link:../config + '@flue/cli': + specifier: 'catalog:' + version: 2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(@types/node@22.20.1)(esbuild@0.28.1)(hono@4.12.34)(jiti@2.7.0)(supports-color@10.2.2)(terser@5.49.0)(typescript@7.0.2)(ws@8.21.1)(yaml@2.9.0)(zod@4.4.3) + '@flue/vite': + specifier: 'catalog:' + version: 2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))(hono@4.12.34)(supports-color@10.2.2)(typescript@7.0.2)(ws@8.21.1)(zod@4.4.3) + '@types/node': + specifier: 'catalog:' + version: 22.20.1 + typescript: + specifier: 'catalog:' + version: 7.0.2 + vite: + specifier: npm:@voidzero-dev/vite-plus-core@0.2.2 + version: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0)' + packages/auth: dependencies: '@better-auth/expo': @@ -250,7 +344,7 @@ importers: version: link:../ui '@convex-dev/better-auth': specifier: 'catalog:' - version: 0.12.5(@standard-schema/spec@1.1.0)(better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@26.1.2)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))))(convex@1.42.3(react@19.2.8))(hono@4.12.32)(react@19.2.8)(typescript@7.0.2) + version: 0.12.5(@standard-schema/spec@1.1.0)(better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@26.1.2)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))))(convex@1.42.3(react@19.2.8))(hono@4.12.34)(react@19.2.8)(typescript@7.0.2) '@tanstack/react-form': specifier: 'catalog:' version: 1.33.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -311,7 +405,7 @@ importers: version: link:../primitives '@convex-dev/better-auth': specifier: 'catalog:' - version: 0.12.5(@standard-schema/spec@1.1.0)(better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))))(convex@1.42.3(react@19.2.8))(hono@4.12.32)(react@19.2.8)(typescript@7.0.2) + version: 0.12.5(@standard-schema/spec@1.1.0)(better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))))(convex@1.42.3(react@19.2.8))(hono@4.12.34)(react@19.2.8)(typescript@7.0.2) better-auth: specifier: 'catalog:' version: 1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))) @@ -441,10 +535,214 @@ importers: packages: + '@agentclientprotocol/sdk@0.16.1': + resolution: {integrity: sha512-1ad+Sc/0sCtZGHthxxvgEUo5Wsbw16I+aF+YwdiLnPwkZG8KAGUEAPK6LM6Pf69lCyJPt1Aomk1d+8oE3C4ZEw==} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + + '@agentos-software/claude-code@0.2.7': + resolution: {integrity: sha512-gXmqqOUWT98QvLkQXHn1UU8OOvqMO8BRSj+0PT99mOL6XNpBlPW6L065FJ9dC4IwJC5xeGzB1XFevjOdP7LwQg==} + hasBin: true + + '@agentos-software/codex-cli@0.3.4': + resolution: {integrity: sha512-SAw3EOTa90dJLgEVVoE7JJIxHwticzdD9cEM9v00gpxhxC9vdLkeBva6rgWIUB9+qD1JEYBvUCyNkIpD2kT5YQ==} + + '@agentos-software/common@0.2.15': + resolution: {integrity: sha512-33roACt3EfAp+C6mciKfthVU7I21XeulM+/yLJRo9tSuXfbMLF18EnkodKhvYAJWjzlLGhbmsxfuSuBF7afrhw==} + + '@agentos-software/coreutils@0.3.4': + resolution: {integrity: sha512-tGd0gQjUjHnm+5KgOBwidwUtlkKnl9biQuD7X2sZl15VOhYqUJpnyLF33h/nF3r9WtOTclSiLj/dc2xCxmAXnw==} + + '@agentos-software/diffutils@0.3.4': + resolution: {integrity: sha512-a5Do+ERMdHPwT0Vrp35fxSgrsJNK8wCsYX8dOAomH9N+xJyV2Hb7/LLyp7XxqGk9BEjMeA6UhbH5ZY/HAlx5sQ==} + + '@agentos-software/findutils@0.3.4': + resolution: {integrity: sha512-wjBWE3lkXe70fRj6da1+2MM/7KlPcBRhr2BycvgvAtglOT/0PtabFU9CrDuX3Vm/8acU/8tw35+WeitPOLi9mg==} + + '@agentos-software/gawk@0.3.4': + resolution: {integrity: sha512-NlU6nGxoqIUc1I2zdBHFwH04gE0tBygP2FcBO12VBptty7lbgq1CNLk909jIcSNFEwlm3VRPHeZNkbdVKZ2Ujg==} + + '@agentos-software/git@0.3.3': + resolution: {integrity: sha512-6hCVv4P9eZ5JiPUcLv7y2I5rgxgKvXfdNRvyXCHecMyz6oxE5T0VW8WkSMuwmGTQFUhIIvPn7DpyNDbCaGMpgw==} + + '@agentos-software/grep@0.3.4': + resolution: {integrity: sha512-Bta2Ljl+kCX/3Bjg06Q9N9LPRcf13S92lHRaYG+CeGVDXabIIgkHLUGIQlI1OKuIr7IRAktjgelUAuJnxGFvvw==} + + '@agentos-software/gzip@0.3.4': + resolution: {integrity: sha512-l7Y/Vwiwsqgna68yYwdNCnUBPGBg5zdmtjEFeG3hnDDFLe/02h17q0gUIqJmDBIAy1q9GoizqcFi7zXO2xygKg==} + + '@agentos-software/manifest@0.2.15': + resolution: {integrity: sha512-3aftCfhOjVWy1I2m7CFO8y7If8/SLpE5T7DeIId6UR+88lVcD5I9GpmooYVOAQ8CBs33TWgqJI2Esvt/eb/nsQ==} + + '@agentos-software/opencode@0.2.7': + resolution: {integrity: sha512-lZspCiMgM0+kPAA08CEvyNy8lfBx463wObKpAwbYyaVvc0KfGvbAPS6VmnuZQWmaBmJJuRMtSo14nmb8XCD16g==} + hasBin: true + + '@agentos-software/pi@0.2.7': + resolution: {integrity: sha512-nOdwksByJgTqt92Ya84CzTGxpVFwGI6gkGWaCD/mmvP11JRA++1nshNdbig2mtiaxT7VG3ovWJmK7ZLTTzkhPA==} + hasBin: true + + '@agentos-software/sed@0.3.4': + resolution: {integrity: sha512-J10nZnZmme2SvXK5WMK2unQlOVncMQVUCS20GZB579a2gNoayLJYHGvfJ9a4+42wOHgDKL1u74byWlydCkEyOQ==} + + '@agentos-software/tar@0.3.5': + resolution: {integrity: sha512-hSf6PY4q1luIomFSDgVHxVDDIPdAVZxdgwrQFEYH4aIE6TXX9qatVmzR36uYLWpnFGAZTR6srREGoTnmOGV4Lg==} + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@anthropic-ai/claude-agent-sdk@0.2.87': + resolution: {integrity: sha512-WWmgBPxPhBOvNT0ujI8vPTI2lK+w5YEkEZ/y1mH0EDkK/0kBnxVJNhCtG5vnueiAViwLoUOFn66pbkDiivijdA==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^4.0.0 + + '@anthropic-ai/sdk@0.73.0': + resolution: {integrity: sha512-URURVzhxXGJDGUGFunIOtBlSl7KWvZiAAKY/ttTkZAkXT9bTPqdk2eK0b8qqSxXpikh3QKPnPYpiyX98zf5ebw==} + hasBin: true + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@anthropic-ai/sdk@0.74.0': + resolution: {integrity: sha512-srbJV7JKsc5cQ6eVuFzjZO7UR3xEPJqPamHFIe29bs38Ij2IripoAhC0S5NslNbaFUYqBKypmmpzMTpqfHEUDw==} + hasBin: true + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@anthropic-ai/sdk@0.91.1': + resolution: {integrity: sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==} + hasBin: true + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@asteasolutions/zod-to-openapi@8.5.0': + resolution: {integrity: sha512-SABbKiObg5dLRiTFnqiW1WWwGcg1BJfmHtT2asIBnBHg6Smy/Ms2KHc650+JI4Hw7lSkdiNebEGXpwoxfben8Q==} + peerDependencies: + zod: ^4.0.0 + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/checksums@3.1000.24': + resolution: {integrity: sha512-7TWLjypP8kk3savsDBRuhZJx7mBuFFA2136BQhwwLllsAnO4Tmq/p+SXZaNxbuulkzUFz3BZzj0bb4YzexZcNQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-bedrock-runtime@3.1048.0': + resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-bedrock-runtime@3.1100.0': + resolution: {integrity: sha512-5Cu26EVPlk9lcx9GUd63AySjR6lXx+Z029N0q/vVxvKYC25SLZc8E+IEX+XOYXNVDibXYsNiEqRjlDUdlILiaA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-s3@3.1101.0': + resolution: {integrity: sha512-16EFb1aTEBgPcfUAWAjjlB57IZCyn7B3rlfT+xqE7M6WoH8AMMU3vFZO0UOitwh/xvvzVx73YED1/n0PU4qBMw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.977.4': + resolution: {integrity: sha512-CEkcQlMOQJCvul60U7wdAOACjtdgFWDsfJI+6wUOGdhGNV2lGbuJpi/R50QLpFG3Tp+sQxa/RmzC3X7KHbhuTA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.65': + resolution: {integrity: sha512-lJT2aRw9wCV8jPHyFJjdZLD4HTydL6/22AnCSOB8e/LqOc55nEJGLHkJQeSxhn8QiqyjFwPKQFtMw0ovjRUY/g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.67': + resolution: {integrity: sha512-N7fw/15hSwI/CPxe5ohOyb7O4ge9f5me1gVIn8OIkBRB0squ8OJqQyDyH/HoL+Sb1W5xdC88jVC+bHkw73iu+Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.973.10': + resolution: {integrity: sha512-Zh9XRaPnDN9buO7GfWBubS22R6Nq5D6hbyYEMN05LiOnXugm/8WDjUx6y756bSPbdn3aJB2qG4zFW3bN82QhoQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.72': + resolution: {integrity: sha512-zZapIKwaHp7TdTf9hbH1I3CVUdEupmt7FXO/BoTQGC+4h6NkXKWpqF2p5WyfpjurDLHCpSyh+BzMlAg8arqWLA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.76': + resolution: {integrity: sha512-1yzLmRiYSgGC25v7ZZEwJn/auhHHTIHgFOmzL2f36hf1+7jSLcX+1QrAz4760WEzPiiQl8xmlpFhHfl2OoyVzA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.65': + resolution: {integrity: sha512-e5DbbNteOSalN58U83G6kFa4ECLEuGbGqNBHIXE7zYXA/m4GHblIGjFbSH7wYv6gBV8iNSDcRZBKfQZF5vF9nw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.973.9': + resolution: {integrity: sha512-0V0u4t+KBku9fbh5CPCaC5hUWwSzDafp8nCuDy817zWbp2gz80jO44rMQkiwnZ+k54B+tjAtzRy00DJRGTKGBg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.71': + resolution: {integrity: sha512-e4dwiRltGAaQ+2yxw57Hj0l/BF3BHiG14+QpYE7bGYBlpAq/fkIri2BDhjWon8c0mhhtd2txQBAkQb9BcTStFg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/eventstream-handler-node@3.972.31': + resolution: {integrity: sha512-/BRzvkp46mF6eXBL/l9WKPQQfifLlUPaWli6n9/T/WDLUg8he7TCyuNFnk6RvHP5j5W/kMj5Gxw7W778LJaXDA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-eventstream@3.972.26': + resolution: {integrity: sha512-2eIvouTZoxPu5ClHY6ij13De1yhY8Rmllt0dlGeBNXX3wmR7fU1pvMCGb50fKm1GxcuntWK0t1T0cMjTyDoUQA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.972.70': + resolution: {integrity: sha512-APdP0iODt39AkjCjzTFIoFrxDH/Cz3CpWRDKLcsJg7eOnfE1htkxL9BhDoe/xL7cXdoMwh2HBYv3DiT1uf64NQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-websocket@3.972.47': + resolution: {integrity: sha512-UcPdY05u3TzvDah86NG6B9FgePYU6bXO7CRQIzQrieFL5xBBGajM7g1lCngmP4WA8EPed/kgT5CvM28cqSlBbA==} + engines: {node: '>= 14.0.0'} + + '@aws-sdk/nested-clients@3.997.39': + resolution: {integrity: sha512-wU5NPnj62Sb7A8xn/Zb+xThe05P3otNtDl37iOIi5DDMeCesNeCckaG+eXWGUs12Z9R34I8CD05TaTe6SIa61g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.996.43': + resolution: {integrity: sha512-lKekx8bLBXSv4O+cslk9Zfnw2XKSkWBs3uWL5QGhH2ZAQfNS7FE0vcSSN2vD/AhxX54ZTywWxR4STThoeOXlBA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1048.0': + resolution: {integrity: sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1100.0': + resolution: {integrity: sha512-THf3MkgY3fNJZ3zdgSenLqR7gSE68KccCj1RCKretlG73Ppszvues02VpCUO9NlB/tZDC483FvGCld+AiPCkvg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.974.2': + resolution: {integrity: sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-locate-window@3.965.8': + resolution: {integrity: sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/xml-builder@3.972.37': + resolution: {integrity: sha512-zKq4HQum8JwDyEuyfuI4bbiAcU0KxP6qy+9PR/IsR92IyE/DaBAikzAS50tjxip4bqIIANpCcG+Yyj6CVhXupg==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.3.0': + resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -973,6 +1271,39 @@ packages: '@blazediff/core@1.9.1': resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==} + '@borewit/text-codec@0.2.2': + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + + '@cbor-extract/cbor-extract-darwin-arm64@2.2.2': + resolution: {integrity: sha512-ZKZ/F8US7JR92J4DMct6cLW/Y66o2K576+zjlEN/MevH70bFIsB10wkZEQPLzl2oNh2SMGy55xpJ9JoBRl5DOA==} + cpu: [arm64] + os: [darwin] + + '@cbor-extract/cbor-extract-darwin-x64@2.2.2': + resolution: {integrity: sha512-32b1mgc+P61Js+KW9VZv/c+xRw5EfmOcPx990JbCBSkYJFY0l25VinvyyWfl+3KjibQmAcYwmyzKF9J4DyKP/Q==} + cpu: [x64] + os: [darwin] + + '@cbor-extract/cbor-extract-linux-arm64@2.2.2': + resolution: {integrity: sha512-wfqgzqCAy/Vn8i6WVIh7qZd0DdBFaWBjPdB6ma+Wihcjv0gHqD/mw3ouVv7kbbUNrab6dKEx/w3xQZEdeXIlzg==} + cpu: [arm64] + os: [linux] + + '@cbor-extract/cbor-extract-linux-arm@2.2.2': + resolution: {integrity: sha512-tNg0za41TpQfkhWjptD+0gSD2fggMiDCSacuIeELyb2xZhr7PrhPe5h66Jc67B/5dmpIhI2QOUtv4SBsricyYQ==} + cpu: [arm] + os: [linux] + + '@cbor-extract/cbor-extract-linux-x64@2.2.2': + resolution: {integrity: sha512-rpiLnVEsqtPJ+mXTdx1rfz4RtUGYIUg2rUAZgd1KjiC1SehYUSkJN7Yh+aVfSjvCGtVP0/bfkQkXpPXKbmSUaA==} + cpu: [x64] + os: [linux] + + '@cbor-extract/cbor-extract-win32-x64@2.2.2': + resolution: {integrity: sha512-dI+9P7cfWxkTQ+oE+7Aa6onEn92PHgfWXZivjNheCRmTBDBf2fx6RyTi0cmgpYLnD1KLZK9ZYrMxaPZ4oiXhGA==} + cpu: [x64] + os: [win32] + '@cfworker/json-schema@4.1.1': resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} @@ -1045,6 +1376,20 @@ packages: '@dotenvx/primitives@0.8.0': resolution: {integrity: sha512-VYJy0uhFm9zTJ1TxBaW/pA8bjbOM/OttaNMwZ1RHG4JKyRG7DhSdiqD1ipQoAyoD22olUtxbP78W9xY3Wd11bg==} + '@durable-streams/client@0.2.6': + resolution: {integrity: sha512-uHKKbWpsKLhFMeGjG0PgM6LXE3oEIi7FHKlJZkmYGxcqd4Yjjd/QEvnQnDzteRP4Av1uJVM8qjTL7kfKsgeS/w==} + engines: {node: '>=18.0.0'} + hasBin: true + + '@earendil-works/pi-agent-core@0.83.0': + resolution: {integrity: sha512-RorGp9OH5l3ElpuC5a5ZQ2eWcchZGXflXRzVGkV99y3y6tT+LLNyxoYIdVKvTKWEObwhExeQbTH0fI2tE4iX4g==} + engines: {node: '>=22.19.0'} + + '@earendil-works/pi-ai@0.83.0': + resolution: {integrity: sha512-m3IZD4g3er0V8TC9+Vpgw/sjTKqcJlkcIBy/JvsgRubuuik3tAVzyugUg4rVrShIkkOT69mEd34NEqKUIsl6JQ==} + engines: {node: '>=22.19.0'} + hasBin: true + '@egjs/hammerjs@2.0.17': resolution: {integrity: sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==} engines: {node: '>=0.8.0'} @@ -1067,6 +1412,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/aix-ppc64@0.28.1': resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} engines: {node: '>=18'} @@ -1079,6 +1430,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.28.1': resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} engines: {node: '>=18'} @@ -1091,6 +1448,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.28.1': resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} engines: {node: '>=18'} @@ -1103,6 +1466,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.28.1': resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} engines: {node: '>=18'} @@ -1115,6 +1484,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.28.1': resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} engines: {node: '>=18'} @@ -1127,6 +1502,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.28.1': resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} engines: {node: '>=18'} @@ -1139,6 +1520,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.28.1': resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} engines: {node: '>=18'} @@ -1151,6 +1538,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.28.1': resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} engines: {node: '>=18'} @@ -1163,6 +1556,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.28.1': resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} engines: {node: '>=18'} @@ -1175,6 +1574,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.28.1': resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} engines: {node: '>=18'} @@ -1187,6 +1592,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.28.1': resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} engines: {node: '>=18'} @@ -1199,6 +1610,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.28.1': resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} engines: {node: '>=18'} @@ -1211,6 +1628,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.28.1': resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} engines: {node: '>=18'} @@ -1223,6 +1646,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.28.1': resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} engines: {node: '>=18'} @@ -1235,6 +1664,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.28.1': resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} engines: {node: '>=18'} @@ -1247,6 +1682,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.28.1': resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} engines: {node: '>=18'} @@ -1259,6 +1700,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.28.1': resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} engines: {node: '>=18'} @@ -1271,6 +1718,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-arm64@0.28.1': resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} engines: {node: '>=18'} @@ -1283,6 +1736,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.28.1': resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} engines: {node: '>=18'} @@ -1295,6 +1754,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.28.1': resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} engines: {node: '>=18'} @@ -1307,6 +1772,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.28.1': resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} engines: {node: '>=18'} @@ -1319,6 +1790,12 @@ packages: cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/openharmony-arm64@0.28.1': resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} engines: {node: '>=18'} @@ -1331,6 +1808,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.28.1': resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} engines: {node: '>=18'} @@ -1343,6 +1826,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.28.1': resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} engines: {node: '>=18'} @@ -1355,6 +1844,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.28.1': resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} engines: {node: '>=18'} @@ -1367,6 +1862,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.28.1': resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} engines: {node: '>=18'} @@ -1574,12 +2075,58 @@ packages: '@floating-ui/utils@0.2.12': resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + '@flue/cli@2.0.1': + resolution: {integrity: sha512-uxZ5LkMFE9mIplnrH9ttKJVVmhts5ptSwsC/DMZGHeN5kZb4uq985t0y8mYSFEk7OIDrQFmaa/o3gJjfx2IlJQ==} + engines: {node: '>=22.19.0'} + hasBin: true + + '@flue/runtime@2.0.1': + resolution: {integrity: sha512-as+rrm8oHLuaLfpSReExwsuzOb1gC0sxQWgz3o+RvJUwHyGcQAcfBcn/R6j8logAq1j+ryfH1WsXf4J7Th9puQ==} + engines: {node: '>=22.19.0'} + + '@flue/sdk@2.0.1': + resolution: {integrity: sha512-RZGeZnpbkvzi2/BezNSSWRrhPuK7CIbIOsO3ETNucvWb/Vh+4/fgdb9XzYnGZdxpHWrmCSu4hMGr+OtbZXc/uQ==} + + '@flue/vite@2.0.1': + resolution: {integrity: sha512-J1BnbDbHZbboDx825Pt27Tlzr5mZ43SrjhFUYDmf4qVT9Ns67tVw6+paXEXMhkgJDT/ucM/trCnBe3pd4Qs/VA==} + engines: {node: '>=22.19.0'} + peerDependencies: + vite: ^8.0.0 + + '@google/genai@1.52.0': + resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.25.2 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + '@hono/node-server@2.0.12': resolution: {integrity: sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg==} engines: {node: '>=20'} peerDependencies: hono: ^4 + '@hono/node-server@2.0.3': + resolution: {integrity: sha512-a0jV+/HRe3G5zjFID3zObAQFdkl6zpxTuqktdDDXS3MJKcrZIkB8OkLpNBlY/WXFqv2HF4a0takPej+aNFczWA==} + engines: {node: '>=20'} + peerDependencies: + hono: ^4 + + '@hono/zod-openapi@1.5.1': + resolution: {integrity: sha512-ZaDdEIkn6PEGjIYHXJeyByg6yhvLzI+UXn968pWtahpwcQ6HMjQYXI3zNffTl0Wl9QZ79nUnGqiN1erEIu23fA==} + engines: {node: '>=16.0.0'} + peerDependencies: + hono: '>=4.10.0' + zod: ^4.0.0 + + '@hono/zod-validator@0.9.0': + resolution: {integrity: sha512-n0ZSXmCiHVIp4Y5wlOOyZCeTd/rsawA/qW1cipB8QOYKZ9N8Tk0nZUZCXho9cu374AN4JpDNKioNKBJ/W+LBug==} + peerDependencies: + hono: '>=4.11.2' + zod: ^3.25.0 || ^4.0.0 + '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} engines: {node: '>=18.18.0'} @@ -1604,12 +2151,24 @@ packages: resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} engines: {node: '>=18'} + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + '@img/sharp-darwin-arm64@0.35.2': resolution: {integrity: sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg==} engines: {node: '>=20.9.0'} cpu: [arm64] os: [darwin] + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + '@img/sharp-darwin-x64@0.35.2': resolution: {integrity: sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw==} engines: {node: '>=20.9.0'} @@ -1621,22 +2180,44 @@ packages: engines: {node: '>=20.9.0'} os: [freebsd] + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + '@img/sharp-libvips-darwin-arm64@1.3.1': resolution: {integrity: sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g==} cpu: [arm64] os: [darwin] + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + '@img/sharp-libvips-darwin-x64@1.3.1': resolution: {integrity: sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ==} cpu: [x64] os: [darwin] + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linux-arm64@1.3.1': resolution: {integrity: sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw==} cpu: [arm64] os: [linux] libc: [glibc] + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linux-arm@1.3.1': resolution: {integrity: sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg==} cpu: [arm] @@ -1661,24 +2242,49 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linux-x64@1.3.1': resolution: {integrity: sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A==} cpu: [x64] os: [linux] libc: [glibc] + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + libc: [musl] + '@img/sharp-libvips-linuxmusl-arm64@1.3.1': resolution: {integrity: sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw==} cpu: [arm64] os: [linux] libc: [musl] + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + libc: [musl] + '@img/sharp-libvips-linuxmusl-x64@1.3.1': resolution: {integrity: sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg==} cpu: [x64] os: [linux] libc: [musl] + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@img/sharp-linux-arm64@0.35.2': resolution: {integrity: sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA==} engines: {node: '>=20.9.0'} @@ -1686,6 +2292,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + libc: [glibc] + '@img/sharp-linux-arm@0.35.2': resolution: {integrity: sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A==} engines: {node: '>=20.9.0'} @@ -1714,6 +2327,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@img/sharp-linux-x64@0.35.2': resolution: {integrity: sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA==} engines: {node: '>=20.9.0'} @@ -1721,6 +2341,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@img/sharp-linuxmusl-arm64@0.35.2': resolution: {integrity: sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg==} engines: {node: '>=20.9.0'} @@ -1728,6 +2355,13 @@ packages: os: [linux] libc: [musl] + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@img/sharp-linuxmusl-x64@0.35.2': resolution: {integrity: sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg==} engines: {node: '>=20.9.0'} @@ -1744,6 +2378,12 @@ packages: engines: {node: '>=20.9.0'} cpu: [wasm32] + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + '@img/sharp-win32-arm64@0.35.2': resolution: {integrity: sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ==} engines: {node: '>=20.9.0'} @@ -1756,6 +2396,12 @@ packages: cpu: [ia32] os: [win32] + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@img/sharp-win32-x64@0.35.2': resolution: {integrity: sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ==} engines: {node: '>=20.9.0'} @@ -1796,6 +2442,122 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@mariozechner/clipboard-darwin-arm64@0.3.9': + resolution: {integrity: sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@mariozechner/clipboard-darwin-universal@0.3.9': + resolution: {integrity: sha512-BGGR4iA9Z2shAjI65eI5xtyb3LYNlDW9X3gxKxDbqtbnREohsrqznov6zpKoIrsRWpzlYVEdKphS7ksJ0/ndSQ==} + engines: {node: '>= 10'} + os: [darwin] + + '@mariozechner/clipboard-darwin-x64@0.3.9': + resolution: {integrity: sha512-4kURmCbS6nt8uYhtmWpUcJWyPHfmAr5dTpXD1nO3pIfa+TSQ9DbrGOYCKH+aEFW47XhQ4Vp8ZTszie+wfFvDKg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@mariozechner/clipboard-linux-arm64-gnu@0.3.9': + resolution: {integrity: sha512-g59OkUGP2DDfCOIKypHeYgv2M55u/cKvXa5dSxFbEJ34XvIQMdcVmpKCkGUro3ZgefXiGVdwguvTMQGpHWzIXw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@mariozechner/clipboard-linux-arm64-musl@0.3.9': + resolution: {integrity: sha512-AGuJdgKsmJdm4Pych7kv3sqe591ERRaAHW3xjLooiFzn8J+PxUyof++7YZrB5Y5tpnTO+K18Og3taj2NpluCRQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@mariozechner/clipboard-linux-riscv64-gnu@0.3.9': + resolution: {integrity: sha512-DXBEAiuMpk7dhS1a9NzNxVAFi1vaKoPu7rQNgY8LIDLGrK3lnIp3nT10DUum+PKVJoJppIP+NAA8IZe4DMNDPw==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@mariozechner/clipboard-linux-x64-gnu@0.3.9': + resolution: {integrity: sha512-WORrMLd6EpElEME7JRKfSaY34nW1P5LbdgK5YNCS1ncG2LqmITsSMEJ8nh2mpvxb3TxqbOOKgY7k9eMJYlW9Mw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@mariozechner/clipboard-linux-x64-musl@0.3.9': + resolution: {integrity: sha512-/DHn+1DrfL6oRaPPWXaOKvonFFrni666fxd+zFqiQEfvBH0tsHVWjq9iqBk0oDp0qaPA72lIMy5BptxISBEhZQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@mariozechner/clipboard-win32-arm64-msvc@0.3.9': + resolution: {integrity: sha512-O5FHD3ErkMwMhNzAfu3ggy0ug4z7btZuoQgwwxlzPrwV2bxlD6WDpqBY4NCgICAgZdDKdp+loUEKVAVt8aYnhQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@mariozechner/clipboard-win32-x64-msvc@0.3.9': + resolution: {integrity: sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@mariozechner/clipboard@0.3.9': + resolution: {integrity: sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA==} + engines: {node: '>= 10'} + + '@mariozechner/jiti@2.6.5': + resolution: {integrity: sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==} + hasBin: true + + '@mariozechner/pi-agent-core@0.60.0': + resolution: {integrity: sha512-1zQcfFp8r0iwZCxCBQ9/ccFJoagns68cndLPTJJXl1ZqkYirzSld1zBOPxLAgeAKWIz3OX8dB2WQwTJFhmEojQ==} + engines: {node: '>=20.0.0'} + deprecated: please use @earendil-works/pi-agent-core instead going forward + + '@mariozechner/pi-ai@0.60.0': + resolution: {integrity: sha512-OiMuXQturnEDPmA+ho7eLe4G8plO2z21yjNMs9niQREauoblWOz7Glv58I66KPzczLED4aZTlQLTRdU6t1rz8A==} + engines: {node: '>=20.0.0'} + deprecated: please use @earendil-works/pi-ai instead going forward + hasBin: true + + '@mariozechner/pi-coding-agent@0.60.0': + resolution: {integrity: sha512-IOv7cTU4nbznFNUE5ofi13k2dmSG39coBoGWIBQTVw3iVyl0HxuHbg0NiTx3ktrPIDNtkii+y7tWXzWqwoo4lw==} + engines: {node: '>=20.6.0'} + deprecated: please use @earendil-works/pi-coding-agent instead going forward + hasBin: true + + '@mariozechner/pi-tui@0.60.0': + resolution: {integrity: sha512-ZAK5gxYhGmfJqMjfWcRBjB8glITltDbTrYJXvcDtfengbKTZN0p39p5uO5pvUB8/PiAWKTRS06yaNMhf/LG26g==} + engines: {node: '>=20.0.0'} + deprecated: please use @earendil-works/pi-tui instead going forward + + '@microsoft/fetch-event-source@2.0.1': + resolution: {integrity: sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==} + + '@mistralai/mistralai@1.14.1': + resolution: {integrity: sha512-IiLmmZFCCTReQgPAT33r7KQ1nYo5JPdvGkrkZqA8qQ2qB1GHgs5LoP5K2ICyrjnpw2n8oSxMM/VP+liiKcGNlQ==} + + '@mistralai/mistralai@2.2.6': + resolution: {integrity: sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + + '@modelcontextprotocol/client@2.0.0': + resolution: {integrity: sha512-8f1OghQ2rjzIOfqgUCP+8GiUWqRs89njoWLNqAe8kWmDePv3s1fZXseej+QXemssEuuOvLLmLO/kqM3IQHtISw==} + engines: {node: '>=20'} + + '@modelcontextprotocol/core@2.0.0': + resolution: {integrity: sha512-pJCEwGG7Lfr/+PQp9ZTwKXNeO5wzbfKL7H3MYpCorM4oFBoQrdjnBgEoqG+RjhsvS1FKrDbKux+M1HhlnGWqcA==} + engines: {node: '>=20'} + '@modelcontextprotocol/sdk@1.30.0': resolution: {integrity: sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==} engines: {node: '>=18'} @@ -1836,6 +2598,11 @@ packages: cpu: [x64] os: [win32] + '@napi-rs/cli@2.18.4': + resolution: {integrity: sha512-SgJeA4df9DE2iAEpr3M2H0OKl/yjtg1BnRI5/JyowS71tUWhrfSu2LT0V3vlHET+g1hBVlrO60PmEXwUEKp8Mg==} + engines: {node: '>= 10'} + hasBin: true + '@napi-rs/wasm-runtime@1.1.6': resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} peerDependencies: @@ -2402,6 +3169,9 @@ packages: resolution: {integrity: sha512-titLmukUt/h8ho7Svlf0xSBjoy2ccZKrXjpXpZCj+v6V4CJccC2KyP45BLSCMx8YIpifMyiDyUptM4+5sruKbQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -2414,6 +3184,33 @@ packages: '@poppinss/exception@1.2.3': resolution: {integrity: sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + + '@protobufjs/eventemitter@1.1.1': + resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==} + + '@protobufjs/fetch@1.1.1': + resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.2': + resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==} + '@radix-ui/primitive@1.1.7': resolution: {integrity: sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==} @@ -2709,6 +3506,317 @@ packages: '@remix-run/node-fetch-server@0.13.3': resolution: {integrity: sha512-UfjOXed/DQteaM5VyTfqTeGpHwyL2J5aoRGY6cydip4tt1ehNNeSwuXCC7AEGE0RWBs/7bgKxYkL/B/+UDe4AA==} + '@rivet-dev/agent-os-core@0.1.1': + resolution: {integrity: sha512-Uw5jr+gUXDY7TDUFqlypjGe1BD2KL9kTHPNo/f1iNS1R+l9IWuvT+FF/MXsLOEkc3fB06OPVu2ZvUuNwp9MpLQ==} + + '@rivet-dev/agent-os-posix@0.1.0': + resolution: {integrity: sha512-NIrI7cCb9x6jdmzRPPx7dAeXoTF/YCqf93ydEzYFA2zshIelLW9Rp5KtgP/2hM6fP0ly4+vVnOeavxJW0wYtcA==} + + '@rivet-dev/agent-os-python@0.1.0': + resolution: {integrity: sha512-1tH1beMf1ceSpicQKwN/a6h+NmJrmfuT4GStiRDZmvN/UWfZhkxuy7HR5VPTQpE/feUZJ01FdtBS3Em/Qoxb2Q==} + peerDependencies: + pyodide: '>=0.28.0' + peerDependenciesMeta: + pyodide: + optional: true + + '@rivet-dev/agentos-core@0.2.15': + resolution: {integrity: sha512-uRg3BmbZzDUwWVmCTcd9Iuo1k8GJeuaXE3FnBbFGzAeI7I077KAhYlVejb9TBWHtjYcblVlMnl591vDm0DbpCQ==} + + '@rivet-dev/agentos-runtime-core@0.2.15': + resolution: {integrity: sha512-u8J9psQbu7gixzasyS8b7MiVXrrNPAGzk46DAGM3g8TwUZdP1muR1aa4FS7XePRmD3YWM5QrgCxFETl4gmE8vQ==} + + '@rivet-dev/agentos-runtime-sidecar-darwin-arm64@0.2.15': + resolution: {integrity: sha512-GN+OJjp8GLNyWSeRNp9Lh27ZWCW7O1RI95RXKCSQCn07d5Hj5QYLbIn7VYN1mpDzOfdbvhvSy5Re0kKU94FZFA==} + engines: {node: '>=20'} + cpu: [arm64] + os: [darwin] + + '@rivet-dev/agentos-runtime-sidecar-darwin-x64@0.2.15': + resolution: {integrity: sha512-3/4WGmd0MGDIYWSCVBvsdElZUEZ0YMZZdOP57hyYV3ut9pQdhnJPciqe6s46RBE78G+2ZtHGf/PgWyHL0zS2gA==} + engines: {node: '>=20'} + cpu: [x64] + os: [darwin] + + '@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu@0.2.15': + resolution: {integrity: sha512-OiUoHPmgOfbUGyPapmT6VBxXTKQBRyOc0O6MWALCc3dNy50C/Tb2K1lH3JlF9upUzcdp7g6HcqaDeja88tQujQ==} + engines: {node: '>=20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu@0.2.15': + resolution: {integrity: sha512-5QIF7C5rQqWf77Fd5tKj4vP8FPPmwIPsdd454CblFQerH5PPDSua5o44w38PyNMgi2tlWu2OTuiYloiOwyHo6g==} + engines: {node: '>=20'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rivet-dev/agentos-runtime-sidecar@0.2.15': + resolution: {integrity: sha512-8eemRmcqp5X9UdpzUD0vJbtG29Ip34n6ulUIFI+ewGXRAxJ+aU5+iqdfRxjYaW71t6zc7r/tMbUSLaPkwMsZqA==} + engines: {node: '>=20'} + + '@rivet-dev/agentos-sidecar-darwin-arm64@0.2.15': + resolution: {integrity: sha512-2csTR3/C3KmNTZln1/u3xU6pKVB/0RdG+MqW3AP2OmS/Q5Lucdd4Y6tnxZGg/ku6Q+Pw9KLOTEuFW1p8cQi1Ig==} + engines: {node: '>=20'} + cpu: [arm64] + os: [darwin] + + '@rivet-dev/agentos-sidecar-darwin-x64@0.2.15': + resolution: {integrity: sha512-xUDxTXARNbQY1Jq0JjxN7D9sfv8iEff4nYnBQR2efo/L5HBObT/fRO2gT+zwUZSRGHnEJCb8gvDxFYc/Th/sqg==} + engines: {node: '>=20'} + cpu: [x64] + os: [darwin] + + '@rivet-dev/agentos-sidecar-linux-arm64-gnu@0.2.15': + resolution: {integrity: sha512-5pzCqLcHYluESd9c6aIohi2x6A7K8vli0DnmkMJwHXJilQyqmjZz8Y0m6Ggi+0jGi2Idad46SzzC1Z7uRrO5Ow==} + engines: {node: '>=20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rivet-dev/agentos-sidecar-linux-x64-gnu@0.2.15': + resolution: {integrity: sha512-2byoXX4ol1PKOvvtPxUk0BgPTv+mlOCX6nXKOsb4Z6OY7OwhMn+z+um1VpWxwMyU8gBS3oG12ungDmVmH8aIYw==} + engines: {node: '>=20'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rivet-dev/agentos-sidecar@0.2.15': + resolution: {integrity: sha512-XvABEkqiA/zLqcOM8AgYvRxxbg8dMviR1D/66GWgEWOAMjcqfn1kXFrsL1d0WbKEn7nwUfguKQVV4weeR3oF5g==} + engines: {node: '>=20'} + + '@rivet-dev/agentos@0.2.15': + resolution: {integrity: sha512-NLJjFNVD0uP/EzGfGOcDaZ+GMx595P9sps/A2aLn+xb/KPUqpc+mxmZi8VYhCj2cr20QBa6jhfA2Ohf+0r72Mg==} + engines: {node: '>=22.0.0'} + peerDependencies: + react: 19.2.8 + react-dom: 19.2.8 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + + '@rivetkit/bare-ts@0.6.2': + resolution: {integrity: sha512-3qndQUQXLdwafMEqfhz24hUtDPcsf1Bu3q52Kb8MqeH8JUh3h6R4HYW3ZJXiQsLcyYyFM68PuIwlLRlg1xDEpg==} + engines: {node: ^14.18.0 || >=16.0.0} + + '@rivetkit/engine-cli-darwin-arm64@2.3.10': + resolution: {integrity: sha512-hu9rfesS9RnmIoGo0z+6YEroeZavaohYmwsc5K5//SPDfUl83mZirU4sWNjo5N2CQz+Y1fEyXcZTcnulF72rvA==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [darwin] + + '@rivetkit/engine-cli-darwin-arm64@2.3.9': + resolution: {integrity: sha512-4mXfCo48055pnNViS+2WjC8p57eLLzLw1ZNgL0b7AoaPpxJ4YKXJ9F8TezSHtTc5ScXtPdfZb5jH4n/e6ePSMA==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [darwin] + + '@rivetkit/engine-cli-darwin-x64@2.3.10': + resolution: {integrity: sha512-l5pgExB9lBt5UeNj9NOZHQv/oQCEMLuirCDAKidOU0bMD9LI2TV0S/JHWG7IWyBf34SEv+/Zo+LC4JoB8iu82Q==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [darwin] + + '@rivetkit/engine-cli-darwin-x64@2.3.9': + resolution: {integrity: sha512-BiNPd5KWKFp9H3xWZqeILJ9bmz7c04fYAAwXWtqmAWfGMBCd11QAGsJFwDnoHsMQhEGpDzbYg5L0KbKUD4HIMA==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [darwin] + + '@rivetkit/engine-cli-linux-arm64-musl@2.3.10': + resolution: {integrity: sha512-opLAOm1Up5BrYk+T3p5yHQ9e5ZtWSjVfA0LyNllYKHNyYJ+L6cxosVBf1uakyENS8ytYu92R6fhQZOUQyjgevA==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [linux] + + '@rivetkit/engine-cli-linux-arm64-musl@2.3.9': + resolution: {integrity: sha512-xbtUVXPK9aMcJgaA9XcLnZ52J9a9YXUWAP7pk9uHY7rRYODOwC8rRReiyeD++/+7+YsciwcIDcHb4daLHrN4tg==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [linux] + + '@rivetkit/engine-cli-linux-x64-musl@2.3.10': + resolution: {integrity: sha512-q0WDESrssRNzVSqmnNgaLt2D8wjYhVPiiJi96kDIaatWAXvPHd7SPN4gNHdvRVUD0hImOEQDw1u3NGRyi7TBkg==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [linux] + + '@rivetkit/engine-cli-linux-x64-musl@2.3.9': + resolution: {integrity: sha512-0OqFgoV4nvRJKtgXEELpwTLKuFJu6DaffG+l9xkDUdcTsf/tAgk5oNU1CLgGK0JsuT77JFucAqVd93pOEWSKhg==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [linux] + + '@rivetkit/engine-cli-win32-x64@2.3.10': + resolution: {integrity: sha512-VnNn3R6YpMzrDauCVZRmt1L2/oUax+KQmOFSiXQwo7JPt2MdZaa5Z5ISWVD51c1/xCPiMiLDsL6V9mjpJculzw==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [win32] + + '@rivetkit/engine-cli-win32-x64@2.3.9': + resolution: {integrity: sha512-Pqr6YAM49vbDUhg6olE07wvIk0AhiEhoHFDoZWxfGLnnNAbZNKEa72j7rOZa0mXMe1JPCTRfG7zG85bIH6y4tQ==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [win32] + + '@rivetkit/engine-cli@2.3.10': + resolution: {integrity: sha512-7NoyfdT8Qk5bBOqnFgsDF2baL0BISNvWNB0mWsjA/AHRqrwg+RCQbTvkWy1iPCUr8/EdndMsNIwjxA1s8vGYwQ==} + engines: {node: '>= 20.0.0'} + + '@rivetkit/engine-cli@2.3.9': + resolution: {integrity: sha512-6sFgD0h5Z6aTioerwCNw3WF0jRysEhJhOlQHHVdnL32KzXfZoAcJLvS3dW/M1IAKydND/MsVwSQjPSYPjTy4UQ==} + engines: {node: '>= 20.0.0'} + + '@rivetkit/engine-envoy-protocol@2.3.10': + resolution: {integrity: sha512-AqYekBbHrxuUOrup2oo+iSBP80ZbI1Jp8euk0rRaaxkwlnWQO3p2ymMOLHW+jaQ6zK6g4f41aSq0l1ji8SoWZA==} + + '@rivetkit/engine-envoy-protocol@2.3.9': + resolution: {integrity: sha512-2IK41V9U8sgMnEYd/P6u/68nCufCU2dvxuHVV3uAV0uIVCdtRV8lkjuR2fSr05bwHmzSmewdqsbiNMiC/GWt8w==} + + '@rivetkit/framework-base@2.3.9': + resolution: {integrity: sha512-ZSxrclYcpmdGsLMiVE2dfWNfUB6diSx+t8k4EQgL4cN02ThzJD3BM5mhU+zQVCCwfNw42eRZVIoxydYDLl/yHw==} + + '@rivetkit/on-change@6.0.1': + resolution: {integrity: sha512-QBN/KRBXLJdCgN4gBTL3XAc/zKm58atSnieXWMOyFSPmo6F1/yIVV/LTRdvAktfCttrGx7W6c32i/lwqCHWnsQ==} + engines: {node: '>=20'} + + '@rivetkit/react@2.3.9': + resolution: {integrity: sha512-j9t82h/yIqqSt17coQZeRu3F9Q5w2FgWPDUC9fCyQUJp9PTjO7ea494PR0lSWvuEiwMRqE5JpgbHdYUQ1woE9w==} + peerDependencies: + react: 19.2.8 + react-dom: 19.2.8 + + '@rivetkit/rivetkit-napi-darwin-arm64@2.3.10': + resolution: {integrity: sha512-/E//AAI/jSMjuSMjWs05sQR6XFrplN8Ni0kuvmpDM9ds+AlcIgScDdRgBgleus9QLMU8aGEz3MrBNO9q4FGwVQ==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [darwin] + + '@rivetkit/rivetkit-napi-darwin-arm64@2.3.9': + resolution: {integrity: sha512-3Ls1gHUeYs1mByNDgt1H3s3b9gZaXyyFrrCagoK2HrBAr0celfMa2zh0fH1BrjZufyF5oC/Jvk3ALPCFCNf4EQ==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [darwin] + + '@rivetkit/rivetkit-napi-darwin-x64@2.3.10': + resolution: {integrity: sha512-U+nzDsGgrslECZ7NxoUm1vvWlO+XxXNoFuBu2eefHkm9J06vXCrSPkiY/kAFa7rhcD9UA1MsNheUxC68BmKeXg==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [darwin] + + '@rivetkit/rivetkit-napi-darwin-x64@2.3.9': + resolution: {integrity: sha512-tsX60L7RXD9BnMU+0b8YnKfuAqYfH8sr6DnUAWk2z2Nnmc7E11RibVWSeny/+2LxD5Zib3f3G7Ea/Pt/NF+ypA==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [darwin] + + '@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.10': + resolution: {integrity: sha512-2uiQOJ5CsRvB6lqhYwezRWBZxuKVs6n0aPsRCdEggLPTEUcsx43ODcVVbkbg0aDM3qE+1itWjzOu086xhqGTQg==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.9': + resolution: {integrity: sha512-Ov1c40CgIXMiOOo8sLLDO4cCcUw3+H/8OMOYoa7a5a5snmbJlDLSi0YYACWGRcBJvCGrjeDtQGIN3JISTL8Q9Q==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.10': + resolution: {integrity: sha512-jad0eDH9MIn2VG3Dsu+UOtQyz3X3V4sBgp7VfiqHtjtV2wqVbGnDEQbdcQK6xCDQrPNFsUbGNznzDa1C/4l3Pg==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.9': + resolution: {integrity: sha512-HgK83QYfT45HI+Ly+gWuoxWDSFzTgYJm0rFlmuOz8zweTirZ4ixHEE/lIQVU16lkHl4cO7PcRbQ1vUeQJMmVtA==} + engines: {node: '>= 20.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.10': + resolution: {integrity: sha512-l2wphS5wSl8xpje743/NYd9gl02FVh4qtqDQPk/LNA/WBT5WkdkkWhhTLiKiTMMA1L309XMQLH3iZbNq1yXFFg==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.9': + resolution: {integrity: sha512-GvGfGUpCpFGWzQdA5Yey5Y5ih+J6Ay/chEwa10UlzF4MC4bX0GM//0m2FXLFUXtBjNRNdhKvAAaXWdWBuZQsSw==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rivetkit/rivetkit-napi-linux-x64-musl@2.3.10': + resolution: {integrity: sha512-kdhVxFm8z7HWG7LWqt1TBi1ye7VDNhgqq3acsh2NlpCHPJ19aElu2yiHR2F4jh1zFZU5SpAKHJGKNbfIqGO4/Q==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rivetkit/rivetkit-napi-linux-x64-musl@2.3.9': + resolution: {integrity: sha512-J48W7iLoqE8i1n1TvhxkxFrwJTxOsdXrVf7HyXUsEyLrb+kal/aS+/ta+Bfq/veJ7wZyDw7YkOIdn0BgPinIuQ==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.10': + resolution: {integrity: sha512-KQdLH8sXyAKF0fEzpFeXl8AZwTObl/G4nT21BQy8B+pba2os9DUjOVy8k/bTiZzcvy8FvaL9KerfVH4Pr8yg4w==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [win32] + + '@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.9': + resolution: {integrity: sha512-3oZYh56m3wTVAbipHI5Rnqw1vSTI1fzoksdm1x4a45TgKi1ULxPyl2fT2E9A/Jyn1LzfTfztazN6mX0//kxmxg==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [win32] + + '@rivetkit/rivetkit-napi@2.3.10': + resolution: {integrity: sha512-nkaimgCcSPVZn+dGhlHMrrxVJrUwujhPlSznxehUWCaG6lR1gIysvlZucdiBTYF1iEKzzmvGqao1z25l1NVWAg==} + engines: {node: '>= 20.0.0'} + + '@rivetkit/rivetkit-napi@2.3.9': + resolution: {integrity: sha512-lUuOK1ja6ZMwnNRsdtqJeXChbBEqyvHuI/1h5XQWHfBUu7DgX5zuyA/FJ+BY6YFWtwnkHnOVCBJeNx/3gj8Xhg==} + engines: {node: '>= 20.0.0'} + + '@rivetkit/rivetkit-wasm@2.3.10': + resolution: {integrity: sha512-90czUWCMQa8mAMkHg/jSUGud0jemNJeU6XHeBw5izzE3kdELo8bWBlF06rprMJV6VOwwdPfluID0FrBmZpuNgQ==} + + '@rivetkit/rivetkit-wasm@2.3.9': + resolution: {integrity: sha512-KRCKnk0h3dvzuLHHDTKdguSCaZdDpeza4XucYi2+XZaZUJUP1zNxCHfKvQRZ1FaGhPx9rhZJTGV19+lLOWKSwA==} + + '@rivetkit/traces@2.3.10': + resolution: {integrity: sha512-CNYz8hJOR0o77wiUQbbWh24Qj6lQk/eH0lJXfHHUisYBsjyZKnN0TlSVfhAIf7UnSMh9ASMuTwPx8s2Yz53xVA==} + engines: {node: '>=18.0.0'} + + '@rivetkit/traces@2.3.9': + resolution: {integrity: sha512-T0og48gPh6RjIdwEuG7mEKOuxVA3R/Zcptf67z8dHVF78yuzHooeW0W0rvH6wlu4XGINWvYhGHMGY0uh4uyPEw==} + engines: {node: '>=18.0.0'} + + '@rivetkit/virtual-websocket@2.3.10': + resolution: {integrity: sha512-CQhhys540fASByQzbu7YqRlKlIziL9FwI/mzAS0NGg+AZMiHc6YhB/cJw/LJ1VYrEQjbm83XFkUr6i6pRnZVNw==} + + '@rivetkit/virtual-websocket@2.3.9': + resolution: {integrity: sha512-exWO75dBB81w3ipXRg7twXY0SYQyDsB9ELJVhi1LtmWnmCn4FnHlzfinZKZlFAf5C9L0m9XAbJGS3WfRGRGlUg==} + + '@rivetkit/workflow-engine@2.3.10': + resolution: {integrity: sha512-+1VcVsWbmCd608tgqrVndMF8jWGCNflXSXmP8NYJnq7uEBcBcQy1bkCdcD1rckAkRkfefXqfW0ReNgLv202elg==} + engines: {node: '>=18.0.0'} + + '@rivetkit/workflow-engine@2.3.9': + resolution: {integrity: sha512-RqbXdQYc2z/PCLwOyi14iimE/+m0v7Oq7DKuzdAxs4Y1jqslUZurkn3B40pjhaNN2Kz212BJXnbmaK4YHE/q8g==} + engines: {node: '>=18.0.0'} + '@rolldown/binding-android-arm64@1.1.4': resolution: {integrity: sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2916,6 +4024,35 @@ packages: '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + '@secure-exec/core@0.2.1': + resolution: {integrity: sha512-HsnUv6gClpMA1BBRmX86j30TKTZtgJC/fO1tVavr7IpM2zNKbHU8LgSlBd7mv2SNy02ImTmU/GnQ3aYB4NSbEg==} + + '@secure-exec/nodejs@0.2.1': + resolution: {integrity: sha512-UJMJqVFxexlHJV0Q9nWURvrz6GElj8673DDOOFln6FHR6JS+9SaSU3eISrN158DuNC3SFi4rgjb/scKnK4YOYQ==} + + '@secure-exec/v8-darwin-arm64@0.2.1': + resolution: {integrity: sha512-gEWhMHzUpLwzuBNAD0lVkZXE8wFlWMLp4IOZ+56FYwOW/C+m07cYxuW4TjHyPqZ+vPm3IkoaMqqH5yT9VhjX/Q==} + cpu: [arm64] + os: [darwin] + + '@secure-exec/v8-darwin-x64@0.2.1': + resolution: {integrity: sha512-H2Z5K+Cq+fn/kxjGvhJzepnNFWG6qNdyhZybVWGr5bAAZoSz/Qkad4WnXcurWU+880tKDtnf19LHBXrg7zewNQ==} + cpu: [x64] + os: [darwin] + + '@secure-exec/v8-linux-arm64-gnu@0.2.1': + resolution: {integrity: sha512-14subGhVV/gW35mYYm7Gv1Keeex7PxIgQfoKji/JH7wYyDuarP6kgaES0nJw+JXVkxEVud52c+kbcIjIggqCEw==} + cpu: [arm64] + os: [linux] + + '@secure-exec/v8-linux-x64-gnu@0.2.1': + resolution: {integrity: sha512-Az4s+vUf+78vWtsC7rTn/jQc6WKJafAdt2YpEjB4Gnu+sX+FFTIst1hRV4gJonbRyJdy6SW+OQ6DZatmwczorQ==} + cpu: [x64] + os: [linux] + + '@secure-exec/v8@0.2.1': + resolution: {integrity: sha512-ye/seCqzvyMGnvyP+AO7RkVMR/lE3x9m0D2PfmiAXA457R78ZmOFmZ6v+JlJG2vv3LM30KsSXTUhwpG+Teh0hw==} + '@shadcn/react@0.2.1': resolution: {integrity: sha512-5krgi3dRMKb5jH6a+qPzVJUy/54s0kKE4Rw4LjDfLqOdVQTWKUgxWf1kW8r912I0jX/Lzxqc+pgjkjWxUIK5BQ==} peerDependencies: @@ -2927,9 +4064,15 @@ packages: react: optional: true + '@silvia-odwyer/photon-node@0.3.4': + resolution: {integrity: sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==} + '@sinclair/typebox@0.27.12': resolution: {integrity: sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==} + '@sinclair/typebox@0.34.52': + resolution: {integrity: sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==} + '@sindresorhus/is@7.2.0': resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} engines: {node: '>=18'} @@ -2938,6 +4081,46 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} + '@smithy/core@3.31.1': + resolution: {integrity: sha512-CyogUINxvi7C7LDsh8Syo6hVJOT9ckz4rG8dRZfTJ8r91HkMY59PnNooaj7WcHyxEkxPfBAmbgztZU+xTo76lg==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.4.16': + resolution: {integrity: sha512-QfuLWAkLzptffFW980AFeHZFdqds2B64rpEd3uJ6lgs3xVn9QegGMUgUcj+4d7dRrAsya3r58ZKpku97WcFb4w==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.6.13': + resolution: {integrity: sha512-4fW86pEUOMbrD5nkbyl/tTvPHHWJFbuB2odl6ps9lWfHoXf9HWh3Q/Smh59qH1g7+c/BSZghX6bbUk4gsiMs8A==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/node-http-handler@4.7.3': + resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.9.13': + resolution: {integrity: sha512-Nmd/Nl35zfYrd+a6OO2cDJb3GPh9bgTjIUhcM+JFfjpp8/osCgboDV5nCT1I01Pv6R13eSKDKLSoVa5ZB6Zsfw==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.6.12': + resolution: {integrity: sha512-I6KLtq3H0qqSuV9vLglfi8puHqzygzWHOnI4z/Rdoo+q50vvo18vBRdPAvvEtcaKROz7Zn6qnPa14kRfPH6PcQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.16.1': + resolution: {integrity: sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + '@solid-primitives/event-listener@2.4.6': resolution: {integrity: sha512-5I0YJcTVYIWoMmgBSROBZGcz+ymhew/pGTg2dHW74BUjFKsV8Li4bOZYl0YAGP4mHw5o4UBd9/BEesqBci3wxw==} peerDependencies: @@ -3159,9 +4342,18 @@ packages: react: 19.2.8 react-dom: 19.2.8 + '@tanstack/react-store@0.7.7': + resolution: {integrity: sha512-qqT0ufegFRDGSof9D/VqaZgjNgp4tRPHZIJq2+QIHkMUtHjaJ0lYrrXjeIUJvjnTbgPfSD1XgOMEt0lmANn6Zg==} + peerDependencies: + react: 19.2.8 + react-dom: 19.2.8 + '@tanstack/store@0.11.0': resolution: {integrity: sha512-WlzzCt3xi0G6pCAJu1U+2jiECwabETDpQDi3hfkFZvJii9AuZqEKbOiVarX1/bWhTNjU486yQtJCCasi/0q+Cw==} + '@tanstack/store@0.7.7': + resolution: {integrity: sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ==} + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -3172,6 +4364,16 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + '@ts-morph/common@0.11.1': resolution: {integrity: sha512-7hWZS0NRpEsNV8vWJzg7FEz6V8MaLNeJOmwmghqUXTpzk16V1LLZhdo+4QvE/+zv4cVci0OviuJFnqhEfoV3+g==} @@ -3217,6 +4419,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/mime-types@2.1.4': + resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} + '@types/node@22.20.1': resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==} @@ -3234,6 +4439,12 @@ packages: '@types/react@19.2.17': resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + '@types/validate-npm-package-name@4.0.2': resolution: {integrity: sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==} @@ -3243,6 +4454,9 @@ packages: '@types/yargs@17.0.35': resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + '@typescript-eslint/project-service@8.65.0': resolution: {integrity: sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3403,10 +4617,19 @@ packages: '@ungap/structured-clone@1.3.3': resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} + '@valibot/to-json-schema@1.7.1': + resolution: {integrity: sha512-3qkmU6KXWh8GIThEAW3kuRHPQBMjWkKy+Ppz3WkUucx53DTpOa6siMn4xDGSOhlVyMrDaJTCTMLYPZVAIk1P0A==} + peerDependencies: + valibot: ^1.4.0 + '@vercel/config@0.5.5': resolution: {integrity: sha512-U0QX7p08vgk8D47HI74wYyRuDJ2IYHbFQyfVdwO81Xchjp5CsV58/xhkV4EAXXj4NuLuELBwdPDa6oOdCYvEhg==} hasBin: true + '@vercel/detect-agent@1.2.3': + resolution: {integrity: sha512-VYNCgUc0nOmC4WJmWw9GkrKdfr8Zl4/rxhC5SvgacBgxiW9W/9NRttUoHHXV8xdII3MaRgkZZVX8Ikzc/Jmjag==} + engines: {node: '>=14'} + '@vercel/react-router@1.3.1': resolution: {integrity: sha512-cDUoEJUjeC1nf5u+LIae5e2YFUWJhKT7EpDveys7uk6zxmAHCj6swkaEf5gZPN597wcc+O0aGeK7xt7J/TRRRA==} peerDependencies: @@ -3607,6 +4830,9 @@ packages: resolution: {integrity: sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==} engines: {node: '>=14.6'} + '@xterm/headless@6.0.0': + resolution: {integrity: sha512-5Yj1QINYCyzrZtf8OFIHi47iQtI+0qYFPHmouEfG8dHNxbZ9Tb9YGSuLcsEwj9Z+OL75GJqPyJbyoFer80a2Hw==} + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -3698,6 +4924,9 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -3710,18 +4939,36 @@ packages: asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + + assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + ast-types@0.16.1: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + atomically@1.7.0: resolution: {integrity: sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==} engines: {node: '>=10.12.0'} + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + babel-dead-code-elimination@1.0.12: resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==} @@ -3789,6 +5036,10 @@ packages: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} + basic-ftp@5.3.1: + resolution: {integrity: sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==} + engines: {node: '>=10.0.0'} + better-auth@1.6.15: resolution: {integrity: sha512-0nuQuEru3ZrLF+9xFUuN3llAmR+6gHLtLunoXaZxB9lXGjSmfBcc6SZUgYq4DfzugPnLvdnzYazsyprZFSFC4Q==} peerDependencies: @@ -3867,6 +5118,9 @@ packages: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} @@ -3876,6 +5130,12 @@ packages: blake3-wasm@2.1.5: resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + bn.js@4.12.5: + resolution: {integrity: sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ==} + + bn.js@5.2.5: + resolution: {integrity: sha512-Vq886eXykuP5E6HcKSSStP3bJgrE6In5WKxVUvJ8XGpWWYs2xZHWqUwzCtGgEtBcxyd57KBFDPFoUfNzdaHCNg==} + body-parser@2.3.0: resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} engines: {node: '>=18'} @@ -3883,6 +5143,9 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + bowser@2.14.1: + resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + bplist-creator@0.1.0: resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==} @@ -3905,6 +5168,32 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browser-resolve@2.0.0: + resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + + browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + + browserify-rsa@4.1.1: + resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} + engines: {node: '>= 0.10'} + + browserify-sign@4.2.6: + resolution: {integrity: sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==} + engines: {node: '>= 0.10'} + + browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + browserslist@4.28.7: resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -3913,12 +5202,24 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + builtin-status-codes@3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + bun-types@1.3.14: resolution: {integrity: sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ==} @@ -3930,10 +5231,18 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + cac@7.0.0: + resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} + engines: {node: '>=20.19.0'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + call-bound@1.0.4: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} @@ -3949,6 +5258,13 @@ packages: caniuse-lite@1.0.30001806: resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + cbor-extract@2.2.2: + resolution: {integrity: sha512-hlSxxI9XO2yQfe9g6msd3g4xCfDqK5T5P0fRMLuaLHhxn4ViPrm+a+MUfhrvH2W962RGxcBwEGzLQyjbDG1gng==} + hasBin: true + + cbor-x@1.6.5: + resolution: {integrity: sha512-yO64CxnSh6kp+pHNRK9IfwnMvCB+c8HvmUjQY/9l9YRF0/cAPka/tUHLwS64QqUpFCq3/OtbKziVJYXH2EaRig==} + chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} @@ -3990,9 +5306,16 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} + cipher-base@1.0.7: + resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} + engines: {node: '>= 0.10'} + citty@0.2.2: resolution: {integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==} + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -4007,10 +5330,18 @@ packages: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} + cli-highlight@2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -4100,6 +5431,12 @@ packages: resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} engines: {node: '>= 0.10.0'} + console-browserify@1.2.0: + resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} + + constants-browserify@1.0.0: + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + content-disposition@1.1.0: resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} engines: {node: '>=18'} @@ -4179,6 +5516,9 @@ packages: core-js-compat@3.49.0: resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.6: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} @@ -4192,10 +5532,30 @@ packages: typescript: optional: true + create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + croner@10.0.1: + resolution: {integrity: sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g==} + engines: {node: '>=18.0'} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crypto-browserify@3.12.1: + resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} + engines: {node: '>= 0.10'} + css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} @@ -4262,6 +5622,14 @@ packages: resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} engines: {node: '>=12'} + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + dayjs@1.11.21: resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} @@ -4328,6 +5696,10 @@ packages: defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} @@ -4336,9 +5708,17 @@ packages: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + defu@6.1.7: resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -4347,6 +5727,9 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -4359,6 +5742,9 @@ packages: resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} engines: {node: '>=0.3.1'} + diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dnssd-advertise@1.1.6: resolution: {integrity: sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg==} @@ -4371,6 +5757,10 @@ packages: dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + domain-browser@4.22.0: + resolution: {integrity: sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==} + engines: {node: '>=10'} + domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} @@ -4389,10 +5779,105 @@ packages: resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} + drizzle-orm@0.44.7: + resolution: {integrity: sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=4' + '@electric-sql/pglite': '>=0.2.0' + '@libsql/client': '>=0.10.0' + '@libsql/client-wasm': '>=0.10.0' + '@neondatabase/serverless': '>=0.10.0' + '@op-engineering/op-sqlite': '>=2' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1.13' + '@prisma/client': '*' + '@tidbcloud/serverless': '*' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@upstash/redis': '>=1.34.7' + '@vercel/postgres': '>=0.8.0' + '@xata.io/client': '*' + better-sqlite3: '>=7' + bun-types: '*' + expo-sqlite: '>=14.0.0' + gel: '>=2' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + prisma: '*' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + '@libsql/client-wasm': + optional: true + '@neondatabase/serverless': + optional: true + '@op-engineering/op-sqlite': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@prisma/client': + optional: true + '@tidbcloud/serverless': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@upstash/redis': + optional: true + '@vercel/postgres': + optional: true + '@xata.io/client': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + gel: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -4402,6 +5887,9 @@ packages: electron-to-chromium@1.5.396: resolution: {integrity: sha512-yHiw2Y3C3H9U6TMbOfoWK/BPreiOPXRfTWPBwQBoZG6/8TB6eOPnsy5oaRYuatR7Fw2SJ4kKforgufeo7fq0EQ==} + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -4452,6 +5940,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.3.1: resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} @@ -4464,6 +5955,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true + esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} engines: {node: '>=18'} @@ -4484,6 +5980,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-scope@9.1.2: resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} @@ -4542,6 +6043,10 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + eventsource-parser@3.1.0: resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} engines: {node: '>=18.0.0'} @@ -4550,6 +6055,9 @@ packages: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -4669,6 +6177,14 @@ packages: exsolve@1.1.1: resolution: {integrity: sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + fast-check@4.9.0: resolution: {integrity: sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg==} engines: {node: '>=12.17.0'} @@ -4709,6 +6225,12 @@ packages: fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fdb-tuple@1.0.0: + resolution: {integrity: sha512-8jSvKPCYCgTpi9Pt87qlfTk6griyMx4Gk3Xv31Dp72Qp8b6XgIyFsMm8KzPmFJ9iJ8K4pGvRxvOS8D0XGnrkjw==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -4718,6 +6240,10 @@ packages: picomatch: optional: true + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + fetch-nodeshim@0.4.10: resolution: {integrity: sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==} @@ -4729,6 +6255,10 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + file-type@21.3.4: + resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} + engines: {node: '>=20'} + file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} @@ -4768,6 +6298,14 @@ packages: fontfaceobserver@2.3.0: resolution: {integrity: sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==} + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -4812,6 +6350,26 @@ packages: fuzzysort@3.1.0: resolution: {integrity: sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==} + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + + gaxios@7.3.0: + resolution: {integrity: sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==} + engines: {node: '>=18'} + + gcp-metadata@6.1.1: + resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} + engines: {node: '>=14'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -4836,6 +6394,10 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -4844,6 +6406,10 @@ packages: resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} engines: {node: '>=18'} + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + getenv@2.0.0: resolution: {integrity: sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==} engines: {node: '>=6'} @@ -4871,6 +6437,30 @@ packages: peerDependencies: csstype: ^3.0.10 + google-auth-library@10.9.1: + resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==} + engines: {node: '>=18'} + + google-auth-library@9.15.1: + resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} + engines: {node: '>=14'} + + google-logging-utils@0.0.2: + resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} + engines: {node: '>=14'} + + google-logging-utils@1.1.3: + resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} + engines: {node: '>=14'} + + googleapis-common@7.2.0: + resolution: {integrity: sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==} + engines: {node: '>=14.0.0'} + + googleapis@144.0.0: + resolution: {integrity: sha512-ELcWOXtJxjPX4vsKMh+7V+jZvgPwYMlEhQFiu2sa9Qmt5veX8nwXPksOWGGN6Zk4xCiLygUyaz7xGtcMO+Onxw==} + engines: {node: '>=14.0.0'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -4878,6 +6468,10 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -4886,10 +6480,28 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hash-base@3.0.5: + resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} + engines: {node: '>= 0.10'} + + hash-base@3.1.2: + resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} + engines: {node: '>= 0.8'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + hasown@2.0.4: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} @@ -4935,6 +6547,12 @@ packages: react-native-screens: optional: true + highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -4942,14 +6560,29 @@ packages: resolution: {integrity: sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==} engines: {node: '>=16.9.0'} + hono@4.12.34: + resolution: {integrity: sha512-GqXJqY/xJkJmuloTrnV1ZEXG3fqte+VjkUqoRNZXcrUidiUOP4fMSIHHY4tsqZBK++kVyWmt/AAfSUuy57/eSA==} + engines: {node: '>=16.9.0'} + hosted-git-info@7.0.2: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} + hosted-git-info@9.0.3: + resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==} + engines: {node: ^20.17.0 || >=22.9.0} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-browserify@1.0.0: + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -4973,6 +6606,14 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + ignore@7.0.6: + resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + engines: {node: '>= 4'} + image-size@1.2.1: resolution: {integrity: sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==} engines: {node: '>=16.x'} @@ -5007,9 +6648,17 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + is-core-module@2.16.2: resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} engines: {node: '>= 0.4'} @@ -5032,6 +6681,10 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -5049,6 +6702,14 @@ packages: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} + is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + + is-network-error@1.3.2: + resolution: {integrity: sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==} + engines: {node: '>=16'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -5068,6 +6729,10 @@ packages: is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + is-regexp@3.1.0: resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} engines: {node: '>=12'} @@ -5080,6 +6745,10 @@ packages: resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} engines: {node: '>=18'} + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + is-unicode-supported@1.3.0: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} @@ -5096,6 +6765,12 @@ packages: resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} engines: {node: '>=16'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + isbot@5.2.1: resolution: {integrity: sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw==} engines: {node: '>=18'} @@ -5107,6 +6782,14 @@ packages: resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} engines: {node: '>=18'} + isolated-vm@6.1.2: + resolution: {integrity: sha512-GGfsHqtlZiiurZaxB/3kY7LLAXR3sgzDul0fom4cSyBjx6ZbjpTrFWiH3z/nUfLJGJ8PIq9LQmQFiAxu24+I7A==} + engines: {node: '>=22.0.0'} + + isomorphic-timers-promises@1.0.1: + resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==} + engines: {node: '>=10'} + jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -5140,6 +6823,10 @@ packages: resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} hasBin: true + js-yaml@5.2.3: + resolution: {integrity: sha512-n+mUVyUX5bVv7G/G2zyIHOhdxfuU1dY2NOFzTQUWiMUbFss8b57NFlgCCaggU78wSw5KVS9cllzeLyzyR+n5nw==} + hasBin: true + jsc-safe-url@0.2.4: resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==} @@ -5148,6 +6835,9 @@ packages: engines: {node: '>=6'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -5157,6 +6847,10 @@ packages: json-schema-to-ts@1.6.4: resolution: {integrity: sha512-pR4yQ9DHz6itqswtHCm26mw45FSNfQ9rEQjosaZErhn5J3J2sIViQiz8rDaezjKAhFGpmsoczYVBgGHzFw/stA==} + json-schema-to-ts@3.1.1: + resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} + engines: {node: '>=16'} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -5183,6 +6877,12 @@ packages: jsonfile@6.2.1: resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -5194,6 +6894,9 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + koffi@2.16.3: + resolution: {integrity: sha512-E9y1AsgYGlaxMhcZzHr8y96QF2U5XzA12GGVAfbWqIubTwPNMXQarfBzePNXHe0xtIEtNd6ifAv3GAKYGUeBAQ==} + kubernetes-types@1.30.0: resolution: {integrity: sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==} @@ -5208,6 +6911,9 @@ packages: launch-editor@2.14.1: resolution: {integrity: sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==} + layerr@3.0.0: + resolution: {integrity: sha512-tv754Ki2dXpPVApOrjTyRo4/QegVb9eVFq4mjqp4+NM5NaX7syQvN5BBNfV/ZpAHCEHV24XdUVrBAoka4jt3pA==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -5395,6 +7101,12 @@ packages: resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} engines: {node: '>=18'} + long-timeout@0.1.1: + resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==} + + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -5409,6 +7121,10 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + lucide-react@1.27.0: resolution: {integrity: sha512-rJicGl/3Fly/E0rOH1YmPZ6e49JCnKknh1ox1vpHnkfjujAkKA6sqUZvH3MTAaXXjgexyUwgNwTJzTtYuAFYJw==} peerDependencies: @@ -5421,9 +7137,17 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@1.1.0: + resolution: {integrity: sha512-kS3VHe0nEPST2saQV4Rbkchcd3UBRkVTQHo1D3h/ZTwFDhai/mfKkmtPAtD129EOI7K3HlHIsFOt0WrI2/oU9g==} + makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + marked@15.0.12: + resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} + engines: {node: '>= 18'} + hasBin: true + marky@1.3.0: resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} @@ -5431,6 +7155,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} @@ -5514,6 +7241,10 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -5560,6 +7291,12 @@ packages: engines: {node: '>=22.0.0'} hasBin: true + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + minimatch@10.2.6: resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} engines: {node: 18 || 20 || >=22} @@ -5574,6 +7311,9 @@ packages: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} + minisearch@7.2.0: + resolution: {integrity: sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==} + mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} @@ -5615,6 +7355,9 @@ packages: multitars@1.0.0: resolution: {integrity: sha512-H/J4fMLedtudftaYMOg7ajzLYgT3/rwbWVJbqr/iUgB8DQztn38ys5HOqI1CzSxx8QhXXwOOnnBvd4v3jG5+Mg==} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.16: resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -5642,6 +7385,10 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} + netmask@2.1.1: + resolution: {integrity: sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==} + engines: {node: '>= 0.4.0'} + next-themes@0.4.6: resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} peerDependencies: @@ -5652,14 +7399,40 @@ packages: resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==} engines: {node: '>=10'} + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-forge@1.4.0: resolution: {integrity: sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==} engines: {node: '>= 6.13.0'} + node-gyp-build-optional-packages@5.1.1: + resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==} + hasBin: true + node-gyp-build-optional-packages@5.2.2: resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} hasBin: true + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} @@ -5667,6 +7440,10 @@ packages: resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} engines: {node: '>=18'} + node-stdlib-browser@1.3.1: + resolution: {integrity: sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==} + engines: {node: '>=10'} + npm-package-arg@11.0.3: resolution: {integrity: sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==} engines: {node: ^16.14.0 || >=18.0.0} @@ -5702,14 +7479,30 @@ packages: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + object-treeify@1.1.33: resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==} engines: {node: '>= 10'} + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + obug@2.1.4: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + on-finished@2.3.0: resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} engines: {node: '>= 0.8'} @@ -5749,6 +7542,21 @@ packages: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} + openai@6.26.0: + resolution: {integrity: sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + openapi3-ts@4.6.1: + resolution: {integrity: sha512-XW9MOldkhoICNeXVzzmXzmOW5G73ppOEGmh7fLCqHjgfdEYCGGN+00MlVCeUZgovjjfC56j9tvtDt1zGabNjjA==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -5761,6 +7569,9 @@ packages: resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} engines: {node: '>=18'} + os-browserify@0.3.0: + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + oxfmt@0.57.0: resolution: {integrity: sha512-ZB7Bi+rGDSqmVIo9jwcLyFgjxXvQhDdU+jx+ZrVy6VRiVXK2+CHc4hO3J4dUQjHe7V0ymHB+MDuv5z+NhK07HA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -5837,14 +7648,37 @@ packages: resolution: {integrity: sha512-I4Prw6ivkd6p8PiYR1tXASOAOBzIJwu0TB7fqaX0c/8c3QAehNYmX57EijyGGGBt3c/BIowGwV03RVBtXvHEVg==} engines: {node: '>=18'} + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-asn1@5.1.9: + resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==} + engines: {node: '>= 0.10'} + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -5857,10 +7691,22 @@ packages: resolution: {integrity: sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==} engines: {node: '>=10'} + parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + + parse5@5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + + parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -5899,6 +7745,13 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pbkdf2@3.1.6: + resolution: {integrity: sha512-BT6eelPB1EyGHo8pC0o9Bl6k6SYVhKO1jEbd3lcTrtr7XHdjP8BW1YpfCV3G9Kwkxgattk+S5q2/RvuttCsS1g==} + engines: {node: '>= 0.10'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -5910,10 +7763,24 @@ packages: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@9.14.0: + resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} + hasBin: true + pkce-challenge@5.0.1: resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} engines: {node: '>=16.20.0'} + pkg-dir@5.0.0: + resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} + engines: {node: '>=10'} + pkg-types@2.3.1: resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} @@ -5933,6 +7800,10 @@ packages: resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} engines: {node: '>=14.19.0'} + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + postcss-selector-parser@7.1.4: resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==} engines: {node: '>=4'} @@ -5980,6 +7851,16 @@ packages: resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process-warning@5.1.0: + resolution: {integrity: sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + progress@2.0.3: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} @@ -5994,13 +7875,33 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + protobufjs@7.6.5: + resolution: {integrity: sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==} + engines: {node: '>=12.0.0'} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -6012,12 +7913,25 @@ packages: resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} engines: {node: '>=0.6'} + querystring-es3@0.2.1: + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} queue@6.0.2: resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -6157,6 +8071,9 @@ packages: resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} engines: {node: '>=0.10.0'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -6165,6 +8082,10 @@ packages: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + recast@0.23.12: resolution: {integrity: sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==} engines: {node: '>= 4'} @@ -6229,10 +8150,52 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + ripemd160@2.0.3: + resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} + engines: {node: '>= 0.8'} + + rivetkit@2.3.10: + resolution: {integrity: sha512-E+H0lBc3O8dK9Pj7W2XW3VwrCnfpwYYm5LlsZyHrmk5bCrJIBdnEFdZXn5nsYMz0waCfP1ieyP6d1tdvBG76Dg==} + engines: {node: '>=22.0.0'} + peerDependencies: + drizzle-kit: ^0.31.2 + eventsource: ^4.0.0 + ws: ^8.0.0 + peerDependenciesMeta: + drizzle-kit: + optional: true + eventsource: + optional: true + ws: + optional: true + + rivetkit@2.3.9: + resolution: {integrity: sha512-m8pd3+nfI81T8uxKPflOKXTvvRf6X/u5zW0vRqq6v+d/Dwh964jKAHp0pVo5R6D9PotNZQIroqy57AZvX7nc4g==} + engines: {node: '>=22.0.0'} + peerDependencies: + drizzle-kit: ^0.31.2 + eventsource: ^4.0.0 + ws: ^8.0.0 + peerDependenciesMeta: + drizzle-kit: + optional: true + eventsource: + optional: true + ws: + optional: true + rolldown@1.1.4: resolution: {integrity: sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6266,6 +8229,14 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -6276,6 +8247,9 @@ packages: scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + secure-exec@0.2.1: + resolution: {integrity: sha512-oaQDzTPDSCOckYC8G0PimIqzEVxY6sYEvcx0fMGsRR/Wl4wkFVHaZgQ3kc2DHWysV6WHWt5g1AXc/6seafO2XQ==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -6318,9 +8292,21 @@ packages: set-cookie-parser@3.1.2: resolution: {integrity: sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==} + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + sha.js@2.4.12: + resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} + engines: {node: '>= 0.10'} + hasBin: true + shadcn@4.16.0: resolution: {integrity: sha512-kPr4RrQmbbZeAjwBYeBSpFvAHV8rkTlNPUluIxkRriq5TpevfFelVO5xvcF6oguHPVn0R6wPuVer4HudfcLy/A==} engines: {node: '>=20.18.1'} @@ -6392,9 +8378,24 @@ packages: resolution: {integrity: sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==} engines: {node: '>=8.0.0'} + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.9: + resolution: {integrity: sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + solid-js@1.9.14: resolution: {integrity: sha512-sAEXC0Kk0S1EDg+8ysEWJDbYhA3RRoEjwuySUGlKIemeo0I5YZfOyumNjNs9Sv3y2nmhD+0rW66ag2HsMuQiGQ==} + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + sonner@2.0.7: resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} peerDependencies: @@ -6416,6 +8417,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -6434,6 +8439,9 @@ packages: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.2.0: resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} @@ -6441,10 +8449,16 @@ packages: resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} engines: {node: '>=18'} + stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + stream-buffers@2.2.0: resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} engines: {node: '>= 0.10.0'} + stream-http@3.2.0: + resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -6453,6 +8467,9 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -6488,6 +8505,10 @@ packages: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} + strtok3@10.3.5: + resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} + engines: {node: '>=18'} + structured-headers@0.4.1: resolution: {integrity: sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==} @@ -6563,9 +8584,23 @@ packages: engines: {node: '>=10'} hasBin: true + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + thread-stream@3.2.0: + resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} + throat@5.0.0: resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + timers-browserify@2.0.12: + resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} + engines: {node: '>=0.6.0'} + timestring@6.0.0: resolution: {integrity: sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==} engines: {node: '>=8'} @@ -6595,6 +8630,10 @@ packages: tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-buffer@1.2.2: + resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} + engines: {node: '>= 0.4'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -6603,6 +8642,10 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} + toml@4.3.0: resolution: {integrity: sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A==} engines: {node: '>=20'} @@ -6614,10 +8657,16 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + ts-algebra@2.0.0: + resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + ts-api-utils@2.5.0: resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} @@ -6651,6 +8700,9 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tty-browserify@0.0.1: + resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} + tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} @@ -6677,11 +8729,26 @@ packages: resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} engines: {node: '>= 18'} + typebox@1.3.7: + resolution: {integrity: sha512-meKuifc33Pccx0O6PdIzYMq3Og8zvP4TIi/a+Bw3AEMZMxOD0+RHGQvpglEe6Zdy3wZ8nqn/j95h8LUZLk/6Hg==} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + typescript@7.0.2: resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} engines: {node: '>=16.20.0'} hasBin: true + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + + ulidx@2.4.1: + resolution: {integrity: sha512-xY7c8LPyzvhvew0Fn+Ek3wBC9STZAuDI/Y5andCKi9AX6/jvfaX45PhsDX8oxgPL0YFp0Jhr8qWMbS/p9375Xg==} + engines: {node: '>=16'} + ultracite@7.9.3: resolution: {integrity: sha512-MqF0cn5DNHy/I61+hL4aYPRVye+rrmUqfv1dhwQ0ORfoFngk1O8tTKigF+zpsh/6qA84gkl26KkrtYzoypPiaw==} hasBin: true @@ -6748,6 +8815,13 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-template@2.0.8: + resolution: {integrity: sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==} + + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + use-sync-external-store@1.6.0: resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} peerDependencies: @@ -6756,10 +8830,17 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@12.0.1: + resolution: {integrity: sha512-9obBF8sMIHJWNQaO6IGOG8giGa/jUpKX34bz6o4whVs8M0WAvhID2tNxYp6A2XEBJPuZSX8wsS/6TEKfIDc+nw==} + hasBin: true + uuid@14.0.1: resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} hasBin: true @@ -6774,6 +8855,11 @@ packages: deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + valibot@1.4.2: resolution: {integrity: sha512-gjdCvJ6d3RyHAneqxMYMW9QMCwYMb3jpOO0IyHZV1bnRHFBHrX3VkIILt5XYR0WhwHiH7Mty8ovuPZ/O3gamrg==} peerDependencies: @@ -6794,6 +8880,10 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + vbare@0.0.4: + resolution: {integrity: sha512-QsxSVw76NqYUWYPVcQmOnQPX8buIVjgn+yqldTHlWISulBTB9TJ9rnzZceDu+GZmycOtzsmuPbPN1YNxvK12fg==} + engines: {node: '>=18.0.0'} + vite-plus@0.2.2: resolution: {integrity: sha512-bXO3O0F2/uxtvX9Ck0o67stTErH/Zh0GEcCMd9pAh22tTHABCNTDPrRMWVo733e7Ux3h0Y7HanJ7neOV/nid4g==} engines: {node: ^20.19.0 || ^22.18.0 || >=24.11.0} @@ -6940,6 +9030,9 @@ packages: vlq@1.0.1: resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} + vm-browserify@1.1.2: + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} + walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} @@ -6949,12 +9042,30 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + web-streams-polyfill@4.3.0: + resolution: {integrity: sha512-/Gnggvj9oSrEvJbDyyPtAnxBt5fGQM2iWOKQNu7ie1OxDgK40iZpyV3TKaRiEzVj1oA1UxKnEy9XPXh6PW3eVw==} + engines: {node: '>= 8'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + whatwg-fetch@3.6.20: resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} whatwg-url-minimum@0.1.2: resolution: {integrity: sha512-XPEm0XFQWNVG292lII1PrRRJl3sItrs7CettZ4ncYxuDVpLyy+NwlGyut2hXI0JswcJUxeCH+CyOJK0ZzAXD6A==} + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-typed-array@1.1.22: + resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} + engines: {node: '>= 0.4'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -7052,6 +9163,10 @@ packages: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -7064,10 +9179,18 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs@16.2.2: + resolution: {integrity: sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==} + engines: {node: '>=10'} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -7076,6 +9199,9 @@ packages: resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} engines: {node: '>=12'} + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -7107,8 +9233,371 @@ packages: snapshots: + '@agentclientprotocol/sdk@0.16.1(zod@4.4.3)': + dependencies: + zod: 4.4.3 + + '@agentos-software/claude-code@0.2.7(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)': + dependencies: + '@agentclientprotocol/sdk': 0.16.1(zod@4.4.3) + '@anthropic-ai/claude-agent-sdk': 0.2.87(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3) + zod: 4.4.3 + transitivePeerDependencies: + - '@cfworker/json-schema' + - supports-color + + '@agentos-software/codex-cli@0.3.4': {} + + '@agentos-software/common@0.2.15': + dependencies: + '@agentos-software/coreutils': 0.3.4 + '@agentos-software/diffutils': 0.3.4 + '@agentos-software/findutils': 0.3.4 + '@agentos-software/gawk': 0.3.4 + '@agentos-software/grep': 0.3.4 + '@agentos-software/gzip': 0.3.4 + '@agentos-software/sed': 0.3.4 + '@agentos-software/tar': 0.3.5 + + '@agentos-software/coreutils@0.3.4': {} + + '@agentos-software/diffutils@0.3.4': {} + + '@agentos-software/findutils@0.3.4': {} + + '@agentos-software/gawk@0.3.4': {} + + '@agentos-software/git@0.3.3': {} + + '@agentos-software/grep@0.3.4': {} + + '@agentos-software/gzip@0.3.4': {} + + '@agentos-software/manifest@0.2.15': {} + + '@agentos-software/opencode@0.2.7': {} + + '@agentos-software/pi@0.2.7(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3)': + dependencies: + '@agentclientprotocol/sdk': 0.16.1(zod@4.4.3) + '@mariozechner/pi-ai': 0.60.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + '@mariozechner/pi-coding-agent': 0.60.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@agentos-software/sed@0.3.4': {} + + '@agentos-software/tar@0.3.5': {} + '@alloc/quick-lru@5.2.0': {} + '@anthropic-ai/claude-agent-sdk@0.2.87(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3)': + dependencies: + '@anthropic-ai/sdk': 0.74.0(zod@4.4.3) + '@modelcontextprotocol/sdk': 1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3) + zod: 4.4.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + transitivePeerDependencies: + - '@cfworker/json-schema' + - supports-color + + '@anthropic-ai/sdk@0.73.0(zod@4.4.3)': + dependencies: + json-schema-to-ts: 3.1.1 + optionalDependencies: + zod: 4.4.3 + + '@anthropic-ai/sdk@0.74.0(zod@4.4.3)': + dependencies: + json-schema-to-ts: 3.1.1 + optionalDependencies: + zod: 4.4.3 + + '@anthropic-ai/sdk@0.91.1(zod@4.4.3)': + dependencies: + json-schema-to-ts: 3.1.1 + optionalDependencies: + zod: 4.4.3 + + '@asteasolutions/zod-to-openapi@8.5.0(zod@4.4.3)': + dependencies: + openapi3-ts: 4.6.1 + zod: 4.4.3 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.974.2 + '@aws-sdk/util-locate-window': 3.965.8 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.974.2 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.974.2 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/checksums@3.1000.24': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/client-bedrock-runtime@3.1048.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.977.4 + '@aws-sdk/credential-provider-node': 3.972.76 + '@aws-sdk/eventstream-handler-node': 3.972.31 + '@aws-sdk/middleware-eventstream': 3.972.26 + '@aws-sdk/middleware-websocket': 3.972.47 + '@aws-sdk/token-providers': 3.1048.0 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/fetch-http-handler': 5.6.13 + '@smithy/node-http-handler': 4.7.3 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/client-bedrock-runtime@3.1100.0': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/credential-provider-node': 3.972.76 + '@aws-sdk/eventstream-handler-node': 3.972.31 + '@aws-sdk/middleware-eventstream': 3.972.26 + '@aws-sdk/middleware-websocket': 3.972.47 + '@aws-sdk/token-providers': 3.1100.0 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/fetch-http-handler': 5.6.13 + '@smithy/node-http-handler': 4.9.13 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/client-s3@3.1101.0': + dependencies: + '@aws-sdk/checksums': 3.1000.24 + '@aws-sdk/core': 3.977.4 + '@aws-sdk/credential-provider-node': 3.972.76 + '@aws-sdk/middleware-sdk-s3': 3.972.70 + '@aws-sdk/signature-v4-multi-region': 3.996.43 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/fetch-http-handler': 5.6.13 + '@smithy/node-http-handler': 4.9.13 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/core@3.977.4': + dependencies: + '@aws-sdk/types': 3.974.2 + '@aws-sdk/xml-builder': 3.972.37 + '@aws/lambda-invoke-store': 0.3.0 + '@smithy/core': 3.31.1 + '@smithy/signature-v4': 5.6.12 + '@smithy/types': 4.16.1 + bowser: 2.14.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.65': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.67': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/fetch-http-handler': 5.6.13 + '@smithy/node-http-handler': 4.9.13 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.973.10': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/credential-provider-env': 3.972.65 + '@aws-sdk/credential-provider-http': 3.972.67 + '@aws-sdk/credential-provider-login': 3.972.72 + '@aws-sdk/credential-provider-process': 3.972.65 + '@aws-sdk/credential-provider-sso': 3.973.9 + '@aws-sdk/credential-provider-web-identity': 3.972.71 + '@aws-sdk/nested-clients': 3.997.39 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/credential-provider-imds': 4.4.16 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-login@3.972.72': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/nested-clients': 3.997.39 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-node@3.972.76': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.65 + '@aws-sdk/credential-provider-http': 3.972.67 + '@aws-sdk/credential-provider-ini': 3.973.10 + '@aws-sdk/credential-provider-process': 3.972.65 + '@aws-sdk/credential-provider-sso': 3.973.9 + '@aws-sdk/credential-provider-web-identity': 3.972.71 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/credential-provider-imds': 4.4.16 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-process@3.972.65': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.973.9': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/nested-clients': 3.997.39 + '@aws-sdk/token-providers': 3.1100.0 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-web-identity@3.972.71': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/nested-clients': 3.997.39 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/eventstream-handler-node@3.972.31': + dependencies: + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-eventstream@3.972.26': + dependencies: + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.972.70': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/signature-v4-multi-region': 3.996.43 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-websocket@3.972.47': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/fetch-http-handler': 5.6.13 + '@smithy/signature-v4': 5.6.12 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.997.39': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/signature-v4-multi-region': 3.996.43 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/fetch-http-handler': 5.6.13 + '@smithy/node-http-handler': 4.9.13 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.996.43': + dependencies: + '@aws-sdk/types': 3.974.2 + '@smithy/signature-v4': 5.6.12 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1048.0': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/nested-clients': 3.997.39 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1100.0': + dependencies: + '@aws-sdk/core': 3.977.4 + '@aws-sdk/nested-clients': 3.997.39 + '@aws-sdk/types': 3.974.2 + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/types@3.974.2': + dependencies: + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.965.8': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.37': + dependencies: + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.3.0': {} + '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -7707,6 +10196,26 @@ snapshots: '@blazediff/core@1.9.1': {} + '@borewit/text-codec@0.2.2': {} + + '@cbor-extract/cbor-extract-darwin-arm64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-darwin-x64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-arm64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-arm@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-x64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-win32-x64@2.2.2': + optional: true + '@cfworker/json-schema@4.1.1': optional: true @@ -7747,13 +10256,13 @@ snapshots: '@cloudflare/workerd-windows-64@1.20260722.1': optional: true - '@convex-dev/better-auth@0.12.5(@standard-schema/spec@1.1.0)(better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))))(convex@1.42.3(react@19.2.8))(hono@4.12.32)(react@19.2.8)(typescript@7.0.2)': + '@convex-dev/better-auth@0.12.5(@standard-schema/spec@1.1.0)(better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))))(convex@1.42.3(react@19.2.8))(hono@4.12.34)(react@19.2.8)(typescript@7.0.2)': dependencies: '@better-fetch/fetch': 1.3.1 better-auth: 1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))) common-tags: 1.8.2 convex: 1.42.3(react@19.2.8) - convex-helpers: 0.1.120(@standard-schema/spec@1.1.0)(convex@1.42.3(react@19.2.8))(hono@4.12.32)(react@19.2.8)(typescript@7.0.2)(zod@4.4.3) + convex-helpers: 0.1.120(@standard-schema/spec@1.1.0)(convex@1.42.3(react@19.2.8))(hono@4.12.34)(react@19.2.8)(typescript@7.0.2)(zod@4.4.3) jose: 6.2.4 react: 19.2.8 remeda: 2.39.0 @@ -7765,13 +10274,13 @@ snapshots: - hono - typescript - '@convex-dev/better-auth@0.12.5(@standard-schema/spec@1.1.0)(better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@26.1.2)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))))(convex@1.42.3(react@19.2.8))(hono@4.12.32)(react@19.2.8)(typescript@7.0.2)': + '@convex-dev/better-auth@0.12.5(@standard-schema/spec@1.1.0)(better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@26.1.2)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))))(convex@1.42.3(react@19.2.8))(hono@4.12.34)(react@19.2.8)(typescript@7.0.2)': dependencies: '@better-fetch/fetch': 1.3.1 better-auth: 1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@26.1.2)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))) common-tags: 1.8.2 convex: 1.42.3(react@19.2.8) - convex-helpers: 0.1.120(@standard-schema/spec@1.1.0)(convex@1.42.3(react@19.2.8))(hono@4.12.32)(react@19.2.8)(typescript@7.0.2)(zod@4.4.3) + convex-helpers: 0.1.120(@standard-schema/spec@1.1.0)(convex@1.42.3(react@19.2.8))(hono@4.12.34)(react@19.2.8)(typescript@7.0.2)(zod@4.4.3) jose: 6.2.4 react: 19.2.8 remeda: 2.39.0 @@ -7809,6 +10318,47 @@ snapshots: '@dotenvx/primitives@0.8.0': {} + '@durable-streams/client@0.2.6': + dependencies: + '@microsoft/fetch-event-source': 2.0.1 + fastq: 1.20.1 + + '@earendil-works/pi-agent-core@0.83.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3)': + dependencies: + '@earendil-works/pi-ai': 0.83.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + diff: 8.0.4 + ignore: 7.0.5 + typebox: 1.3.7 + yaml: 2.9.0 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-ai@0.83.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3)': + dependencies: + '@anthropic-ai/sdk': 0.91.1(zod@4.4.3) + '@aws-sdk/client-bedrock-runtime': 3.1048.0 + '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2) + '@mistralai/mistralai': 2.2.6(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.0 + '@smithy/node-http-handler': 4.7.3 + http-proxy-agent: 7.0.2(supports-color@10.2.2) + https-proxy-agent: 7.0.6(supports-color@10.2.2) + openai: 6.26.0(ws@8.21.1)(zod@4.4.3) + partial-json: 0.1.7 + typebox: 1.3.7 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + '@egjs/hammerjs@2.0.17': dependencies: '@types/hammerjs': 2.0.46 @@ -7837,156 +10387,234 @@ snapshots: '@esbuild/aix-ppc64@0.27.0': optional: true + '@esbuild/aix-ppc64@0.27.7': + optional: true + '@esbuild/aix-ppc64@0.28.1': optional: true '@esbuild/android-arm64@0.27.0': optional: true + '@esbuild/android-arm64@0.27.7': + optional: true + '@esbuild/android-arm64@0.28.1': optional: true '@esbuild/android-arm@0.27.0': optional: true + '@esbuild/android-arm@0.27.7': + optional: true + '@esbuild/android-arm@0.28.1': optional: true '@esbuild/android-x64@0.27.0': optional: true + '@esbuild/android-x64@0.27.7': + optional: true + '@esbuild/android-x64@0.28.1': optional: true '@esbuild/darwin-arm64@0.27.0': optional: true + '@esbuild/darwin-arm64@0.27.7': + optional: true + '@esbuild/darwin-arm64@0.28.1': optional: true '@esbuild/darwin-x64@0.27.0': optional: true + '@esbuild/darwin-x64@0.27.7': + optional: true + '@esbuild/darwin-x64@0.28.1': optional: true '@esbuild/freebsd-arm64@0.27.0': optional: true + '@esbuild/freebsd-arm64@0.27.7': + optional: true + '@esbuild/freebsd-arm64@0.28.1': optional: true '@esbuild/freebsd-x64@0.27.0': optional: true + '@esbuild/freebsd-x64@0.27.7': + optional: true + '@esbuild/freebsd-x64@0.28.1': optional: true '@esbuild/linux-arm64@0.27.0': optional: true + '@esbuild/linux-arm64@0.27.7': + optional: true + '@esbuild/linux-arm64@0.28.1': optional: true '@esbuild/linux-arm@0.27.0': optional: true + '@esbuild/linux-arm@0.27.7': + optional: true + '@esbuild/linux-arm@0.28.1': optional: true '@esbuild/linux-ia32@0.27.0': optional: true + '@esbuild/linux-ia32@0.27.7': + optional: true + '@esbuild/linux-ia32@0.28.1': optional: true '@esbuild/linux-loong64@0.27.0': optional: true + '@esbuild/linux-loong64@0.27.7': + optional: true + '@esbuild/linux-loong64@0.28.1': optional: true '@esbuild/linux-mips64el@0.27.0': optional: true + '@esbuild/linux-mips64el@0.27.7': + optional: true + '@esbuild/linux-mips64el@0.28.1': optional: true '@esbuild/linux-ppc64@0.27.0': optional: true + '@esbuild/linux-ppc64@0.27.7': + optional: true + '@esbuild/linux-ppc64@0.28.1': optional: true '@esbuild/linux-riscv64@0.27.0': optional: true + '@esbuild/linux-riscv64@0.27.7': + optional: true + '@esbuild/linux-riscv64@0.28.1': optional: true '@esbuild/linux-s390x@0.27.0': optional: true + '@esbuild/linux-s390x@0.27.7': + optional: true + '@esbuild/linux-s390x@0.28.1': optional: true '@esbuild/linux-x64@0.27.0': optional: true + '@esbuild/linux-x64@0.27.7': + optional: true + '@esbuild/linux-x64@0.28.1': optional: true '@esbuild/netbsd-arm64@0.27.0': optional: true + '@esbuild/netbsd-arm64@0.27.7': + optional: true + '@esbuild/netbsd-arm64@0.28.1': optional: true '@esbuild/netbsd-x64@0.27.0': optional: true + '@esbuild/netbsd-x64@0.27.7': + optional: true + '@esbuild/netbsd-x64@0.28.1': optional: true '@esbuild/openbsd-arm64@0.27.0': optional: true + '@esbuild/openbsd-arm64@0.27.7': + optional: true + '@esbuild/openbsd-arm64@0.28.1': optional: true '@esbuild/openbsd-x64@0.27.0': optional: true + '@esbuild/openbsd-x64@0.27.7': + optional: true + '@esbuild/openbsd-x64@0.28.1': optional: true '@esbuild/openharmony-arm64@0.27.0': optional: true + '@esbuild/openharmony-arm64@0.27.7': + optional: true + '@esbuild/openharmony-arm64@0.28.1': optional: true '@esbuild/sunos-x64@0.27.0': optional: true + '@esbuild/sunos-x64@0.27.7': + optional: true + '@esbuild/sunos-x64@0.28.1': optional: true '@esbuild/win32-arm64@0.27.0': optional: true + '@esbuild/win32-arm64@0.27.7': + optional: true + '@esbuild/win32-arm64@0.28.1': optional: true '@esbuild/win32-ia32@0.27.0': optional: true + '@esbuild/win32-ia32@0.27.7': + optional: true + '@esbuild/win32-ia32@0.28.1': optional: true '@esbuild/win32-x64@0.27.0': optional: true + '@esbuild/win32-x64@0.27.7': + optional: true + '@esbuild/win32-x64@0.28.1': optional: true @@ -8501,10 +11129,123 @@ snapshots: '@floating-ui/utils@0.2.12': {} + '@flue/cli@2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(@types/node@22.20.1)(esbuild@0.28.1)(hono@4.12.34)(jiti@2.7.0)(supports-color@10.2.2)(terser@5.49.0)(typescript@7.0.2)(ws@8.21.1)(yaml@2.9.0)(zod@4.4.3)': + dependencies: + '@flue/runtime': 2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(typescript@7.0.2)(ws@8.21.1)(zod@4.4.3) + '@flue/vite': 2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))(hono@4.12.34)(supports-color@10.2.2)(typescript@7.0.2)(ws@8.21.1)(zod@4.4.3) + '@vercel/detect-agent': 1.2.3 + cac: 7.0.0 + minisearch: 7.2.0 + picocolors: 1.1.1 + prompts: 2.4.2 + ulidx: 2.4.1 + vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0)' + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@modelcontextprotocol/sdk' + - '@types/node' + - '@vitejs/devtools' + - bufferutil + - esbuild + - hono + - jiti + - less + - publint + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - utf-8-validate + - ws + - yaml + - zod + + '@flue/runtime@2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(typescript@7.0.2)(ws@8.21.1)(zod@4.4.3)': + dependencies: + '@earendil-works/pi-agent-core': 0.83.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + '@earendil-works/pi-ai': 0.83.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + '@hono/node-server': 2.0.12(hono@4.12.32) + '@modelcontextprotocol/client': 2.0.0 + '@valibot/to-json-schema': 1.7.1(valibot@1.4.2(typescript@7.0.2)) + hono: 4.12.32 + js-yaml: 5.2.3 + ulidx: 2.4.1 + valibot: 1.4.2(typescript@7.0.2) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - typescript + - utf-8-validate + - ws + - zod + + '@flue/sdk@2.0.1': + dependencies: + '@durable-streams/client': 0.2.6 + + '@flue/vite@2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))(hono@4.12.34)(supports-color@10.2.2)(typescript@7.0.2)(ws@8.21.1)(zod@4.4.3)': + dependencies: + '@flue/runtime': 2.0.1(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(typescript@7.0.2)(ws@8.21.1)(zod@4.4.3) + '@hono/node-server': 2.0.12(hono@4.12.34) + magic-string: 1.1.0 + tinyglobby: 0.2.17 + ulidx: 2.4.1 + vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0)' + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - hono + - supports-color + - typescript + - utf-8-validate + - ws + - zod + + '@google/genai@1.52.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)': + dependencies: + google-auth-library: 10.9.1(supports-color@10.2.2) + p-retry: 4.6.2 + protobufjs: 7.6.5 + ws: 8.21.1 + optionalDependencies: + '@modelcontextprotocol/sdk': 1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + '@hono/node-server@2.0.12(hono@4.12.32)': dependencies: hono: 4.12.32 + '@hono/node-server@2.0.12(hono@4.12.34)': + dependencies: + hono: 4.12.34 + + '@hono/node-server@2.0.3(hono@4.12.34)': + dependencies: + hono: 4.12.34 + + '@hono/zod-openapi@1.5.1(hono@4.12.32)(zod@4.4.3)': + dependencies: + '@asteasolutions/zod-to-openapi': 8.5.0(zod@4.4.3) + '@hono/zod-validator': 0.9.0(hono@4.12.32)(zod@4.4.3) + hono: 4.12.32 + openapi3-ts: 4.6.1 + zod: 4.4.3 + + '@hono/zod-validator@0.9.0(hono@4.12.32)(zod@4.4.3)': + dependencies: + hono: 4.12.32 + zod: 4.4.3 + '@humanfs/core@0.19.2': dependencies: '@humanfs/types': 0.15.0 @@ -8524,11 +11265,21 @@ snapshots: '@img/colour@1.1.0': optional: true + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + '@img/sharp-darwin-arm64@0.35.2': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.3.1 optional: true + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + '@img/sharp-darwin-x64@0.35.2': optionalDependencies: '@img/sharp-libvips-darwin-x64': 1.3.1 @@ -8539,15 +11290,27 @@ snapshots: '@img/sharp-wasm32': 0.35.2 optional: true + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + '@img/sharp-libvips-darwin-arm64@1.3.1': optional: true + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + '@img/sharp-libvips-darwin-x64@1.3.1': optional: true + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + '@img/sharp-libvips-linux-arm64@1.3.1': optional: true + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + '@img/sharp-libvips-linux-arm@1.3.1': optional: true @@ -8560,20 +11323,39 @@ snapshots: '@img/sharp-libvips-linux-s390x@1.3.1': optional: true + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + '@img/sharp-libvips-linux-x64@1.3.1': optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.3.1': optional: true + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + '@img/sharp-libvips-linuxmusl-x64@1.3.1': optional: true + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + '@img/sharp-linux-arm64@0.35.2': optionalDependencies: '@img/sharp-libvips-linux-arm64': 1.3.1 optional: true + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + '@img/sharp-linux-arm@0.35.2': optionalDependencies: '@img/sharp-libvips-linux-arm': 1.3.1 @@ -8594,16 +11376,31 @@ snapshots: '@img/sharp-libvips-linux-s390x': 1.3.1 optional: true + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + '@img/sharp-linux-x64@0.35.2': optionalDependencies: '@img/sharp-libvips-linux-x64': 1.3.1 optional: true + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + '@img/sharp-linuxmusl-arm64@0.35.2': optionalDependencies: '@img/sharp-libvips-linuxmusl-arm64': 1.3.1 optional: true + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + '@img/sharp-linuxmusl-x64@0.35.2': optionalDependencies: '@img/sharp-libvips-linuxmusl-x64': 1.3.1 @@ -8619,12 +11416,18 @@ snapshots: '@img/sharp-wasm32': 0.35.2 optional: true + '@img/sharp-win32-arm64@0.34.5': + optional: true + '@img/sharp-win32-arm64@0.35.2': optional: true '@img/sharp-win32-ia32@0.35.2': optional: true + '@img/sharp-win32-x64@0.34.5': + optional: true + '@img/sharp-win32-x64@0.35.2': optional: true @@ -8673,9 +11476,170 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.5 optional: true + '@mariozechner/clipboard-darwin-arm64@0.3.9': + optional: true + + '@mariozechner/clipboard-darwin-universal@0.3.9': + optional: true + + '@mariozechner/clipboard-darwin-x64@0.3.9': + optional: true + + '@mariozechner/clipboard-linux-arm64-gnu@0.3.9': + optional: true + + '@mariozechner/clipboard-linux-arm64-musl@0.3.9': + optional: true + + '@mariozechner/clipboard-linux-riscv64-gnu@0.3.9': + optional: true + + '@mariozechner/clipboard-linux-x64-gnu@0.3.9': + optional: true + + '@mariozechner/clipboard-linux-x64-musl@0.3.9': + optional: true + + '@mariozechner/clipboard-win32-arm64-msvc@0.3.9': + optional: true + + '@mariozechner/clipboard-win32-x64-msvc@0.3.9': + optional: true + + '@mariozechner/clipboard@0.3.9': + optionalDependencies: + '@mariozechner/clipboard-darwin-arm64': 0.3.9 + '@mariozechner/clipboard-darwin-universal': 0.3.9 + '@mariozechner/clipboard-darwin-x64': 0.3.9 + '@mariozechner/clipboard-linux-arm64-gnu': 0.3.9 + '@mariozechner/clipboard-linux-arm64-musl': 0.3.9 + '@mariozechner/clipboard-linux-riscv64-gnu': 0.3.9 + '@mariozechner/clipboard-linux-x64-gnu': 0.3.9 + '@mariozechner/clipboard-linux-x64-musl': 0.3.9 + '@mariozechner/clipboard-win32-arm64-msvc': 0.3.9 + '@mariozechner/clipboard-win32-x64-msvc': 0.3.9 + optional: true + + '@mariozechner/jiti@2.6.5': + dependencies: + std-env: 3.10.0 + yoctocolors: 2.2.0 + + '@mariozechner/pi-agent-core@0.60.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3)': + dependencies: + '@mariozechner/pi-ai': 0.60.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-ai@0.60.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3)': + dependencies: + '@anthropic-ai/sdk': 0.73.0(zod@4.4.3) + '@aws-sdk/client-bedrock-runtime': 3.1100.0 + '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2) + '@mistralai/mistralai': 1.14.1 + '@sinclair/typebox': 0.34.52 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + chalk: 5.6.2 + openai: 6.26.0(ws@8.21.1)(zod@4.4.3) + partial-json: 0.1.7 + proxy-agent: 6.5.0(supports-color@10.2.2) + undici: 7.29.0 + zod-to-json-schema: 3.25.2(zod@4.4.3) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-coding-agent@0.60.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3)': + dependencies: + '@mariozechner/jiti': 2.6.5 + '@mariozechner/pi-agent-core': 0.60.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + '@mariozechner/pi-ai': 0.60.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + '@mariozechner/pi-tui': 0.60.0 + '@silvia-odwyer/photon-node': 0.3.4 + chalk: 5.6.2 + cli-highlight: 2.1.11 + diff: 8.0.4 + extract-zip: 2.0.1(supports-color@10.2.2) + file-type: 21.3.4(supports-color@10.2.2) + glob: 13.0.6 + hosted-git-info: 9.0.3 + ignore: 7.0.6 + marked: 15.0.12 + minimatch: 10.2.6 + proper-lockfile: 4.1.2 + strip-ansi: 7.2.0 + undici: 7.29.0 + yaml: 2.9.0 + optionalDependencies: + '@mariozechner/clipboard': 0.3.9 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-tui@0.60.0': + dependencies: + '@types/mime-types': 2.1.4 + chalk: 5.6.2 + get-east-asian-width: 1.6.0 + marked: 15.0.12 + mime-types: 3.0.2 + optionalDependencies: + koffi: 2.16.3 + + '@microsoft/fetch-event-source@2.0.1': {} + + '@mistralai/mistralai@1.14.1': + dependencies: + ws: 8.21.1 + zod: 4.4.3 + zod-to-json-schema: 3.25.2(zod@4.4.3) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@mistralai/mistralai@2.2.6(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/semantic-conventions': 1.43.0 + ws: 8.21.1 + zod: 4.4.3 + zod-to-json-schema: 3.25.2(zod@4.4.3) + optionalDependencies: + '@opentelemetry/api': 1.9.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@modelcontextprotocol/client@2.0.0': + dependencies: + '@modelcontextprotocol/core': 2.0.0 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.0 + jose: 6.2.4 + pkce-challenge: 5.0.1 + zod: 4.4.3 + + '@modelcontextprotocol/core@2.0.0': + dependencies: + zod: 4.4.3 + '@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@3.25.76)': dependencies: - '@hono/node-server': 2.0.12(hono@4.12.32) + '@hono/node-server': 2.0.12(hono@4.12.34) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 @@ -8685,7 +11649,7 @@ snapshots: eventsource-parser: 3.1.0 express: 5.2.1(supports-color@10.2.2) express-rate-limit: 8.6.1(express@5.2.1(supports-color@10.2.2))(supports-color@10.2.2) - hono: 4.12.32 + hono: 4.12.34 jose: 6.2.4 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -8697,6 +11661,30 @@ snapshots: transitivePeerDependencies: - supports-color + '@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3)': + dependencies: + '@hono/node-server': 2.0.12(hono@4.12.34) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.0 + express: 5.2.1(supports-color@10.2.2) + express-rate-limit: 8.6.1(express@5.2.1(supports-color@10.2.2))(supports-color@10.2.2) + hono: 4.12.34 + jose: 6.2.4 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + 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 + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': optional: true @@ -8715,6 +11703,8 @@ snapshots: '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': optional: true + '@napi-rs/cli@2.18.4': {} + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@emnapi/core': 1.11.1 @@ -8738,8 +11728,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@opentelemetry/api@1.9.0': - optional: true + '@opentelemetry/api@1.9.0': {} '@opentelemetry/semantic-conventions@1.43.0': {} @@ -8997,6 +11986,8 @@ snapshots: '@oxlint/plugins@1.68.0': {} + '@pinojs/redact@0.4.0': {} + '@polka/url@1.0.0-next.29': {} '@poppinss/colors@4.1.6': @@ -9014,6 +12005,26 @@ snapshots: '@poppinss/exception@1.2.3': optional: true + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.5': {} + + '@protobufjs/eventemitter@1.1.1': {} + + '@protobufjs/fetch@1.1.1': + dependencies: + '@protobufjs/aspromise': 1.1.2 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.2': {} + '@radix-ui/primitive@1.1.7': {} '@radix-ui/react-accordion@1.2.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': @@ -9378,6 +12389,400 @@ snapshots: '@remix-run/node-fetch-server@0.13.3': {} + '@rivet-dev/agent-os-core@0.1.1': + dependencies: + '@rivet-dev/agent-os-posix': 0.1.0 + '@rivet-dev/agent-os-python': 0.1.0 + '@secure-exec/core': 0.2.1 + '@secure-exec/nodejs': 0.2.1 + '@secure-exec/v8': 0.2.1 + croner: 10.0.1 + long-timeout: 0.1.1 + secure-exec: 0.2.1 + transitivePeerDependencies: + - pyodide + + '@rivet-dev/agent-os-posix@0.1.0': + dependencies: + '@secure-exec/core': 0.2.1 + + '@rivet-dev/agent-os-python@0.1.0': + dependencies: + '@secure-exec/core': 0.2.1 + + '@rivet-dev/agentos-core@0.2.15(@cfworker/json-schema@4.1.1)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)': + dependencies: + '@agentclientprotocol/sdk': 0.16.1(zod@4.4.3) + '@agentos-software/claude-code': 0.2.7(@cfworker/json-schema@4.1.1)(supports-color@10.2.2) + '@agentos-software/codex-cli': 0.3.4 + '@agentos-software/common': 0.2.15 + '@agentos-software/manifest': 0.2.15 + '@agentos-software/opencode': 0.2.7 + '@agentos-software/pi': 0.2.7(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1)(zod@4.4.3) + '@aws-sdk/client-s3': 3.1101.0 + '@rivet-dev/agentos-runtime-core': 0.2.15 + '@rivet-dev/agentos-sidecar': 0.2.15 + '@rivetkit/bare-ts': 0.6.2 + '@xterm/headless': 6.0.0 + better-sqlite3: 12.11.1 + croner: 10.0.1 + googleapis: 144.0.0(supports-color@10.2.2) + isolated-vm: 6.1.2 + long-timeout: 0.1.1 + minimatch: 10.2.6 + zod: 4.4.3 + zod-to-json-schema: 3.25.2(zod@4.4.3) + transitivePeerDependencies: + - '@cfworker/json-schema' + - '@modelcontextprotocol/sdk' + - bufferutil + - encoding + - supports-color + - utf-8-validate + - ws + + '@rivet-dev/agentos-runtime-core@0.2.15': + dependencies: + '@rivet-dev/agentos-runtime-sidecar': 0.2.15 + '@rivetkit/bare-ts': 0.6.2 + zod: 4.4.3 + + '@rivet-dev/agentos-runtime-sidecar-darwin-arm64@0.2.15': + optional: true + + '@rivet-dev/agentos-runtime-sidecar-darwin-x64@0.2.15': + optional: true + + '@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu@0.2.15': + optional: true + + '@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu@0.2.15': + optional: true + + '@rivet-dev/agentos-runtime-sidecar@0.2.15': + optionalDependencies: + '@rivet-dev/agentos-runtime-sidecar-darwin-arm64': 0.2.15 + '@rivet-dev/agentos-runtime-sidecar-darwin-x64': 0.2.15 + '@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu': 0.2.15 + '@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu': 0.2.15 + + '@rivet-dev/agentos-sidecar-darwin-arm64@0.2.15': + optional: true + + '@rivet-dev/agentos-sidecar-darwin-x64@0.2.15': + optional: true + + '@rivet-dev/agentos-sidecar-linux-arm64-gnu@0.2.15': + optional: true + + '@rivet-dev/agentos-sidecar-linux-x64-gnu@0.2.15': + optional: true + + '@rivet-dev/agentos-sidecar@0.2.15': + optionalDependencies: + '@rivet-dev/agentos-sidecar-darwin-arm64': 0.2.15 + '@rivet-dev/agentos-sidecar-darwin-x64': 0.2.15 + '@rivet-dev/agentos-sidecar-linux-arm64-gnu': 0.2.15 + '@rivet-dev/agentos-sidecar-linux-x64-gnu': 0.2.15 + + '@rivet-dev/agentos@0.2.15(@cfworker/json-schema@4.1.1)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)(ws@8.21.1)': + dependencies: + '@agentclientprotocol/sdk': 0.16.1(zod@4.4.3) + '@agentos-software/common': 0.2.15 + '@rivet-dev/agentos-core': 0.2.15(@cfworker/json-schema@4.1.1)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(zod@4.4.3))(supports-color@10.2.2)(ws@8.21.1) + '@rivetkit/react': 2.3.9(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(ws@8.21.1) + rivetkit: 2.3.9(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(ws@8.21.1) + zod: 4.4.3 + optionalDependencies: + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + transitivePeerDependencies: + - '@aws-sdk/client-rds-data' + - '@cfworker/json-schema' + - '@cloudflare/workers-types' + - '@electric-sql/pglite' + - '@libsql/client' + - '@libsql/client-wasm' + - '@modelcontextprotocol/sdk' + - '@neondatabase/serverless' + - '@op-engineering/op-sqlite' + - '@opentelemetry/api' + - '@planetscale/database' + - '@prisma/client' + - '@tidbcloud/serverless' + - '@types/better-sqlite3' + - '@types/pg' + - '@types/sql.js' + - '@upstash/redis' + - '@vercel/postgres' + - '@xata.io/client' + - better-sqlite3 + - bufferutil + - bun-types + - drizzle-kit + - encoding + - eventsource + - expo-sqlite + - gel + - knex + - kysely + - mysql2 + - pg + - postgres + - prisma + - pyodide + - sql.js + - sqlite3 + - supports-color + - utf-8-validate + - ws + + '@rivetkit/bare-ts@0.6.2': {} + + '@rivetkit/engine-cli-darwin-arm64@2.3.10': + optional: true + + '@rivetkit/engine-cli-darwin-arm64@2.3.9': + optional: true + + '@rivetkit/engine-cli-darwin-x64@2.3.10': + optional: true + + '@rivetkit/engine-cli-darwin-x64@2.3.9': + optional: true + + '@rivetkit/engine-cli-linux-arm64-musl@2.3.10': + optional: true + + '@rivetkit/engine-cli-linux-arm64-musl@2.3.9': + optional: true + + '@rivetkit/engine-cli-linux-x64-musl@2.3.10': + optional: true + + '@rivetkit/engine-cli-linux-x64-musl@2.3.9': + optional: true + + '@rivetkit/engine-cli-win32-x64@2.3.10': + optional: true + + '@rivetkit/engine-cli-win32-x64@2.3.9': + optional: true + + '@rivetkit/engine-cli@2.3.10': + optionalDependencies: + '@rivetkit/engine-cli-darwin-arm64': 2.3.10 + '@rivetkit/engine-cli-darwin-x64': 2.3.10 + '@rivetkit/engine-cli-linux-arm64-musl': 2.3.10 + '@rivetkit/engine-cli-linux-x64-musl': 2.3.10 + '@rivetkit/engine-cli-win32-x64': 2.3.10 + + '@rivetkit/engine-cli@2.3.9': + optionalDependencies: + '@rivetkit/engine-cli-darwin-arm64': 2.3.9 + '@rivetkit/engine-cli-darwin-x64': 2.3.9 + '@rivetkit/engine-cli-linux-arm64-musl': 2.3.9 + '@rivetkit/engine-cli-linux-x64-musl': 2.3.9 + '@rivetkit/engine-cli-win32-x64': 2.3.9 + + '@rivetkit/engine-envoy-protocol@2.3.10': + dependencies: + '@rivetkit/bare-ts': 0.6.2 + + '@rivetkit/engine-envoy-protocol@2.3.9': + dependencies: + '@rivetkit/bare-ts': 0.6.2 + + '@rivetkit/framework-base@2.3.9(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(ws@8.21.1)': + dependencies: + '@tanstack/store': 0.7.7 + fast-deep-equal: 3.1.3 + rivetkit: 2.3.9(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(ws@8.21.1) + transitivePeerDependencies: + - '@aws-sdk/client-rds-data' + - '@cloudflare/workers-types' + - '@electric-sql/pglite' + - '@libsql/client' + - '@libsql/client-wasm' + - '@neondatabase/serverless' + - '@op-engineering/op-sqlite' + - '@opentelemetry/api' + - '@planetscale/database' + - '@prisma/client' + - '@tidbcloud/serverless' + - '@types/better-sqlite3' + - '@types/pg' + - '@types/sql.js' + - '@upstash/redis' + - '@vercel/postgres' + - '@xata.io/client' + - better-sqlite3 + - bun-types + - drizzle-kit + - eventsource + - expo-sqlite + - gel + - knex + - kysely + - mysql2 + - pg + - postgres + - prisma + - pyodide + - sql.js + - sqlite3 + - ws + + '@rivetkit/on-change@6.0.1': {} + + '@rivetkit/react@2.3.9(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(ws@8.21.1)': + dependencies: + '@rivetkit/framework-base': 2.3.9(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(ws@8.21.1) + '@tanstack/react-store': 0.7.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + rivetkit: 2.3.9(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(ws@8.21.1) + transitivePeerDependencies: + - '@aws-sdk/client-rds-data' + - '@cloudflare/workers-types' + - '@electric-sql/pglite' + - '@libsql/client' + - '@libsql/client-wasm' + - '@neondatabase/serverless' + - '@op-engineering/op-sqlite' + - '@opentelemetry/api' + - '@planetscale/database' + - '@prisma/client' + - '@tidbcloud/serverless' + - '@types/better-sqlite3' + - '@types/pg' + - '@types/sql.js' + - '@upstash/redis' + - '@vercel/postgres' + - '@xata.io/client' + - better-sqlite3 + - bun-types + - drizzle-kit + - eventsource + - expo-sqlite + - gel + - knex + - kysely + - mysql2 + - pg + - postgres + - prisma + - pyodide + - sql.js + - sqlite3 + - ws + + '@rivetkit/rivetkit-napi-darwin-arm64@2.3.10': + optional: true + + '@rivetkit/rivetkit-napi-darwin-arm64@2.3.9': + optional: true + + '@rivetkit/rivetkit-napi-darwin-x64@2.3.10': + optional: true + + '@rivetkit/rivetkit-napi-darwin-x64@2.3.9': + optional: true + + '@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.10': + optional: true + + '@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.9': + optional: true + + '@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.10': + optional: true + + '@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.9': + optional: true + + '@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.10': + optional: true + + '@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.9': + optional: true + + '@rivetkit/rivetkit-napi-linux-x64-musl@2.3.10': + optional: true + + '@rivetkit/rivetkit-napi-linux-x64-musl@2.3.9': + optional: true + + '@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.10': + optional: true + + '@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.9': + optional: true + + '@rivetkit/rivetkit-napi@2.3.10': + dependencies: + '@napi-rs/cli': 2.18.4 + '@rivetkit/engine-envoy-protocol': 2.3.10 + optionalDependencies: + '@rivetkit/rivetkit-napi-darwin-arm64': 2.3.10 + '@rivetkit/rivetkit-napi-darwin-x64': 2.3.10 + '@rivetkit/rivetkit-napi-linux-arm64-gnu': 2.3.10 + '@rivetkit/rivetkit-napi-linux-arm64-musl': 2.3.10 + '@rivetkit/rivetkit-napi-linux-x64-gnu': 2.3.10 + '@rivetkit/rivetkit-napi-linux-x64-musl': 2.3.10 + '@rivetkit/rivetkit-napi-win32-x64-msvc': 2.3.10 + + '@rivetkit/rivetkit-napi@2.3.9': + dependencies: + '@napi-rs/cli': 2.18.4 + '@rivetkit/engine-envoy-protocol': 2.3.9 + optionalDependencies: + '@rivetkit/rivetkit-napi-darwin-arm64': 2.3.9 + '@rivetkit/rivetkit-napi-darwin-x64': 2.3.9 + '@rivetkit/rivetkit-napi-linux-arm64-gnu': 2.3.9 + '@rivetkit/rivetkit-napi-linux-arm64-musl': 2.3.9 + '@rivetkit/rivetkit-napi-linux-x64-gnu': 2.3.9 + '@rivetkit/rivetkit-napi-linux-x64-musl': 2.3.9 + '@rivetkit/rivetkit-napi-win32-x64-msvc': 2.3.9 + + '@rivetkit/rivetkit-wasm@2.3.10': {} + + '@rivetkit/rivetkit-wasm@2.3.9': {} + + '@rivetkit/traces@2.3.10': + dependencies: + '@rivetkit/bare-ts': 0.6.2 + cbor-x: 1.6.5 + fdb-tuple: 1.0.0 + vbare: 0.0.4 + + '@rivetkit/traces@2.3.9': + dependencies: + '@rivetkit/bare-ts': 0.6.2 + cbor-x: 1.6.5 + fdb-tuple: 1.0.0 + vbare: 0.0.4 + + '@rivetkit/virtual-websocket@2.3.10': {} + + '@rivetkit/virtual-websocket@2.3.9': {} + + '@rivetkit/workflow-engine@2.3.10': + dependencies: + '@rivetkit/bare-ts': 0.6.2 + cbor-x: 1.6.5 + fdb-tuple: 1.0.0 + pino: 9.14.0 + vbare: 0.0.4 + + '@rivetkit/workflow-engine@2.3.9': + dependencies: + '@rivetkit/bare-ts': 0.6.2 + cbor-x: 1.6.5 + fdb-tuple: 1.0.0 + pino: 9.14.0 + vbare: 0.0.4 + '@rolldown/binding-android-arm64@1.1.4': optional: true @@ -9486,18 +12891,111 @@ snapshots: '@sec-ant/readable-stream@0.4.1': {} + '@secure-exec/core@0.2.1': + dependencies: + better-sqlite3: 12.11.1 + + '@secure-exec/nodejs@0.2.1': + dependencies: + '@secure-exec/core': 0.2.1 + '@secure-exec/v8': 0.2.1 + cbor-x: 1.6.5 + cjs-module-lexer: 2.2.0 + es-module-lexer: 1.7.0 + esbuild: 0.27.7 + node-stdlib-browser: 1.3.1 + web-streams-polyfill: 4.3.0 + + '@secure-exec/v8-darwin-arm64@0.2.1': + optional: true + + '@secure-exec/v8-darwin-x64@0.2.1': + optional: true + + '@secure-exec/v8-linux-arm64-gnu@0.2.1': + optional: true + + '@secure-exec/v8-linux-x64-gnu@0.2.1': + optional: true + + '@secure-exec/v8@0.2.1': + dependencies: + cbor-x: 1.6.5 + optionalDependencies: + '@secure-exec/v8-darwin-arm64': 0.2.1 + '@secure-exec/v8-darwin-x64': 0.2.1 + '@secure-exec/v8-linux-arm64-gnu': 0.2.1 + '@secure-exec/v8-linux-x64-gnu': 0.2.1 + '@shadcn/react@0.2.1(@types/react@19.2.17)(react@19.2.8)': optionalDependencies: '@types/react': 19.2.17 react: 19.2.8 + '@silvia-odwyer/photon-node@0.3.4': {} + '@sinclair/typebox@0.27.12': {} + '@sinclair/typebox@0.34.52': {} + '@sindresorhus/is@7.2.0': optional: true '@sindresorhus/merge-streams@4.0.0': {} + '@smithy/core@3.31.1': + dependencies: + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.4.16': + dependencies: + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.6.13': + dependencies: + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/node-http-handler@4.7.3': + dependencies: + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.9.13': + dependencies: + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@smithy/signature-v4@5.6.12': + dependencies: + '@smithy/core': 3.31.1 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + + '@smithy/types@4.16.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + '@solid-primitives/event-listener@2.4.6(solid-js@1.9.14)': dependencies: '@solid-primitives/utils': 6.4.1(solid-js@1.9.14) @@ -9722,8 +13220,17 @@ snapshots: react-dom: 19.2.8(react@19.2.8) use-sync-external-store: 1.6.0(react@19.2.8) + '@tanstack/react-store@0.7.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + dependencies: + '@tanstack/store': 0.7.7 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + use-sync-external-store: 1.6.0(react@19.2.8) + '@tanstack/store@0.11.0': {} + '@tanstack/store@0.7.7': {} + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.7 @@ -9739,6 +13246,17 @@ snapshots: dependencies: '@testing-library/dom': 10.4.1 + '@tokenizer/inflate@0.4.1(supports-color@10.2.2)': + dependencies: + debug: 4.4.3(supports-color@10.2.2) + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + + '@tokenizer/token@0.3.0': {} + + '@tootallnate/quickjs-emscripten@0.23.0': {} + '@ts-morph/common@0.11.1': dependencies: fast-glob: 3.3.3 @@ -9790,6 +13308,8 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/mime-types@2.1.4': {} + '@types/node@22.20.1': dependencies: undici-types: 6.21.0 @@ -9810,6 +13330,10 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/retry@0.12.0': {} + + '@types/retry@0.12.2': {} + '@types/validate-npm-package-name@4.0.2': {} '@types/yargs-parser@21.0.3': {} @@ -9818,6 +13342,11 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 26.1.2 + optional: true + '@typescript-eslint/project-service@8.65.0(supports-color@10.2.2)(typescript@7.0.2)': dependencies: '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@7.0.2) @@ -9931,12 +13460,18 @@ snapshots: '@ungap/structured-clone@1.3.3': {} + '@valibot/to-json-schema@1.7.1(valibot@1.4.2(typescript@7.0.2))': + dependencies: + valibot: 1.4.2(typescript@7.0.2) + '@vercel/config@0.5.5': dependencies: '@vercel/routing-utils': 6.4.0 pretty-cache-header: 1.0.0 zod: 3.25.76 + '@vercel/detect-agent@1.2.3': {} + '@vercel/react-router@1.3.1(@react-router/dev@8.3.0(@react-router/serve@8.3.0(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(supports-color@10.2.2)(typescript@7.0.2))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(supports-color@10.2.2)(typescript@7.0.2)(wrangler@4.114.0))(@react-router/node@8.3.0(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(typescript@7.0.2))(isbot@5.2.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@react-router/dev': 8.3.0(@react-router/serve@8.3.0(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(supports-color@10.2.2)(typescript@7.0.2))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(yaml@2.9.0))(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(supports-color@10.2.2)(typescript@7.0.2)(wrangler@4.114.0) @@ -10145,6 +13680,8 @@ snapshots: '@xmldom/xmldom@0.9.10': {} + '@xterm/headless@6.0.0': {} + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -10222,6 +13759,8 @@ snapshots: ansi-styles@5.2.0: {} + any-promise@1.3.0: {} + arg@5.0.2: {} argparse@2.0.1: {} @@ -10232,14 +13771,38 @@ snapshots: asap@2.0.6: {} + asn1.js@4.10.1: + dependencies: + bn.js: 4.12.5 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + assert@2.1.0: + dependencies: + call-bind: 1.0.9 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.7 + util: 0.12.5 + assertion-error@2.0.1: {} + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + ast-types@0.16.1: dependencies: tslib: 2.8.1 + atomic-sleep@1.0.0: {} + atomically@1.7.0: {} + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + babel-dead-code-elimination@1.0.12(supports-color@10.2.2): dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) @@ -10357,6 +13920,8 @@ snapshots: dependencies: safe-buffer: 5.1.2 + basic-ftp@5.3.1: {} + better-auth@1.6.15(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(solid-js@1.9.14)(vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(@vitest/browser-preview@4.1.9(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vitest@4.1.9))(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))): dependencies: '@better-auth/core': 1.6.15(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) @@ -10428,25 +13993,28 @@ snapshots: dependencies: bindings: 1.5.0 prebuild-install: 7.1.3 - optional: true big-integer@1.6.52: {} + bignumber.js@9.3.1: {} + bindings@1.5.0: dependencies: file-uri-to-path: 1.0.0 - optional: true bl@4.1.0: dependencies: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 - optional: true blake3-wasm@2.1.5: optional: true + bn.js@4.12.5: {} + + bn.js@5.2.5: {} + body-parser@2.3.0(supports-color@10.2.2): dependencies: bytes: 3.1.2 @@ -10463,6 +14031,8 @@ snapshots: boolbase@1.0.0: {} + bowser@2.14.1: {} + bplist-creator@0.1.0: dependencies: stream-buffers: 2.2.0 @@ -10488,6 +14058,56 @@ snapshots: dependencies: fill-range: 7.1.1 + brorand@1.1.0: {} + + browser-resolve@2.0.0: + dependencies: + resolve: 1.22.12 + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.7 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-cipher@1.0.1: + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + + browserify-des@1.0.2: + dependencies: + cipher-base: 1.0.7 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-rsa@4.1.1: + dependencies: + bn.js: 5.2.5 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + browserify-sign@4.2.6: + dependencies: + bn.js: 5.2.5 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.6.1 + inherits: 2.0.4 + parse-asn1: 5.1.9 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + + browserify-zlib@0.2.0: + dependencies: + pako: 1.0.11 + browserslist@4.28.7: dependencies: baseline-browser-mapping: 2.11.5 @@ -10500,13 +14120,20 @@ snapshots: dependencies: node-int64: 0.4.0 + buffer-crc32@0.2.13: {} + + buffer-equal-constant-time@1.0.1: {} + buffer-from@1.1.2: {} + buffer-xor@1.0.3: {} + buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - optional: true + + builtin-status-codes@3.0.0: {} bun-types@1.3.14: dependencies: @@ -10518,11 +14145,20 @@ snapshots: bytes@3.1.2: {} + cac@7.0.0: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + call-bound@1.0.4: dependencies: call-bind-apply-helpers: 1.0.2 @@ -10534,6 +14170,22 @@ snapshots: caniuse-lite@1.0.30001806: {} + cbor-extract@2.2.2: + dependencies: + node-gyp-build-optional-packages: 5.1.1 + optionalDependencies: + '@cbor-extract/cbor-extract-darwin-arm64': 2.2.2 + '@cbor-extract/cbor-extract-darwin-x64': 2.2.2 + '@cbor-extract/cbor-extract-linux-arm': 2.2.2 + '@cbor-extract/cbor-extract-linux-arm64': 2.2.2 + '@cbor-extract/cbor-extract-linux-x64': 2.2.2 + '@cbor-extract/cbor-extract-win32-x64': 2.2.2 + optional: true + + cbor-x@1.6.5: + optionalDependencies: + cbor-extract: 2.2.2 + chai@6.2.2: {} chain-function@1.0.1: {} @@ -10555,8 +14207,7 @@ snapshots: dependencies: readdirp: 5.0.0 - chownr@1.1.4: - optional: true + chownr@1.1.4: {} chrome-launcher@0.15.2(supports-color@10.2.2): dependencies: @@ -10581,8 +14232,16 @@ snapshots: ci-info@3.9.0: {} + cipher-base@1.0.7: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + citty@0.2.2: {} + cjs-module-lexer@2.2.0: {} + class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -10597,8 +14256,23 @@ snapshots: dependencies: restore-cursor: 5.1.0 + cli-highlight@2.1.11: + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.2 + cli-spinners@2.9.2: {} + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -10692,6 +14366,10 @@ snapshots: transitivePeerDependencies: - supports-color + console-browserify@1.2.0: {} + + constants-browserify@1.0.0: {} + content-disposition@1.1.0: {} content-type@1.0.5: {} @@ -10700,12 +14378,12 @@ snapshots: convert-source-map@2.0.0: {} - convex-helpers@0.1.120(@standard-schema/spec@1.1.0)(convex@1.42.3(react@19.2.8))(hono@4.12.32)(react@19.2.8)(typescript@7.0.2)(zod@4.4.3): + convex-helpers@0.1.120(@standard-schema/spec@1.1.0)(convex@1.42.3(react@19.2.8))(hono@4.12.34)(react@19.2.8)(typescript@7.0.2)(zod@4.4.3): dependencies: convex: 1.42.3(react@19.2.8) optionalDependencies: '@standard-schema/spec': 1.1.0 - hono: 4.12.32 + hono: 4.12.34 react: 19.2.8 typescript: 7.0.2 zod: 4.4.3 @@ -10738,6 +14416,8 @@ snapshots: dependencies: browserslist: 4.28.7 + core-util-is@1.0.3: {} + cors@2.8.6: dependencies: object-assign: 4.1.1 @@ -10752,12 +14432,53 @@ snapshots: optionalDependencies: typescript: 7.0.2 + create-ecdh@4.0.4: + dependencies: + bn.js: 4.12.5 + elliptic: 6.6.1 + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.7 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.3 + sha.js: 2.4.12 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.7 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.3 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + + create-require@1.1.1: {} + + croner@10.0.1: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + crypto-browserify@3.12.1: + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.6 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + hash-base: 3.0.5 + inherits: 2.0.4 + pbkdf2: 3.1.6 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + css-select@5.2.2: dependencies: boolbase: 1.0.0 @@ -10821,6 +14542,10 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) + data-uri-to-buffer@4.0.1: {} + + data-uri-to-buffer@6.0.2: {} + dayjs@1.11.21: {} debounce-fn@4.0.0: @@ -10848,12 +14573,10 @@ snapshots: decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 - optional: true dedent@1.7.2: {} - deep-extend@0.6.0: - optional: true + deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -10870,22 +14593,51 @@ snapshots: dependencies: clone: 1.0.4 + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + define-lazy-prop@2.0.0: {} define-lazy-prop@3.0.0: {} + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + defu@6.1.7: {} + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + depd@2.0.0: {} dequal@2.0.3: {} + des.js@1.1.0: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + destroy@1.2.0: {} detect-libc@2.1.2: {} diff@8.0.4: {} + diffie-hellman@5.0.3: + dependencies: + bn.js: 4.12.5 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + dnssd-advertise@1.1.6: {} dom-accessibility-api@0.5.16: {} @@ -10900,6 +14652,8 @@ snapshots: domhandler: 5.0.3 entities: 4.5.0 + domain-browser@4.22.0: {} + domelementtype@2.3.0: {} domhandler@5.0.3: @@ -10918,12 +14672,23 @@ snapshots: dotenv@17.4.2: {} + drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4): + optionalDependencies: + '@opentelemetry/api': 1.9.0 + better-sqlite3: 12.11.1 + bun-types: 1.3.14 + kysely: 0.29.4 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 es-errors: 1.3.0 gopd: 1.2.0 + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + ee-first@1.1.1: {} effect@4.0.0-beta.99: @@ -10941,6 +14706,16 @@ snapshots: electron-to-chromium@1.5.396: {} + elliptic@6.6.1: + dependencies: + bn.js: 4.12.5 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} @@ -10952,7 +14727,6 @@ snapshots: end-of-stream@1.4.5: dependencies: once: 1.4.0 - optional: true enhanced-resolve@5.24.3: dependencies: @@ -10983,6 +14757,8 @@ snapshots: es-errors@1.3.0: {} + es-module-lexer@1.7.0: {} + es-module-lexer@2.3.1: {} es-object-atoms@1.1.2: @@ -11018,6 +14794,35 @@ snapshots: '@esbuild/win32-ia32': 0.27.0 '@esbuild/win32-x64': 0.27.0 + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + esbuild@0.28.1: optionalDependencies: '@esbuild/aix-ppc64': 0.28.1 @@ -11056,6 +14861,14 @@ snapshots: escape-string-regexp@4.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + eslint-scope@9.1.2: dependencies: '@types/esrecurse': 4.3.1 @@ -11132,12 +14945,19 @@ snapshots: event-target-shim@5.0.1: {} + events@3.3.0: {} + eventsource-parser@3.1.0: {} eventsource@3.0.7: dependencies: eventsource-parser: 3.1.0 + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -11167,8 +14987,7 @@ snapshots: exit-hook@5.1.0: {} - expand-template@2.0.3: - optional: true + expand-template@2.0.3: {} expect-type@1.4.0: {} @@ -11413,6 +15232,18 @@ snapshots: exsolve@1.1.1: {} + extend@3.0.2: {} + + extract-zip@2.0.1(supports-color@10.2.2): + dependencies: + debug: 4.4.3(supports-color@10.2.2) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + fast-check@4.9.0: dependencies: pure-rand: 8.4.2 @@ -11453,10 +15284,21 @@ snapshots: dependencies: bser: 2.1.1 + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fdb-tuple@1.0.0: {} + fdir@6.5.0(picomatch@4.0.5): optionalDependencies: picomatch: 4.0.5 + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + fetch-nodeshim@0.4.10: {} figures@6.1.0: @@ -11467,8 +15309,16 @@ snapshots: dependencies: flat-cache: 4.0.1 - file-uri-to-path@1.0.0: - optional: true + file-type@21.3.4(supports-color@10.2.2): + dependencies: + '@tokenizer/inflate': 0.4.1(supports-color@10.2.2) + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + + file-uri-to-path@1.0.0: {} fill-range@7.1.1: dependencies: @@ -11519,6 +15369,14 @@ snapshots: fontfaceobserver@2.3.0: {} + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + forwarded@0.2.0: {} framer-motion@12.42.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8): @@ -11534,8 +15392,7 @@ snapshots: fresh@2.0.0: {} - fs-constants@1.0.0: - optional: true + fs-constants@1.0.0: {} fs-extra@11.4.0: dependencies: @@ -11550,6 +15407,44 @@ snapshots: fuzzysort@3.1.0: {} + gaxios@6.7.1(supports-color@10.2.2): + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6(supports-color@10.2.2) + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gaxios@7.3.0(supports-color@10.2.2): + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6(supports-color@10.2.2) + node-fetch: 3.3.2 + transitivePeerDependencies: + - supports-color + + gcp-metadata@6.1.1(supports-color@10.2.2): + dependencies: + gaxios: 6.7.1(supports-color@10.2.2) + google-logging-utils: 0.0.2 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@8.1.2(supports-color@10.2.2): + dependencies: + gaxios: 7.3.0(supports-color@10.2.2) + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + + generator-function@2.0.1: {} + gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} @@ -11576,6 +15471,10 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.2 + get-stream@5.2.0: + dependencies: + pump: 3.0.4 + get-stream@6.0.1: {} get-stream@9.0.1: @@ -11583,10 +15482,17 @@ snapshots: '@sec-ant/readable-stream': 0.4.1 is-stream: 4.0.1 + get-uri@6.0.5(supports-color@10.2.2): + dependencies: + basic-ftp: 5.3.1 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3(supports-color@10.2.2) + transitivePeerDependencies: + - supports-color + getenv@2.0.0: {} - github-from-package@0.0.0: - optional: true + github-from-package@0.0.0: {} glob-parent@5.1.2: dependencies: @@ -11608,16 +15514,96 @@ snapshots: dependencies: csstype: 3.2.3 + google-auth-library@10.9.1(supports-color@10.2.2): + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.3.0(supports-color@10.2.2) + gcp-metadata: 8.1.2(supports-color@10.2.2) + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-auth-library@9.15.1(supports-color@10.2.2): + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1(supports-color@10.2.2) + gcp-metadata: 6.1.1(supports-color@10.2.2) + gtoken: 7.1.0(supports-color@10.2.2) + jws: 4.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + google-logging-utils@0.0.2: {} + + google-logging-utils@1.1.3: {} + + googleapis-common@7.2.0(supports-color@10.2.2): + dependencies: + extend: 3.0.2 + gaxios: 6.7.1(supports-color@10.2.2) + google-auth-library: 9.15.1(supports-color@10.2.2) + qs: 6.15.3 + url-template: 2.0.8 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + googleapis@144.0.0(supports-color@10.2.2): + dependencies: + google-auth-library: 9.15.1(supports-color@10.2.2) + googleapis-common: 7.2.0(supports-color@10.2.2) + transitivePeerDependencies: + - encoding + - supports-color + gopd@1.2.0: {} graceful-fs@4.2.11: {} + gtoken@7.1.0(supports-color@10.2.2): + dependencies: + gaxios: 6.7.1(supports-color@10.2.2) + jws: 4.0.1 + transitivePeerDependencies: + - encoding + - supports-color + has-flag@3.0.0: {} has-flag@4.0.0: {} + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + has-symbols@1.1.0: {} + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hash-base@3.0.5: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + hash-base@3.1.2: + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -11654,16 +15640,30 @@ snapshots: tailwind-merge: 3.6.0 tailwind-variants: 3.3.0(tailwind-merge@3.6.0)(tailwindcss@4.3.3) + highlight.js@10.7.3: {} + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + hoist-non-react-statics@3.3.2: dependencies: react-is: 16.13.1 hono@4.12.32: {} + hono@4.12.34: {} + hosted-git-info@7.0.2: dependencies: lru-cache: 10.4.3 + hosted-git-info@9.0.3: + dependencies: + lru-cache: 11.5.2 + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -11672,6 +15672,15 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 + http-proxy-agent@7.0.2(supports-color@10.2.2): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@10.2.2) + transitivePeerDependencies: + - supports-color + + https-browserify@1.0.0: {} + https-proxy-agent@7.0.6(supports-color@10.2.2): dependencies: agent-base: 7.1.4 @@ -11687,11 +15696,14 @@ snapshots: dependencies: safer-buffer: 2.1.2 - ieee754@1.2.1: - optional: true + ieee754@1.2.1: {} ignore@5.3.2: {} + ignore@7.0.5: {} + + ignore@7.0.6: {} + image-size@1.2.1: dependencies: queue: 6.0.2 @@ -11705,8 +15717,7 @@ snapshots: inherits@2.0.4: {} - ini@1.3.8: - optional: true + ini@1.3.8: {} ini@7.0.0: {} @@ -11718,8 +15729,15 @@ snapshots: ipaddr.js@1.9.1: {} + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-arrayish@0.2.1: {} + is-callable@1.2.7: {} + is-core-module@2.16.2: dependencies: hasown: 2.0.4 @@ -11732,6 +15750,14 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -11744,6 +15770,13 @@ snapshots: is-interactive@2.0.0: {} + is-nan@1.3.2: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + + is-network-error@1.3.2: {} + is-number@7.0.0: {} is-obj@2.0.0: {} @@ -11754,12 +15787,23 @@ snapshots: is-promise@4.0.0: {} + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + is-regexp@3.1.0: {} is-stream@2.0.1: {} is-stream@4.0.1: {} + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.22 + is-unicode-supported@1.3.0: {} is-unicode-supported@2.1.0: {} @@ -11772,12 +15816,22 @@ snapshots: dependencies: is-inside-container: 1.0.0 + isarray@1.0.0: {} + + isarray@2.0.5: {} + isbot@5.2.1: {} isexe@2.0.0: {} isexe@3.1.5: {} + isolated-vm@6.1.2: + dependencies: + node-gyp-build: 4.8.4 + + isomorphic-timers-promises@1.0.1: {} + jest-get-type@29.6.3: {} jest-util@29.7.0: @@ -11817,10 +15871,18 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@5.2.3: + dependencies: + argparse: 2.0.1 + jsc-safe-url@0.2.4: {} jsesc@3.1.0: {} + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} @@ -11830,6 +15892,11 @@ snapshots: '@types/json-schema': 7.0.15 ts-toolbelt: 6.15.5 + json-schema-to-ts@3.1.1: + dependencies: + '@babel/runtime': 7.29.7 + ts-algebra: 2.0.0 + json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -11850,6 +15917,17 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -11858,6 +15936,9 @@ snapshots: kleur@4.1.5: {} + koffi@2.16.3: + optional: true + kubernetes-types@1.30.0: {} kysely@0.29.4: {} @@ -11869,6 +15950,8 @@ snapshots: picocolors: 1.1.1 shell-quote: 1.10.0 + layerr@3.0.0: {} + leven@3.1.0: {} levn@0.4.1: @@ -12007,6 +16090,10 @@ snapshots: chalk: 5.6.2 is-unicode-supported: 1.3.0 + long-timeout@0.1.1: {} + + long@5.3.2: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -12019,6 +16106,8 @@ snapshots: dependencies: yallist: 3.1.1 + lru-cache@7.18.3: {} + lucide-react@1.27.0(react@19.2.8): dependencies: react: 19.2.8 @@ -12029,14 +16118,26 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@1.1.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + makeerror@1.0.12: dependencies: tmpl: 1.0.5 + marked@15.0.12: {} + marky@1.3.0: {} math-intrinsics@1.1.0: {} + md5.js@1.3.5: + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + safe-buffer: 5.2.1 + mdn-data@2.0.14: {} media-typer@1.1.1: {} @@ -12228,6 +16329,11 @@ snapshots: braces: 3.0.3 picomatch: 2.3.2 + miller-rabin@4.0.1: + dependencies: + bn.js: 4.12.5 + brorand: 1.1.0 + mime-db@1.52.0: {} mime-db@1.54.0: {} @@ -12250,8 +16356,7 @@ snapshots: mimic-function@5.0.1: {} - mimic-response@3.1.0: - optional: true + mimic-response@3.1.0: {} miniflare@4.20260722.0: dependencies: @@ -12266,6 +16371,10 @@ snapshots: - utf-8-validate optional: true + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + minimatch@10.2.6: dependencies: brace-expansion: 5.0.8 @@ -12278,8 +16387,9 @@ snapshots: minipass@7.1.3: {} - mkdirp-classic@0.5.3: - optional: true + minisearch@7.2.0: {} + + mkdirp-classic@0.5.3: {} mkdirp@1.0.4: {} @@ -12325,12 +16435,17 @@ snapshots: multitars@1.0.0: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nanoid@3.3.16: {} nanostores@1.4.1: {} - napi-build-utils@2.0.0: - optional: true + napi-build-utils@2.0.0: {} natural-compare@1.4.0: {} @@ -12340,6 +16455,8 @@ snapshots: negotiator@1.0.0: {} + netmask@2.1.1: {} + next-themes@0.4.6(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: react: 19.2.8 @@ -12348,19 +16465,67 @@ snapshots: node-abi@3.94.0: dependencies: semver: 7.8.5 - optional: true + + node-domexception@1.0.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 node-forge@1.4.0: {} + node-gyp-build-optional-packages@5.1.1: + dependencies: + detect-libc: 2.1.2 + optional: true + node-gyp-build-optional-packages@5.2.2: dependencies: detect-libc: 2.1.2 optional: true + node-gyp-build@4.8.4: {} + node-int64@0.4.0: {} node-releases@2.0.51: {} + node-stdlib-browser@1.3.1: + dependencies: + assert: 2.1.0 + browser-resolve: 2.0.0 + browserify-zlib: 0.2.0 + buffer: 5.7.1 + console-browserify: 1.2.0 + constants-browserify: 1.0.0 + create-require: 1.1.1 + crypto-browserify: 3.12.1 + domain-browser: 4.22.0 + events: 3.3.0 + https-browserify: 1.0.0 + isomorphic-timers-promises: 1.0.1 + os-browserify: 0.3.0 + path-browserify: 1.0.1 + pkg-dir: 5.0.0 + process: 0.11.10 + punycode: 1.4.1 + querystring-es3: 0.2.1 + readable-stream: 3.6.2 + stream-browserify: 3.0.0 + stream-http: 3.2.0 + string_decoder: 1.3.0 + timers-browserify: 2.0.12 + tty-browserify: 0.0.1 + url: 0.11.4 + util: 0.12.5 + vm-browserify: 1.1.2 + npm-package-arg@11.0.3: dependencies: hosted-git-info: 7.0.2 @@ -12397,10 +16562,28 @@ snapshots: object-inspect@1.13.4: {} + object-is@1.1.6: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + object-treeify@1.1.33: {} + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + has-symbols: 1.1.0 + object-keys: 1.1.1 + obug@2.1.4: {} + on-exit-leak-free@2.1.2: {} + on-finished@2.3.0: dependencies: ee-first: 1.1.1 @@ -12447,6 +16630,15 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 + openai@6.26.0(ws@8.21.1)(zod@4.4.3): + optionalDependencies: + ws: 8.21.1 + zod: 4.4.3 + + openapi3-ts@4.6.1: + dependencies: + yaml: 2.9.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -12477,6 +16669,8 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.2.0 + os-browserify@0.3.0: {} + oxfmt@0.57.0(vite-plus@0.2.2(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(yaml@2.9.0)): dependencies: tinypool: 2.1.0 @@ -12602,12 +16796,51 @@ snapshots: p-map@7.0.6: {} + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.3.2 + retry: 0.13.1 + p-try@2.2.0: {} + pac-proxy-agent@7.2.0(supports-color@10.2.2): + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.4 + debug: 4.4.3(supports-color@10.2.2) + get-uri: 6.0.5(supports-color@10.2.2) + http-proxy-agent: 7.0.2(supports-color@10.2.2) + https-proxy-agent: 7.0.6(supports-color@10.2.2) + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5(supports-color@10.2.2) + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.1.1 + + pako@1.0.11: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 + parse-asn1@5.1.9: + dependencies: + asn1.js: 4.10.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + pbkdf2: 3.1.6 + safe-buffer: 5.2.1 + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.29.7 @@ -12621,8 +16854,18 @@ snapshots: dependencies: pngjs: 3.4.0 + parse5-htmlparser2-tree-adapter@6.0.1: + dependencies: + parse5: 6.0.1 + + parse5@5.1.1: {} + + parse5@6.0.1: {} + parseurl@1.3.3: {} + partial-json@0.1.7: {} + path-browserify@1.0.1: {} path-exists@3.0.0: {} @@ -12648,14 +16891,49 @@ snapshots: pathe@2.0.3: {} + pbkdf2@3.1.6: + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.3 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + to-buffer: 1.2.2 + + pend@1.2.0: {} + picocolors@1.1.1: {} picomatch@2.3.2: {} picomatch@4.0.5: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.1.0: {} + + pino@9.14.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.1.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 3.2.0 + pkce-challenge@5.0.1: {} + pkg-dir@5.0.0: + dependencies: + find-up: 5.0.0 + pkg-types@2.3.1: dependencies: confbox: 0.2.4 @@ -12676,6 +16954,8 @@ snapshots: pngjs@7.0.0: {} + possible-typed-array-names@1.1.0: {} + postcss-selector-parser@7.1.4: dependencies: cssesc: 3.0.0 @@ -12703,7 +16983,6 @@ snapshots: simple-get: 4.0.1 tar-fs: 2.1.5 tunnel-agent: 0.6.0 - optional: true prelude-ls@1.2.1: {} @@ -12731,6 +17010,12 @@ snapshots: proc-log@4.2.0: {} + process-nextick-args@2.0.1: {} + + process-warning@5.1.0: {} + + process@0.11.10: {} + progress@2.0.3: {} promise@8.3.0: @@ -12748,16 +17033,61 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + + protobufjs@7.6.5: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.1 + '@protobufjs/fetch': 1.1.1 + '@protobufjs/float': 1.0.2 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.2 + '@types/node': 26.1.2 + long: 5.3.2 + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-agent@6.5.0(supports-color@10.2.2): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@10.2.2) + http-proxy-agent: 7.0.2(supports-color@10.2.2) + https-proxy-agent: 7.0.6(supports-color@10.2.2) + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0(supports-color@10.2.2) + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5(supports-color@10.2.2) + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + + public-encrypt@4.0.3: + dependencies: + bn.js: 4.12.5 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + parse-asn1: 5.1.9 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + pump@3.0.4: dependencies: end-of-stream: 1.4.5 once: 1.4.0 - optional: true + + punycode@1.4.1: {} punycode@2.3.1: {} @@ -12768,12 +17098,25 @@ snapshots: es-define-property: 1.0.1 side-channel: 1.1.1 + querystring-es3@0.2.1: {} + queue-microtask@1.2.3: {} queue@6.0.2: dependencies: inherits: 2.0.4 + quick-format-unescaped@4.0.4: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + randomfill@1.0.4: + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + range-parser@1.2.1: {} range-parser@1.3.0: {} @@ -12791,7 +17134,6 @@ snapshots: ini: 1.3.8 minimist: 1.2.8 strip-json-comments: 2.0.1 - optional: true react-d3-tree@3.6.6(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: @@ -13038,15 +17380,26 @@ snapshots: react@19.2.8: {} + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - optional: true readdirp@5.0.0: {} + real-require@0.2.0: {} + recast@0.23.12: dependencies: ast-types: 0.16.1 @@ -13109,8 +17462,129 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 + retry@0.12.0: {} + + retry@0.13.1: {} + reusify@1.1.0: {} + ripemd160@2.0.3: + dependencies: + hash-base: 3.1.2 + inherits: 2.0.4 + + rivetkit@2.3.10(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(ws@8.21.1): + dependencies: + '@hono/zod-openapi': 1.5.1(hono@4.12.32)(zod@4.4.3) + '@rivet-dev/agent-os-core': 0.1.1 + '@rivetkit/bare-ts': 0.6.2 + '@rivetkit/engine-cli': 2.3.10 + '@rivetkit/engine-envoy-protocol': 2.3.10 + '@rivetkit/on-change': 6.0.1 + '@rivetkit/rivetkit-napi': 2.3.10 + '@rivetkit/rivetkit-wasm': 2.3.10 + '@rivetkit/traces': 2.3.10 + '@rivetkit/virtual-websocket': 2.3.10 + '@rivetkit/workflow-engine': 2.3.10 + cbor-x: 1.6.5 + drizzle-orm: 0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4) + hono: 4.12.32 + invariant: 2.2.4 + p-retry: 6.2.1 + pino: 9.14.0 + uuid: 12.0.1 + vbare: 0.0.4 + zod: 4.4.3 + optionalDependencies: + ws: 8.21.1 + transitivePeerDependencies: + - '@aws-sdk/client-rds-data' + - '@cloudflare/workers-types' + - '@electric-sql/pglite' + - '@libsql/client' + - '@libsql/client-wasm' + - '@neondatabase/serverless' + - '@op-engineering/op-sqlite' + - '@opentelemetry/api' + - '@planetscale/database' + - '@prisma/client' + - '@tidbcloud/serverless' + - '@types/better-sqlite3' + - '@types/pg' + - '@types/sql.js' + - '@upstash/redis' + - '@vercel/postgres' + - '@xata.io/client' + - better-sqlite3 + - bun-types + - expo-sqlite + - gel + - knex + - kysely + - mysql2 + - pg + - postgres + - prisma + - pyodide + - sql.js + - sqlite3 + + rivetkit@2.3.9(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4)(ws@8.21.1): + dependencies: + '@hono/zod-openapi': 1.5.1(hono@4.12.32)(zod@4.4.3) + '@rivet-dev/agent-os-core': 0.1.1 + '@rivetkit/bare-ts': 0.6.2 + '@rivetkit/engine-cli': 2.3.9 + '@rivetkit/engine-envoy-protocol': 2.3.9 + '@rivetkit/on-change': 6.0.1 + '@rivetkit/rivetkit-napi': 2.3.9 + '@rivetkit/rivetkit-wasm': 2.3.9 + '@rivetkit/traces': 2.3.9 + '@rivetkit/virtual-websocket': 2.3.9 + '@rivetkit/workflow-engine': 2.3.9 + cbor-x: 1.6.5 + drizzle-orm: 0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.11.1)(bun-types@1.3.14)(kysely@0.29.4) + hono: 4.12.32 + invariant: 2.2.4 + p-retry: 6.2.1 + pino: 9.14.0 + uuid: 12.0.1 + vbare: 0.0.4 + zod: 4.4.3 + optionalDependencies: + ws: 8.21.1 + transitivePeerDependencies: + - '@aws-sdk/client-rds-data' + - '@cloudflare/workers-types' + - '@electric-sql/pglite' + - '@libsql/client' + - '@libsql/client-wasm' + - '@neondatabase/serverless' + - '@op-engineering/op-sqlite' + - '@opentelemetry/api' + - '@planetscale/database' + - '@prisma/client' + - '@tidbcloud/serverless' + - '@types/better-sqlite3' + - '@types/pg' + - '@types/sql.js' + - '@upstash/redis' + - '@vercel/postgres' + - '@xata.io/client' + - better-sqlite3 + - bun-types + - expo-sqlite + - gel + - knex + - kysely + - mysql2 + - pg + - postgres + - prisma + - pyodide + - sql.js + - sqlite3 + rolldown@1.1.4: dependencies: '@oxc-project/types': 0.138.0 @@ -13179,12 +17653,25 @@ snapshots: safe-buffer@5.2.1: {} + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} sax@1.6.1: {} scheduler@0.27.0: {} + secure-exec@0.2.1: + dependencies: + '@secure-exec/core': 0.2.1 + '@secure-exec/nodejs': 0.2.1 + semver@6.3.1: {} semver@7.8.5: {} @@ -13251,8 +17738,25 @@ snapshots: set-cookie-parser@3.1.2: {} + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + setimmediate@1.0.5: {} + setprototypeof@1.2.0: {} + sha.js@2.4.12: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + shadcn@4.16.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)(typescript@7.0.2): dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) @@ -13370,15 +17874,13 @@ snapshots: signal-exit@4.1.0: {} - simple-concat@1.0.1: - optional: true + simple-concat@1.0.1: {} simple-get@4.0.1: dependencies: decompress-response: 6.0.0 once: 1.4.0 simple-concat: 1.0.1 - optional: true simple-plist@1.3.1: dependencies: @@ -13396,12 +17898,31 @@ snapshots: slugify@1.6.9: {} + smart-buffer@4.2.0: {} + + socks-proxy-agent@8.0.5(supports-color@10.2.2): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@10.2.2) + socks: 2.8.9 + transitivePeerDependencies: + - supports-color + + socks@2.8.9: + dependencies: + ip-address: 10.3.1 + smart-buffer: 4.2.0 + solid-js@1.9.14: dependencies: csstype: 3.2.3 seroval: 1.5.6 seroval-plugins: 1.5.6(seroval@1.5.6) + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + sonner@2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: react: 19.2.8 @@ -13418,6 +17939,8 @@ snapshots: source-map@0.6.1: {} + split2@4.2.0: {} + stackback@0.0.2: {} stackframe@1.3.4: {} @@ -13430,12 +17953,26 @@ snapshots: statuses@2.0.2: {} + std-env@3.10.0: {} + std-env@4.2.0: {} stdin-discarder@0.2.2: {} + stream-browserify@3.0.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-buffers@2.2.0: {} + stream-http@3.2.0: + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + xtend: 4.0.2 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -13448,10 +17985,13 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - optional: true stringify-object@5.0.0: dependencies: @@ -13477,8 +18017,11 @@ snapshots: strip-final-newline@4.0.0: {} - strip-json-comments@2.0.1: - optional: true + strip-json-comments@2.0.1: {} + + strtok3@10.3.5: + dependencies: + '@tokenizer/token': 0.3.0 structured-headers@0.4.1: {} @@ -13525,7 +18068,6 @@ snapshots: mkdirp-classic: 0.5.3 pump: 3.0.4 tar-stream: 2.2.0 - optional: true tar-stream@2.2.0: dependencies: @@ -13534,7 +18076,6 @@ snapshots: fs-constants: 1.0.0 inherits: 2.0.4 readable-stream: 3.6.2 - optional: true terminal-link@2.1.1: dependencies: @@ -13548,8 +18089,24 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + thread-stream@3.2.0: + dependencies: + real-require: 0.2.0 + throat@5.0.0: {} + timers-browserify@2.0.12: + dependencies: + setimmediate: 1.0.5 + timestring@6.0.0: {} tiny-invariant@1.3.3: {} @@ -13569,20 +18126,36 @@ snapshots: tmpl@1.0.5: {} + to-buffer@1.2.2: + dependencies: + isarray: 2.0.5 + safe-buffer: 5.2.1 + typed-array-buffer: 1.0.3 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 toidentifier@1.0.1: {} + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.2 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + toml@4.3.0: {} toqr@0.1.1: {} totalist@3.0.1: {} + tr46@0.0.3: {} + tree-kill@1.2.2: {} + ts-algebra@2.0.0: {} + ts-api-utils@2.5.0(typescript@7.0.2): dependencies: typescript: 7.0.2 @@ -13611,10 +18184,11 @@ snapshots: tslib@2.8.1: {} + tty-browserify@0.0.1: {} + tunnel-agent@0.6.0: dependencies: safe-buffer: 5.2.1 - optional: true tw-animate-css@1.4.0: {} @@ -13636,6 +18210,14 @@ snapshots: media-typer: 1.1.1 mime-types: 3.0.2 + typebox@1.3.7: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + typescript@7.0.2: optionalDependencies: '@typescript/typescript-aix-ppc64': 7.0.2 @@ -13659,6 +18241,12 @@ snapshots: '@typescript/typescript-win32-arm64': 7.0.2 '@typescript/typescript-win32-x64': 7.0.2 + uint8array-extras@1.5.0: {} + + ulidx@2.4.1: + dependencies: + layerr: 3.0.0 + ultracite@7.9.3(eslint@10.8.0(jiti@2.7.0)(supports-color@10.2.2))(oxfmt@0.61.0(vite-plus@0.2.2(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(yaml@2.9.0)))(oxlint@1.76.0(oxlint-tsgolint@0.24.0)(vite-plus@0.2.2(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(yaml@2.9.0)))(supports-color@10.2.2)(typescript@7.0.2): dependencies: '@clack/prompts': 1.7.0 @@ -13720,20 +18308,39 @@ snapshots: dependencies: punycode: 2.3.1 + url-template@2.0.8: {} + + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.15.3 + use-sync-external-store@1.6.0(react@19.2.8): dependencies: react: 19.2.8 util-deprecate@1.0.2: {} + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.2 + is-typed-array: 1.1.15 + which-typed-array: 1.1.22 + utils-merge@1.0.1: {} + uuid@12.0.1: {} + uuid@14.0.1: {} uuid@7.0.3: {} uuid@8.3.2: {} + uuid@9.0.1: {} + valibot@1.4.2(typescript@7.0.2): optionalDependencies: typescript: 7.0.2 @@ -13744,6 +18351,8 @@ snapshots: vary@1.1.2: {} + vbare@0.0.4: {} + vite-plus@0.2.2(@opentelemetry/api@1.9.0)(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(typescript@7.0.2)(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(yaml@2.9.0): dependencies: '@oxc-project/types': 0.138.0 @@ -13945,6 +18554,8 @@ snapshots: vlq@1.0.1: {} + vm-browserify@1.1.2: {} + walker@1.0.8: dependencies: makeerror: 1.0.12 @@ -13957,10 +18568,31 @@ snapshots: dependencies: defaults: 1.0.4 + web-streams-polyfill@3.3.3: {} + + web-streams-polyfill@4.3.0: {} + + webidl-conversions@3.0.1: {} + whatwg-fetch@3.6.20: {} whatwg-url-minimum@0.1.2: {} + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-typed-array@1.1.22: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -14035,14 +18667,28 @@ snapshots: xmlbuilder@15.1.1: {} + xtend@4.0.2: {} + y18n@5.0.8: {} yallist@3.1.1: {} yaml@2.9.0: {} + yargs-parser@20.2.9: {} + yargs-parser@21.1.1: {} + yargs@16.2.2: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + yargs@17.7.2: dependencies: cliui: 8.0.1 @@ -14063,6 +18709,11 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + yocto-queue@0.1.0: {} yocto-spinner@1.2.2: @@ -14090,6 +18741,10 @@ snapshots: dependencies: zod: 3.25.76 + zod-to-json-schema@3.25.2(zod@4.4.3): + dependencies: + zod: 4.4.3 + zod@3.25.76: {} zod@4.4.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a15105c..3635c8d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - apps/web + - packages/agents - packages/auth - packages/backend - packages/config @@ -41,6 +42,20 @@ catalog: typescript: "7.0.2" "@types/bun": "1.3.14" heroui-native: "1.0.6" + "@tailwindcss/vite": "4.3.3" + "@flue/runtime": "2.0.1" + "@flue/cli": "2.0.1" + "@flue/vite": "2.0.1" + "@flue/sdk": "2.0.1" + hono: "4.12.34" + "@hono/node-server": "2.0.3" + "@rivet-dev/agentos": "0.2.15" + "@rivet-dev/agentos-core": "0.2.15" + "@rivet-dev/agentos-flue": "0.2.15" + rivetkit: "2.3.10" + "@earendil-works/pi-ai": "0.83.0" + "@agentos-software/common": "0.2.15" + "@agentos-software/git": "0.3.3" vite: "8.1.5" vitest: "4.1.10" convex-test: "0.0.54" @@ -48,7 +63,9 @@ catalog: "@types/react": "19.2.17" "@types/node": "22.20.1" "@tailwindcss/postcss": "4.3.3" - "@tailwindcss/vite": "4.3.3" + +minimumReleaseAgeExclude: + - hono@4.12.34 overrides: react: "19.2.8" diff --git a/scripts/release-agents.sh b/scripts/release-agents.sh new file mode 100755 index 0000000..622d329 --- /dev/null +++ b/scripts/release-agents.sh @@ -0,0 +1,422 @@ +#!/bin/sh +# scripts/release-agents.sh +# +# Build @code/agents locally, package a release bundle (excluding secrets and +# development-only workspace clutter), upload it to a staging directory on the +# VDS, then atomically promote it to /releases/ and repoint +# /current at it. +# +# Why deps are installed on the target, not shipped from the build host: +# The runtime tree contains platform-specific native binaries +# (@rivetkit/rivetkit-napi, @rivet-dev/agentos-sidecar, +# @rivet-dev/agentos-runtime-sidecar, @rivetkit/engine-cli), selected by +# os/cpu. The build host (macOS arm64) resolves the *-darwin-arm64 variants; +# the Linux VDS needs the *-linux-* variants. The pnpm lockfile records every +# platform variant, so a frozen-lockfile `pnpm install --prod` on the target +# fetches the correct architecture. Shipping the local node_modules would +# deliver wrong-architecture binaries. The built JS bundles under dist/ are +# platform-independent. +# +# Documentation lives in the usage text below; do not edit other docs. + +set -eu + +# --------------------------------------------------------------------------- +# Usage +# --------------------------------------------------------------------------- + +usage() { + cat <<'EOF' +Usage: scripts/release-agents.sh [options] + +Build @code/agents, package a release bundle, upload it to the VDS, and +atomically promote it so /current points at the new release. + +Positional arguments (required): + host SSH destination for the VDS, passed verbatim to ssh/scp. + May be "user@host", an alias from ~/.ssh/config, or a bare host. + release-id Opaque release identifier. Names the release directory + (/releases/). Must match [A-Za-z0-9][A-Za-z0-9._-]*. + +Options: + --target DIR Base directory on the VDS (default: /srv/zopu). + Must be absolute and non-empty. The release is promoted + to /releases/ and /current + is repointed at it. + --skip-build Use the existing packages/agents/dist instead of rebuilding. + --dry-run Validate arguments and print every command that would run, + but perform no build, packaging, upload, or promotion. + -h, --help Show this help and exit. + +Environment: + Builds run via pnpm (the workspace's package manager). The VDS promote step + uses corepack (shipped with Node) to activate pnpm if it is not already + installed; otherwise an existing global pnpm is used. + +Examples: + scripts/release-agents.sh zopu-vds 2026-08-04-a1b2c3 + scripts/release-agents.sh deploy@10.0.0.5 v1.2.0 --target /srv/zopu + scripts/release-agents.sh zopu-vds 2026-08-04-a1b2c3 --dry-run + +Exit status: + 0 release promoted successfully (or dry-run completed) + 1 invalid arguments, missing prerequisites, or a step failed +EOF +} + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + +die() { + echo "release-agents: ERROR: $*" >&2 + exit 1 +} + +# Repository root detection. This script must run from the repo root so the +# workspace manifests and package sources resolve relative to the cwd. +require_repo_root() { + [ -f "./pnpm-workspace.yaml" ] || die "must run from the repository root (pnpm-workspace.yaml not found in $(pwd))." + [ -f "./packages/agents/package.json" ] || die "packages/agents/package.json not found; run from the repository root." + [ -f "./pnpm-lock.yaml" ] || die "pnpm-lock.yaml not found; run from the repository root after install." +} + +# Validate the release id: a single path segment with no traversal/escape chars. +# It becomes a directory name under /releases/, so reject anything that +# could escape or alter the path. +validate_release_id() { + release_id=$1 + [ -n "$release_id" ] || die "release-id is required." + # Positive whitelist: start with alnum, then alnum/dot/dash/underscore. + if ! expr "$release_id" : '[A-Za-z0-9][A-Za-z0-9._-]*$' >/dev/null 2>&1; then + die "release-id must match [A-Za-z0-9][A-Za-z0-9._-]* (got: $release_id)." + fi + # Defense in depth: reject literal traversal even though the whitelist above + # already excludes '/' and '..'. + case "$release_id" in + *..* | */* | *\** | *' '* | *'~'*) + die "release-id must not contain '..', '/', spaces, '*', or '~' (got: $release_id)." + ;; + esac +} + +# Validate the target base directory: absolute and non-empty. +validate_target() { + target=$1 + [ -n "$target" ] || die "--target must be a non-empty absolute path." + case "$target" in + /*) ;; + *) die "--target must be an absolute path (got: $target)." ;; + esac + # Reject traversal segments. + case "$target" in + *'/../'* | *'/..' | *'~'* | *'*'*) + die "--target must not contain path traversal or glob characters (got: $target)." + ;; + esac +} + +# Emit a trimmed pnpm-workspace.yaml containing the runtime packages plus every +# manifest named by the root workspace's dependency graph. Production install +# does not materialize root devDependencies, but pnpm still resolves their +# workspace locators against this manifest set. +emit_trimmed_workspace() { + awk ' + # A top-level key begins at column 0. + /^[A-Za-z_-][A-Za-z0-9_-]*:/ { + key = $0 + sub(/:.*/, "", key) + if (key == "packages") { + print "packages:" + print " - packages/agents" + print " - packages/backend" + print " - packages/config" + print " - packages/env" + print " - packages/primitives" + print "" + skip = 1 + next + } + skip = 0 + } + { if (!skip) print } + ' ./pnpm-workspace.yaml +} + +# --------------------------------------------------------------------------- +# Argument parsing +# --------------------------------------------------------------------------- + +host="" +release_id="" +target="/srv/zopu" +skip_build=0 +dry_run=0 + +while [ $# -gt 0 ]; do + case "$1" in + -h | --help) + usage + exit 0 + ;; + --target) + [ $# -ge 2 ] || die "--target requires a value." + target=$2 + shift 2 + ;; + --target=*) + target=${1#--target=} + shift + ;; + --skip-build) + skip_build=1 + shift + ;; + --dry-run) + dry_run=1 + shift + ;; + --) + shift + break + ;; + -*) + die "unknown option: $1 (see --help)" + ;; + *) + if [ -z "$host" ]; then + host=$1 + elif [ -z "$release_id" ]; then + release_id=$1 + else + die "unexpected extra argument: $1 (usage: )" + fi + shift + ;; + esac +done + +# Extra positionals after "--" are not supported. +[ $# -eq 0 ] || die "unexpected extra arguments: $* (usage: )" + +# --------------------------------------------------------------------------- +# Validate ALL arguments before any side-effect command. +# --------------------------------------------------------------------------- + +[ -n "$host" ] || die "host is required (usage: )." +validate_release_id "$release_id" +validate_target "$target" + +require_repo_root + +# pnpm version: derive from the root packageManager field (single source of +# truth). Fall back to a pinned default if the field is absent. +pnpm_ver=$(sed -n 's/.*"packageManager"[[:space:]]*:[[:space:]]*"pnpm@\([^"]*\)".*/\1/p' ./package.json) +[ -n "$pnpm_ver" ] || pnpm_ver="11.17.0" + +command -v pnpm >/dev/null 2>&1 || die "pnpm is required on the build host (found via corepack or PATH)." +command -v tar >/dev/null 2>&1 || die "tar is required on the build host." +command -v ssh >/dev/null 2>&1 || die "ssh is required on the build host." +command -v scp >/dev/null 2>&1 || die "scp is required on the build host." + +# Derived remote paths. /.staging is kept on the same filesystem as +# /releases so the final promotion is an atomic rename. +staging_root="$target/.staging" +releases_dir="$target/releases" +remote_tarball="$staging_root/$release_id.tar.gz" +remote_stage="$staging_root/$release_id" +remote_release="$releases_dir/$release_id" +remote_current="$target/current" + +echo "release-agents: host=$host release-id=$release_id target=$target pnpm=$pnpm_ver" +[ "$skip_build" -eq 1 ] && echo "release-agents: --skip-build: using existing dist" +[ "$dry_run" -eq 1 ] && echo "release-agents: --dry-run: no commands will be executed" + +# --------------------------------------------------------------------------- +# Build +# --------------------------------------------------------------------------- + +if [ "$dry_run" -eq 0 ]; then + if [ "$skip_build" -eq 0 ]; then + echo "release-agents: installing workspace dependencies (frozen lockfile)" + pnpm install --frozen-lockfile + echo "release-agents: building @code/agents" + pnpm --filter @code/agents build + fi + [ -f "./packages/agents/dist/server.mjs" ] || die "build output missing: packages/agents/dist/server.mjs (run without --skip-build)." +else + if [ "$skip_build" -eq 0 ]; then + echo "[dry-run] pnpm install --frozen-lockfile" + echo "[dry-run] pnpm --filter @code/agents build" + fi + echo "[dry-run] verify: packages/agents/dist/server.mjs" +fi + +# --------------------------------------------------------------------------- +# Package the release bundle +# --------------------------------------------------------------------------- + +# Curated allowlist: root manifests required for pnpm workspace resolution, +# the built agents output, and runtime source required by Flue's bundled +# server. @code/env resolves from TypeScript source at runtime. The backend and +# primitives are manifests only: root devDependencies name them but production +# installation does not materialize them. No unrelated package sources, +# node_modules, .git, repos/, apps/, docs/, or .env* files are shipped. +bundle_files="package.json pnpm-lock.yaml .npmrc \ + packages/agents/package.json \ + packages/backend/package.json \ + packages/config/package.json \ + packages/env/package.json \ + packages/primitives/package.json" + +bundle_dirs="packages/agents/dist packages/env/src deploy/vds" + +if [ "$dry_run" -eq 0 ]; then + stage_dir=$(mktemp -d 2>/dev/null || mktemp -d -t release-agents) + trap 'rm -rf "$stage_dir"' EXIT INT TERM + + mkdir -p "$stage_dir/packages/agents" "$stage_dir/packages/backend" "$stage_dir/packages/config" "$stage_dir/packages/env" "$stage_dir/packages/primitives" + + for f in $bundle_files; do + [ -f "./$f" ] || die "required file not found: $f" + cp "./$f" "$stage_dir/$f" + done + for d in $bundle_dirs; do + [ -d "./$d" ] || die "required directory not found: $d" + mkdir -p "$(dirname "$stage_dir/$d")" + cp -R "./$d" "$stage_dir/$d" + done + + # Trimmed workspace manifest scoped to the release subset. + emit_trimmed_workspace >"$stage_dir/pnpm-workspace.yaml" + + # Refuse to ship any environment file. Belt-and-suspenders: the allowlist + # above cannot include one, but assert it on the packed tarball. + tarball="$stage_dir/$release_id.tar.gz" + # tar into a path inside the tree is fine; exclude the output itself. + tar -czf "$tarball" -C "$stage_dir" \ + --exclude="$release_id.tar.gz" \ + package.json pnpm-lock.yaml .npmrc pnpm-workspace.yaml packages deploy + + if tar -tzf "$tarball" | grep -Eq '(^|/)\.env($|\.)'; then + die "refusing to ship release: environment file detected in bundle." + fi + + echo "release-agents: packaged $(tar -tzf "$tarball" | wc -l | tr -d ' ') files" +else + echo "[dry-run] would package allowlist: $bundle_files $bundle_dirs + trimmed pnpm-workspace.yaml" + echo "[dry-run] would assert: no .env in bundle" +fi + +# --------------------------------------------------------------------------- +# Upload to staging +# --------------------------------------------------------------------------- + +if [ "$dry_run" -eq 0 ]; then + echo "release-agents: uploading to $host:$remote_tarball" + ssh "$host" "mkdir -p '$staging_root'" + scp -q "$tarball" "$host:$remote_tarball" +else + echo "[dry-run] ssh $host mkdir -p '$staging_root'" + echo "[dry-run] scp -q $host:$remote_tarball" +fi + +# --------------------------------------------------------------------------- +# Promote on the VDS (remote) +# --------------------------------------------------------------------------- + +# The remote script runs with set -eu. It receives release-id, target, and pnpm +# version as positional arguments so no local values are interpolated into the +# heredoc (the 'REMOTE' delimiter is quoted). Staging, releases, and current all +# live under on the same filesystem, so the rename-based promotion is +# atomic. The running service is never disturbed: it keeps serving via the old +# /current symlink until the final atomic rename repoints it. +if [ "$dry_run" -eq 0 ]; then + echo "release-agents: promoting $release_id on $host" + ssh "$host" "sh -s -- '$release_id' '$target' '$pnpm_ver'" <<'REMOTE' +set -eu + +release_id=$1 +target=$2 +pnpm_ver=$3 + +staging_root="$target/.staging" +releases_dir="$target/releases" +stage="$staging_root/$release_id" +release="$releases_dir/$release_id" +current="$target/current" +tarball="$staging_root/$release_id.tar.gz" + +echo "[remote] preparing $release under $target" + +mkdir -p "$staging_root" "$releases_dir" + +# Release ids are immutable. Refuse replacement rather than deleting a release +# that may still back `current` or be needed for rollback. +if [ -e "$release" ]; then + echo "[remote] ERROR: release already exists: $release" >&2 + exit 1 +fi + +# Fresh staging directory. +rm -rf "$stage" +mkdir -p "$stage" +tar -xzf "$tarball" -C "$stage" +rm -f "$tarball" + +# Ensure pnpm is available. corepack ships with Node; activate pnpm only if a +# global pnpm is not already on PATH. +if ! command -v pnpm >/dev/null 2>&1; then + if ! command -v corepack >/dev/null 2>&1; then + echo "[remote] ERROR: neither pnpm nor corepack is available on the VDS." >&2 + exit 1 + fi + corepack enable + corepack prepare "pnpm@$pnpm_ver" --activate +fi + +# Materialize production dependencies for THIS platform. The frozen lockfile is +# cross-platform (records every os/cpu variant), so the correct native binaries +# for the VDS are fetched here. --prod excludes devDependencies. +cd "$stage" +pnpm install --prod --frozen-lockfile + +# Sanity: the runtime entry and the deployment artifacts must exist before +# promotion. The latter are installed with the release so the unit's Documents= +# target remains valid after an atomic switch. +if [ ! -f "$stage/packages/agents/dist/server.mjs" ]; then + echo "[remote] ERROR: packages/agents/dist/server.mjs missing after install." >&2 + exit 1 +fi +if [ ! -f "$stage/deploy/vds/zopu-agents.service" ]; then + echo "[remote] ERROR: deploy/vds/zopu-agents.service missing after install." >&2 + exit 1 +fi + +# Atomic promotion into releases/ (rename on the same filesystem). +mv "$stage" "$release" + +# Atomic symlink swap for /current. Create a temporary symlink then +# rename it over the existing current (mv -T treats the destination as a file, +# not a directory, giving an atomic rename). GNU coreutils (standard on Linux) +# provides -T. +tmp_link="$current.tmp.$$" +ln -s "$release" "$tmp_link" +mv -T "$tmp_link" "$current" + +echo "[remote] promoted: $current -> $release" +REMOTE +else + cat <