remote-codex 0.11.3 → 0.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/apps/relay-server/dist/index.js +35 -2
- package/apps/supervisor-api/dist/chunk-ZWZQVPDT.js +27893 -0
- package/apps/supervisor-api/dist/index.js +4 -25727
- package/apps/supervisor-api/dist/worker-index.d.ts +2 -0
- package/apps/supervisor-api/dist/worker-index.js +197 -0
- package/apps/supervisor-web/dist/assets/index-CbdWtyx0.js +5 -0
- package/apps/supervisor-web/dist/assets/index-Di1JBevU.css +1 -0
- package/apps/supervisor-web/dist/assets/thread-ui-ICfwCbte.js +3604 -0
- package/apps/supervisor-web/dist/assets/ui-vendor-D1uxdi-d.js +430 -0
- package/apps/supervisor-web/dist/index.html +6 -7
- package/bin/remote-codex.mjs +534 -19
- package/package.json +41 -2
- package/packages/agent-runtime/src/types.ts +2 -1
- package/packages/codex/src/appServerManager.ts +1 -0
- package/packages/codex/src/historyItems.test.ts +45 -0
- package/packages/codex/src/historyItems.ts +22 -0
- package/packages/codex/src/runtimeAdapter.ts +6 -0
- package/packages/codex/src/types.ts +2 -1
- package/packages/db/migrations/0018_control_plane.sql +129 -0
- package/packages/db/migrations/0019_control_plane_projects.sql +19 -0
- package/packages/db/migrations/0020_control_workspace_status.sql +1 -0
- package/packages/db/migrations/0021_control_sandbox_lifecycle_fields.sql +3 -0
- package/packages/db/migrations/0022_control_sandbox_resource_profile.sql +1 -0
- package/packages/db/migrations/0023_control_usage_import_state.sql +18 -0
- package/packages/db/migrations/0024_control_auth.sql +23 -0
- package/packages/db/migrations/0025_control_harness_credentials.sql +29 -0
- package/packages/db/migrations/0026_control_harness_usage_events.sql +27 -0
- package/packages/db/src/schema.ts +305 -1
- package/packages/shared/src/index.ts +32 -0
- package/packages/shared/src/tokens.ts +137 -0
- package/apps/supervisor-web/dist/assets/index-CBIze1VS.css +0 -1
- package/apps/supervisor-web/dist/assets/index-YpGAPjED.js +0 -4
- package/apps/supervisor-web/dist/assets/thread-ui-BEieA99i.css +0 -1
- package/apps/supervisor-web/dist/assets/thread-ui-CF80LEEN.js +0 -3613
- package/apps/supervisor-web/dist/assets/ui-vendor-CW6egZBG.js +0 -430
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remote-codex",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.4",
|
|
4
4
|
"description": "Local web supervisor for Codex workspaces and threads.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -40,17 +40,56 @@
|
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"dev": "concurrently -k -n api,web -c blue,green \"pnpm --filter @remote-codex/supervisor-api dev\" \"pnpm --filter @remote-codex/supervisor-web dev\"",
|
|
43
|
+
"dev:control-plane": "pnpm --filter @remote-codex/control-plane-api dev",
|
|
43
44
|
"dev:stop": "node scripts/stop-dev-servers.mjs",
|
|
44
45
|
"dev:reset": "pnpm dev:stop && pnpm dev",
|
|
46
|
+
"smoke:local-route-token": "tsx scripts/local-route-token-smoke.ts",
|
|
47
|
+
"smoke:local-worker-checkpoint": "tsx scripts/local-worker-checkpoint-smoke.ts",
|
|
48
|
+
"smoke:production-auth": "tsx scripts/local-production-auth-smoke.ts",
|
|
49
|
+
"smoke:harness-admin-contract": "tsx scripts/harness-admin-contract-smoke.ts",
|
|
50
|
+
"smoke:harness-k8s-secret": "tsx scripts/harness-k8s-secret-smoke.ts",
|
|
51
|
+
"smoke:provider-gateway": "tsx scripts/provider-gateway-smoke.ts",
|
|
52
|
+
"smoke:staging-phase-one": "tsx scripts/staging-phase-one-smoke.ts",
|
|
53
|
+
"collect:harness-integration-evidence": "tsx scripts/collect-harness-integration-evidence.ts",
|
|
54
|
+
"collect:aws-staging-preflight-evidence": "tsx scripts/collect-aws-staging-preflight-evidence.ts",
|
|
55
|
+
"collect:phase-zero-six-evidence": "tsx scripts/run-phase-zero-six-staging-evidence.ts",
|
|
56
|
+
"verify:aws-staging-preflight-evidence": "tsx scripts/verify-aws-staging-preflight-evidence.ts",
|
|
57
|
+
"verify:staging-phase-one-evidence": "tsx scripts/verify-staging-phase-one-evidence.ts",
|
|
58
|
+
"verify:phase-zero-six-env-ready": "tsx scripts/verify-phase-zero-six-env-ready.ts",
|
|
59
|
+
"verify:phase-zero-six-evidence": "tsx scripts/verify-phase-zero-six-evidence.ts",
|
|
60
|
+
"verify:harness-integration-evidence": "tsx scripts/verify-harness-integration-evidence.ts",
|
|
61
|
+
"verify:harness-evidence-review": "tsx scripts/verify-harness-evidence-review.ts",
|
|
62
|
+
"verify:harness-evidence-env": "tsx scripts/verify-harness-evidence-env.ts",
|
|
63
|
+
"verify:phase-zero-six-artifacts-safe": "tsx scripts/verify-phase-zero-six-artifacts-safe.ts",
|
|
64
|
+
"verify:github-staging-evidence-env": "tsx scripts/verify-github-staging-evidence-env.ts",
|
|
65
|
+
"phase-zero-six:env": "pnpm verify:phase-zero-six-env-ready",
|
|
66
|
+
"phase-zero-six:env:aws": "pnpm verify:phase-zero-six-env-ready -- --skip-staging-smoke",
|
|
67
|
+
"phase-zero-six:env:report": "pnpm verify:phase-zero-six-env-ready -- --format text --no-fail",
|
|
68
|
+
"phase-zero-six:env:aws:report": "pnpm verify:phase-zero-six-env-ready -- --skip-staging-smoke --format text --no-fail",
|
|
69
|
+
"phase-zero-six:template": "pnpm verify:phase-zero-six-env-ready -- --write-env-template ./.temp/phase-zero-six-evidence/phase-zero-six.env.sh",
|
|
70
|
+
"phase-zero-six:template:aws": "pnpm verify:phase-zero-six-env-ready -- --skip-staging-smoke --write-env-template ./.temp/phase-zero-six-evidence/aws-preflight.env.sh",
|
|
71
|
+
"phase-zero-six:collect": "pnpm collect:phase-zero-six-evidence -- --output-dir ./.temp/phase-zero-six-evidence/latest",
|
|
72
|
+
"phase-zero-six:collect:aws": "pnpm collect:phase-zero-six-evidence -- --output-dir ./.temp/phase-zero-six-evidence/latest-aws --skip-staging-smoke",
|
|
73
|
+
"phase-zero-six:apply": "pnpm collect:phase-zero-six-evidence -- --from-output-dir ./.temp/phase-zero-six-evidence/latest --output-dir ./.temp/phase-zero-six-evidence/latest-apply --apply-ready",
|
|
74
|
+
"phase-zero-six:apply:aws": "pnpm collect:phase-zero-six-evidence -- --from-output-dir ./.temp/phase-zero-six-evidence/latest-aws --output-dir ./.temp/phase-zero-six-evidence/latest-aws-apply --apply-ready --skip-staging-smoke",
|
|
75
|
+
"phase-zero-six:audit": "pnpm verify:phase-zero-six-evidence",
|
|
76
|
+
"phase-zero-six:audit:report": "pnpm verify:phase-zero-six-evidence -- --format text",
|
|
77
|
+
"phase-zero-six:github-env": "pnpm verify:github-staging-evidence-env",
|
|
78
|
+
"phase-zero-six:github-env:report": "pnpm verify:github-staging-evidence-env -- --format text --no-fail",
|
|
79
|
+
"phase-zero-six:github-env:template": "tsx scripts/configure-github-staging-evidence-env.ts --write-template ./.temp/phase-zero-six-evidence/github-staging.env.sh",
|
|
80
|
+
"phase-zero-six:github-env:configure": "tsx scripts/configure-github-staging-evidence-env.ts",
|
|
45
81
|
"service:start": "node scripts/service-manager.mjs start",
|
|
46
82
|
"service:stop": "node scripts/service-manager.mjs stop",
|
|
47
83
|
"service:status": "node scripts/service-manager.mjs status",
|
|
48
84
|
"service:restart": "node scripts/service-restart.mjs launch",
|
|
49
|
-
"prepack": "pnpm build",
|
|
85
|
+
"prepack": "pnpm build:package",
|
|
50
86
|
"build": "pnpm -r --if-present build",
|
|
87
|
+
"build:package": "pnpm --filter @remote-codex/supervisor-api build && pnpm --filter @remote-codex/relay-server build && pnpm --filter @remote-codex/supervisor-web build",
|
|
88
|
+
"build:worker-image": "docker build -f Dockerfile.worker -t remote-codex-worker:local .",
|
|
51
89
|
"lint": "pnpm -r --if-present lint",
|
|
52
90
|
"typecheck": "pnpm -r --if-present typecheck",
|
|
53
91
|
"test": "NODE_ENV=test pnpm -r --if-present test",
|
|
92
|
+
"test:phase-zero-six-evidence": "vitest run scripts/phase-zero-six-evidence.test.ts",
|
|
54
93
|
"test:e2e": "playwright test",
|
|
55
94
|
"db:migrate": "pnpm --filter @remote-codex/db db:migrate",
|
|
56
95
|
"impeccable": "impeccable",
|
|
@@ -227,6 +227,7 @@ export interface ReadAgentSessionOptions {
|
|
|
227
227
|
export interface StartAgentSessionInput {
|
|
228
228
|
cwd: string;
|
|
229
229
|
model: string;
|
|
230
|
+
reasoningEffort?: string | null;
|
|
230
231
|
approvalMode: 'yolo' | 'guarded';
|
|
231
232
|
sandboxMode?: 'read-only' | 'workspace-write' | 'danger-full-access' | null;
|
|
232
233
|
performanceMode?: 'standard' | 'fast' | null;
|
|
@@ -253,13 +254,13 @@ export interface StartAgentTurnInput {
|
|
|
253
254
|
providerSessionId: string;
|
|
254
255
|
prompt: string;
|
|
255
256
|
displayPrompt?: string | null;
|
|
257
|
+
developerInstructions?: string | null;
|
|
256
258
|
model?: string | null;
|
|
257
259
|
reasoningEffort?: string | null;
|
|
258
260
|
collaborationMode?: 'default' | 'plan' | null;
|
|
259
261
|
sandboxMode?: 'read-only' | 'workspace-write' | 'danger-full-access' | null;
|
|
260
262
|
workspacePath?: string | null;
|
|
261
263
|
performanceMode?: 'standard' | 'fast' | null;
|
|
262
|
-
developerInstructions?: string | null;
|
|
263
264
|
hidden?: boolean;
|
|
264
265
|
displayTurnId?: string | null;
|
|
265
266
|
}
|
|
@@ -387,6 +387,7 @@ export class CodexAppServerManager extends EventEmitter {
|
|
|
387
387
|
const response = await this.client!.request<{ thread: any; model: string; reasoningEffort?: ReasoningEffort | null; sandbox?: string | null }>('thread/start', {
|
|
388
388
|
cwd: input.cwd,
|
|
389
389
|
model: input.model,
|
|
390
|
+
effort: input.effort,
|
|
390
391
|
serviceTier: input.serviceTier,
|
|
391
392
|
approvalPolicy: input.approvalPolicy,
|
|
392
393
|
sandbox: input.sandbox ?? null,
|
|
@@ -84,6 +84,51 @@ describe('codex history item persistence policy', () => {
|
|
|
84
84
|
});
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
+
it('keeps MCP tool result text extractable for plugin artifacts', () => {
|
|
88
|
+
const artifactText = [
|
|
89
|
+
'Created a 3D molecule artifact for Methane.',
|
|
90
|
+
'',
|
|
91
|
+
'```remote-codex-artifact',
|
|
92
|
+
'{"type":"remote-codex.artifact","artifactType":"chemistry.molecule3d","title":"Methane","payload":{"format":"xyz","content":["5\\nmethane example"]}}',
|
|
93
|
+
'```',
|
|
94
|
+
].join('\n');
|
|
95
|
+
|
|
96
|
+
const turn = codexTurnToAgentTurn({
|
|
97
|
+
id: 'turn-1',
|
|
98
|
+
status: 'completed',
|
|
99
|
+
error: null,
|
|
100
|
+
items: [
|
|
101
|
+
{
|
|
102
|
+
id: 'mcp-tool-1',
|
|
103
|
+
type: 'mcpToolCall',
|
|
104
|
+
status: 'completed',
|
|
105
|
+
action: {
|
|
106
|
+
mcpServer: 'remote_codex_plugins',
|
|
107
|
+
toolName: 'remote_codex_render_molecule',
|
|
108
|
+
},
|
|
109
|
+
result: {
|
|
110
|
+
output: {
|
|
111
|
+
content: [
|
|
112
|
+
{
|
|
113
|
+
type: 'text',
|
|
114
|
+
text: artifactText,
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const toolItem = turn.items[0];
|
|
124
|
+
expect(toolItem).toMatchObject({
|
|
125
|
+
kind: 'toolCall',
|
|
126
|
+
text: 'remote_codex_plugins/remote_codex_render_molecule',
|
|
127
|
+
detailText: expect.stringContaining('```remote-codex-artifact'),
|
|
128
|
+
});
|
|
129
|
+
expect(toolItem?.detailText).toContain('\n```remote-codex-artifact\n');
|
|
130
|
+
});
|
|
131
|
+
|
|
87
132
|
it('keeps Codex collab agent tool calls visible while running', () => {
|
|
88
133
|
expect(
|
|
89
134
|
liveCodexItemToHistoryItem(
|
|
@@ -191,6 +191,10 @@ function summarizeToolCallText(text: string) {
|
|
|
191
191
|
return lines.find((line) => line.trim().length > 0) ?? lines[0] ?? 'Tool call';
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
function containsRemoteCodexArtifact(text: string | null | undefined) {
|
|
195
|
+
return /```(?:artifact|remote-codex-artifact)\b/i.test(text ?? '');
|
|
196
|
+
}
|
|
197
|
+
|
|
194
198
|
function deferCommandHistoryItem(
|
|
195
199
|
item: ThreadHistoryItemDto & { kind: 'commandExecution' },
|
|
196
200
|
deferredDetails: Map<string, ThreadHistoryItemDetailDto>,
|
|
@@ -305,6 +309,19 @@ function valueFromNestedRecords(
|
|
|
305
309
|
return null;
|
|
306
310
|
}
|
|
307
311
|
|
|
312
|
+
function textContentFromMcpToolResult(value: unknown) {
|
|
313
|
+
if (!isRecord(value) || !Array.isArray(value.content)) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const texts = value.content
|
|
318
|
+
.map((entry) =>
|
|
319
|
+
isRecord(entry) && entry.type === 'text' ? stringOrNull(entry.text) : null,
|
|
320
|
+
)
|
|
321
|
+
.filter((entry): entry is string => Boolean(entry));
|
|
322
|
+
return texts.length > 0 ? texts.join('\n\n') : null;
|
|
323
|
+
}
|
|
324
|
+
|
|
308
325
|
function formatToolCallHistoryItem(
|
|
309
326
|
item: CodexTurnItem,
|
|
310
327
|
deferredDetails?: Map<string, ThreadHistoryItemDetailDto>,
|
|
@@ -356,6 +373,7 @@ function formatToolCallHistoryItem(
|
|
|
356
373
|
const resultPayload = output ?? result;
|
|
357
374
|
const argumentText = safeJsonStringify(argumentPayload);
|
|
358
375
|
const resultText = safeJsonStringify(resultPayload);
|
|
376
|
+
const resultContentText = textContentFromMcpToolResult(resultPayload);
|
|
359
377
|
|
|
360
378
|
if (argumentText) {
|
|
361
379
|
detailLines.push('', 'Arguments', argumentText);
|
|
@@ -363,6 +381,9 @@ function formatToolCallHistoryItem(
|
|
|
363
381
|
if (resultText) {
|
|
364
382
|
detailLines.push('', 'Result', resultText);
|
|
365
383
|
}
|
|
384
|
+
if (resultContentText && resultContentText !== resultText) {
|
|
385
|
+
detailLines.push('', 'Result Text', resultContentText);
|
|
386
|
+
}
|
|
366
387
|
|
|
367
388
|
const historyItem: ThreadHistoryItemDto = {
|
|
368
389
|
id: item.id,
|
|
@@ -375,6 +396,7 @@ function formatToolCallHistoryItem(
|
|
|
375
396
|
|
|
376
397
|
if (
|
|
377
398
|
deferredDetails &&
|
|
399
|
+
!containsRemoteCodexArtifact(historyItem.detailText) &&
|
|
378
400
|
(Boolean(argumentText) ||
|
|
379
401
|
Boolean(resultText) ||
|
|
380
402
|
(historyItem.detailText?.length ?? 0) > 240)
|
|
@@ -606,6 +606,9 @@ export class CodexRuntimeAdapter extends EventEmitter implements AgentRuntime {
|
|
|
606
606
|
model: input.model,
|
|
607
607
|
approvalPolicy: input.approvalMode === 'guarded' ? 'on-request' : 'never',
|
|
608
608
|
};
|
|
609
|
+
if (input.reasoningEffort !== undefined) {
|
|
610
|
+
startInput.effort = input.reasoningEffort as ReasoningEffort | null;
|
|
611
|
+
}
|
|
609
612
|
if (input.sandboxMode !== undefined) {
|
|
610
613
|
startInput.sandbox = input.sandboxMode as SandboxMode | null;
|
|
611
614
|
}
|
|
@@ -658,6 +661,9 @@ export class CodexRuntimeAdapter extends EventEmitter implements AgentRuntime {
|
|
|
658
661
|
threadId: input.providerSessionId,
|
|
659
662
|
prompt: input.prompt,
|
|
660
663
|
};
|
|
664
|
+
if (input.developerInstructions !== undefined) {
|
|
665
|
+
turnInput.developerInstructions = input.developerInstructions;
|
|
666
|
+
}
|
|
661
667
|
if (input.model !== undefined) {
|
|
662
668
|
turnInput.model = input.model;
|
|
663
669
|
}
|
|
@@ -293,6 +293,7 @@ export interface CodexThreadGoalRecord {
|
|
|
293
293
|
export interface ThreadStartInput {
|
|
294
294
|
cwd: string;
|
|
295
295
|
model: string;
|
|
296
|
+
effort?: ReasoningEffort | null;
|
|
296
297
|
approvalPolicy: 'never' | 'on-request';
|
|
297
298
|
sandbox?: SandboxMode | null;
|
|
298
299
|
serviceTier?: ServiceTier | null;
|
|
@@ -317,12 +318,12 @@ export interface ThreadRollbackInput {
|
|
|
317
318
|
export interface TurnStartInput {
|
|
318
319
|
threadId: string;
|
|
319
320
|
prompt: string;
|
|
321
|
+
developerInstructions?: string | null;
|
|
320
322
|
model?: string | null;
|
|
321
323
|
effort?: ReasoningEffort | null;
|
|
322
324
|
collaborationMode?: CollaborationModeKind | null;
|
|
323
325
|
sandboxPolicy?: SandboxPolicy | null;
|
|
324
326
|
serviceTier?: ServiceTier | null;
|
|
325
|
-
developerInstructions?: string | null;
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
export interface TurnSteerInput {
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS control_users (
|
|
2
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
3
|
+
auth_provider TEXT NOT NULL,
|
|
4
|
+
auth_subject TEXT NOT NULL,
|
|
5
|
+
email TEXT NOT NULL,
|
|
6
|
+
display_name TEXT,
|
|
7
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
8
|
+
plan TEXT NOT NULL DEFAULT 'developer',
|
|
9
|
+
created_at TEXT NOT NULL,
|
|
10
|
+
updated_at TEXT NOT NULL,
|
|
11
|
+
last_seen_at TEXT,
|
|
12
|
+
UNIQUE(auth_provider, auth_subject)
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE TABLE IF NOT EXISTS control_sandboxes (
|
|
16
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
17
|
+
user_id TEXT NOT NULL UNIQUE,
|
|
18
|
+
state TEXT NOT NULL,
|
|
19
|
+
image TEXT NOT NULL,
|
|
20
|
+
region TEXT NOT NULL,
|
|
21
|
+
k8s_namespace TEXT,
|
|
22
|
+
k8s_pod_name TEXT,
|
|
23
|
+
router_base_url TEXT,
|
|
24
|
+
worker_service_name TEXT,
|
|
25
|
+
s3_prefix TEXT NOT NULL,
|
|
26
|
+
gateway_key_id TEXT,
|
|
27
|
+
last_started_at TEXT,
|
|
28
|
+
last_seen_at TEXT,
|
|
29
|
+
idle_timeout_at TEXT,
|
|
30
|
+
created_at TEXT NOT NULL,
|
|
31
|
+
updated_at TEXT NOT NULL,
|
|
32
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
CREATE TABLE IF NOT EXISTS control_workspaces (
|
|
36
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
37
|
+
user_id TEXT NOT NULL,
|
|
38
|
+
sandbox_id TEXT NOT NULL,
|
|
39
|
+
name TEXT NOT NULL,
|
|
40
|
+
slug TEXT NOT NULL,
|
|
41
|
+
path TEXT NOT NULL,
|
|
42
|
+
source_type TEXT NOT NULL,
|
|
43
|
+
git_url TEXT,
|
|
44
|
+
default_branch TEXT,
|
|
45
|
+
created_at TEXT NOT NULL,
|
|
46
|
+
updated_at TEXT NOT NULL,
|
|
47
|
+
UNIQUE(sandbox_id, slug),
|
|
48
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id),
|
|
49
|
+
FOREIGN KEY(sandbox_id) REFERENCES control_sandboxes(id)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
CREATE TABLE IF NOT EXISTS control_sessions (
|
|
53
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
54
|
+
user_id TEXT NOT NULL,
|
|
55
|
+
sandbox_id TEXT NOT NULL,
|
|
56
|
+
workspace_id TEXT NOT NULL,
|
|
57
|
+
provider TEXT NOT NULL,
|
|
58
|
+
worker_session_id TEXT,
|
|
59
|
+
title TEXT NOT NULL,
|
|
60
|
+
status TEXT NOT NULL,
|
|
61
|
+
last_activity_at TEXT,
|
|
62
|
+
created_at TEXT NOT NULL,
|
|
63
|
+
updated_at TEXT NOT NULL,
|
|
64
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id),
|
|
65
|
+
FOREIGN KEY(sandbox_id) REFERENCES control_sandboxes(id),
|
|
66
|
+
FOREIGN KEY(workspace_id) REFERENCES control_workspaces(id)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
CREATE TABLE IF NOT EXISTS control_gateway_users (
|
|
70
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
71
|
+
user_id TEXT NOT NULL,
|
|
72
|
+
provider TEXT NOT NULL,
|
|
73
|
+
external_user_id TEXT NOT NULL,
|
|
74
|
+
created_at TEXT NOT NULL,
|
|
75
|
+
UNIQUE(provider, external_user_id),
|
|
76
|
+
UNIQUE(user_id, provider),
|
|
77
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
CREATE TABLE IF NOT EXISTS control_gateway_keys (
|
|
81
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
82
|
+
user_id TEXT NOT NULL,
|
|
83
|
+
sandbox_id TEXT NOT NULL,
|
|
84
|
+
provider TEXT NOT NULL,
|
|
85
|
+
external_key_id TEXT NOT NULL,
|
|
86
|
+
key_ciphertext TEXT,
|
|
87
|
+
status TEXT NOT NULL,
|
|
88
|
+
created_at TEXT NOT NULL,
|
|
89
|
+
rotated_at TEXT,
|
|
90
|
+
revoked_at TEXT,
|
|
91
|
+
UNIQUE(provider, external_key_id),
|
|
92
|
+
UNIQUE(sandbox_id, provider),
|
|
93
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id),
|
|
94
|
+
FOREIGN KEY(sandbox_id) REFERENCES control_sandboxes(id)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
CREATE TABLE IF NOT EXISTS control_usage_events (
|
|
98
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
99
|
+
user_id TEXT NOT NULL,
|
|
100
|
+
sandbox_id TEXT NOT NULL,
|
|
101
|
+
workspace_id TEXT,
|
|
102
|
+
session_id TEXT,
|
|
103
|
+
gateway_key_id TEXT,
|
|
104
|
+
provider TEXT NOT NULL,
|
|
105
|
+
model TEXT NOT NULL,
|
|
106
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
107
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
108
|
+
cached_tokens INTEGER NOT NULL DEFAULT 0,
|
|
109
|
+
cost_usd REAL NOT NULL DEFAULT 0,
|
|
110
|
+
external_request_id TEXT,
|
|
111
|
+
occurred_at TEXT NOT NULL,
|
|
112
|
+
imported_at TEXT NOT NULL,
|
|
113
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id),
|
|
114
|
+
FOREIGN KEY(sandbox_id) REFERENCES control_sandboxes(id)
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
CREATE TABLE IF NOT EXISTS control_audit_logs (
|
|
118
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
119
|
+
user_id TEXT,
|
|
120
|
+
action TEXT NOT NULL,
|
|
121
|
+
resource_type TEXT NOT NULL,
|
|
122
|
+
resource_id TEXT,
|
|
123
|
+
metadata_json TEXT NOT NULL,
|
|
124
|
+
created_at TEXT NOT NULL
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
CREATE INDEX IF NOT EXISTS control_workspaces_user_idx ON control_workspaces(user_id);
|
|
128
|
+
CREATE INDEX IF NOT EXISTS control_sessions_workspace_idx ON control_sessions(workspace_id);
|
|
129
|
+
CREATE INDEX IF NOT EXISTS control_usage_user_occurred_idx ON control_usage_events(user_id, occurred_at);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
ALTER TABLE control_users ADD COLUMN billing_customer_id TEXT;
|
|
2
|
+
ALTER TABLE control_users ADD COLUMN quota_profile TEXT NOT NULL DEFAULT 'developer';
|
|
3
|
+
ALTER TABLE control_sandboxes ADD COLUMN status_reason TEXT;
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS control_projects (
|
|
6
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
7
|
+
user_id TEXT NOT NULL,
|
|
8
|
+
name TEXT NOT NULL,
|
|
9
|
+
slug TEXT NOT NULL,
|
|
10
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
11
|
+
created_at TEXT NOT NULL,
|
|
12
|
+
updated_at TEXT NOT NULL,
|
|
13
|
+
UNIQUE(user_id, slug),
|
|
14
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
ALTER TABLE control_workspaces ADD COLUMN project_id TEXT REFERENCES control_projects(id);
|
|
18
|
+
|
|
19
|
+
CREATE INDEX IF NOT EXISTS control_projects_user_idx ON control_projects(user_id);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE control_workspaces ADD COLUMN status TEXT NOT NULL DEFAULT 'active';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE control_sandboxes ADD COLUMN resource_profile TEXT NOT NULL DEFAULT 'standard';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS control_usage_import_state (
|
|
2
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
3
|
+
provider TEXT NOT NULL,
|
|
4
|
+
source TEXT NOT NULL,
|
|
5
|
+
cursor TEXT,
|
|
6
|
+
last_started_at TEXT,
|
|
7
|
+
last_succeeded_at TEXT,
|
|
8
|
+
last_failed_at TEXT,
|
|
9
|
+
last_failure_message TEXT,
|
|
10
|
+
last_source_count INTEGER NOT NULL DEFAULT 0,
|
|
11
|
+
last_imported_count INTEGER NOT NULL DEFAULT 0,
|
|
12
|
+
last_duplicate_count INTEGER NOT NULL DEFAULT 0,
|
|
13
|
+
last_failure_count INTEGER NOT NULL DEFAULT 0,
|
|
14
|
+
updated_at TEXT NOT NULL
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
CREATE UNIQUE INDEX IF NOT EXISTS control_usage_import_state_provider_source_idx
|
|
18
|
+
ON control_usage_import_state(provider, source);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS control_auth_identities (
|
|
2
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
3
|
+
user_id TEXT NOT NULL,
|
|
4
|
+
auth_provider TEXT NOT NULL,
|
|
5
|
+
auth_subject TEXT NOT NULL,
|
|
6
|
+
email TEXT,
|
|
7
|
+
display_name TEXT,
|
|
8
|
+
created_at TEXT NOT NULL,
|
|
9
|
+
updated_at TEXT NOT NULL,
|
|
10
|
+
UNIQUE(auth_provider, auth_subject),
|
|
11
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id)
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
CREATE TABLE IF NOT EXISTS control_password_credentials (
|
|
15
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
16
|
+
user_id TEXT NOT NULL UNIQUE,
|
|
17
|
+
email TEXT NOT NULL UNIQUE,
|
|
18
|
+
password_hash TEXT NOT NULL,
|
|
19
|
+
created_at TEXT NOT NULL,
|
|
20
|
+
updated_at TEXT NOT NULL,
|
|
21
|
+
last_used_at TEXT,
|
|
22
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id)
|
|
23
|
+
);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS control_harness_users (
|
|
2
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
3
|
+
user_id TEXT NOT NULL,
|
|
4
|
+
provider TEXT NOT NULL,
|
|
5
|
+
external_user_id TEXT NOT NULL,
|
|
6
|
+
created_at TEXT NOT NULL,
|
|
7
|
+
UNIQUE(provider, external_user_id),
|
|
8
|
+
UNIQUE(user_id, provider),
|
|
9
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id)
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
CREATE TABLE IF NOT EXISTS control_harness_keys (
|
|
13
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
14
|
+
user_id TEXT NOT NULL,
|
|
15
|
+
sandbox_id TEXT NOT NULL,
|
|
16
|
+
provider TEXT NOT NULL,
|
|
17
|
+
external_key_id TEXT NOT NULL,
|
|
18
|
+
key_ciphertext TEXT,
|
|
19
|
+
secret_name TEXT,
|
|
20
|
+
secret_key TEXT,
|
|
21
|
+
status TEXT NOT NULL,
|
|
22
|
+
created_at TEXT NOT NULL,
|
|
23
|
+
rotated_at TEXT,
|
|
24
|
+
revoked_at TEXT,
|
|
25
|
+
UNIQUE(provider, external_key_id),
|
|
26
|
+
UNIQUE(sandbox_id, provider),
|
|
27
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id),
|
|
28
|
+
FOREIGN KEY(sandbox_id) REFERENCES control_sandboxes(id)
|
|
29
|
+
);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS control_harness_usage_events (
|
|
2
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
3
|
+
user_id TEXT NOT NULL,
|
|
4
|
+
sandbox_id TEXT NOT NULL,
|
|
5
|
+
workspace_id TEXT,
|
|
6
|
+
session_id TEXT,
|
|
7
|
+
provider TEXT NOT NULL,
|
|
8
|
+
module TEXT NOT NULL,
|
|
9
|
+
tool TEXT,
|
|
10
|
+
run_id TEXT,
|
|
11
|
+
job_id TEXT,
|
|
12
|
+
external_event_id TEXT,
|
|
13
|
+
compute_units REAL NOT NULL DEFAULT 0,
|
|
14
|
+
cost_usd REAL NOT NULL DEFAULT 0,
|
|
15
|
+
status TEXT NOT NULL DEFAULT 'unknown',
|
|
16
|
+
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
17
|
+
occurred_at TEXT NOT NULL,
|
|
18
|
+
imported_at TEXT NOT NULL,
|
|
19
|
+
FOREIGN KEY(user_id) REFERENCES control_users(id),
|
|
20
|
+
FOREIGN KEY(sandbox_id) REFERENCES control_sandboxes(id),
|
|
21
|
+
FOREIGN KEY(workspace_id) REFERENCES control_workspaces(id),
|
|
22
|
+
FOREIGN KEY(session_id) REFERENCES control_sessions(id)
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
CREATE UNIQUE INDEX IF NOT EXISTS control_harness_usage_provider_event_idx
|
|
26
|
+
ON control_harness_usage_events(provider, external_event_id)
|
|
27
|
+
WHERE external_event_id IS NOT NULL;
|