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
3 "private": true,3 "private": true,
4 "type": "module",4 "type": "module",
5 "dependencies": {5 "dependencies": {
6 "@executor/contracts": "workspace:*",
6 "@apidevtools/swagger-parser": "^12.1.0",7 "@apidevtools/swagger-parser": "^12.1.0",
7 "@elysiajs/eden": "^1.4.6",
8 "@modelcontextprotocol/sdk": "^1.26.0",8 "@modelcontextprotocol/sdk": "^1.26.0",
9 "@vercel/sandbox": "latest",9 "@vercel/sandbox": "latest",
10 "convex": "latest",10 "convex": "^1.31.7",
11 "elysia": "^1.4.22",11 "elysia": "^1.4.22",
12 "openapi-typescript": "^7.10.1",12 "openapi-typescript": "^7.10.1",
13 "zod": "^4.3.6"13 "zod": "^4.3.6"
executor/apps/server/src/types.ts+22−114
@@ -1,57 +1,25 @@
1export type TaskStatus =1// Re-export shared types from contracts
2 | "queued"2export type {
3 | "running"3 TaskStatus,
4 | "completed"4 ApprovalStatus,
5 | "failed"5 PolicyDecision,
6 | "timed_out"6 CredentialScope,
7 | "denied";7 ToolApprovalMode,
8 8 ToolSourceType,
9export type ApprovalStatus = "pending" | "approved" | "denied";9 TaskRecord,
10 10 ApprovalRecord,
11export interface TaskRecord {11 PendingApprovalRecord,
12 id: string;12 TaskEventRecord,
13 code: string;13 AccessPolicyRecord,
14 runtimeId: string;14 CredentialRecord,
15 status: TaskStatus;15 ToolSourceRecord,
16 timeoutMs: number;16 ToolDescriptor,
17 metadata: Record<string, unknown>;17 AnonymousContext,
18 workspaceId: string;18} from "@executor/contracts";
19 actorId?: string;19
20 clientId?: string;20import type { TaskStatus, CredentialScope, ToolApprovalMode } from "@executor/contracts";
21 createdAt: number;21
22 updatedAt: number;22// ── Server-only types ─────────────────────────────────────────────────────────
23 startedAt?: number;
24 completedAt?: number;
25 error?: string;
26 stdout?: string;
27 stderr?: string;
28 exitCode?: number;
29}
30
31export 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
43export interface PendingApprovalRecord extends ApprovalRecord {
44 task: Pick<TaskRecord, "id" | "status" | "runtimeId" | "timeoutMs" | "createdAt">;
45}
46
47export interface TaskEventRecord {
48 id: number;
49 taskId: string;
50 eventName: string;
51 type: string;
52 payload: unknown;
53 createdAt: number;
54}
55 23
56export interface CreateTaskInput {24export interface CreateTaskInput {
57 code: string;25 code: string;
@@ -63,15 +31,6 @@ export interface CreateTaskInput { · 5 unmodified lines
63 clientId?: string;31 clientId?: string;
64}32}
65 33
66export interface AnonymousContext {
67 sessionId: string;
68 workspaceId: string;
69 actorId: string;
70 clientId: string;
71 createdAt: number;
72 lastSeenAt: number;
73}
74
75export interface SandboxExecutionRequest {34export interface SandboxExecutionRequest {
76 taskId: string;35 taskId: string;
77 code: string;36 code: string;
@@ -122,35 +81,6 @@ export interface SandboxRuntime { · 44 unmodified lines
122 ): Promise<SandboxExecutionResult>;81 ): Promise<SandboxExecutionResult>;
123}82}
124 83
125export type ToolApprovalMode = "auto" | "required";
126
127export type PolicyDecision = "allow" | "require_approval" | "deny";
128
129export 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
141export type CredentialScope = "workspace" | "actor";
142
143export 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
154export type ToolCredentialAuthType = "bearer" | "apiKey" | "basic";84export type ToolCredentialAuthType = "bearer" | "apiKey" | "basic";
155 85
156export interface ToolCredentialSpec {86export interface ToolCredentialSpec {
@@ -194,25 +124,3 @@ export interface ToolDefinition { · 37 unmodified lines
194 _pseudoTool?: boolean;124 _pseudoTool?: boolean;
195 run(input: unknown, context: ToolRunContext): Promise<unknown>;125 run(input: unknown, context: ToolRunContext): Promise<unknown>;
196}126}
197
198export interface ToolDescriptor {
199 path: string;
200 description: string;
201 approval: ToolApprovalMode;
202 source?: string;
203 argsType?: string;
204 returnsType?: string;
205}
206
207export type ToolSourceType = "mcp" | "openapi" | "graphql";
208
209export 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
9 "lint": "eslint"9 "lint": "eslint"
10 },10 },
11 "dependencies": {11 "dependencies": {
12 "@executor/contracts": "workspace:*",
12 "@monaco-editor/react": "^4.7.0",13 "@monaco-editor/react": "^4.7.0",
13 "class-variance-authority": "^0.7.1",14 "class-variance-authority": "^0.7.1",
14 "clsx": "^2.1.1",15 "clsx": "^2.1.1",
15 "convex": "latest",16 "convex": "^1.31.7",
16 "lucide-react": "^0.563.0",17 "lucide-react": "^0.563.0",
17 "monaco-editor": "^0.55.1",18 "monaco-editor": "^0.55.1",
18 "next": "16.1.6",19 "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 package1// Re-export shared types from contracts
2// from the Next.js app easily. These mirror @executor/contracts exactly.2export 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
22import type { TaskStatus, ApprovalStatus, CredentialScope } from "@executor/contracts";
3 23
4export type TaskStatus =
5 | "queued"
6 | "running"
7 | "completed"
8 | "failed"
9 | "timed_out"
10 | "denied";
11
12export type ApprovalStatus = "pending" | "approved" | "denied";
13export type ApprovalDecision = "approved" | "denied";24export type ApprovalDecision = "approved" | "denied";
14export type PolicyDecision = "allow" | "require_approval" | "deny";
15export type CredentialScope = "workspace" | "actor";
16 25
17export interface CreateTaskRequest {26export interface CreateTaskRequest {
18 code: string;27 code: string;
@@ -29,45 +38,6 @@ export interface CreateTaskResponse { · 10 unmodified lines
29 status: TaskStatus;38 status: TaskStatus;
30}39}
31 40
32export 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
52export 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
64export interface PendingApprovalRecord extends ApprovalRecord {
65 task: Pick<
66 TaskRecord,
67 "id" | "status" | "runtimeId" | "timeoutMs" | "createdAt"
68 >;
69}
70
71export interface ResolveApprovalRequest {41export interface ResolveApprovalRequest {
72 workspaceId: string;42 workspaceId: string;
73 decision: ApprovalDecision;43 decision: ApprovalDecision;
@@ -75,42 +45,12 @@ export interface ResolveApprovalRequest { · 1 unmodified line
75 reason?: string;45 reason?: string;
76}46}
77 47
78export interface AnonymousContext {
79 sessionId: string;
80 workspaceId: string;
81 actorId: string;
82 clientId: string;
83 createdAt: number;
84 lastSeenAt: number;
85}
86
87export interface RuntimeTargetDescriptor {48export interface RuntimeTargetDescriptor {
88 id: string;49 id: string;
89 label: string;50 label: string;
90 description: string;51 description: string;
91}52}
92 53
93export interface ToolDescriptor {
94 path: string;
95 description: string;
96 approval: "auto" | "required";
97 source?: string;
98 argsType?: string;
99 returnsType?: string;
100}
101
102export 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
114export interface CredentialDescriptor {54export interface CredentialDescriptor {
115 id: string;55 id: string;
116 workspaceId: string;56 workspaceId: string;
@@ -119,25 +59,3 @@ export interface CredentialDescriptor { · 2 unmodified lines
119 actorId?: string;59 actorId?: string;
120 hasSecret: boolean;60 hasSecret: boolean;
121}61}
122
123export type ToolSourceType = "mcp" | "openapi" | "graphql";
124
125export 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
136export 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
2 "name": "executor-monorepo",2 "name": "executor-monorepo",
3 "private": true,3 "private": true,
4 "type": "module",4 "type": "module",
5 "workspaces": [
6 "apps/*",
7 "packages/*"
8 ],
5 "scripts": {9 "scripts": {
6 "dev": "bun run --cwd apps/server dev",10 "dev": "bun run --cwd apps/server dev",
7 "dev:worker": "bun run --cwd apps/server worker",11 "dev:worker": "bun run --cwd apps/server worker",
@@ -14,12 +18,11 @@ · 6 unmodified lines
14 "typecheck": "bunx tsc --noEmit -p tsconfig.json"18 "typecheck": "bunx tsc --noEmit -p tsconfig.json"
15 },19 },
16 "dependencies": {20 "dependencies": {
17 "convex": "latest"21 "convex": "^1.31.7"
18 },22 },
19 "devDependencies": {23 "devDependencies": {
20 "@types/bun": "latest",24 "@types/bun": "latest",
21 "convex-test": "^0.0.41",25 "convex-test": "^0.0.41",
22 "esbuild": "^0.27.3",
23 "typescript": "latest"26 "typescript": "latest"
24 }27 }
25}28}
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
3export type TaskStatus =
4 | "queued"
5 | "running"
6 | "completed"
7 | "failed"
8 | "timed_out"
9 | "denied";
10
11export type ApprovalStatus = "pending" | "approved" | "denied";
12
13export type PolicyDecision = "allow" | "require_approval" | "deny";
14
15export type CredentialScope = "workspace" | "actor";
16
17export type ToolApprovalMode = "auto" | "required";
18
19export type ToolSourceType = "mcp" | "openapi" | "graphql";
20
21// ── Records ───────────────────────────────────────────────────────────────────
22
23export 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
43export 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
55export interface PendingApprovalRecord extends ApprovalRecord {
56 task: Pick<TaskRecord, "id" | "status" | "runtimeId" | "timeoutMs" | "createdAt">;
57}
58
59export interface TaskEventRecord {
60 id: number;
61 taskId: string;
62 eventName: string;
63 type: string;
64 payload: unknown;
65 createdAt: number;
66}
67
68export 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
80export 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
91export 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
104export interface ToolDescriptor {
105 path: string;
106 description: string;
107 approval: ToolApprovalMode;
108 source?: string;
109 argsType?: string;
110 returnsType?: string;
111}
112
113export 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