diff --git a/apps/web/src/components/slice-one/slice-one-page.tsx b/apps/web/src/components/slice-one/slice-one-page.tsx index f7f007f..9729f88 100644 --- a/apps/web/src/components/slice-one/slice-one-page.tsx +++ b/apps/web/src/components/slice-one/slice-one-page.tsx @@ -17,6 +17,7 @@ import { RotateCcw, Send, Sparkles, + Settings, X, } from "lucide-react"; import { useMemo, useRef, useState } from "react"; @@ -258,19 +259,61 @@ const WorkCard = ({ onSourceSelect, work, slice }: WorkCardProps) => { Build

{latestRun ? ( -

- Run {latestRun.status}:{" "} - {latestRun.terminalSummary ?? - latestRun.terminalClassification ?? - "activity is still arriving"} -

+
+

+ {latestRun.executionKind === "real" + ? "AgentOS" + : "Simulation"}{" "} + run {latestRun.status}:{" "} + {latestRun.terminalSummary ?? + latestRun.terminalClassification ?? + "activity is still arriving"} +

+ {latestRun.attemptEvents?.slice(-5).map((item) => ( +

+ {item.message} +

+ ))} + {latestRun.baseRevision ? ( +

+ {latestRun.baseRevision.slice(0, 8)} →{" "} + {latestRun.candidateRevision?.slice(0, 8) ?? "working"} +

+ ) : null} + {latestRun.artifacts?.map((artifact) => ( + + {artifact.title} + + ))} +
) : ( -

No simulation Run yet.

+

No implementation Run yet.

)}
{work.status === "ready" ? ( + ) : null} + {work.status === "ready" ? ( + @@ -388,6 +435,10 @@ export const SliceOnePage = () => { const attachments = useChatImages(); const imageInput = useRef(null); const [drawerOpen, setDrawerOpen] = useState(false); + const [settingsOpen, setSettingsOpen] = useState(false); + const [giteaUrl, setGiteaUrl] = useState("https://git.openputer.com"); + const [giteaUsername, setGiteaUsername] = useState(""); + const [giteaToken, setGiteaToken] = useState(""); const [highlightedMessageId, setHighlightedMessageId] = useState(); const highlightTimer = useRef | null>(null); const works = slice.works ?? EMPTY_WORKS; @@ -450,7 +501,7 @@ export const SliceOnePage = () => { style={viewportStyle} >
-
+
setGiteaUrl(event.target.value)} + value={giteaUrl} + /> + setGiteaUsername(event.target.value)} + placeholder="Username (optional)" + value={giteaUsername} + /> + setGiteaToken(event.target.value)} + placeholder="Personal access token" + type="password" + value={giteaToken} + /> + +
+
+ ) : null} diff --git a/apps/web/src/hooks/slice-one/use-slice-one.ts b/apps/web/src/hooks/slice-one/use-slice-one.ts index ab4e0be..92072cd 100644 --- a/apps/web/src/hooks/slice-one/use-slice-one.ts +++ b/apps/web/src/hooks/slice-one/use-slice-one.ts @@ -1,3 +1,4 @@ +import { authClient } from "@code/auth/web"; import { api } from "@code/backend/convex/_generated/api"; import type { Id } from "@code/backend/convex/_generated/dataModel"; import { useAction, useMutation, useQuery } from "convex/react"; @@ -27,6 +28,23 @@ interface WorkRecord { readonly designs: readonly unknown[]; readonly slices: readonly unknown[]; readonly runs: readonly { + readonly artifacts?: readonly { + _id: string; + kind: string; + metadataJson: string; + sourceRevision?: string; + title: string; + uri?: string; + }[]; + readonly attemptEvents?: readonly { + _id: string; + kind: string; + message: string; + occurredAt: number; + }[]; + readonly baseRevision?: string; + readonly candidateRevision?: string; + readonly executionKind?: string; _id: Id<"workRuns">; status: string; terminalClassification?: string; @@ -96,6 +114,57 @@ const retrySimulationRef = makeFunctionReference< { runId: Id<"workRuns"> }, unknown >("workExecution:retrySimulatedExecution"); +const startExecutionRef = makeFunctionReference< + "mutation", + { workId: Id<"works">; sliceId?: string }, + unknown +>("workExecutionWorkflow:startExecution"); +const cancelExecutionRef = makeFunctionReference< + "mutation", + { runId: Id<"workRuns"> }, + unknown +>("workExecutionWorkflow:cancelExecution"); +const listGitConnectionsRef = makeFunctionReference< + "query", + Record, + readonly { + id: string; + provider: "github" | "gitea"; + serverUrl: string; + username?: string; + }[] +>("gitConnectionData:list"); +const projectGitConnectionRef = makeFunctionReference< + "query", + { projectId: Id<"projects"> }, + { + id: string; + provider: "github" | "gitea"; + serverUrl: string; + username?: string; + } | null +>("gitConnectionData:getForProject"); +const connectGiteaRef = makeFunctionReference< + "action", + { serverUrl: string; token: string; username?: string }, + { connectionId: Id<"gitConnections"> } +>("gitConnections:connectGitea"); +const connectGithubRef = makeFunctionReference< + "action", + Record, + { connectionId: Id<"gitConnections"> } +>("gitConnections:connectGithub"); +const attachGitConnectionRef = makeFunctionReference< + "mutation", + { connectionId: Id<"gitConnections">; projectId: Id<"projects"> }, + unknown +>("gitConnectionData:attachToProject"); + +const authorizeGithub = () => + authClient.signIn.social({ + callbackURL: window.location.href, + provider: "github", + }); export const useSliceOne = () => { const organization = usePersonalOrganization(); @@ -120,6 +189,14 @@ export const useSliceOne = () => { workListRef, activeProjectId ? { projectId: activeProjectId } : "skip" ); + const gitConnections = useQuery( + listGitConnectionsRef, + organization.organizationId ? {} : "skip" + ); + const projectGitConnection = useQuery( + projectGitConnectionRef, + activeProjectId ? { projectId: activeProjectId } : "skip" + ); const requestDefinitionMutation = useMutation(requestDefinitionRef); const saveDefinitionMutation = useMutation(saveDefinitionRef); const approveDefinitionMutation = useMutation(approveDefinitionRef); @@ -128,6 +205,11 @@ export const useSliceOne = () => { const startSimulationMutation = useMutation(startSimulationRef); const cancelSimulationMutation = useMutation(cancelSimulationRef); const retrySimulationMutation = useMutation(retrySimulationRef); + const startExecutionMutation = useMutation(startExecutionRef); + const cancelExecutionMutation = useMutation(cancelExecutionRef); + const attachGitConnectionMutation = useMutation(attachGitConnectionRef); + const connectGiteaAction = useAction(connectGiteaRef); + const connectGithubAction = useAction(connectGithubRef); const selectedProject = useMemo( () => projects?.find( @@ -185,15 +267,46 @@ export const useSliceOne = () => { cancelSimulationMutation({ runId }); const retrySimulation = (runId: Id<"workRuns">) => retrySimulationMutation({ runId }); + const startExecution = (workId: Id<"works">, sliceId?: string) => + startExecutionMutation({ sliceId, workId }); + const cancelExecution = (runId: Id<"workRuns">) => + cancelExecutionMutation({ runId }); + const attachConnection = async (connectionId: Id<"gitConnections">) => { + if (!activeProjectId) { + throw new Error("Select a project first"); + } + await attachGitConnectionMutation({ + connectionId, + projectId: activeProjectId, + }); + }; + const connectGitea = async (input: { + serverUrl: string; + token: string; + username?: string; + }) => { + const result = await connectGiteaAction(input); + await attachConnection(result.connectionId); + }; + const connectLinkedGithub = async () => { + const result = await connectGithubAction({}); + await attachConnection(result.connectionId); + }; return { agent, approveDefinition, approveDesign, + authorizeGithub, + cancelExecution, cancelSimulation, + connectGitea, + connectLinkedGithub, connectRepository, error, + gitConnections, pending, + projectGitConnection, projects, repository, requestDefinition, @@ -203,6 +316,7 @@ export const useSliceOne = () => { selectProject, selectedProject, setRepository, + startExecution, startSimulation, works, } as const; diff --git a/bun.lock b/bun.lock index 122d3cf..0dfba1b 100644 --- a/bun.lock +++ b/bun.lock @@ -64,11 +64,16 @@ "name": "@code/agents", "version": "0.0.0", "dependencies": { + "@agentos-software/codex-cli": "0.3.4", + "@agentos-software/git": "0.3.3", "@code/backend": "workspace:*", "@code/env": "workspace:*", + "@code/primitives": "workspace:*", "@flue/runtime": "latest", + "@rivet-dev/agentos": "0.2.10", "convex": "catalog:", "hono": "catalog:", + "rivetkit": "2.3.9", "valibot": "catalog:", }, "devDependencies": { @@ -114,6 +119,7 @@ "@code/env": "workspace:*", "@code/primitives": "workspace:*", "@convex-dev/better-auth": "catalog:", + "@convex-dev/workflow": "0.4.4", "better-auth": "catalog:", "convex": "catalog:", "effect": "catalog:", @@ -242,7 +248,7 @@ "@agentos-software/codex-cli": ["@agentos-software/codex-cli@0.3.4", "", {}, "sha512-SAw3EOTa90dJLgEVVoE7JJIxHwticzdD9cEM9v00gpxhxC9vdLkeBva6rgWIUB9+qD1JEYBvUCyNkIpD2kT5YQ=="], - "@agentos-software/common": ["@agentos-software/common@0.2.14", "", { "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" } }, "sha512-ve/ks2MZtXFN9JK+kcFnSMGI1tqoUy36sTKWYGqApcgg/3JJwqnMs4JIKL5OXjgCtDuTvTjRySbQvEKxGkeeSQ=="], + "@agentos-software/common": ["@agentos-software/common@0.2.10", "", { "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.4" } }, "sha512-hkqm0U2tlPraKdAIB7oi4YT7vNN6JT6fk2eRhF9r2tqeOdn2JN/Zql5gQh1+wKYIgdWu1JBj5TJlf99Px010Hg=="], "@agentos-software/coreutils": ["@agentos-software/coreutils@0.3.4", "", {}, "sha512-tGd0gQjUjHnm+5KgOBwidwUtlkKnl9biQuD7X2sZl15VOhYqUJpnyLF33h/nF3r9WtOTclSiLj/dc2xCxmAXnw=="], @@ -258,7 +264,7 @@ "@agentos-software/gzip": ["@agentos-software/gzip@0.3.4", "", {}, "sha512-l7Y/Vwiwsqgna68yYwdNCnUBPGBg5zdmtjEFeG3hnDDFLe/02h17q0gUIqJmDBIAy1q9GoizqcFi7zXO2xygKg=="], - "@agentos-software/manifest": ["@agentos-software/manifest@0.2.14", "", {}, "sha512-c1lGWN7/d1lku6Kl+wj6w1YoLX6wI93IyiUoE6M/Hgl1PP1YIPUqGFM5P5sZ9gG9M0qQ86T/587gECj1elZQBg=="], + "@agentos-software/manifest": ["@agentos-software/manifest@0.2.10", "", {}, "sha512-eKmqcnmrzowntVV8F65JD7ZzJHD8u6zM7YKz3o+r3qq8Z5JF/0iGpxCVnTt66/Abg/5vZqjhEIRHkik+2snrWw=="], "@agentos-software/opencode": ["@agentos-software/opencode@0.2.7", "", { "bin": { "agentos-opencode-acp": "dist/adapter.js" } }, "sha512-lZspCiMgM0+kPAA08CEvyNy8lfBx463wObKpAwbYyaVvc0KfGvbAPS6VmnuZQWmaBmJJuRMtSo14nmb8XCD16g=="], @@ -266,7 +272,7 @@ "@agentos-software/sed": ["@agentos-software/sed@0.3.4", "", {}, "sha512-J10nZnZmme2SvXK5WMK2unQlOVncMQVUCS20GZB579a2gNoayLJYHGvfJ9a4+42wOHgDKL1u74byWlydCkEyOQ=="], - "@agentos-software/tar": ["@agentos-software/tar@0.3.5", "", {}, "sha512-hSf6PY4q1luIomFSDgVHxVDDIPdAVZxdgwrQFEYH4aIE6TXX9qatVmzR36uYLWpnFGAZTR6srREGoTnmOGV4Lg=="], + "@agentos-software/tar": ["@agentos-software/tar@0.3.4", "", {}, "sha512-/SSqfgS5xOufvulsz5kVDTCFxpDy+5s7Og1iJe9krjU7Jvtgnp9TpPaJnSr721h6uY6tsWHcs3u8E457EwSkNw=="], "@ai-sdk/gateway": ["@ai-sdk/gateway@4.0.28", "", { "dependencies": { "@ai-sdk/provider": "4.0.3", "@ai-sdk/provider-utils": "5.0.12", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ee9TsNO3mkgHDWmTmJ8Fvltr6PFh52zhrV2+FaKJY3F3iu7kWZi5tCRJCR1HVhhlpj6lHniUb28nLQdPHkA/1Q=="], @@ -566,6 +572,10 @@ "@convex-dev/better-auth": ["@convex-dev/better-auth@0.12.5", "", { "dependencies": { "@better-fetch/fetch": "^1.1.18", "common-tags": "^1.8.2", "convex-helpers": "^0.1.95", "jose": "^6.1.0", "remeda": "^2.32.0", "semver": "^7.7.3", "type-fest": "^5.0.0", "zod": "^4.0.0" }, "peerDependencies": { "better-auth": ">=1.6.11 <1.7.0", "convex": "^1.25.0", "react": "^18.3.1 || ^19.0.0" } }, "sha512-YFUbGk04OlINno9FpOTNZN67AP+kSQsblfep5zs1f/WTgMWjD5FymU6rSSh3mu52gukmDNnBJTjC/lj4QRpjlQ=="], + "@convex-dev/workflow": ["@convex-dev/workflow@0.4.4", "", { "dependencies": { "async-channel": "^0.2.0" }, "peerDependencies": { "@convex-dev/workpool": "^0.4.4", "convex": "^1.36.1", "convex-helpers": "^0.1.99" } }, "sha512-ZQfVspAAxG4zZJEep2qaRtupw8OewwMezq6KNKaXKjo/gA+YffS9bXz13x+L/TSt9/Lb6gioae6Y9PDrqh7xQg=="], + + "@convex-dev/workpool": ["@convex-dev/workpool@0.4.8", "", { "peerDependencies": { "convex": "^1.36.1", "convex-helpers": "^0.1.94" } }, "sha512-ExUV3dVxUK/m2gQGB0PGuTNX/8pNtJM1T2Z+iprEhu7/4UBKM5flmu5odKBcffDnTzlGTPUQ2X+dwzy8l9T19g=="], + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], "@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.75.1", "", { "dependencies": { "@dotenvx/primitives": "^0.8.0", "commander": "^11.1.0", "conf": "^10.2.0", "dotenv": "^17.2.1", "enquirer": "^2.4.1", "env-paths": "^2.2.1", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "open": "^8.4.2", "picomatch": "^4.0.4", "systeminformation": "^5.22.11", "undici": "^7.11.0", "which": "^4.0.0", "yocto-spinner": "^1.1.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-/BITOC9dmS/edY2zQwZNicQ059O6RKabtQfyEafV0nGtfYRNHYy1DIPiYVcov40+tob9hfmBnbR963dS+EQ1DQ=="], @@ -1106,31 +1116,31 @@ "@rivet-dev/agent-os-python": ["@rivet-dev/agent-os-python@0.1.0", "", { "dependencies": { "@secure-exec/core": "^0.2.1", "pyodide": "^0.28.3" } }, "sha512-1tH1beMf1ceSpicQKwN/a6h+NmJrmfuT4GStiRDZmvN/UWfZhkxuy7HR5VPTQpE/feUZJ01FdtBS3Em/Qoxb2Q=="], - "@rivet-dev/agentos": ["@rivet-dev/agentos@0.2.14", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/common": "0.2.14", "@rivet-dev/agentos-core": "0.2.14", "@rivetkit/react": "2.3.9", "rivetkit": "2.3.9", "zod": "^4.1.11" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" }, "optionalPeers": ["react", "react-dom"] }, "sha512-dr7GU8AA02wB906gdQ6tyfCTyOa08KtT8djpUdtprbx7GLkaUQpq0j60BVeS/OkTUzEwYexWEKmKyGL1U/EgiQ=="], + "@rivet-dev/agentos": ["@rivet-dev/agentos@0.2.10", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/common": "0.2.10", "@rivet-dev/agentos-core": "0.2.10", "@rivetkit/react": "2.3.7", "rivetkit": "2.3.7", "zod": "^4.1.11" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" }, "optionalPeers": ["react", "react-dom"] }, "sha512-0R/1p1iesYJtOSarHmfO5pV6BurCQx0z7V+ssIAIXtNaNs7pgMFRrooWsr9UnAJj/xWJ+lM9xIUTHe+o8dE3dw=="], - "@rivet-dev/agentos-core": ["@rivet-dev/agentos-core@0.2.14", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/claude-code": "0.2.7", "@agentos-software/codex-cli": "0.3.4", "@agentos-software/common": "0.2.14", "@agentos-software/manifest": "0.2.14", "@agentos-software/opencode": "0.2.7", "@agentos-software/pi": "0.2.7", "@aws-sdk/client-s3": "^3.1019.0", "@rivet-dev/agentos-runtime-core": "0.2.14", "@rivet-dev/agentos-sidecar": "0.2.14", "@rivetkit/bare-ts": "^0.6.2", "@xterm/headless": "^6.0.0", "better-sqlite3": "^12.8.0", "croner": "^10.0.1", "googleapis": "^144.0.0", "isolated-vm": "^6.0.0", "long-timeout": "^0.1.1", "minimatch": "^10.2.4", "zod": "^4.1.11", "zod-to-json-schema": "^3.25.2" } }, "sha512-YAbK0NpauQKlcuSKl0eXB95ZdNopMGmXw1dBaoSlODKVYoKTjOEKwUtSEvx/zZB0Cse2kSQ/IrJpLe183QeQPw=="], + "@rivet-dev/agentos-core": ["@rivet-dev/agentos-core@0.2.10", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/claude-code": "0.2.7", "@agentos-software/codex-cli": "0.3.4", "@agentos-software/common": "0.2.10", "@agentos-software/manifest": "0.2.10", "@agentos-software/opencode": "0.2.7", "@agentos-software/pi": "0.2.7", "@aws-sdk/client-s3": "^3.1019.0", "@rivet-dev/agentos-runtime-core": "0.2.10", "@rivet-dev/agentos-sidecar": "0.2.10", "@rivetkit/bare-ts": "^0.6.2", "@xterm/headless": "^6.0.0", "better-sqlite3": "^12.8.0", "croner": "^10.0.1", "googleapis": "^144.0.0", "isolated-vm": "^6.0.0", "long-timeout": "^0.1.1", "minimatch": "^10.2.4", "zod": "^4.1.11", "zod-to-json-schema": "^3.25.2" } }, "sha512-0UMQgBFOmMtiZ0UhQ3cJei44tRmY9VzTpkJh4a+g0HWjAz5thUH2OCYtmF+tGNU8qzHhyN9hBFwT744YMRV/Dg=="], - "@rivet-dev/agentos-runtime-core": ["@rivet-dev/agentos-runtime-core@0.2.14", "", { "dependencies": { "@rivet-dev/agentos-runtime-sidecar": "0.2.14", "@rivetkit/bare-ts": "^0.6.2", "zod": "^4.1.11" } }, "sha512-mZYas5wUZXjwLLLHq6uMOaajtyc/3iLQ6vGzOH4E3OHBwCfK054YwGU8iunRqWtk+Wd7MPetzstxzdu+72nBug=="], + "@rivet-dev/agentos-runtime-core": ["@rivet-dev/agentos-runtime-core@0.2.10", "", { "dependencies": { "@rivet-dev/agentos-runtime-sidecar": "0.2.10", "@rivetkit/bare-ts": "^0.6.2", "zod": "^4.1.11" } }, "sha512-qMmWhDZ/IWL0QOKnASl1STHwRQaDknX34DTX1p+fCjcWbf2QD+ScQMTLdll52oyhQl8KhXn+Tlyhp+XTdqaySQ=="], - "@rivet-dev/agentos-runtime-sidecar": ["@rivet-dev/agentos-runtime-sidecar@0.2.14", "", { "optionalDependencies": { "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-darwin-x64": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": "0.2.14" } }, "sha512-dsA1wNg+0Y6DYRB8no962k1tAQk1y5kfdAbrpKjJQJjfgfwkv0q8XZ3ybtt1hLml/thgE32CI++8F7MRWz4TFA=="], + "@rivet-dev/agentos-runtime-sidecar": ["@rivet-dev/agentos-runtime-sidecar@0.2.10", "", { "optionalDependencies": { "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": "0.2.10", "@rivet-dev/agentos-runtime-sidecar-darwin-x64": "0.2.10", "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": "0.2.10", "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": "0.2.10" } }, "sha512-v2KXHTTQYHdMpNFhBt3/wCyKajwxq9o4jKLYpaa9mYiaBdHfORuBaDI9e3WDGEly7HCIEWNnwvkNMvoQoHnXnQ=="], - "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": ["@rivet-dev/agentos-runtime-sidecar-darwin-arm64@0.2.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5pKvG7TC3lKbCMbQZptyXd3QPQyfiJ+wKqA+u5SqoP+Lqwim9C4PVSYMLUaxx0QqxliNuNu+VWif1xM91yECiw=="], + "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": ["@rivet-dev/agentos-runtime-sidecar-darwin-arm64@0.2.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PJ5rJZmgpS/EX9Zn1UA6Z5Ol0Y31UJKfD7Fisdqy7hlJuxhQVS9cVFrp3bud2og9s3n32riEYTx1mUE1PVQKZA=="], - "@rivet-dev/agentos-runtime-sidecar-darwin-x64": ["@rivet-dev/agentos-runtime-sidecar-darwin-x64@0.2.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-mTSDuMXKHSpMJ3SVLCb/3sBCpOaBw0fnEsnLzVSuicuSWSzhNe4yyUeAcyz4wsuT4l+M+Z5mDH1eydfpz7nltw=="], + "@rivet-dev/agentos-runtime-sidecar-darwin-x64": ["@rivet-dev/agentos-runtime-sidecar-darwin-x64@0.2.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-+C4gEE7/pT36fclYqdUYt6bMUj6CsDDZ+2Kxuej57/q06cSa9W5Od2zIO4wxZbI6g0EoN5zVJ8qXv+jSOtTLbg=="], - "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu@0.2.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-bVtITOH4sNxcq8RuBMJF+Srlwa/Rl1ARZIej+MUDBR8VM7DGnBMWCaCHvYxy3JBmdP5aTb3gCwUm6e7m4/Khgw=="], + "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu@0.2.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-BSs/LkKkNxvNBD9qEmxPWHmdHQokNGkGS3dcI3LTY4D6Sgat1Vun1OQ53v1HQSGf/TuAfgYOzbQPikvOU3zkmQ=="], - "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu@0.2.14", "", { "os": "linux", "cpu": "x64" }, "sha512-NOI1m456Ev06ey4O0pVnITaYA7emeoKR2lJIFJP4j9Kv0XuXpbmaz1aigfa3/SZQ7AvqOzxbNLCcH5m22iO8ng=="], + "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu@0.2.10", "", { "os": "linux", "cpu": "x64" }, "sha512-IIM0ILGdPNjettgBVOXvrNTICggo/xNtKO0V3kM7XJiQ4DkQQkjA1/Y0JBdLvsigt7HAcEJ38zQ3ahl+HOXK8w=="], - "@rivet-dev/agentos-sidecar": ["@rivet-dev/agentos-sidecar@0.2.14", "", { "optionalDependencies": { "@rivet-dev/agentos-sidecar-darwin-arm64": "0.2.14", "@rivet-dev/agentos-sidecar-darwin-x64": "0.2.14", "@rivet-dev/agentos-sidecar-linux-arm64-gnu": "0.2.14", "@rivet-dev/agentos-sidecar-linux-x64-gnu": "0.2.14" } }, "sha512-aISMeC7UY5Mjum/DiYp3idZa/EnNZ76FGke29FVQHmBfwVX6dTx2R/FHjZdEE+iOCi9APxAHIvdu8C+EVp6q2A=="], + "@rivet-dev/agentos-sidecar": ["@rivet-dev/agentos-sidecar@0.2.10", "", { "optionalDependencies": { "@rivet-dev/agentos-sidecar-darwin-arm64": "0.2.10", "@rivet-dev/agentos-sidecar-darwin-x64": "0.2.10", "@rivet-dev/agentos-sidecar-linux-arm64-gnu": "0.2.10", "@rivet-dev/agentos-sidecar-linux-x64-gnu": "0.2.10" } }, "sha512-3bq7k/OrtMffUT+aDSeXPIEDEaJLbPXzQ5oUqnjsU+6Hsmvvf+nAl/zTvHyQOMmriQiQ1BPMPqgNyXAc5BrV3w=="], - "@rivet-dev/agentos-sidecar-darwin-arm64": ["@rivet-dev/agentos-sidecar-darwin-arm64@0.2.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-U1R4wYvlsLCdASC5Lf6oP/6bW6ONGsiILtTQSVgxIHl/J1TrmOifrAbRgDC205kThJEZQ2op8kVzol5aEWOpbA=="], + "@rivet-dev/agentos-sidecar-darwin-arm64": ["@rivet-dev/agentos-sidecar-darwin-arm64@0.2.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q+54J8WLa/Diyn5H+TVZwIHt4kVFCBkwtco5DjUmFmG6y5ozzPl6MM0vVzIx6iNTzhWiYOFLz5PybICmy6j7BQ=="], - "@rivet-dev/agentos-sidecar-darwin-x64": ["@rivet-dev/agentos-sidecar-darwin-x64@0.2.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-vuij3BYGjVSCGMNB3HbS0EiDS50xG68cjH3ItuZL77GPHsw5V765TOheWDVgUOo1Q3+VWjdMaS2wNWv63qCf0w=="], + "@rivet-dev/agentos-sidecar-darwin-x64": ["@rivet-dev/agentos-sidecar-darwin-x64@0.2.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-Q0rAxtGjddpDcaB9keicukuExtIiynwX+DqVRG6hWjki0PSYqFqqrNFCzPiUswWf0u5Pakq1iBM+RgNu19PxZA=="], - "@rivet-dev/agentos-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-sidecar-linux-arm64-gnu@0.2.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-nauooe07/NhHb+Wn4xvJTUMNFzhOvrNoPwceiC0eGvkK7+imRyZpAgSGB4qRiaa2NRyuNRVh+d6kzp5iKzBwnA=="], + "@rivet-dev/agentos-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-sidecar-linux-arm64-gnu@0.2.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVgsnPczeT4oMoiUTrOfadAtDGoHhd30lrAU2p/xxyeCOhHAsZt1h0xo2oCteLmZ78DJm3rLcsR+4zhY6AhtOw=="], - "@rivet-dev/agentos-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-sidecar-linux-x64-gnu@0.2.14", "", { "os": "linux", "cpu": "x64" }, "sha512-PaGPXi5mS0Ef023nqS9lbMkMH6KGoOsHA3apAaOQz95lrmVx7E/z5BPzKYl3aYMYjmlo004mnNETVBZOy0VbQw=="], + "@rivet-dev/agentos-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-sidecar-linux-x64-gnu@0.2.10", "", { "os": "linux", "cpu": "x64" }, "sha512-WXKLIeZJvOo2Kxw2wPmPNc7QWM0lq69Xt/Yy2W86gYKORAFPVJ9GVag85ywP3LrjIW1oEDwzqrvMp3PGVkvVXg=="], "@rivetkit/bare-ts": ["@rivetkit/bare-ts@0.6.2", "", {}, "sha512-3qndQUQXLdwafMEqfhz24hUtDPcsf1Bu3q52Kb8MqeH8JUh3h6R4HYW3ZJXiQsLcyYyFM68PuIwlLRlg1xDEpg=="], @@ -1148,11 +1158,11 @@ "@rivetkit/engine-envoy-protocol": ["@rivetkit/engine-envoy-protocol@2.3.9", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2" } }, "sha512-2IK41V9U8sgMnEYd/P6u/68nCufCU2dvxuHVV3uAV0uIVCdtRV8lkjuR2fSr05bwHmzSmewdqsbiNMiC/GWt8w=="], - "@rivetkit/framework-base": ["@rivetkit/framework-base@2.3.9", "", { "dependencies": { "@tanstack/store": "^0.7.1", "fast-deep-equal": "^3.1.3", "rivetkit": "2.3.9" } }, "sha512-ZSxrclYcpmdGsLMiVE2dfWNfUB6diSx+t8k4EQgL4cN02ThzJD3BM5mhU+zQVCCwfNw42eRZVIoxydYDLl/yHw=="], + "@rivetkit/framework-base": ["@rivetkit/framework-base@2.3.7", "", { "dependencies": { "@tanstack/store": "^0.7.1", "fast-deep-equal": "^3.1.3", "rivetkit": "2.3.7" } }, "sha512-zxmdAzFogA3PeT3ZgFIoYlEAJVi3iCwbPBXczZKf2x2QMCl2cTZ2jswFCAgHUUMQWj+AWiX65usxq73a9Ls/qQ=="], "@rivetkit/on-change": ["@rivetkit/on-change@6.0.1", "", {}, "sha512-QBN/KRBXLJdCgN4gBTL3XAc/zKm58atSnieXWMOyFSPmo6F1/yIVV/LTRdvAktfCttrGx7W6c32i/lwqCHWnsQ=="], - "@rivetkit/react": ["@rivetkit/react@2.3.9", "", { "dependencies": { "@rivetkit/framework-base": "2.3.9", "@tanstack/react-store": "^0.7.1", "rivetkit": "2.3.9" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" } }, "sha512-j9t82h/yIqqSt17coQZeRu3F9Q5w2FgWPDUC9fCyQUJp9PTjO7ea494PR0lSWvuEiwMRqE5JpgbHdYUQ1woE9w=="], + "@rivetkit/react": ["@rivetkit/react@2.3.7", "", { "dependencies": { "@rivetkit/framework-base": "2.3.7", "@tanstack/react-store": "^0.7.1", "rivetkit": "2.3.7" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" } }, "sha512-Y3UoUYhkLKDQrJdloCmYK+fhJMlPw5BPHbRb5VutFh5L8csIRZLoCoMitzV7mjNUxuDE1+k10iGuUHYPZUP4aA=="], "@rivetkit/rivetkit-napi": ["@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" } }, "sha512-lUuOK1ja6ZMwnNRsdtqJeXChbBEqyvHuI/1h5XQWHfBUu7DgX5zuyA/FJ+BY6YFWtwnkHnOVCBJeNx/3gj8Xhg=="], @@ -1610,6 +1620,8 @@ "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], + "async-channel": ["async-channel@0.2.0", "", {}, "sha512-BJyjI/sfKlyijaBt2hbOSxT28xGNtLR0QLzAKO1Hlnv5BULY7sAoYoTPW3lfr1ZIC7y+FxabxO9T8GXpyoofGg=="], + "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], "atomically": ["atomically@1.7.0", "", {}, "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w=="], @@ -2330,7 +2342,7 @@ "hono-openapi": ["hono-openapi@1.3.1", "", { "peerDependencies": { "@hono/standard-validator": "^0.2.0", "@standard-community/standard-json": "^0.3.5", "@standard-community/standard-openapi": "^0.2.9", "@types/json-schema": "^7.0.15", "hono": "^4.11.2", "openapi-types": "^12.1.3" }, "optionalPeers": ["@hono/standard-validator", "hono"] }, "sha512-NLVeVkhKZ3drmQNEIPac8HX8Y54uf1hJAgIM/7MfDsaeVVmB+QILWQxx5x3R3NvRHgedcbEbOCGY2uR7WQYyMw=="], - "hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], + "hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="], "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], @@ -3020,7 +3032,7 @@ "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "punycode": ["punycode@1.4.1", "", {}, "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="], "pure-rand": ["pure-rand@8.4.2", "", {}, "sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng=="], @@ -3642,6 +3654,8 @@ "@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@code/primitives/@rivet-dev/agentos": ["@rivet-dev/agentos@0.2.14", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/common": "0.2.14", "@rivet-dev/agentos-core": "0.2.14", "@rivetkit/react": "2.3.9", "rivetkit": "2.3.9", "zod": "^4.1.11" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" }, "optionalPeers": ["react", "react-dom"] }, "sha512-dr7GU8AA02wB906gdQ6tyfCTyOa08KtT8djpUdtprbx7GLkaUQpq0j60BVeS/OkTUzEwYexWEKmKyGL1U/EgiQ=="], + "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], "@dotenvx/dotenvx/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], @@ -3702,8 +3716,6 @@ "@mariozechner/pi-ai/@sinclair/typebox": ["@sinclair/typebox@0.34.52", "", {}, "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw=="], - "@mariozechner/pi-coding-agent/hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="], - "@mariozechner/pi-coding-agent/ignore": ["ignore@7.0.6", "", {}, "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw=="], "@mariozechner/pi-coding-agent/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], @@ -3724,10 +3736,16 @@ "@react-router/dev/react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="], + "@rivet-dev/agentos/rivetkit": ["rivetkit@2.3.7", "", { "dependencies": { "@hono/zod-openapi": "^1.1.5", "@rivet-dev/agent-os-core": "^0.1.1", "@rivetkit/bare-ts": "^0.6.2", "@rivetkit/engine-cli": "2.3.7", "@rivetkit/engine-envoy-protocol": "2.3.7", "@rivetkit/on-change": "6.0.1", "@rivetkit/rivetkit-napi": "2.3.7", "@rivetkit/rivetkit-wasm": "2.3.7", "@rivetkit/traces": "2.3.7", "@rivetkit/virtual-websocket": "2.3.7", "@rivetkit/workflow-engine": "2.3.7", "cbor-x": "^1.6.0", "drizzle-orm": "^0.44.2", "hono": "^4.7.0", "invariant": "^2.2.4", "p-retry": "^6.2.1", "pino": "^9.5.0", "uuid": "^12.0.0", "vbare": "^0.0.4", "zod": "^4.1.0" }, "peerDependencies": { "drizzle-kit": "^0.31.2", "eventsource": "^4.0.0", "ws": "^8.0.0" }, "optionalPeers": ["drizzle-kit", "eventsource", "ws"] }, "sha512-V2IWlXq9SRLJWrcYVa8WUftELCpbdsBVWZIqz2WQjhhzRK9Aan65RfMoZVx62A9k8HuIO6MH1nAPLhOuk1xePQ=="], + "@rivetkit/framework-base/@tanstack/store": ["@tanstack/store@0.7.7", "", {}, "sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ=="], + "@rivetkit/framework-base/rivetkit": ["rivetkit@2.3.7", "", { "dependencies": { "@hono/zod-openapi": "^1.1.5", "@rivet-dev/agent-os-core": "^0.1.1", "@rivetkit/bare-ts": "^0.6.2", "@rivetkit/engine-cli": "2.3.7", "@rivetkit/engine-envoy-protocol": "2.3.7", "@rivetkit/on-change": "6.0.1", "@rivetkit/rivetkit-napi": "2.3.7", "@rivetkit/rivetkit-wasm": "2.3.7", "@rivetkit/traces": "2.3.7", "@rivetkit/virtual-websocket": "2.3.7", "@rivetkit/workflow-engine": "2.3.7", "cbor-x": "^1.6.0", "drizzle-orm": "^0.44.2", "hono": "^4.7.0", "invariant": "^2.2.4", "p-retry": "^6.2.1", "pino": "^9.5.0", "uuid": "^12.0.0", "vbare": "^0.0.4", "zod": "^4.1.0" }, "peerDependencies": { "drizzle-kit": "^0.31.2", "eventsource": "^4.0.0", "ws": "^8.0.0" }, "optionalPeers": ["drizzle-kit", "eventsource", "ws"] }, "sha512-V2IWlXq9SRLJWrcYVa8WUftELCpbdsBVWZIqz2WQjhhzRK9Aan65RfMoZVx62A9k8HuIO6MH1nAPLhOuk1xePQ=="], + "@rivetkit/react/@tanstack/react-store": ["@tanstack/react-store@0.7.7", "", { "dependencies": { "@tanstack/store": "0.7.7", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-qqT0ufegFRDGSof9D/VqaZgjNgp4tRPHZIJq2+QIHkMUtHjaJ0lYrrXjeIUJvjnTbgPfSD1XgOMEt0lmANn6Zg=="], + "@rivetkit/react/rivetkit": ["rivetkit@2.3.7", "", { "dependencies": { "@hono/zod-openapi": "^1.1.5", "@rivet-dev/agent-os-core": "^0.1.1", "@rivetkit/bare-ts": "^0.6.2", "@rivetkit/engine-cli": "2.3.7", "@rivetkit/engine-envoy-protocol": "2.3.7", "@rivetkit/on-change": "6.0.1", "@rivetkit/rivetkit-napi": "2.3.7", "@rivetkit/rivetkit-wasm": "2.3.7", "@rivetkit/traces": "2.3.7", "@rivetkit/virtual-websocket": "2.3.7", "@rivetkit/workflow-engine": "2.3.7", "cbor-x": "^1.6.0", "drizzle-orm": "^0.44.2", "hono": "^4.7.0", "invariant": "^2.2.4", "p-retry": "^6.2.1", "pino": "^9.5.0", "uuid": "^12.0.0", "vbare": "^0.0.4", "zod": "^4.1.0" }, "peerDependencies": { "drizzle-kit": "^0.31.2", "eventsource": "^4.0.0", "ws": "^8.0.0" }, "optionalPeers": ["drizzle-kit", "eventsource", "ws"] }, "sha512-V2IWlXq9SRLJWrcYVa8WUftELCpbdsBVWZIqz2WQjhhzRK9Aan65RfMoZVx62A9k8HuIO6MH1nAPLhOuk1xePQ=="], + "@secure-exec/nodejs/es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], "@secure-exec/nodejs/esbuild": ["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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], @@ -3856,8 +3874,6 @@ "hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], - "hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], @@ -3900,7 +3916,7 @@ "morgan/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "node-stdlib-browser/punycode": ["punycode@1.4.1", "", {}, "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="], + "npm-package-arg/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], "npm-package-arg/validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="], @@ -3974,7 +3990,7 @@ "type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], - "url/punycode": ["punycode@1.4.1", "", {}, "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="], + "uri-js/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "vite-plus/oxfmt": ["oxfmt@0.57.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.57.0", "@oxfmt/binding-android-arm64": "0.57.0", "@oxfmt/binding-darwin-arm64": "0.57.0", "@oxfmt/binding-darwin-x64": "0.57.0", "@oxfmt/binding-freebsd-x64": "0.57.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.57.0", "@oxfmt/binding-linux-arm-musleabihf": "0.57.0", "@oxfmt/binding-linux-arm64-gnu": "0.57.0", "@oxfmt/binding-linux-arm64-musl": "0.57.0", "@oxfmt/binding-linux-ppc64-gnu": "0.57.0", "@oxfmt/binding-linux-riscv64-gnu": "0.57.0", "@oxfmt/binding-linux-riscv64-musl": "0.57.0", "@oxfmt/binding-linux-s390x-gnu": "0.57.0", "@oxfmt/binding-linux-x64-gnu": "0.57.0", "@oxfmt/binding-linux-x64-musl": "0.57.0", "@oxfmt/binding-openharmony-arm64": "0.57.0", "@oxfmt/binding-win32-arm64-msvc": "0.57.0", "@oxfmt/binding-win32-ia32-msvc": "0.57.0", "@oxfmt/binding-win32-x64-msvc": "0.57.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-ZB7Bi+rGDSqmVIo9jwcLyFgjxXvQhDdU+jx+ZrVy6VRiVXK2+CHc4hO3J4dUQjHe7V0ymHB+MDuv5z+NhK07HA=="], @@ -4024,6 +4040,12 @@ "@anthropic-ai/claude-agent-sdk/@img/sharp-linuxmusl-x64/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], + "@code/primitives/@rivet-dev/agentos/@agentos-software/common": ["@agentos-software/common@0.2.14", "", { "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" } }, "sha512-ve/ks2MZtXFN9JK+kcFnSMGI1tqoUy36sTKWYGqApcgg/3JJwqnMs4JIKL5OXjgCtDuTvTjRySbQvEKxGkeeSQ=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core": ["@rivet-dev/agentos-core@0.2.14", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/claude-code": "0.2.7", "@agentos-software/codex-cli": "0.3.4", "@agentos-software/common": "0.2.14", "@agentos-software/manifest": "0.2.14", "@agentos-software/opencode": "0.2.7", "@agentos-software/pi": "0.2.7", "@aws-sdk/client-s3": "^3.1019.0", "@rivet-dev/agentos-runtime-core": "0.2.14", "@rivet-dev/agentos-sidecar": "0.2.14", "@rivetkit/bare-ts": "^0.6.2", "@xterm/headless": "^6.0.0", "better-sqlite3": "^12.8.0", "croner": "^10.0.1", "googleapis": "^144.0.0", "isolated-vm": "^6.0.0", "long-timeout": "^0.1.1", "minimatch": "^10.2.4", "zod": "^4.1.11", "zod-to-json-schema": "^3.25.2" } }, "sha512-YAbK0NpauQKlcuSKl0eXB95ZdNopMGmXw1dBaoSlODKVYoKTjOEKwUtSEvx/zZB0Cse2kSQ/IrJpLe183QeQPw=="], + + "@code/primitives/@rivet-dev/agentos/@rivetkit/react": ["@rivetkit/react@2.3.9", "", { "dependencies": { "@rivetkit/framework-base": "2.3.9", "@tanstack/react-store": "^0.7.1", "rivetkit": "2.3.9" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" } }, "sha512-j9t82h/yIqqSt17coQZeRu3F9Q5w2FgWPDUC9fCyQUJp9PTjO7ea494PR0lSWvuEiwMRqE5JpgbHdYUQ1woE9w=="], + "@dotenvx/dotenvx/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], "@dotenvx/dotenvx/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], @@ -4098,8 +4120,56 @@ "@react-native/dev-middleware/serve-static/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], + "@rivet-dev/agentos/rivetkit/@rivetkit/engine-cli": ["@rivetkit/engine-cli@2.3.7", "", { "optionalDependencies": { "@rivetkit/engine-cli-darwin-arm64": "2.3.7", "@rivetkit/engine-cli-darwin-x64": "2.3.7", "@rivetkit/engine-cli-linux-arm64-musl": "2.3.7", "@rivetkit/engine-cli-linux-x64-musl": "2.3.7", "@rivetkit/engine-cli-win32-x64": "2.3.7" } }, "sha512-CezLwJ0B7dWDbA7qM6Aq04mwnrJAdrDActRrrcb4NBa20h7wO9KPAYBwyJz/dRnKm9EUUNcFZ6hrSDpp6T3+Rg=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/engine-envoy-protocol": ["@rivetkit/engine-envoy-protocol@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2" } }, "sha512-lsJM3ERwozQCebaOMKJzqIQlcLbbN3LXurRB0+7LsM6FUUL2l6hMoq5I2De/G35DJ6OWDva9AmzfvzI+5f1GPg=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-napi": ["@rivetkit/rivetkit-napi@2.3.7", "", { "dependencies": { "@napi-rs/cli": "^2.18.4", "@rivetkit/engine-envoy-protocol": "2.3.7" }, "optionalDependencies": { "@rivetkit/rivetkit-napi-darwin-arm64": "2.3.7", "@rivetkit/rivetkit-napi-darwin-x64": "2.3.7", "@rivetkit/rivetkit-napi-linux-arm64-gnu": "2.3.7", "@rivetkit/rivetkit-napi-linux-arm64-musl": "2.3.7", "@rivetkit/rivetkit-napi-linux-x64-gnu": "2.3.7", "@rivetkit/rivetkit-napi-linux-x64-musl": "2.3.7", "@rivetkit/rivetkit-napi-win32-x64-msvc": "2.3.7" } }, "sha512-1d3HtNKzJwdkznWDWSpCwg1rBn+nVwUfcKrApINTfiEhfDyVeznwbVFkfHWqOBHsjU17vvWFfjjTtf8QsjLwUQ=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-wasm": ["@rivetkit/rivetkit-wasm@2.3.7", "", {}, "sha512-o7QBtFOJrajyPVBIDQ32k8sDNFsUc8v2ETfNpr+Ch374ydmZMzCv3XKJU9vubc9bZa7WpCHSzf5ztc8b8i/Xpg=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/traces": ["@rivetkit/traces@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "vbare": "^0.0.4" } }, "sha512-B7QYjFP2HPxyfPsVjfcNIV7FPLWgGWGypmlT/dZM1i1Cf1WRdeuBumPLffgs3YceiY7Pm4D/gZZVt5p0m4Cx+A=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/virtual-websocket": ["@rivetkit/virtual-websocket@2.3.7", "", {}, "sha512-jwxDvYbr3YB6vFuxwRdB/AqUUMwdtC1rIAc4tNN6VQR3weHbE+PrDoHKbe85zrtlBtcnG89/p8tlovrj8qyQWA=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/workflow-engine": ["@rivetkit/workflow-engine@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "pino": "^9.6.0", "vbare": "^0.0.4" } }, "sha512-+C4kGuSNysrw2zs/LQoYxouOxufKHHMxiIXKF8Ab9GU2BCJ32RUST9dYU/gaQE/w9uM+hqAHUz0DTlOBYU6p6g=="], + + "@rivet-dev/agentos/rivetkit/uuid": ["uuid@12.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-9obBF8sMIHJWNQaO6IGOG8giGa/jUpKX34bz6o4whVs8M0WAvhID2tNxYp6A2XEBJPuZSX8wsS/6TEKfIDc+nw=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/engine-cli": ["@rivetkit/engine-cli@2.3.7", "", { "optionalDependencies": { "@rivetkit/engine-cli-darwin-arm64": "2.3.7", "@rivetkit/engine-cli-darwin-x64": "2.3.7", "@rivetkit/engine-cli-linux-arm64-musl": "2.3.7", "@rivetkit/engine-cli-linux-x64-musl": "2.3.7", "@rivetkit/engine-cli-win32-x64": "2.3.7" } }, "sha512-CezLwJ0B7dWDbA7qM6Aq04mwnrJAdrDActRrrcb4NBa20h7wO9KPAYBwyJz/dRnKm9EUUNcFZ6hrSDpp6T3+Rg=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/engine-envoy-protocol": ["@rivetkit/engine-envoy-protocol@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2" } }, "sha512-lsJM3ERwozQCebaOMKJzqIQlcLbbN3LXurRB0+7LsM6FUUL2l6hMoq5I2De/G35DJ6OWDva9AmzfvzI+5f1GPg=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-napi": ["@rivetkit/rivetkit-napi@2.3.7", "", { "dependencies": { "@napi-rs/cli": "^2.18.4", "@rivetkit/engine-envoy-protocol": "2.3.7" }, "optionalDependencies": { "@rivetkit/rivetkit-napi-darwin-arm64": "2.3.7", "@rivetkit/rivetkit-napi-darwin-x64": "2.3.7", "@rivetkit/rivetkit-napi-linux-arm64-gnu": "2.3.7", "@rivetkit/rivetkit-napi-linux-arm64-musl": "2.3.7", "@rivetkit/rivetkit-napi-linux-x64-gnu": "2.3.7", "@rivetkit/rivetkit-napi-linux-x64-musl": "2.3.7", "@rivetkit/rivetkit-napi-win32-x64-msvc": "2.3.7" } }, "sha512-1d3HtNKzJwdkznWDWSpCwg1rBn+nVwUfcKrApINTfiEhfDyVeznwbVFkfHWqOBHsjU17vvWFfjjTtf8QsjLwUQ=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-wasm": ["@rivetkit/rivetkit-wasm@2.3.7", "", {}, "sha512-o7QBtFOJrajyPVBIDQ32k8sDNFsUc8v2ETfNpr+Ch374ydmZMzCv3XKJU9vubc9bZa7WpCHSzf5ztc8b8i/Xpg=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/traces": ["@rivetkit/traces@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "vbare": "^0.0.4" } }, "sha512-B7QYjFP2HPxyfPsVjfcNIV7FPLWgGWGypmlT/dZM1i1Cf1WRdeuBumPLffgs3YceiY7Pm4D/gZZVt5p0m4Cx+A=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/virtual-websocket": ["@rivetkit/virtual-websocket@2.3.7", "", {}, "sha512-jwxDvYbr3YB6vFuxwRdB/AqUUMwdtC1rIAc4tNN6VQR3weHbE+PrDoHKbe85zrtlBtcnG89/p8tlovrj8qyQWA=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/workflow-engine": ["@rivetkit/workflow-engine@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "pino": "^9.6.0", "vbare": "^0.0.4" } }, "sha512-+C4kGuSNysrw2zs/LQoYxouOxufKHHMxiIXKF8Ab9GU2BCJ32RUST9dYU/gaQE/w9uM+hqAHUz0DTlOBYU6p6g=="], + + "@rivetkit/framework-base/rivetkit/uuid": ["uuid@12.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-9obBF8sMIHJWNQaO6IGOG8giGa/jUpKX34bz6o4whVs8M0WAvhID2tNxYp6A2XEBJPuZSX8wsS/6TEKfIDc+nw=="], + "@rivetkit/react/@tanstack/react-store/@tanstack/store": ["@tanstack/store@0.7.7", "", {}, "sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ=="], + "@rivetkit/react/rivetkit/@rivetkit/engine-cli": ["@rivetkit/engine-cli@2.3.7", "", { "optionalDependencies": { "@rivetkit/engine-cli-darwin-arm64": "2.3.7", "@rivetkit/engine-cli-darwin-x64": "2.3.7", "@rivetkit/engine-cli-linux-arm64-musl": "2.3.7", "@rivetkit/engine-cli-linux-x64-musl": "2.3.7", "@rivetkit/engine-cli-win32-x64": "2.3.7" } }, "sha512-CezLwJ0B7dWDbA7qM6Aq04mwnrJAdrDActRrrcb4NBa20h7wO9KPAYBwyJz/dRnKm9EUUNcFZ6hrSDpp6T3+Rg=="], + + "@rivetkit/react/rivetkit/@rivetkit/engine-envoy-protocol": ["@rivetkit/engine-envoy-protocol@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2" } }, "sha512-lsJM3ERwozQCebaOMKJzqIQlcLbbN3LXurRB0+7LsM6FUUL2l6hMoq5I2De/G35DJ6OWDva9AmzfvzI+5f1GPg=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-napi": ["@rivetkit/rivetkit-napi@2.3.7", "", { "dependencies": { "@napi-rs/cli": "^2.18.4", "@rivetkit/engine-envoy-protocol": "2.3.7" }, "optionalDependencies": { "@rivetkit/rivetkit-napi-darwin-arm64": "2.3.7", "@rivetkit/rivetkit-napi-darwin-x64": "2.3.7", "@rivetkit/rivetkit-napi-linux-arm64-gnu": "2.3.7", "@rivetkit/rivetkit-napi-linux-arm64-musl": "2.3.7", "@rivetkit/rivetkit-napi-linux-x64-gnu": "2.3.7", "@rivetkit/rivetkit-napi-linux-x64-musl": "2.3.7", "@rivetkit/rivetkit-napi-win32-x64-msvc": "2.3.7" } }, "sha512-1d3HtNKzJwdkznWDWSpCwg1rBn+nVwUfcKrApINTfiEhfDyVeznwbVFkfHWqOBHsjU17vvWFfjjTtf8QsjLwUQ=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-wasm": ["@rivetkit/rivetkit-wasm@2.3.7", "", {}, "sha512-o7QBtFOJrajyPVBIDQ32k8sDNFsUc8v2ETfNpr+Ch374ydmZMzCv3XKJU9vubc9bZa7WpCHSzf5ztc8b8i/Xpg=="], + + "@rivetkit/react/rivetkit/@rivetkit/traces": ["@rivetkit/traces@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "vbare": "^0.0.4" } }, "sha512-B7QYjFP2HPxyfPsVjfcNIV7FPLWgGWGypmlT/dZM1i1Cf1WRdeuBumPLffgs3YceiY7Pm4D/gZZVt5p0m4Cx+A=="], + + "@rivetkit/react/rivetkit/@rivetkit/virtual-websocket": ["@rivetkit/virtual-websocket@2.3.7", "", {}, "sha512-jwxDvYbr3YB6vFuxwRdB/AqUUMwdtC1rIAc4tNN6VQR3weHbE+PrDoHKbe85zrtlBtcnG89/p8tlovrj8qyQWA=="], + + "@rivetkit/react/rivetkit/@rivetkit/workflow-engine": ["@rivetkit/workflow-engine@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "pino": "^9.6.0", "vbare": "^0.0.4" } }, "sha512-+C4kGuSNysrw2zs/LQoYxouOxufKHHMxiIXKF8Ab9GU2BCJ32RUST9dYU/gaQE/w9uM+hqAHUz0DTlOBYU6p6g=="], + + "@rivetkit/react/rivetkit/uuid": ["uuid@12.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-9obBF8sMIHJWNQaO6IGOG8giGa/jUpKX34bz6o4whVs8M0WAvhID2tNxYp6A2XEBJPuZSX8wsS/6TEKfIDc+nw=="], + "@secure-exec/nodejs/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], "@secure-exec/nodejs/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], @@ -4246,6 +4316,8 @@ "morgan/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "npm-package-arg/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], "pkg-up/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], @@ -4380,6 +4452,18 @@ "wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], + "@code/primitives/@rivet-dev/agentos/@agentos-software/common/@agentos-software/tar": ["@agentos-software/tar@0.3.5", "", {}, "sha512-hSf6PY4q1luIomFSDgVHxVDDIPdAVZxdgwrQFEYH4aIE6TXX9qatVmzR36uYLWpnFGAZTR6srREGoTnmOGV4Lg=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@agentos-software/manifest": ["@agentos-software/manifest@0.2.14", "", {}, "sha512-c1lGWN7/d1lku6Kl+wj6w1YoLX6wI93IyiUoE6M/Hgl1PP1YIPUqGFM5P5sZ9gG9M0qQ86T/587gECj1elZQBg=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-runtime-core": ["@rivet-dev/agentos-runtime-core@0.2.14", "", { "dependencies": { "@rivet-dev/agentos-runtime-sidecar": "0.2.14", "@rivetkit/bare-ts": "^0.6.2", "zod": "^4.1.11" } }, "sha512-mZYas5wUZXjwLLLHq6uMOaajtyc/3iLQ6vGzOH4E3OHBwCfK054YwGU8iunRqWtk+Wd7MPetzstxzdu+72nBug=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-sidecar": ["@rivet-dev/agentos-sidecar@0.2.14", "", { "optionalDependencies": { "@rivet-dev/agentos-sidecar-darwin-arm64": "0.2.14", "@rivet-dev/agentos-sidecar-darwin-x64": "0.2.14", "@rivet-dev/agentos-sidecar-linux-arm64-gnu": "0.2.14", "@rivet-dev/agentos-sidecar-linux-x64-gnu": "0.2.14" } }, "sha512-aISMeC7UY5Mjum/DiYp3idZa/EnNZ76FGke29FVQHmBfwVX6dTx2R/FHjZdEE+iOCi9APxAHIvdu8C+EVp6q2A=="], + + "@code/primitives/@rivet-dev/agentos/@rivetkit/react/@rivetkit/framework-base": ["@rivetkit/framework-base@2.3.9", "", { "dependencies": { "@tanstack/store": "^0.7.1", "fast-deep-equal": "^3.1.3", "rivetkit": "2.3.9" } }, "sha512-ZSxrclYcpmdGsLMiVE2dfWNfUB6diSx+t8k4EQgL4cN02ThzJD3BM5mhU+zQVCCwfNw42eRZVIoxydYDLl/yHw=="], + + "@code/primitives/@rivet-dev/agentos/@rivetkit/react/@tanstack/react-store": ["@tanstack/react-store@0.7.7", "", { "dependencies": { "@tanstack/store": "0.7.7", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-qqT0ufegFRDGSof9D/VqaZgjNgp4tRPHZIJq2+QIHkMUtHjaJ0lYrrXjeIUJvjnTbgPfSD1XgOMEt0lmANn6Zg=="], + "@expo/cli/accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "@expo/cli/ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], @@ -4410,6 +4494,78 @@ "@react-native/dev-middleware/serve-static/send/range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + "@rivet-dev/agentos/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-darwin-arm64": ["@rivetkit/engine-cli-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-F3yGSDIaW94BZzuAm3erQRT/Ki55wHJ/b6tOaE7d9tRmTAZw/XqHmjNdUYjOvFUQKLb+SSsOittM4dINrAANQQ=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-darwin-x64": ["@rivetkit/engine-cli-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-P8BbQsamIvv8U/cEoJUFr+uAzwjjl9cG+ZZxjDX9OJxbuD11ESpHvDLgge54ijynO3IjoP8cIzjIXat6mr2Gkw=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-linux-arm64-musl": ["@rivetkit/engine-cli-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-G3s76BHfIs6R9rm6JYI13sOjPLy08+C8WvVoFwSdMqsibEaqlfo36wVkp/x1g0sEZUek/dBxVrKqMMR7c4/gug=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-linux-x64-musl": ["@rivetkit/engine-cli-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-LWhrUVzULcsZ4ufCLsx23YfrdMW2INd9g0ANBac9+PzGwL8qYfVIXnDpR3587lapu68EbSEPZcconf1tBlvJxQ=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-win32-x64": ["@rivetkit/engine-cli-win32-x64@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-jyA5PlHivHXyyq2ehnuXwxd5TUSbB4emomnph9EovsJo7qIdmSNaaCO13NYBT483fd0uXiNI0MK/lkJa9ePY5A=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-darwin-arm64": ["@rivetkit/rivetkit-napi-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gI1wMe6z85VDeR4K/wnzevVakXTg5UCfvjlDOp1+23nyU3NlInhN156dEWO8EsfRMrs+1bYoGdc4rcoN+4PUrw=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-darwin-x64": ["@rivetkit/rivetkit-napi-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-H5tUwvCbKwTIBiyQG01ikK5mdc9ISg+bv8gPUw41mYOKq8rb9nBLkcl2TKcreFHac8KaGxtnBZzYcjbUV3NcwQ=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-arm64-gnu": ["@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-MpOeiO5M737e93hM/FjcH+zv8xBEX1tgBd/59K/Uw7qlRbWW7JGz8WGjavdxv211LRqxsn8EUlGRxcADDsXnBA=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-arm64-musl": ["@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-0GsUgd/HHvIq6v92kp0H175mGm2Exvs4krBLih0MIpVAkqJk8EIcKI6wJhCwY04Fr0MS8sHkUhjuHXa7QcmlYA=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-x64-gnu": ["@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-8wCD1FuDpM+yiKRG8ro1K8ILVpJXzCNKViJ1axq1b4Nyqgod/nyEvvKDaT4qhA5+Om+W5i6YRO1uddjC6QjJSQ=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-x64-musl": ["@rivetkit/rivetkit-napi-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-8RGzXD33GH1/DWufFzCZRI+npF5IL/9z7Ja3pthsuYgrL+axGG0iqfAjbwj5HHnB/ceUGQVT+uCKzoLnG+odtw=="], + + "@rivet-dev/agentos/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-win32-x64-msvc": ["@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-n1by/coKxWOb2FZDGLM2qmULxcLSqx8hxJuk7Hsb1gl4uNHGviUzYr+r7WAiOzonK/Dgy477u3OKf5yBie743A=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-darwin-arm64": ["@rivetkit/engine-cli-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-F3yGSDIaW94BZzuAm3erQRT/Ki55wHJ/b6tOaE7d9tRmTAZw/XqHmjNdUYjOvFUQKLb+SSsOittM4dINrAANQQ=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-darwin-x64": ["@rivetkit/engine-cli-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-P8BbQsamIvv8U/cEoJUFr+uAzwjjl9cG+ZZxjDX9OJxbuD11ESpHvDLgge54ijynO3IjoP8cIzjIXat6mr2Gkw=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-linux-arm64-musl": ["@rivetkit/engine-cli-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-G3s76BHfIs6R9rm6JYI13sOjPLy08+C8WvVoFwSdMqsibEaqlfo36wVkp/x1g0sEZUek/dBxVrKqMMR7c4/gug=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-linux-x64-musl": ["@rivetkit/engine-cli-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-LWhrUVzULcsZ4ufCLsx23YfrdMW2INd9g0ANBac9+PzGwL8qYfVIXnDpR3587lapu68EbSEPZcconf1tBlvJxQ=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-win32-x64": ["@rivetkit/engine-cli-win32-x64@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-jyA5PlHivHXyyq2ehnuXwxd5TUSbB4emomnph9EovsJo7qIdmSNaaCO13NYBT483fd0uXiNI0MK/lkJa9ePY5A=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-darwin-arm64": ["@rivetkit/rivetkit-napi-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gI1wMe6z85VDeR4K/wnzevVakXTg5UCfvjlDOp1+23nyU3NlInhN156dEWO8EsfRMrs+1bYoGdc4rcoN+4PUrw=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-darwin-x64": ["@rivetkit/rivetkit-napi-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-H5tUwvCbKwTIBiyQG01ikK5mdc9ISg+bv8gPUw41mYOKq8rb9nBLkcl2TKcreFHac8KaGxtnBZzYcjbUV3NcwQ=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-arm64-gnu": ["@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-MpOeiO5M737e93hM/FjcH+zv8xBEX1tgBd/59K/Uw7qlRbWW7JGz8WGjavdxv211LRqxsn8EUlGRxcADDsXnBA=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-arm64-musl": ["@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-0GsUgd/HHvIq6v92kp0H175mGm2Exvs4krBLih0MIpVAkqJk8EIcKI6wJhCwY04Fr0MS8sHkUhjuHXa7QcmlYA=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-x64-gnu": ["@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-8wCD1FuDpM+yiKRG8ro1K8ILVpJXzCNKViJ1axq1b4Nyqgod/nyEvvKDaT4qhA5+Om+W5i6YRO1uddjC6QjJSQ=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-x64-musl": ["@rivetkit/rivetkit-napi-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-8RGzXD33GH1/DWufFzCZRI+npF5IL/9z7Ja3pthsuYgrL+axGG0iqfAjbwj5HHnB/ceUGQVT+uCKzoLnG+odtw=="], + + "@rivetkit/framework-base/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-win32-x64-msvc": ["@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-n1by/coKxWOb2FZDGLM2qmULxcLSqx8hxJuk7Hsb1gl4uNHGviUzYr+r7WAiOzonK/Dgy477u3OKf5yBie743A=="], + + "@rivetkit/react/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-darwin-arm64": ["@rivetkit/engine-cli-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-F3yGSDIaW94BZzuAm3erQRT/Ki55wHJ/b6tOaE7d9tRmTAZw/XqHmjNdUYjOvFUQKLb+SSsOittM4dINrAANQQ=="], + + "@rivetkit/react/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-darwin-x64": ["@rivetkit/engine-cli-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-P8BbQsamIvv8U/cEoJUFr+uAzwjjl9cG+ZZxjDX9OJxbuD11ESpHvDLgge54ijynO3IjoP8cIzjIXat6mr2Gkw=="], + + "@rivetkit/react/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-linux-arm64-musl": ["@rivetkit/engine-cli-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-G3s76BHfIs6R9rm6JYI13sOjPLy08+C8WvVoFwSdMqsibEaqlfo36wVkp/x1g0sEZUek/dBxVrKqMMR7c4/gug=="], + + "@rivetkit/react/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-linux-x64-musl": ["@rivetkit/engine-cli-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-LWhrUVzULcsZ4ufCLsx23YfrdMW2INd9g0ANBac9+PzGwL8qYfVIXnDpR3587lapu68EbSEPZcconf1tBlvJxQ=="], + + "@rivetkit/react/rivetkit/@rivetkit/engine-cli/@rivetkit/engine-cli-win32-x64": ["@rivetkit/engine-cli-win32-x64@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-jyA5PlHivHXyyq2ehnuXwxd5TUSbB4emomnph9EovsJo7qIdmSNaaCO13NYBT483fd0uXiNI0MK/lkJa9ePY5A=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-darwin-arm64": ["@rivetkit/rivetkit-napi-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gI1wMe6z85VDeR4K/wnzevVakXTg5UCfvjlDOp1+23nyU3NlInhN156dEWO8EsfRMrs+1bYoGdc4rcoN+4PUrw=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-darwin-x64": ["@rivetkit/rivetkit-napi-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-H5tUwvCbKwTIBiyQG01ikK5mdc9ISg+bv8gPUw41mYOKq8rb9nBLkcl2TKcreFHac8KaGxtnBZzYcjbUV3NcwQ=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-arm64-gnu": ["@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-MpOeiO5M737e93hM/FjcH+zv8xBEX1tgBd/59K/Uw7qlRbWW7JGz8WGjavdxv211LRqxsn8EUlGRxcADDsXnBA=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-arm64-musl": ["@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-0GsUgd/HHvIq6v92kp0H175mGm2Exvs4krBLih0MIpVAkqJk8EIcKI6wJhCwY04Fr0MS8sHkUhjuHXa7QcmlYA=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-x64-gnu": ["@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-8wCD1FuDpM+yiKRG8ro1K8ILVpJXzCNKViJ1axq1b4Nyqgod/nyEvvKDaT4qhA5+Om+W5i6YRO1uddjC6QjJSQ=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-linux-x64-musl": ["@rivetkit/rivetkit-napi-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-8RGzXD33GH1/DWufFzCZRI+npF5IL/9z7Ja3pthsuYgrL+axGG0iqfAjbwj5HHnB/ceUGQVT+uCKzoLnG+odtw=="], + + "@rivetkit/react/rivetkit/@rivetkit/rivetkit-napi/@rivetkit/rivetkit-napi-win32-x64-msvc": ["@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-n1by/coKxWOb2FZDGLM2qmULxcLSqx8hxJuk7Hsb1gl4uNHGviUzYr+r7WAiOzonK/Dgy477u3OKf5yBie743A=="], + "cli-highlight/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "googleapis-common/google-auth-library/gcp-metadata/google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="], @@ -4434,6 +4590,20 @@ "ripemd160/hash-base/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-runtime-core/@rivet-dev/agentos-runtime-sidecar": ["@rivet-dev/agentos-runtime-sidecar@0.2.14", "", { "optionalDependencies": { "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-darwin-x64": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": "0.2.14" } }, "sha512-dsA1wNg+0Y6DYRB8no962k1tAQk1y5kfdAbrpKjJQJjfgfwkv0q8XZ3ybtt1hLml/thgE32CI++8F7MRWz4TFA=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-sidecar/@rivet-dev/agentos-sidecar-darwin-arm64": ["@rivet-dev/agentos-sidecar-darwin-arm64@0.2.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-U1R4wYvlsLCdASC5Lf6oP/6bW6ONGsiILtTQSVgxIHl/J1TrmOifrAbRgDC205kThJEZQ2op8kVzol5aEWOpbA=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-sidecar/@rivet-dev/agentos-sidecar-darwin-x64": ["@rivet-dev/agentos-sidecar-darwin-x64@0.2.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-vuij3BYGjVSCGMNB3HbS0EiDS50xG68cjH3ItuZL77GPHsw5V765TOheWDVgUOo1Q3+VWjdMaS2wNWv63qCf0w=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-sidecar/@rivet-dev/agentos-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-sidecar-linux-arm64-gnu@0.2.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-nauooe07/NhHb+Wn4xvJTUMNFzhOvrNoPwceiC0eGvkK7+imRyZpAgSGB4qRiaa2NRyuNRVh+d6kzp5iKzBwnA=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-sidecar/@rivet-dev/agentos-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-sidecar-linux-x64-gnu@0.2.14", "", { "os": "linux", "cpu": "x64" }, "sha512-PaGPXi5mS0Ef023nqS9lbMkMH6KGoOsHA3apAaOQz95lrmVx7E/z5BPzKYl3aYMYjmlo004mnNETVBZOy0VbQw=="], + + "@code/primitives/@rivet-dev/agentos/@rivetkit/react/@rivetkit/framework-base/@tanstack/store": ["@tanstack/store@0.7.7", "", {}, "sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ=="], + + "@code/primitives/@rivet-dev/agentos/@rivetkit/react/@tanstack/react-store/@tanstack/store": ["@tanstack/store@0.7.7", "", {}, "sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ=="], + "@expo/cli/ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], "@expo/cli/ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], @@ -4454,6 +4624,14 @@ "pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-runtime-core/@rivet-dev/agentos-runtime-sidecar/@rivet-dev/agentos-runtime-sidecar-darwin-arm64": ["@rivet-dev/agentos-runtime-sidecar-darwin-arm64@0.2.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5pKvG7TC3lKbCMbQZptyXd3QPQyfiJ+wKqA+u5SqoP+Lqwim9C4PVSYMLUaxx0QqxliNuNu+VWif1xM91yECiw=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-runtime-core/@rivet-dev/agentos-runtime-sidecar/@rivet-dev/agentos-runtime-sidecar-darwin-x64": ["@rivet-dev/agentos-runtime-sidecar-darwin-x64@0.2.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-mTSDuMXKHSpMJ3SVLCb/3sBCpOaBw0fnEsnLzVSuicuSWSzhNe4yyUeAcyz4wsuT4l+M+Z5mDH1eydfpz7nltw=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-runtime-core/@rivet-dev/agentos-runtime-sidecar/@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu@0.2.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-bVtITOH4sNxcq8RuBMJF+Srlwa/Rl1ARZIej+MUDBR8VM7DGnBMWCaCHvYxy3JBmdP5aTb3gCwUm6e7m4/Khgw=="], + + "@code/primitives/@rivet-dev/agentos/@rivet-dev/agentos-core/@rivet-dev/agentos-runtime-core/@rivet-dev/agentos-runtime-sidecar/@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu@0.2.14", "", { "os": "linux", "cpu": "x64" }, "sha512-NOI1m456Ev06ey4O0pVnITaYA7emeoKR2lJIFJP4j9Kv0XuXpbmaz1aigfa3/SZQ7AvqOzxbNLCcH5m22iO8ng=="], + "@expo/cli/ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "@expo/cli/ora/cli-cursor/restore-cursor/onetime/mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="], diff --git a/deploy/zopu-runtime/runner/Dockerfile b/deploy/zopu-runtime/runner/Dockerfile new file mode 100644 index 0000000..f27bb9f --- /dev/null +++ b/deploy/zopu-runtime/runner/Dockerfile @@ -0,0 +1,8 @@ +FROM oven/bun:1.3.14 + +WORKDIR /app + +COPY . . +RUN bun install --frozen-lockfile + +CMD ["bun", "packages/agents/src/runner.ts"] diff --git a/deploy/zopu-runtime/runner/docker-compose.yml b/deploy/zopu-runtime/runner/docker-compose.yml new file mode 100644 index 0000000..c6a5c23 --- /dev/null +++ b/deploy/zopu-runtime/runner/docker-compose.yml @@ -0,0 +1,11 @@ +services: + zopu-agentos-runner: + build: + context: ../../.. + dockerfile: deploy/zopu-runtime/runner/Dockerfile + environment: + RIVET_ENDPOINT: ${RIVET_ENDPOINT} + RIVET_PUBLIC_ENDPOINT: ${RIVET_PUBLIC_ENDPOINT} + RIVET_RUNNER: default + RIVET_RUNNER_VERSION: ${RIVET_RUNNER_VERSION} + restart: unless-stopped diff --git a/docs/TECH.md b/docs/TECH.md index e2673e3..4b51b5d 100644 --- a/docs/TECH.md +++ b/docs/TECH.md @@ -18,29 +18,28 @@ Convex application backend ├── normalized product data ├── conversation turn queue └── reactive client projections - │ service-authenticated dispatch + │ durable Workflow steps + service-authenticated dispatch ▼ -FLUE orchestration service -├── model calls -├── typed tools -└── canonical Flue persistence in Convex - │ later execution commands +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 ▼ -Rivet Engine + AgentOS (post-Slice 1) -└── sandboxes, harnesses, and durable execution +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. +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 | -| FLUE | private programmable orchestration and domain-specific agents | -| Rivet actors (later) | serialized execution ownership, recovery, timers, leases | +| 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 | @@ -63,11 +62,7 @@ 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. +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 @@ -106,93 +101,93 @@ Avoid package proliferation in v0; logical boundaries may begin as folders. Minimal durable model: ```ts -type Id = string +type Id = string; interface Message { - id: Id - projectId: Id - content: string - createdAt: number + 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" + 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 + 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 + 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 + 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 + 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 + 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 + id: Id; + workId: Id; + stepId?: Id; + attemptId?: Id; + prompt: string; + recommendation?: string; + alternatives: readonly string[]; + status: "open" | "answered" | "withdrawn"; + answer?: string; } ``` @@ -337,35 +332,49 @@ 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 + 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 + 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 + 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 + execute( + plan: VerificationPlan, + env: EnvironmentRef + ): Effect.Effect; } ``` @@ -420,6 +429,10 @@ Zopu owns Work, branches, worktrees, budgets, approvals, artifacts, and completi ## 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: @@ -443,7 +456,7 @@ Best for: - actor-adjacent orchestration; - context/files/networking that fit runtime limits. -Use an attached full sandbox when native/heavy tooling is needed. +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 diff --git a/docs/slices.md b/docs/slices.md index 055031e..21992cd 100644 --- a/docs/slices.md +++ b/docs/slices.md @@ -211,16 +211,18 @@ Zopu implements one approved slice in an isolated repository environment and str Initial adapter choice: ```text -SandboxRuntime = CubeSandboxLive -HarnessRuntime = OmpHarnessLive (or one chosen harness) +SandboxRuntime = AgentOsSandboxLive +HarnessRuntime = CodexHarnessLive +Durable orchestration = Convex Workflow ``` Flow: ```text -prepare worktree -→ create sandbox -→ clone/mount repo +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 @@ -230,14 +232,15 @@ prepare worktree Security: -- scoped Git/model tokens; +- 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 -Current activity, changed files, artifact links, expandable raw logs. +Project selector/settings, Git connection status, current activity, changed files, artifact links, expandable raw logs, cancel/retry, and manual Git delivery controls. ### Acceptance @@ -247,6 +250,8 @@ Current activity, changed files, artifact links, expandable raw logs. - 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 @@ -490,4 +495,4 @@ browser-tester integration-coordinator 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. +Parallel engineering is allowed _within_ a slice after contracts land, but product release order remains sequential. diff --git a/packages/agents/package.json b/packages/agents/package.json index d7854d9..dd0647a 100644 --- a/packages/agents/package.json +++ b/packages/agents/package.json @@ -9,15 +9,21 @@ "dev": "bun --env-file=../../.env flue dev", "dev:tailscale": "bun --env-file=../../.env flue dev", "run": "bun --env-file=../../.env flue run", + "runner": "bun --env-file=../../.env src/runner.ts", "run:zopu": "bun --env-file=../../.env flue run zopu", "run:work-planner": "bun --env-file=../../.env flue run work-planner" }, "dependencies": { + "@agentos-software/codex-cli": "0.3.4", + "@agentos-software/git": "0.3.3", "@code/backend": "workspace:*", "@code/env": "workspace:*", + "@code/primitives": "workspace:*", "@flue/runtime": "latest", + "@rivet-dev/agentos": "0.2.10", "convex": "catalog:", "hono": "catalog:", + "rivetkit": "2.3.9", "valibot": "catalog:" }, "devDependencies": { diff --git a/packages/agents/src/app.ts b/packages/agents/src/app.ts index 17fbe91..a8c101b 100644 --- a/packages/agents/src/app.ts +++ b/packages/agents/src/app.ts @@ -2,6 +2,13 @@ import { parseAgentEnv } from "@code/env/agent"; import { registerProvider } from "@flue/runtime"; import type { Fetchable } from "@flue/runtime/routing"; import { flue } from "@flue/runtime/routing"; +import { Hono } from "hono"; + +import { + cancelAgentOsAttempt, + executeAgentOsAttempt, + runtimeRegistry, +} from "./runtime/agent-os"; const agentEnv = parseAgentEnv(process.env); @@ -24,5 +31,35 @@ registerProvider(agentEnv.AGENT_MODEL_PROVIDER, { }, }); -// flue() returns a complete Hono app; the Fetchable contract accepts it. -export default flue() satisfies Fetchable; +const app = new Hono(); + +app.post("/internal/work-attempts/execute", async (context) => { + if ( + context.req.header("authorization") !== `Bearer ${agentEnv.FLUE_DB_TOKEN}` + ) { + return context.json({ error: "Unauthorized" }, 401); + } + try { + return context.json(await executeAgentOsAttempt(await context.req.json())); + } catch (error) { + return context.json( + { error: error instanceof Error ? error.message : "Execution failed" }, + 500 + ); + } +}); + +app.post("/internal/work-attempts/:workspaceKey/cancel", async (context) => { + if ( + context.req.header("authorization") !== `Bearer ${agentEnv.FLUE_DB_TOKEN}` + ) { + return context.json({ error: "Unauthorized" }, 401); + } + await cancelAgentOsAttempt(context.req.param("workspaceKey")); + return context.json({ cancelled: true }); +}); + +app.all("/api/rivet/*", (context) => runtimeRegistry.handler(context.req.raw)); +app.route("/", flue()); + +export default app satisfies Fetchable; diff --git a/packages/agents/src/runner.ts b/packages/agents/src/runner.ts new file mode 100644 index 0000000..a7d6f03 --- /dev/null +++ b/packages/agents/src/runner.ts @@ -0,0 +1,3 @@ +import { runtimeRegistry } from "./runtime/agent-os"; + +await runtimeRegistry.startEnvoy(); diff --git a/packages/agents/src/runtime/agent-os.ts b/packages/agents/src/runtime/agent-os.ts new file mode 100644 index 0000000..2b0177b --- /dev/null +++ b/packages/agents/src/runtime/agent-os.ts @@ -0,0 +1,213 @@ +import { parseAgentEnv } from "@code/env/agent"; +import { agentOS, setup } from "@rivet-dev/agentos"; +import { createClient } from "@rivet-dev/agentos/client"; +import { Effect } from "effect"; + +import { + codexSessionEnv, + makeCodexAgentOsConfig, +} from "../../../primitives/src/agent-os"; +import { decodeWorkAttemptExecutionInput } from "../../../primitives/src/execution-runtime"; +import type { + ExecutionEvent, + WorkAttemptExecutionResult, +} from "../../../primitives/src/execution-runtime"; + +const workspace = agentOS(makeCodexAgentOsConfig() as never); + +export const runtimeRegistry = setup({ use: { workspace } }); + +const shellQuote = (value: string): string => + `'${value.replaceAll("'", `'"'"'`)}'`; + +const event = ( + sequence: number, + kind: ExecutionEvent["kind"], + message: string, + metadata: Record = {} +): ExecutionEvent => ({ + kind, + message, + metadata, + occurredAt: Date.now(), + sequence, +}); + +const requireSuccess = ( + result: { exitCode: number; stderr: string; stdout: string }, + operation: string +) => { + if (result.exitCode !== 0) { + throw new Error(`${operation} failed: ${result.stderr || result.stdout}`); + } + return result.stdout.trim(); +}; + +const gitAuthEnv = (username: string, credential: string) => ({ + GIT_CONFIG_COUNT: "1", + GIT_CONFIG_KEY_0: "http.extraHeader", + GIT_CONFIG_VALUE_0: `Authorization: Basic ${Buffer.from(`${username}:${credential}`).toString("base64")}`, +}); + +export const executeAgentOsAttempt = async ( + rawInput: unknown +): Promise => { + const input = await Effect.runPromise( + decodeWorkAttemptExecutionInput(rawInput) + ); + const env = parseAgentEnv(process.env); + const client = createClient({ + endpoint: env.RIVET_PUBLIC_ENDPOINT ?? env.RIVET_ENDPOINT, + }); + const vm = client.workspace.getOrCreate([input.workspaceKey]); + const events: ExecutionEvent[] = [ + event(0, "runtime.preparing", "AgentOS workspace selected", { + workspaceKey: input.workspaceKey, + }), + ]; + const authEnv = gitAuthEnv( + input.auth.username ?? + (input.auth.provider === "github" ? "x-access-token" : "git"), + input.auth.credential + ); + + await vm.mkdir("/workspace", { recursive: true }); + if (!(await vm.exists("/workspace/repository/.git"))) { + events.push(event(1, "repository.cloning", "Cloning project repository")); + const clone = await vm.execArgv( + "git", + ["clone", input.repositoryUrl, "/workspace/repository"], + { + cwd: "/workspace", + env: authEnv, + } + ); + requireSuccess(clone, "Repository clone"); + } + + const checkout = await vm.exec( + `git fetch origin ${shellQuote(input.baseBranch)} && git checkout -B ${shellQuote(`zopu/${input.runId}`)} ${shellQuote(`origin/${input.baseBranch}`)}`, + { cwd: "/workspace/repository", env: authEnv } + ); + requireSuccess(checkout, "Repository checkout"); + const baseRevision = requireSuccess( + await vm.execArgv("git", ["rev-parse", "HEAD"], { + cwd: "/workspace/repository", + }), + "Base revision lookup" + ); + events.push( + event(2, "repository.ready", "Repository checkout is ready", { + baseRevision, + }) + ); + + const sessionId = `codex-${input.attemptId}`; + await vm.openSession({ + additionalInstructions: + "Work only inside /workspace/repository. Do not reveal credentials. Make the requested change and run focused verification. Do not push or open a pull request.", + agent: "codex", + cwd: "/workspace/repository", + env: codexSessionEnv({ + apiKey: env.AGENT_MODEL_API_KEY, + baseUrl: env.AGENT_MODEL_BASE_URL, + model: env.AGENT_MODEL_NAME, + }), + permissionPolicy: "allow_all", + sessionId, + }); + events.push( + event(3, "harness.started", "Codex implementation session started") + ); + const promptResult = await vm.prompt({ + content: [{ text: input.prompt, type: "text" }], + idempotencyKey: input.attemptId, + sessionId, + }); + events.push( + event(4, "harness.progress", "Codex implementation turn completed", { + stopReason: String(promptResult.stopReason), + }) + ); + + const status = requireSuccess( + await vm.execArgv("git", ["status", "--porcelain"], { + cwd: "/workspace/repository", + }), + "Changed file lookup" + ); + const diff = requireSuccess( + await vm.execArgv("git", ["diff", "--binary", "HEAD"], { + cwd: "/workspace/repository", + }), + "Diff collection" + ); + const changedFiles = status + .split("\n") + .filter(Boolean) + .map((line) => line.slice(3).trim()); + let candidateRevision = baseRevision; + if (changedFiles.length > 0) { + requireSuccess( + await vm.execArgv("git", ["add", "-A"], { cwd: "/workspace/repository" }), + "Candidate staging" + ); + const tree = requireSuccess( + await vm.execArgv("git", ["write-tree"], { + cwd: "/workspace/repository", + }), + "Candidate tree creation" + ); + candidateRevision = requireSuccess( + await vm.exec( + `printf %s ${shellQuote(`Zopu candidate for ${input.attemptId}`)} | git commit-tree ${shellQuote(tree)} -p ${shellQuote(baseRevision)}`, + { + cwd: "/workspace/repository", + env: { + GIT_AUTHOR_EMAIL: "agent@zopu.dev", + GIT_AUTHOR_NAME: "Zopu Agent", + GIT_COMMITTER_EMAIL: "agent@zopu.dev", + GIT_COMMITTER_NAME: "Zopu Agent", + }, + } + ), + "Candidate revision creation" + ); + requireSuccess( + await vm.execArgv("git", ["reset"], { cwd: "/workspace/repository" }), + "Candidate index reset" + ); + } + events.push( + event( + 5, + "repository.changed", + `${changedFiles.length} changed file(s) collected`, + { + candidateRevision, + } + ), + event(6, "runtime.completed", "AgentOS execution completed") + ); + + return { + baseRevision, + candidateRevision, + changedFiles, + diff, + environmentId: input.workspaceKey, + events, + summary: + changedFiles.length > 0 + ? `Codex changed ${changedFiles.length} file(s)` + : "Codex completed without repository changes", + }; +}; + +export const cancelAgentOsAttempt = async (workspaceKey: string) => { + const env = parseAgentEnv(process.env); + const client = createClient({ + endpoint: env.RIVET_PUBLIC_ENDPOINT ?? env.RIVET_ENDPOINT, + }); + await client.workspace.getOrCreate([workspaceKey]).cancelPrompt({}); +}; diff --git a/packages/backend/convex/_generated/api.d.ts b/packages/backend/convex/_generated/api.d.ts index 9ec3228..9c9398c 100644 --- a/packages/backend/convex/_generated/api.d.ts +++ b/packages/backend/convex/_generated/api.d.ts @@ -11,7 +11,10 @@ import type * as auth from "../auth.js"; import type * as authz from "../authz.js"; import type * as conversationMessages from "../conversationMessages.js"; +import type * as crons from "../crons.js"; import type * as fluePersistence from "../fluePersistence.js"; +import type * as gitConnectionData from "../gitConnectionData.js"; +import type * as gitConnections from "../gitConnections.js"; import type * as healthCheck from "../healthCheck.js"; import type * as http from "../http.js"; import type * as organizations from "../organizations.js"; @@ -19,6 +22,11 @@ import type * as privateData from "../privateData.js"; import type * as projects from "../projects.js"; import type * as publicGit from "../publicGit.js"; import type * as signalRouting from "../signalRouting.js"; +import type * as workArtifacts from "../workArtifacts.js"; +import type * as workExecution from "../workExecution.js"; +import type * as workExecutionAgent from "../workExecutionAgent.js"; +import type * as workExecutionWorkflow from "../workExecutionWorkflow.js"; +import type * as workPlanning from "../workPlanning.js"; import type * as works from "../works.js"; import type { @@ -31,7 +39,10 @@ declare const fullApi: ApiFromModules<{ auth: typeof auth; authz: typeof authz; conversationMessages: typeof conversationMessages; + crons: typeof crons; fluePersistence: typeof fluePersistence; + gitConnectionData: typeof gitConnectionData; + gitConnections: typeof gitConnections; healthCheck: typeof healthCheck; http: typeof http; organizations: typeof organizations; @@ -39,6 +50,11 @@ declare const fullApi: ApiFromModules<{ projects: typeof projects; publicGit: typeof publicGit; signalRouting: typeof signalRouting; + workArtifacts: typeof workArtifacts; + workExecution: typeof workExecution; + workExecutionAgent: typeof workExecutionAgent; + workExecutionWorkflow: typeof workExecutionWorkflow; + workPlanning: typeof workPlanning; works: typeof works; }>; @@ -70,4 +86,5 @@ export declare const internal: FilterApi< export declare const components: { betterAuth: import("@convex-dev/better-auth/_generated/component.js").ComponentApi<"betterAuth">; + workflow: import("@convex-dev/workflow/_generated/component.js").ComponentApi<"workflow">; }; diff --git a/packages/backend/convex/_generated/server.d.ts b/packages/backend/convex/_generated/server.d.ts index 41c734c..f072e0e 100644 --- a/packages/backend/convex/_generated/server.d.ts +++ b/packages/backend/convex/_generated/server.d.ts @@ -25,10 +25,14 @@ 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; readonly FLUE_URL: string | undefined; readonly GITEA_TOKEN: string | undefined; readonly GITEA_URL: string | undefined; + readonly GITHUB_CLIENT_ID: string | undefined; + readonly GITHUB_CLIENT_SECRET: string | undefined; + readonly GIT_CREDENTIAL_ENCRYPTION_KEY: string | undefined; readonly NATIVE_APP_URL: string | undefined; readonly SITE_URL: string; }; diff --git a/packages/backend/convex/auth.ts b/packages/backend/convex/auth.ts index 48fa16f..bf9ae7f 100644 --- a/packages/backend/convex/auth.ts +++ b/packages/backend/convex/auth.ts @@ -30,6 +30,15 @@ const createAuth = (ctx: GenericCtx) => jwksRotateOnTokenGenerationError: true, }), ], + socialProviders: + env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET + ? { + github: { + clientId: env.GITHUB_CLIENT_ID, + clientSecret: env.GITHUB_CLIENT_SECRET, + }, + } + : {}, trustedOrigins: [siteUrl, nativeAppUrl, "exp://"], }); diff --git a/packages/backend/convex/convex.config.ts b/packages/backend/convex/convex.config.ts index a6700e2..c16158b 100644 --- a/packages/backend/convex/convex.config.ts +++ b/packages/backend/convex/convex.config.ts @@ -1,17 +1,23 @@ import betterAuth from "@convex-dev/better-auth/convex.config"; +import workflow from "@convex-dev/workflow/convex.config.js"; import { defineApp } from "convex/server"; import { v } from "convex/values"; const app = defineApp({ env: { + AGENT_BACKEND_URL: v.optional(v.string()), FLUE_DB_TOKEN: v.string(), FLUE_URL: v.optional(v.string()), GITEA_TOKEN: v.optional(v.string()), GITEA_URL: v.optional(v.string()), + GITHUB_CLIENT_ID: v.optional(v.string()), + GITHUB_CLIENT_SECRET: v.optional(v.string()), + GIT_CREDENTIAL_ENCRYPTION_KEY: v.optional(v.string()), NATIVE_APP_URL: v.optional(v.string()), SITE_URL: v.string(), }, }); app.use(betterAuth); +app.use(workflow); export default app; diff --git a/packages/backend/convex/gitConnectionData.ts b/packages/backend/convex/gitConnectionData.ts new file mode 100644 index 0000000..bd3fd9a --- /dev/null +++ b/packages/backend/convex/gitConnectionData.ts @@ -0,0 +1,119 @@ +import { ConvexError, v } from "convex/values"; + +import { internalMutation, mutation, query } from "./_generated/server"; +import { requireCurrentOrganization, requireProjectMember } from "./authz"; + +export const persist = internalMutation({ + args: { + credentialCiphertext: v.string(), + credentialIv: v.string(), + credentialKind: v.union(v.literal("oauth"), v.literal("token")), + provider: v.union(v.literal("github"), v.literal("gitea")), + serverUrl: v.string(), + userId: v.string(), + username: v.optional(v.string()), + }, + handler: async (ctx, args) => { + const organization = await ctx.db + .query("organizations") + .withIndex("by_createdBy_and_kind", (q) => + q.eq("createdBy", args.userId).eq("kind", "personal") + ) + .unique(); + if (!organization) { + throw new ConvexError("Organization not found"); + } + const existing = await ctx.db + .query("gitConnections") + .withIndex("by_organizationId_and_provider_and_serverUrl", (q) => + q + .eq("organizationId", organization._id) + .eq("provider", args.provider) + .eq("serverUrl", args.serverUrl) + ) + .unique(); + const timestamp = Date.now(); + if (existing) { + await ctx.db.patch(existing._id, { + credentialCiphertext: args.credentialCiphertext, + credentialIv: args.credentialIv, + credentialKind: args.credentialKind, + updatedAt: timestamp, + username: args.username, + }); + return existing._id; + } + return await ctx.db.insert("gitConnections", { + connectedAt: timestamp, + credentialCiphertext: args.credentialCiphertext, + credentialIv: args.credentialIv, + credentialKind: args.credentialKind, + organizationId: organization._id, + provider: args.provider, + serverUrl: args.serverUrl, + updatedAt: timestamp, + username: args.username, + }); + }, +}); + +export const list = query({ + args: {}, + handler: async (ctx) => { + const { organizationId } = await requireCurrentOrganization(ctx); + const connections = await ctx.db + .query("gitConnections") + .withIndex("by_organizationId", (q) => + q.eq("organizationId", organizationId) + ) + .collect(); + return connections.map((connection) => ({ + connectedAt: connection.connectedAt, + credentialKind: connection.credentialKind, + id: String(connection._id), + provider: connection.provider, + serverUrl: connection.serverUrl, + username: connection.username, + })); + }, +}); + +export const getForProject = query({ + args: { projectId: v.id("projects") }, + handler: async (ctx, args) => { + await requireProjectMember(ctx, args.projectId); + const project = await ctx.db.get(args.projectId); + const connection = project?.gitConnectionId + ? await ctx.db.get(project.gitConnectionId) + : null; + return connection + ? { + connectedAt: connection.connectedAt, + credentialKind: connection.credentialKind, + id: String(connection._id), + provider: connection.provider, + serverUrl: connection.serverUrl, + username: connection.username, + } + : null; + }, +}); + +export const attachToProject = mutation({ + args: { + connectionId: v.id("gitConnections"), + projectId: v.id("projects"), + }, + handler: async (ctx, args) => { + const { organizationId } = await requireProjectMember(ctx, args.projectId); + const connection = await ctx.db.get(args.connectionId); + if (!connection || connection.organizationId !== organizationId) { + throw new ConvexError("Git connection not found"); + } + await ctx.db.patch(args.projectId, { + gitConnectionId: connection._id, + updatedAt: Date.now(), + }); + return { attached: true }; + }, +}); diff --git a/packages/backend/convex/gitConnections.ts b/packages/backend/convex/gitConnections.ts new file mode 100644 index 0000000..181f5a2 --- /dev/null +++ b/packages/backend/convex/gitConnections.ts @@ -0,0 +1,124 @@ +"use node"; + +import { env } from "@code/env/convex"; +import { decodeGitConnectionInput } from "@code/primitives/execution-runtime"; +import { ConvexError, v } from "convex/values"; +import { Effect } from "effect"; + +import { internal } from "./_generated/api"; +import type { Id } from "./_generated/dataModel"; +import { action } from "./_generated/server"; +import { authComponent, createAuth } from "./auth"; + +const encryptionKey = async (): Promise => { + if (!env.GIT_CREDENTIAL_ENCRYPTION_KEY) { + throw new ConvexError("Git credential encryption is not configured"); + } + const bytes = Buffer.from(env.GIT_CREDENTIAL_ENCRYPTION_KEY, "base64url"); + if (bytes.byteLength !== 32) { + throw new ConvexError("Git credential encryption key must be 32 bytes"); + } + return await crypto.subtle.importKey("raw", bytes, "AES-GCM", false, [ + "encrypt", + "decrypt", + ]); +}; + +const encryptCredential = async (credential: string) => { + const iv = crypto.getRandomValues(new Uint8Array(12)); + const encrypted = await crypto.subtle.encrypt( + { iv, name: "AES-GCM" }, + await encryptionKey(), + new TextEncoder().encode(credential) + ); + return { + credentialCiphertext: Buffer.from(encrypted).toString("base64url"), + credentialIv: Buffer.from(iv).toString("base64url"), + }; +}; + +export const decryptCredential = async ( + credentialCiphertext: string, + credentialIv: string +): Promise => { + const decrypted = await crypto.subtle.decrypt( + { + iv: Buffer.from(credentialIv, "base64url"), + name: "AES-GCM", + }, + await encryptionKey(), + Buffer.from(credentialCiphertext, "base64url") + ); + return new TextDecoder().decode(decrypted); +}; + +export const connectGitea = action({ + args: { + serverUrl: v.string(), + token: v.string(), + username: v.optional(v.string()), + }, + handler: async ( + ctx, + args + ): Promise<{ connectionId: Id<"gitConnections"> }> => { + const userId = await ctx.auth.getUserIdentity().then((identity) => { + if (!identity) { + throw new ConvexError("Authentication required"); + } + return identity.tokenIdentifier; + }); + const connection = await Effect.runPromise( + decodeGitConnectionInput({ + credential: args.token, + credentialKind: "token", + provider: "gitea", + serverUrl: args.serverUrl, + username: args.username, + }) + ); + const encrypted = await encryptCredential(connection.credential); + const connectionId = await ctx.runMutation( + internal.gitConnectionData.persist, + { + ...encrypted, + credentialKind: connection.credentialKind, + provider: connection.provider, + serverUrl: connection.serverUrl, + userId, + username: connection.username, + } + ); + return { connectionId }; + }, +}); + +export const connectGithub = action({ + args: {}, + handler: async (ctx): Promise<{ connectionId: Id<"gitConnections"> }> => { + const identity = await ctx.auth.getUserIdentity(); + if (!identity) { + throw new ConvexError("Authentication required"); + } + const { auth, headers } = await authComponent.getAuth(createAuth, ctx); + const token = await auth.api.getAccessToken({ + body: { providerId: "github" }, + headers, + }); + if (!token.accessToken) { + throw new ConvexError("GitHub account is not connected"); + } + const encrypted = await encryptCredential(token.accessToken); + const connectionId = await ctx.runMutation( + internal.gitConnectionData.persist, + { + ...encrypted, + credentialKind: "oauth", + provider: "github", + serverUrl: "https://github.com", + userId: identity.tokenIdentifier, + } + ); + return { connectionId }; + }, +}); diff --git a/packages/backend/convex/schema.ts b/packages/backend/convex/schema.ts index b5d7031..d0395bf 100644 --- a/packages/backend/convex/schema.ts +++ b/packages/backend/convex/schema.ts @@ -44,10 +44,28 @@ export default defineSchema({ .index("by_userId", ["userId"]) .index("by_organizationId", ["organizationId"]) .index("by_organizationId_and_userId", ["organizationId", "userId"]), + gitConnections: defineTable({ + connectedAt: v.number(), + credentialCiphertext: v.string(), + credentialIv: v.string(), + credentialKind: v.union(v.literal("oauth"), v.literal("token")), + organizationId: v.id("organizations"), + provider: v.union(v.literal("github"), v.literal("gitea")), + serverUrl: v.string(), + updatedAt: v.number(), + username: v.optional(v.string()), + }) + .index("by_organizationId", ["organizationId"]) + .index("by_organizationId_and_provider_and_serverUrl", [ + "organizationId", + "provider", + "serverUrl", + ]), projects: defineTable({ createdAt: v.number(), defaultBranch: v.optional(v.string()), description: v.optional(v.string()), + gitConnectionId: v.optional(v.id("gitConnections")), name: v.string(), normalizedSourceUrl: v.string(), organizationId: v.id("organizations"), @@ -314,11 +332,17 @@ export default defineSchema({ ]), workRuns: defineTable({ + baseRevision: v.optional(v.string()), + candidateRevision: v.optional(v.string()), createdAt: v.number(), designVersion: v.optional(v.number()), endedAt: v.optional(v.number()), kitId: v.string(), kitVersion: v.string(), + environmentId: v.optional(v.string()), + executionKind: v.optional( + v.union(v.literal("simulated"), v.literal("real")) + ), scenario: v.union( v.literal("success"), v.literal("transient-failure-then-success"), @@ -337,6 +361,7 @@ export default defineSchema({ ), terminalClassification: v.optional(attemptClassification), terminalSummary: v.optional(v.string()), + workflowId: v.optional(v.string()), workId: v.id("works"), }).index("by_work_and_createdAt", ["workId", "createdAt"]), @@ -356,6 +381,7 @@ export default defineSchema({ ), summary: v.optional(v.string()), workId: v.id("works"), + workspaceKey: v.optional(v.string()), }) .index("by_runId_and_number", ["runId", "number"]) .index("by_status_and_leaseExpiresAt", ["status", "leaseExpiresAt"]), diff --git a/packages/backend/convex/workExecutionAgent.ts b/packages/backend/convex/workExecutionAgent.ts new file mode 100644 index 0000000..f198c51 --- /dev/null +++ b/packages/backend/convex/workExecutionAgent.ts @@ -0,0 +1,80 @@ +"use node"; + +import { env } from "@code/env/convex"; +import { decodeWorkAttemptExecutionResult } from "@code/primitives/execution-runtime"; +import { ConvexError, v } from "convex/values"; +import { Effect } from "effect"; + +import { internal } from "./_generated/api"; +import { internalAction } from "./_generated/server"; +import { decryptCredential } from "./gitConnections"; + +const backendUrl = () => env.AGENT_BACKEND_URL ?? env.FLUE_URL; + +export const executeAttempt = internalAction({ + args: { attemptId: v.id("workAttempts") }, + handler: async (ctx, args) => { + const running = await ctx.runMutation( + internal.workExecutionWorkflow.markAttemptRunning, + args + ); + if (!running) { + throw new ConvexError("Attempt is no longer runnable"); + } + const context = await ctx.runQuery( + internal.workExecutionWorkflow.executionContext, + args + ); + const credential = await decryptCredential( + context.connection.credentialCiphertext, + context.connection.credentialIv + ); + const response = await fetch( + `${backendUrl()}/internal/work-attempts/execute`, + { + body: JSON.stringify({ + attemptId: String(context.attempt._id), + auth: { + credential, + provider: context.connection.provider, + serverUrl: context.connection.serverUrl, + username: context.connection.username, + }, + baseBranch: context.project.defaultBranch ?? "main", + prompt: context.prompt, + repositoryUrl: context.project.sourceUrl, + runId: String(context.run._id), + workId: String(context.work._id), + workspaceKey: context.attempt.workspaceKey, + }), + headers: { + authorization: `Bearer ${env.FLUE_DB_TOKEN}`, + "content-type": "application/json", + }, + method: "POST", + } + ); + const payload = (await response.json()) as unknown; + if (!response.ok) { + throw new ConvexError( + typeof payload === "object" && payload && "error" in payload + ? String(payload.error) + : `Agent backend returned ${response.status}` + ); + } + return await Effect.runPromise(decodeWorkAttemptExecutionResult(payload)); + }, +}); + +export const cancelAttempt = internalAction({ + args: { workspaceKey: v.string() }, + handler: async (_ctx, args) => { + await fetch( + `${backendUrl()}/internal/work-attempts/${encodeURIComponent(args.workspaceKey)}/cancel`, + { + headers: { authorization: `Bearer ${env.FLUE_DB_TOKEN}` }, + method: "POST", + } + ); + }, +}); diff --git a/packages/backend/convex/workExecutionWorkflow.test.ts b/packages/backend/convex/workExecutionWorkflow.test.ts new file mode 100644 index 0000000..9c604df --- /dev/null +++ b/packages/backend/convex/workExecutionWorkflow.test.ts @@ -0,0 +1,111 @@ +import { convexTest } from "convex-test"; +import { anyApi } from "convex/server"; +import { describe, expect, test } from "vitest"; + +import schema from "./schema"; + +const modules = import.meta.glob("./**/*.ts"); +const api = anyApi; + +describe("real work execution persistence", () => { + test("records revisions, activity, diff, and terminal state atomically", async () => { + const t = convexTest({ modules, schema }); + const seeded = await t.run(async (ctx) => { + const organizationId = await ctx.db.insert("organizations", { + createdAt: 1, + createdBy: "user", + kind: "personal", + name: "Personal", + }); + const projectId = await ctx.db.insert("projects", { + createdAt: 1, + name: "Zopu", + normalizedSourceUrl: "https://example.com/zopu", + organizationId, + repositoryPath: "puter/zopu", + sourceHost: "example.com", + sourceUrl: "https://example.com/zopu", + updatedAt: 1, + }); + const workId = await ctx.db.insert("works", { + createdAt: 1, + objective: "Implement a real slice", + organizationId, + projectId, + status: "executing", + title: "Real execution", + updatedAt: 1, + }); + const sliceRowId = await ctx.db.insert("workSlices", { + designVersion: 1, + objective: "Change the repo", + observableBehavior: "A diff exists", + ordinal: 0, + payloadJson: "{}", + sliceId: "slice-1", + status: "running", + title: "Implementation", + workId, + }); + const runId = await ctx.db.insert("workRuns", { + createdAt: 1, + designVersion: 1, + executionKind: "real", + kitId: "coding-v0", + kitVersion: "1", + scenario: "success", + sliceId: "slice-1", + sliceRowId, + status: "running", + workId, + }); + const attemptId = await ctx.db.insert("workAttempts", { + number: 1, + runId, + status: "running", + workId, + workspaceKey: "workspace-1", + }); + return { attemptId, runId, workId }; + }); + + await t.mutation(api.workExecutionWorkflow.completeAttempt, { + attemptId: seeded.attemptId, + result: { + baseRevision: "base123", + candidateRevision: "candidate456", + changedFiles: ["src/index.ts"], + diff: "+export const ready = true;", + environmentId: "workspace-1", + events: [ + { + kind: "runtime.completed", + message: "completed", + metadata: {}, + occurredAt: 2, + sequence: 0, + }, + ], + summary: "Changed one file", + }, + }); + + const state = await t.run(async (ctx) => ({ + artifacts: await ctx.db.query("workArtifacts").collect(), + attempt: await ctx.db.get(seeded.attemptId), + run: await ctx.db.get(seeded.runId), + work: await ctx.db.get(seeded.workId), + })); + expect(state.attempt?.classification).toBe("Succeeded"); + expect(state.run).toMatchObject({ + baseRevision: "base123", + candidateRevision: "candidate456", + terminalClassification: "Succeeded", + }); + expect(state.work?.status).toBe("completed"); + expect(state.artifacts[0]).toMatchObject({ + kind: "diff", + sourceRevision: "candidate456", + }); + }); +}); diff --git a/packages/backend/convex/workExecutionWorkflow.ts b/packages/backend/convex/workExecutionWorkflow.ts new file mode 100644 index 0000000..2ba2909 --- /dev/null +++ b/packages/backend/convex/workExecutionWorkflow.ts @@ -0,0 +1,403 @@ +import { defaultCodingKitV0 } from "@code/primitives/resolver"; +import { WorkflowManager } from "@convex-dev/workflow"; +import type { WorkflowId } from "@convex-dev/workflow"; +import { ConvexError, v } from "convex/values"; + +import { components, internal } from "./_generated/api"; +import type { Doc, Id } from "./_generated/dataModel"; +import { internalMutation, internalQuery, mutation } from "./_generated/server"; +import type { MutationCtx } from "./_generated/server"; +import { requireProjectMember } from "./authz"; + +export const workflow = new WorkflowManager(components.workflow); + +const resolveReadySlice = async ( + ctx: MutationCtx, + work: Doc<"works">, + sliceId?: string +) => { + if (work.designVersion === undefined) { + throw new ConvexError("Work has no approved Design to execute"); + } + const slices = await ctx.db + .query("workSlices") + .withIndex("by_workId_and_designVersion", (q) => + q.eq("workId", work._id).eq("designVersion", work.designVersion!) + ) + .collect(); + const slice = sliceId + ? slices.find((candidate) => candidate.sliceId === sliceId) + : slices + .sort((left, right) => left.ordinal - right.ordinal) + .find((candidate) => candidate.status === "ready"); + if (!slice || slice.status !== "ready") { + throw new ConvexError("Only the next ready slice can be executed"); + } + return slice; +}; + +export const execute = workflow + .define({ args: { attemptId: v.id("workAttempts") } }) + .handler(async (step, args): Promise => { + try { + const result = await step.runAction( + internal.workExecutionAgent.executeAttempt, + args, + { retry: true } + ); + await step.runMutation(internal.workExecutionWorkflow.completeAttempt, { + attemptId: args.attemptId, + result: { + ...result, + changedFiles: [...result.changedFiles], + events: result.events.map((item) => ({ + ...item, + metadata: { ...item.metadata }, + })), + }, + }); + } catch (error) { + await step.runMutation(internal.workExecutionWorkflow.failAttempt, { + attemptId: args.attemptId, + summary: error instanceof Error ? error.message : "Execution failed", + }); + } + }); + +export const startExecution = mutation({ + args: { + sliceId: v.optional(v.string()), + workId: v.id("works"), + }, + handler: async ( + ctx, + args + ): Promise<{ + attemptId: Id<"workAttempts">; + runId: Id<"workRuns">; + workflowId: WorkflowId; + }> => { + const work = await ctx.db.get(args.workId); + if (!work) { + throw new ConvexError("Work not found"); + } + await requireProjectMember(ctx, work.projectId); + if (work.status !== "ready") { + throw new ConvexError("Work must be Ready before execution"); + } + if ( + work.definitionApprovalVersion !== work.definitionVersion || + work.designApprovalVersion !== work.designVersion + ) { + throw new ConvexError("Execution requires exact approved versions"); + } + const project = await ctx.db.get(work.projectId); + if (!project?.gitConnectionId) { + throw new ConvexError("Connect Git credentials to this project first"); + } + const slice = await resolveReadySlice(ctx, work, args.sliceId); + const createdAt = Date.now(); + const runId = await ctx.db.insert("workRuns", { + createdAt, + designVersion: slice.designVersion, + executionKind: "real", + kitId: defaultCodingKitV0.id, + kitVersion: defaultCodingKitV0.version, + scenario: "success", + sliceId: slice.sliceId, + sliceRowId: slice._id, + status: "running", + workId: work._id, + }); + const workspaceKey = `work-${work._id}-run-${runId}`; + const attemptId = await ctx.db.insert("workAttempts", { + number: 1, + runId, + status: "queued", + workId: work._id, + workspaceKey, + }); + const workflowId: WorkflowId = await workflow.start( + ctx, + internal.workExecutionWorkflow.execute, + { attemptId } + ); + await ctx.db.patch(runId, { startedAt: createdAt, workflowId }); + await ctx.db.patch(slice._id, { status: "running" }); + await ctx.db.patch(work._id, { status: "executing", updatedAt: createdAt }); + await ctx.db.insert("workEvents", { + createdAt, + idempotencyKey: `real-run-started:${runId}`, + kind: "run.started", + referenceId: String(runId), + workId: work._id, + }); + return { attemptId, runId, workflowId }; + }, +}); + +export const executionContext = internalQuery({ + args: { attemptId: v.id("workAttempts") }, + handler: async (ctx, args) => { + const attempt = await ctx.db.get(args.attemptId); + if (!attempt) { + throw new ConvexError("Attempt not found"); + } + const run = await ctx.db.get(attempt.runId); + const work = await ctx.db.get(attempt.workId); + if (!run || !work || !run.sliceRowId) { + throw new ConvexError("Execution records are incomplete"); + } + const [slice, project] = await Promise.all([ + ctx.db.get(run.sliceRowId), + ctx.db.get(work.projectId), + ]); + if (!slice || !project?.gitConnectionId) { + throw new ConvexError("Project execution configuration is incomplete"); + } + const connection = await ctx.db.get(project.gitConnectionId); + if (!connection) { + throw new ConvexError("Git connection not found"); + } + return { + attempt, + connection, + project, + prompt: [ + `Implement this approved Zopu slice: ${slice.title}`, + `Objective: ${slice.objective}`, + `Observable behavior: ${slice.observableBehavior}`, + "Inspect the repository instructions first. Make focused changes and run relevant checks.", + ].join("\n\n"), + run, + work, + }; + }, +}); + +export const markAttemptRunning = internalMutation({ + args: { attemptId: v.id("workAttempts") }, + handler: async (ctx, args) => { + const attempt = await ctx.db.get(args.attemptId); + if (!attempt || attempt.status !== "queued") { + return false; + } + await ctx.db.patch(attempt._id, { + startedAt: Date.now(), + status: "running", + }); + return true; + }, +}); + +const settleSliceAndWork = async ( + ctx: MutationCtx, + run: Doc<"workRuns">, + succeeded: boolean +) => { + if (!run.sliceRowId) { + return; + } + const slice = await ctx.db.get(run.sliceRowId); + if (!slice) { + return; + } + await ctx.db.patch(slice._id, { status: succeeded ? "completed" : "ready" }); + const work = await ctx.db.get(run.workId); + if (!work) { + return; + } + let status: Doc<"works">["status"] = succeeded ? "completed" : "failed"; + if (succeeded) { + const slices = await ctx.db + .query("workSlices") + .withIndex("by_workId_and_designVersion", (q) => + q.eq("workId", work._id).eq("designVersion", slice.designVersion) + ) + .collect(); + const next = slices + .sort((left, right) => left.ordinal - right.ordinal) + .find((candidate) => candidate.status === "planned"); + if (next) { + await ctx.db.patch(next._id, { status: "ready" }); + status = "ready"; + } + } + await ctx.db.patch(work._id, { status, updatedAt: Date.now() }); +}; + +export const completeAttempt = internalMutation({ + args: { + attemptId: v.id("workAttempts"), + result: v.object({ + baseRevision: v.string(), + candidateRevision: v.string(), + changedFiles: v.array(v.string()), + diff: v.string(), + environmentId: v.string(), + events: v.array( + v.object({ + kind: v.string(), + message: v.string(), + metadata: v.record(v.string(), v.string()), + occurredAt: v.number(), + sequence: v.number(), + }) + ), + summary: v.string(), + }), + }, + handler: async (ctx, args) => { + const attempt = await ctx.db.get(args.attemptId); + if (!attempt || attempt.status === "terminal") { + return; + } + const run = await ctx.db.get(attempt.runId); + const work = await ctx.db.get(attempt.workId); + if (!run || !work) { + throw new ConvexError("Execution records not found"); + } + for (const item of args.result.events) { + await ctx.db.insert("workAttemptEvents", { + attemptId: attempt._id, + kind: item.kind, + message: item.message, + metadataJson: JSON.stringify(item.metadata), + occurredAt: item.occurredAt, + sequence: item.sequence, + }); + } + const endedAt = Date.now(); + await ctx.db.patch(attempt._id, { + classification: "Succeeded", + endedAt, + status: "terminal", + summary: args.result.summary, + }); + await ctx.db.patch(run._id, { + baseRevision: args.result.baseRevision, + candidateRevision: args.result.candidateRevision, + endedAt, + environmentId: args.result.environmentId, + status: "terminal", + terminalClassification: "Succeeded", + terminalSummary: args.result.summary, + }); + await ctx.db.insert("workArtifacts", { + attemptId: attempt._id, + createdAt: endedAt, + designVersion: run.designVersion, + environmentId: args.result.environmentId, + idempotencyKey: `real-diff:${attempt._id}`, + kind: "diff", + metadataJson: JSON.stringify({ changedFiles: args.result.changedFiles }), + organizationId: work.organizationId, + producer: "agentos-codex", + projectId: work.projectId, + provenanceJson: JSON.stringify({ + baseRevision: args.result.baseRevision, + }), + runId: run._id, + sliceId: run.sliceId, + sourceRevision: args.result.candidateRevision, + title: "Implementation diff", + verificationStatus: "unverified", + workId: work._id, + ...(args.result.diff.length > 0 + ? { + uri: `data:text/plain;charset=utf-8,${encodeURIComponent(args.result.diff.slice(0, 50_000))}`, + } + : {}), + }); + await settleSliceAndWork(ctx, run, true); + await ctx.db.insert("workEvents", { + createdAt: endedAt, + idempotencyKey: `real-run-completed:${run._id}`, + kind: "run.completed", + payloadJson: JSON.stringify({ classification: "Succeeded" }), + referenceId: String(run._id), + workId: work._id, + }); + }, +}); + +export const failAttempt = internalMutation({ + args: { attemptId: v.id("workAttempts"), summary: v.string() }, + handler: async (ctx, args) => { + const attempt = await ctx.db.get(args.attemptId); + if (!attempt || attempt.status === "terminal") { + return; + } + const run = await ctx.db.get(attempt.runId); + if (!run) { + return; + } + const endedAt = Date.now(); + await ctx.db.patch(attempt._id, { + classification: "PermanentFailure", + endedAt, + status: "terminal", + summary: args.summary, + }); + await ctx.db.patch(run._id, { + endedAt, + status: "terminal", + terminalClassification: "PermanentFailure", + terminalSummary: args.summary, + }); + await settleSliceAndWork(ctx, run, false); + }, +}); + +export const cancelExecution = mutation({ + args: { runId: v.id("workRuns") }, + handler: async (ctx, args) => { + const run = await ctx.db.get(args.runId); + if (!run) { + throw new ConvexError("Run not found"); + } + await requireProjectMember(ctx, (await ctx.db.get(run.workId))!.projectId); + if (run.status !== "running") { + return { cancelled: false }; + } + if (run.workflowId) { + await workflow.cancel(ctx, run.workflowId as WorkflowId); + } + const attempts = await ctx.db + .query("workAttempts") + .withIndex("by_runId_and_number", (q) => q.eq("runId", run._id)) + .collect(); + const attempt = attempts.find( + (candidate) => candidate.status !== "terminal" + ); + if (attempt?.workspaceKey) { + await ctx.scheduler.runAfter( + 0, + internal.workExecutionAgent.cancelAttempt, + { + workspaceKey: attempt.workspaceKey, + } + ); + await ctx.db.patch(attempt._id, { + classification: "Cancelled", + endedAt: Date.now(), + status: "terminal", + summary: "Execution cancelled", + }); + } + await ctx.db.patch(run._id, { + endedAt: Date.now(), + status: "cancelled", + terminalClassification: "Cancelled", + terminalSummary: "Execution cancelled", + }); + if (run.sliceRowId) { + await ctx.db.patch(run.sliceRowId, { status: "ready" }); + } + const work = await ctx.db.get(run.workId); + if (work) { + await ctx.db.patch(work._id, { status: "ready", updatedAt: Date.now() }); + } + return { cancelled: true }; + }, +}); diff --git a/packages/backend/convex/workPlanning.ts b/packages/backend/convex/workPlanning.ts index 1621692..876a00e 100644 --- a/packages/backend/convex/workPlanning.ts +++ b/packages/backend/convex/workPlanning.ts @@ -771,13 +771,41 @@ export const listForProject = query({ .eq("designVersion", work.designVersion ?? 0) ) .collect(); - const runs = await ctx.db + const runRows = await ctx.db .query("workRuns") .withIndex("by_work_and_createdAt", (q: any) => q.eq("workId", work._id) ) .order("desc") .take(10); + const runs = await Promise.all( + runRows.map(async (run) => { + const attempts = await ctx.db + .query("workAttempts") + .withIndex("by_runId_and_number", (q) => q.eq("runId", run._id)) + .collect(); + const eventsByAttempt = await Promise.all( + attempts.map((attempt) => + ctx.db + .query("workAttemptEvents") + .withIndex("by_attempt_and_sequence", (q: any) => + q.eq("attemptId", attempt._id) + ) + .collect() + ) + ); + const attemptEvents = eventsByAttempt + .flat() + .sort((left, right) => left.occurredAt - right.occurredAt); + const artifacts = await ctx.db + .query("workArtifacts") + .withIndex("by_runId_and_createdAt", (q) => + q.eq("runId", run._id) + ) + .collect(); + return { ...run, artifacts, attemptEvents, attempts }; + }) + ); const events = await ctx.db .query("workEvents") .withIndex("by_work_and_createdAt", (q: any) => diff --git a/packages/backend/package.json b/packages/backend/package.json index e2ccb13..7bed8f6 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -16,6 +16,7 @@ "@code/env": "workspace:*", "@code/primitives": "workspace:*", "@convex-dev/better-auth": "catalog:", + "@convex-dev/workflow": "0.4.4", "better-auth": "catalog:", "convex": "catalog:", "effect": "catalog:", diff --git a/packages/env/src/agent.ts b/packages/env/src/agent.ts index 7c8180b..2d39051 100644 --- a/packages/env/src/agent.ts +++ b/packages/env/src/agent.ts @@ -14,6 +14,8 @@ const agentEnvSchema = z.object({ GITEA_TOKEN: z.string().min(1).optional(), GITEA_URL: z.url().default("https://git.openputer.com"), OPENROUTER_API_KEY: z.string().min(1).optional(), + RIVET_ENDPOINT: z.url(), + RIVET_PUBLIC_ENDPOINT: z.url().optional(), }); export type AgentEnv = z.infer; diff --git a/packages/env/src/convex.ts b/packages/env/src/convex.ts index f5ae653..0f08968 100644 --- a/packages/env/src/convex.ts +++ b/packages/env/src/convex.ts @@ -5,10 +5,15 @@ export const env = createEnv({ emptyStringAsUndefined: true, runtimeEnv: process.env, server: { + AGENT_BACKEND_URL: z.url().optional(), CONVEX_SITE_URL: z.url(), FLUE_DB_TOKEN: z.string().min(1), + FLUE_URL: z.url().optional(), GITEA_TOKEN: z.string().min(1).optional(), GITEA_URL: z.url().default("https://git.openputer.com"), + GITHUB_CLIENT_ID: z.string().min(1).optional(), + GITHUB_CLIENT_SECRET: z.string().min(1).optional(), + GIT_CREDENTIAL_ENCRYPTION_KEY: z.string().min(43).optional(), NATIVE_APP_URL: z.string().min(1).default("code://"), SITE_URL: z.url(), }, diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 18c9196..63e63a8 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -6,6 +6,7 @@ "exports": { ".": "./src/index.ts", "./agent-os": "./src/agent-os.ts", + "./execution-runtime": "./src/execution-runtime.ts", "./git": "./src/git.ts", "./git-local-runtime": "./src/git-local-runtime.ts", "./git-remote-runtime": "./src/git-remote-runtime.ts", diff --git a/packages/primitives/src/execution-runtime.test.ts b/packages/primitives/src/execution-runtime.test.ts new file mode 100644 index 0000000..c682997 --- /dev/null +++ b/packages/primitives/src/execution-runtime.test.ts @@ -0,0 +1,38 @@ +import { Effect } from "effect"; +import { describe, expect, test } from "vitest"; + +import { + decodeGitConnectionInput, + decodeWorkAttemptExecutionResult, +} from "./execution-runtime"; + +describe("execution runtime contracts", () => { + test("accepts one authenticated Gitea connection", async () => { + const decoded = await Effect.runPromise( + decodeGitConnectionInput({ + credential: "secret", + credentialKind: "token", + provider: "gitea", + serverUrl: "https://git.example.com", + username: "zopu", + }) + ); + expect(decoded.provider).toBe("gitea"); + }); + + test("requires exact base and candidate revisions", async () => { + await expect( + Effect.runPromise( + decodeWorkAttemptExecutionResult({ + baseRevision: "", + candidateRevision: "abc123", + changedFiles: [], + diff: "", + environmentId: "workspace-1", + events: [], + summary: "done", + }) + ) + ).rejects.toMatchObject({ reason: "InvalidInput" }); + }); +}); diff --git a/packages/primitives/src/execution-runtime.ts b/packages/primitives/src/execution-runtime.ts new file mode 100644 index 0000000..e724517 --- /dev/null +++ b/packages/primitives/src/execution-runtime.ts @@ -0,0 +1,155 @@ +/* eslint-disable max-classes-per-file -- execution boundary errors live with their schemas. */ +import { Effect, Schema } from "effect"; + +const Text = Schema.String.check( + Schema.makeFilter((value) => value.trim().length > 0, { + expected: "a non-empty string", + }) +); + +const HttpUrl = Schema.String.check( + Schema.makeFilter( + (value) => { + try { + const url = new URL(value); + return url.protocol === "http:" || url.protocol === "https:"; + } catch { + return false; + } + }, + { expected: "an HTTP URL" } + ) +); + +export const GitProvider = Schema.Literals(["github", "gitea"]); +export type GitProvider = typeof GitProvider.Type; + +export const GitCredentialKind = Schema.Literals(["oauth", "token"]); +export type GitCredentialKind = typeof GitCredentialKind.Type; + +export const GitConnectionInput = Schema.Struct({ + credential: Text, + credentialKind: GitCredentialKind, + provider: GitProvider, + serverUrl: HttpUrl, + username: Schema.optional(Text), +}); +export type GitConnectionInput = typeof GitConnectionInput.Type; + +export const GitConnectionView = Schema.Struct({ + connectedAt: Schema.Number, + credentialKind: GitCredentialKind, + id: Text, + provider: GitProvider, + serverUrl: HttpUrl, + username: Schema.optional(Text), +}); +export type GitConnectionView = typeof GitConnectionView.Type; + +export const RepositoryExecutionAuth = Schema.Struct({ + credential: Text, + provider: GitProvider, + serverUrl: HttpUrl, + username: Schema.optional(Text), +}); +export type RepositoryExecutionAuth = typeof RepositoryExecutionAuth.Type; + +export const ExecutionEventKind = Schema.Literals([ + "runtime.preparing", + "repository.cloning", + "repository.ready", + "harness.started", + "harness.progress", + "harness.log", + "repository.changed", + "runtime.completed", + "runtime.failed", + "runtime.cancelled", +]); +export type ExecutionEventKind = typeof ExecutionEventKind.Type; + +export const ExecutionEvent = Schema.Struct({ + kind: ExecutionEventKind, + message: Text, + metadata: Schema.Record(Schema.String, Schema.String), + occurredAt: Schema.Number, + sequence: Schema.Int, +}); +export type ExecutionEvent = typeof ExecutionEvent.Type; + +export const WorkAttemptExecutionInput = Schema.Struct({ + attemptId: Text, + auth: RepositoryExecutionAuth, + baseBranch: Text, + prompt: Text, + repositoryUrl: HttpUrl, + runId: Text, + workId: Text, + workspaceKey: Text, +}); +export type WorkAttemptExecutionInput = typeof WorkAttemptExecutionInput.Type; + +export const WorkAttemptExecutionResult = Schema.Struct({ + baseRevision: Text, + candidateRevision: Text, + changedFiles: Schema.Array(Text), + diff: Schema.String, + environmentId: Text, + events: Schema.Array(ExecutionEvent), + summary: Text, +}); +export type WorkAttemptExecutionResult = typeof WorkAttemptExecutionResult.Type; + +export const WorkAttemptExecutionErrorReason = Schema.Literals([ + "Authentication", + "Cancelled", + "HarnessFailed", + "InvalidInput", + "ProviderUnavailable", + "RepositoryFailed", + "Timeout", +]); +export type WorkAttemptExecutionErrorReason = + typeof WorkAttemptExecutionErrorReason.Type; + +export class WorkAttemptExecutionError extends Schema.TaggedErrorClass()( + "WorkAttemptExecutionError", + { + message: Schema.String, + reason: WorkAttemptExecutionErrorReason, + retryable: Schema.Boolean, + } +) {} + +const invalidInput = (message: string) => + new WorkAttemptExecutionError({ + message, + reason: "InvalidInput", + retryable: false, + }); + +export const decodeGitConnectionInput = (input: unknown) => + Schema.decodeUnknownEffect(GitConnectionInput)(input).pipe( + Effect.mapError((cause) => invalidInput(cause.message)) + ); + +export const decodeWorkAttemptExecutionInput = (input: unknown) => + Schema.decodeUnknownEffect(WorkAttemptExecutionInput)(input).pipe( + Effect.mapError((cause) => invalidInput(cause.message)) + ); + +export const decodeWorkAttemptExecutionResult = (input: unknown) => + Schema.decodeUnknownEffect(WorkAttemptExecutionResult)(input).pipe( + Effect.mapError((cause) => invalidInput(cause.message)) + ); + +export interface SandboxRuntime { + readonly name: string; + readonly execute: ( + input: WorkAttemptExecutionInput, + signal?: AbortSignal + ) => Effect.Effect; + readonly cancel: ( + workspaceKey: string + ) => Effect.Effect; +} diff --git a/packages/primitives/src/index.ts b/packages/primitives/src/index.ts index bce942f..e97417d 100644 --- a/packages/primitives/src/index.ts +++ b/packages/primitives/src/index.ts @@ -1,5 +1,6 @@ // oxlint-disable-next-line no-barrel-file -- The package root intentionally exposes its public modules. export * from "./agent-os"; +export * from "./execution-runtime"; export * from "./git"; export * from "./git-local-runtime"; export * from "./git-remote-runtime";