CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
0069_hosted_claude_loops.sql
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| c6db5ee | 1 | -- Gluecron migration 0069: hosted Claude tool-use loops. |
| 2 | -- | |
| 3 | -- Users paste a Claude-flavoured tool-use loop at /connect/claude/deploy, | |
| 4 | -- pick a budget cap, and get back a hosted endpoint that runs the code in | |
| 5 | -- a sandboxed Bun subprocess on demand. Each loop is paired to an | |
| 6 | -- agent_sessions row so it inherits multiplayer namespacing + the daily | |
| 7 | -- budget mutex from src/lib/agent-multiplayer.ts. | |
| 8 | -- | |
| 9 | -- hosted_claude_loops — one row per deployed loop | |
| 10 | -- hosted_claude_loop_runs — one row per invocation | |
| 11 | -- | |
| 12 | -- Wrapped in DO blocks so the migration is safe to re-run and degrades | |
| 13 | -- gracefully when (e.g.) the agent_sessions table is missing on a partial | |
| 14 | -- replay. Helpers in src/lib/hosted-claude-loop.ts already return null / | |
| 15 | -- empty when these tables are absent. | |
| 16 | ||
| 17 | --> statement-breakpoint | |
| 18 | DO $$ | |
| 19 | BEGIN | |
| 20 | CREATE TABLE IF NOT EXISTS "hosted_claude_loops" ( | |
| 21 | "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(), | |
| 22 | "owner_user_id" uuid NOT NULL REFERENCES "users"("id") ON DELETE CASCADE, | |
| 23 | "name" text NOT NULL, | |
| 24 | "source_code" text NOT NULL, | |
| 25 | "endpoint_path" text NOT NULL UNIQUE, | |
| 26 | "agent_session_id" uuid REFERENCES "agent_sessions"("id") ON DELETE SET NULL, | |
| 27 | "status" text NOT NULL DEFAULT 'paused', | |
| 28 | "is_public" boolean NOT NULL DEFAULT false, | |
| 29 | "monthly_budget_cents" integer NOT NULL DEFAULT 500, | |
| 30 | "last_run_at" timestamptz, | |
| 31 | "total_invocations" integer NOT NULL DEFAULT 0, | |
| 32 | "total_cents_spent" integer NOT NULL DEFAULT 0, | |
| 33 | "created_at" timestamptz NOT NULL DEFAULT now(), | |
| 34 | "updated_at" timestamptz NOT NULL DEFAULT now() | |
| 35 | ); | |
| 36 | EXCEPTION WHEN OTHERS THEN | |
| 37 | RAISE NOTICE 'hosted_claude_loops create failed (%); /connect/claude/deploy will degrade to empty', SQLERRM; | |
| 38 | END $$; | |
| 39 | ||
| 40 | --> statement-breakpoint | |
| 41 | DO $$ | |
| 42 | BEGIN | |
| 43 | CREATE INDEX IF NOT EXISTS "hosted_claude_loops_owner" | |
| 44 | ON "hosted_claude_loops" ("owner_user_id", "updated_at" DESC); | |
| 45 | EXCEPTION WHEN OTHERS THEN | |
| 46 | RAISE NOTICE 'hosted_claude_loops_owner index failed (%)', SQLERRM; | |
| 47 | END $$; | |
| 48 | ||
| 49 | --> statement-breakpoint | |
| 50 | DO $$ | |
| 51 | BEGIN | |
| 52 | CREATE INDEX IF NOT EXISTS "hosted_claude_loops_status" | |
| 53 | ON "hosted_claude_loops" ("status"); | |
| 54 | EXCEPTION WHEN OTHERS THEN | |
| 55 | RAISE NOTICE 'hosted_claude_loops_status index failed (%)', SQLERRM; | |
| 56 | END $$; | |
| 57 | ||
| 58 | --> statement-breakpoint | |
| 59 | DO $$ | |
| 60 | BEGIN | |
| 61 | CREATE TABLE IF NOT EXISTS "hosted_claude_loop_runs" ( | |
| 62 | "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(), | |
| 63 | "loop_id" uuid NOT NULL REFERENCES "hosted_claude_loops"("id") ON DELETE CASCADE, | |
| 64 | "input_payload" jsonb NOT NULL DEFAULT '{}'::jsonb, | |
| 65 | "output_payload" jsonb, | |
| 66 | "stdout" text, | |
| 67 | "stderr" text, | |
| 68 | "started_at" timestamptz NOT NULL DEFAULT now(), | |
| 69 | "finished_at" timestamptz, | |
| 70 | "status" text NOT NULL DEFAULT 'running', | |
| 71 | "cents_estimate" integer NOT NULL DEFAULT 0, | |
| 72 | "claude_input_tokens" integer NOT NULL DEFAULT 0, | |
| 73 | "claude_output_tokens" integer NOT NULL DEFAULT 0, | |
| 74 | "exit_code" integer, | |
| 75 | "error_message" text, | |
| 76 | "created_at" timestamptz NOT NULL DEFAULT now() | |
| 77 | ); | |
| 78 | EXCEPTION WHEN OTHERS THEN | |
| 79 | RAISE NOTICE 'hosted_claude_loop_runs create failed (%); run history will be unavailable', SQLERRM; | |
| 80 | END $$; | |
| 81 | ||
| 82 | --> statement-breakpoint | |
| 83 | DO $$ | |
| 84 | BEGIN | |
| 85 | CREATE INDEX IF NOT EXISTS "hosted_claude_loop_runs_loop_time" | |
| 86 | ON "hosted_claude_loop_runs" ("loop_id", "started_at" DESC); | |
| 87 | EXCEPTION WHEN OTHERS THEN | |
| 88 | RAISE NOTICE 'hosted_claude_loop_runs_loop_time index failed (%)', SQLERRM; | |
| 89 | END $$; | |
| 90 | ||
| 91 | --> statement-breakpoint | |
| 92 | DO $$ | |
| 93 | BEGIN | |
| 94 | CREATE INDEX IF NOT EXISTS "hosted_claude_loop_runs_status" | |
| 95 | ON "hosted_claude_loop_runs" ("status", "started_at" DESC); | |
| 96 | EXCEPTION WHEN OTHERS THEN | |
| 97 | RAISE NOTICE 'hosted_claude_loop_runs_status index failed (%)', SQLERRM; | |
| 98 | END $$; |