History

Add @executor/contracts shared types package, eliminate type duplication

- Create executor/packages/contracts/ with all shared type definitions - Server and web now import from @executor/contracts instead of maintaining copies - Fixes type drift (e.g. TaskEventRecord.eventName was narrower in web) - Remove empty package stubs (confect/, convex/, database/) - Pin convex versions consistently, remove unused deps (@elysiajs/eden, esbuild)

Rhys Sullivan committed 9 months ago

Commit 419f7241 parent e2dd09a8 files · +191 −223Browse files

Unified · Split

8 files
  1. executor/apps/server/package.json +2 −2
  2. executor/apps/server/src/types.ts +22 −114
  3. executor/apps/web/package.json +2 −1
  4. executor/apps/web/src/lib/types.ts +22 −104
  5. executor/package.json +5 −2
  6. executor/packages/contracts/package.json +7 −0
  7. executor/packages/contracts/src/index.ts +120 −0
  8. executor/packages/contracts/tsconfig.json +11 −0
executor/apps/server/package.json+2−2
@@ -3,11 +3,11 @@ · 2 unmodified lines
33 "private": true,
44 "type": "module",
55 "dependencies": {
6+ "@executor/contracts": "workspace:*",
67 "@apidevtools/swagger-parser": "^12.1.0",
7− "@elysiajs/eden": "^1.4.6",
88 "@modelcontextprotocol/sdk": "^1.26.0",
99 "@vercel/sandbox": "latest",
10− "convex": "latest",
10+ "convex": "^1.31.7",
1111 "elysia": "^1.4.22",
1212 "openapi-typescript": "^7.10.1",
1313 "zod": "^4.3.6"
executor/apps/server/src/types.ts+22−114
@@ -1,57 +1,25 @@
1−export type TaskStatus =
2− | "queued"
3− | "running"
4− | "completed"
5− | "failed"
6− | "timed_out"
7− | "denied";
8−
9−export type ApprovalStatus = "pending" | "approved" | "denied";
10−
11−export interface TaskRecord {
12− id: string;
13− code: string;
14− runtimeId: string;
15− status: TaskStatus;
16− timeoutMs: number;
17− metadata: Record<string, unknown>;
18− workspaceId: string;
19− actorId?: string;
20− clientId?: string;
21− createdAt: number;
22− updatedAt: number;
23− startedAt?: number;
24− completedAt?: number;
25− error?: string;
26− stdout?: string;
27− stderr?: string;
28− exitCode?: number;
29−}
30−
31−export interface ApprovalRecord {
32− id: string;
33− taskId: string;
34− toolPath: string;
35− input: unknown;
36− status: ApprovalStatus;
37− reason?: string;
38− reviewerId?: string;
39− createdAt: number;
40− resolvedAt?: number;
41−}
42−
43−export interface PendingApprovalRecord extends ApprovalRecord {
44− task: Pick<TaskRecord, "id" | "status" | "runtimeId" | "timeoutMs" | "createdAt">;
45−}
46−
47−export interface TaskEventRecord {
48− id: number;
49− taskId: string;
50− eventName: string;
51− type: string;
52− payload: unknown;
53− createdAt: number;
54−}
1+// Re-export shared types from contracts
2+export type {
3+ TaskStatus,
4+ ApprovalStatus,
5+ PolicyDecision,
6+ CredentialScope,
7+ ToolApprovalMode,
8+ ToolSourceType,
9+ TaskRecord,
10+ ApprovalRecord,
11+ PendingApprovalRecord,
12+ TaskEventRecord,
13+ AccessPolicyRecord,
14+ CredentialRecord,
15+ ToolSourceRecord,
16+ ToolDescriptor,
17+ AnonymousContext,
18+} from "@executor/contracts";
19+
20+import type { TaskStatus, CredentialScope, ToolApprovalMode } from "@executor/contracts";
21+
22+// ── Server-only types ─────────────────────────────────────────────────────────
5523
5624 export interface CreateTaskInput {
5725 code: string;
@@ -63,15 +31,6 @@ export interface CreateTaskInput { · 5 unmodified lines
6331 clientId?: string;
6432 }
6533
66−export interface AnonymousContext {
67− sessionId: string;
68− workspaceId: string;
69− actorId: string;
70− clientId: string;
71− createdAt: number;
72− lastSeenAt: number;
73−}
74−
7534 export interface SandboxExecutionRequest {
7635 taskId: string;
7736 code: string;
@@ -122,35 +81,6 @@ export interface SandboxRuntime { · 44 unmodified lines
12281 ): Promise<SandboxExecutionResult>;
12382 }
12483
125−export type ToolApprovalMode = "auto" | "required";
126−
127−export type PolicyDecision = "allow" | "require_approval" | "deny";
128−
129−export interface AccessPolicyRecord {
130− id: string;
131− workspaceId: string;
132− actorId?: string;
133− clientId?: string;
134− toolPathPattern: string;
135− decision: PolicyDecision;
136− priority: number;
137− createdAt: number;
138− updatedAt: number;
139−}
140−
141−export type CredentialScope = "workspace" | "actor";
142−
143−export interface CredentialRecord {
144− id: string;
145− workspaceId: string;
146− sourceKey: string;
147− scope: CredentialScope;
148− actorId?: string;
149− secretJson: Record<string, unknown>;
150− createdAt: number;
151− updatedAt: number;
152−}
153−
15484 export type ToolCredentialAuthType = "bearer" | "apiKey" | "basic";
15585
15686 export interface ToolCredentialSpec {
@@ -194,25 +124,3 @@ export interface ToolDefinition { · 37 unmodified lines
194124 _pseudoTool?: boolean;
195125 run(input: unknown, context: ToolRunContext): Promise<unknown>;
196126 }
197−
198−export interface ToolDescriptor {
199− path: string;
200− description: string;
201− approval: ToolApprovalMode;
202− source?: string;
203− argsType?: string;
204− returnsType?: string;
205−}
206−
207−export type ToolSourceType = "mcp" | "openapi" | "graphql";
208−
209−export interface ToolSourceRecord {
210− id: string;
211− workspaceId: string;
212− name: string;
213− type: ToolSourceType;
214− config: Record<string, unknown>;
215− enabled: boolean;
216− createdAt: number;
217− updatedAt: number;
218−}
executor/apps/web/package.json+2−1
@@ -9,10 +9,11 @@ · 8 unmodified lines
99 "lint": "eslint"
1010 },
1111 "dependencies": {
12+ "@executor/contracts": "workspace:*",
1213 "@monaco-editor/react": "^4.7.0",
1314 "class-variance-authority": "^0.7.1",
1415 "clsx": "^2.1.1",
15− "convex": "latest",
16+ "convex": "^1.31.7",
1617 "lucide-react": "^0.563.0",
1718 "monaco-editor": "^0.55.1",
1819 "next": "16.1.6",
executor/apps/web/src/lib/types.ts+22−104
@@ -1,18 +1,27 @@
1−// Re-declare types locally since we can't use the monorepo contracts package
2−// from the Next.js app easily. These mirror @executor/contracts exactly.
1+// Re-export shared types from contracts
2+export type {
3+ TaskStatus,
4+ ApprovalStatus,
5+ PolicyDecision,
6+ CredentialScope,
7+ ToolApprovalMode,
8+ ToolSourceType,
9+ TaskRecord,
10+ ApprovalRecord,
11+ PendingApprovalRecord,
12+ TaskEventRecord,
13+ AccessPolicyRecord,
14+ CredentialRecord,
15+ ToolSourceRecord,
16+ ToolDescriptor,
17+ AnonymousContext,
18+} from "@executor/contracts";
19+
20+// ── Web-only types ────────────────────────────────────────────────────────────
21+
22+import type { TaskStatus, ApprovalStatus, CredentialScope } from "@executor/contracts";
323
4−export type TaskStatus =
5− | "queued"
6− | "running"
7− | "completed"
8− | "failed"
9− | "timed_out"
10− | "denied";
11−
12−export type ApprovalStatus = "pending" | "approved" | "denied";
1324 export type ApprovalDecision = "approved" | "denied";
14−export type PolicyDecision = "allow" | "require_approval" | "deny";
15−export type CredentialScope = "workspace" | "actor";
1625
1726 export interface CreateTaskRequest {
1827 code: string;
@@ -29,45 +38,6 @@ export interface CreateTaskResponse { · 10 unmodified lines
2938 status: TaskStatus;
3039 }
3140
32−export interface TaskRecord {
33− id: string;
34− code: string;
35− runtimeId: string;
36− timeoutMs: number;
37− metadata: Record<string, unknown>;
38− workspaceId: string;
39− actorId?: string;
40− clientId?: string;
41− status: TaskStatus;
42− createdAt: number;
43− updatedAt: number;
44− startedAt?: number;
45− completedAt?: number;
46− stdout?: string;
47− stderr?: string;
48− exitCode?: number;
49− error?: string;
50−}
51−
52−export interface ApprovalRecord {
53− id: string;
54− taskId: string;
55− toolPath: string;
56− input: unknown;
57− status: ApprovalStatus;
58− createdAt: number;
59− resolvedAt?: number;
60− reviewerId?: string;
61− reason?: string;
62−}
63−
64−export interface PendingApprovalRecord extends ApprovalRecord {
65− task: Pick<
66− TaskRecord,
67− "id" | "status" | "runtimeId" | "timeoutMs" | "createdAt"
68− >;
69−}
70−
7141 export interface ResolveApprovalRequest {
7242 workspaceId: string;
7343 decision: ApprovalDecision;
@@ -75,42 +45,12 @@ export interface ResolveApprovalRequest { · 1 unmodified line
7545 reason?: string;
7646 }
7747
78−export interface AnonymousContext {
79− sessionId: string;
80− workspaceId: string;
81− actorId: string;
82− clientId: string;
83− createdAt: number;
84− lastSeenAt: number;
85−}
86−
8748 export interface RuntimeTargetDescriptor {
8849 id: string;
8950 label: string;
9051 description: string;
9152 }
9253
93−export interface ToolDescriptor {
94− path: string;
95− description: string;
96− approval: "auto" | "required";
97− source?: string;
98− argsType?: string;
99− returnsType?: string;
100−}
101−
102−export interface AccessPolicyRecord {
103− id: string;
104− workspaceId: string;
105− actorId?: string;
106− clientId?: string;
107− toolPathPattern: string;
108− decision: PolicyDecision;
109− priority: number;
110− createdAt: number;
111− updatedAt: number;
112−}
113−
11454 export interface CredentialDescriptor {
11555 id: string;
11656 workspaceId: string;
@@ -119,25 +59,3 @@ export interface CredentialDescriptor { · 2 unmodified lines
11959 actorId?: string;
12060 hasSecret: boolean;
12161 }
122−
123−export type ToolSourceType = "mcp" | "openapi" | "graphql";
124−
125−export interface ToolSourceRecord {
126− id: string;
127− workspaceId: string;
128− name: string;
129− type: ToolSourceType;
130− config: Record<string, unknown>;
131− enabled: boolean;
132− createdAt: number;
133− updatedAt: number;
134−}
135−
136−export interface TaskEventRecord {
137− id: number;
138− taskId: string;
139− eventName: "task" | "approval";
140− type: string;
141− payload: Record<string, unknown>;
142− createdAt: number;
143−}
executor/package.json+5−2
@@ -2,6 +2,10 @@ · 1 unmodified line
22 "name": "executor-monorepo",
33 "private": true,
44 "type": "module",
5+ "workspaces": [
6+ "apps/*",
7+ "packages/*"
8+ ],
59 "scripts": {
610 "dev": "bun run --cwd apps/server dev",
711 "dev:worker": "bun run --cwd apps/server worker",
@@ -14,12 +18,11 @@ · 6 unmodified lines
1418 "typecheck": "bunx tsc --noEmit -p tsconfig.json"
1519 },
1620 "dependencies": {
17− "convex": "latest"
21+ "convex": "^1.31.7"
1822 },
1923 "devDependencies": {
2024 "@types/bun": "latest",
2125 "convex-test": "^0.0.41",
22− "esbuild": "^0.27.3",
2326 "typescript": "latest"
2427 }
2528 }
executor/packages/contracts/package.json+7−0
@@ -0,0 +1,7 @@
1+{
2+ "name": "@executor/contracts",
3+ "version": "0.0.1",
4+ "private": true,
5+ "main": "src/index.ts",
6+ "types": "src/index.ts"
7+}
executor/packages/contracts/src/index.ts+120−0
@@ -0,0 +1,120 @@
1+// ── Status enums ──────────────────────────────────────────────────────────────
2+
3+export type TaskStatus =
4+ | "queued"
5+ | "running"
6+ | "completed"
7+ | "failed"
8+ | "timed_out"
9+ | "denied";
10+
11+export type ApprovalStatus = "pending" | "approved" | "denied";
12+
13+export type PolicyDecision = "allow" | "require_approval" | "deny";
14+
15+export type CredentialScope = "workspace" | "actor";
16+
17+export type ToolApprovalMode = "auto" | "required";
18+
19+export type ToolSourceType = "mcp" | "openapi" | "graphql";
20+
21+// ── Records ───────────────────────────────────────────────────────────────────
22+
23+export interface TaskRecord {
24+ id: string;
25+ code: string;
26+ runtimeId: string;
27+ status: TaskStatus;
28+ timeoutMs: number;
29+ metadata: Record<string, unknown>;
30+ workspaceId: string;
31+ actorId?: string;
32+ clientId?: string;
33+ createdAt: number;
34+ updatedAt: number;
35+ startedAt?: number;
36+ completedAt?: number;
37+ error?: string;
38+ stdout?: string;
39+ stderr?: string;
40+ exitCode?: number;
41+}
42+
43+export interface ApprovalRecord {
44+ id: string;
45+ taskId: string;
46+ toolPath: string;
47+ input: unknown;
48+ status: ApprovalStatus;
49+ reason?: string;
50+ reviewerId?: string;
51+ createdAt: number;
52+ resolvedAt?: number;
53+}
54+
55+export interface PendingApprovalRecord extends ApprovalRecord {
56+ task: Pick<TaskRecord, "id" | "status" | "runtimeId" | "timeoutMs" | "createdAt">;
57+}
58+
59+export interface TaskEventRecord {
60+ id: number;
61+ taskId: string;
62+ eventName: string;
63+ type: string;
64+ payload: unknown;
65+ createdAt: number;
66+}
67+
68+export interface AccessPolicyRecord {
69+ id: string;
70+ workspaceId: string;
71+ actorId?: string;
72+ clientId?: string;
73+ toolPathPattern: string;
74+ decision: PolicyDecision;
75+ priority: number;
76+ createdAt: number;
77+ updatedAt: number;
78+}
79+
80+export interface CredentialRecord {
81+ id: string;
82+ workspaceId: string;
83+ sourceKey: string;
84+ scope: CredentialScope;
85+ actorId?: string;
86+ secretJson: Record<string, unknown>;
87+ createdAt: number;
88+ updatedAt: number;
89+}
90+
91+export interface ToolSourceRecord {
92+ id: string;
93+ workspaceId: string;
94+ name: string;
95+ type: ToolSourceType;
96+ config: Record<string, unknown>;
97+ enabled: boolean;
98+ createdAt: number;
99+ updatedAt: number;
100+}
101+
102+// ── Descriptors ───────────────────────────────────────────────────────────────
103+
104+export interface ToolDescriptor {
105+ path: string;
106+ description: string;
107+ approval: ToolApprovalMode;
108+ source?: string;
109+ argsType?: string;
110+ returnsType?: string;
111+}
112+
113+export interface AnonymousContext {
114+ sessionId: string;
115+ workspaceId: string;
116+ actorId: string;
117+ clientId: string;
118+ createdAt: number;
119+ lastSeenAt: number;
120+}
executor/packages/contracts/tsconfig.json+11−0
@@ -0,0 +1,11 @@
1+{
2+ "compilerOptions": {
3+ "strict": true,
4+ "moduleResolution": "bundler",
5+ "target": "ESNext",
6+ "module": "ESNext",
7+ "noEmit": true,
8+ "skipLibCheck": true
9+ },
10+ "include": ["src/**/*.ts"]
11+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t