@treeseed/sdk 0.10.12 → 0.10.14
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/dist/api/auth/d1-store.js +20 -1
- package/dist/db/market-schema.d.ts +7515 -6263
- package/dist/db/market-schema.js +71 -15
- package/dist/index.d.ts +3 -1
- package/dist/index.js +18 -0
- package/dist/market-client.d.ts +107 -0
- package/dist/market-client.js +91 -1
- package/dist/operations/services/deploy.d.ts +8 -0
- package/dist/operations/services/deploy.js +12 -1
- package/dist/operations/services/github-api.d.ts +83 -0
- package/dist/operations/services/github-api.js +167 -0
- package/dist/operations/services/mailpit-runtime.d.ts +13 -2
- package/dist/operations/services/mailpit-runtime.js +19 -14
- package/dist/operations/services/project-web-monitor.d.ts +15 -0
- package/dist/operations/services/project-web-monitor.js +260 -0
- package/dist/operations/services/railway-api.js +2 -2
- package/dist/operations.d.ts +1 -0
- package/dist/operations.js +11 -1
- package/dist/platform-operation-store.d.ts +4 -0
- package/dist/platform-operation-store.js +29 -3
- package/dist/platform-operations.d.ts +8 -0
- package/dist/platform-operations.js +19 -0
- package/dist/remote.js +6 -6
- package/dist/scripts/test-cloudflare-local.js +1 -1
- package/dist/scripts/workspace-command-e2e.js +3 -1
- package/dist/sdk-types.d.ts +109 -1
- package/dist/sdk-types.js +5 -1
- package/drizzle/market/0000_market_control_plane.sql +80 -14
- package/drizzle/market/0002_user_email_addresses.sql +26 -0
- package/package.json +1 -1
- package/templates/github/deploy-web.workflow.yml +1 -0
package/dist/operations.js
CHANGED
|
@@ -14,6 +14,12 @@ import {
|
|
|
14
14
|
validateRepositoryHost
|
|
15
15
|
} from "./operations/services/hub-launch.js";
|
|
16
16
|
import { TreeseedOperationsSdk } from "./operations/runtime.js";
|
|
17
|
+
import {
|
|
18
|
+
cancelGitHubWorkflowRun,
|
|
19
|
+
dispatchGitHubWorkflowRun,
|
|
20
|
+
formatGitHubWorkflowFailure,
|
|
21
|
+
waitForGitHubWorkflowRunCompletion
|
|
22
|
+
} from "./operations/services/github-api.js";
|
|
17
23
|
import { TreeseedOperationError } from "./operations-types.js";
|
|
18
24
|
import {
|
|
19
25
|
AGENT_OPERATION_MODES,
|
|
@@ -32,19 +38,23 @@ export {
|
|
|
32
38
|
TreeseedOperationError,
|
|
33
39
|
TreeseedOperationsSdk,
|
|
34
40
|
TreeseedWorkflowSdk,
|
|
41
|
+
cancelGitHubWorkflowRun,
|
|
35
42
|
collectTreeseedConfigSeedValues,
|
|
36
43
|
createAgentOperationEvent,
|
|
37
44
|
createKnowledgeHubRepositories,
|
|
38
45
|
decideAgentOperationPermission,
|
|
39
46
|
defaultHubContentResolutionPolicy,
|
|
40
47
|
deniedAgentOperationResult,
|
|
48
|
+
dispatchGitHubWorkflowRun,
|
|
41
49
|
executeKnowledgeHubLaunch,
|
|
42
50
|
findTreeseedOperation,
|
|
51
|
+
formatGitHubWorkflowFailure,
|
|
43
52
|
isAgentOperationName,
|
|
44
53
|
listTreeseedOperationNames,
|
|
45
54
|
normalizeKnowledgeHubLaunchIntent,
|
|
46
55
|
planKnowledgeHubLaunch,
|
|
47
56
|
planKnowledgeHubRepositories,
|
|
48
57
|
resolveAgentOperationGrant,
|
|
49
|
-
validateRepositoryHost
|
|
58
|
+
validateRepositoryHost,
|
|
59
|
+
waitForGitHubWorkflowRunCompletion
|
|
50
60
|
};
|
|
@@ -84,6 +84,10 @@ export declare class PlatformOperationStore {
|
|
|
84
84
|
ok: true;
|
|
85
85
|
operation: PlatformOperation;
|
|
86
86
|
}>;
|
|
87
|
+
cancel(operationId: string, request: PlatformRunnerJobUpdateRequest): Promise<{
|
|
88
|
+
ok: true;
|
|
89
|
+
operation: PlatformOperation;
|
|
90
|
+
}>;
|
|
87
91
|
private upsertRepositoryClaim;
|
|
88
92
|
private renewRepositoryClaimsForRunner;
|
|
89
93
|
private releaseRepositoryClaimsForRunner;
|
|
@@ -131,6 +131,9 @@ function repositoryWorkspacePath(workspaceRoot, repository = {}) {
|
|
|
131
131
|
const root = String(workspaceRoot ?? "/data").replace(/\/+$/u, "") || "/data";
|
|
132
132
|
return `${root}/repositories/${repositoryKey(repository)}/repo`;
|
|
133
133
|
}
|
|
134
|
+
function normalizeOperationCapabilities(capabilities) {
|
|
135
|
+
return Array.isArray(capabilities) ? capabilities.map((entry) => String(entry ?? "").trim()).filter(Boolean) : [];
|
|
136
|
+
}
|
|
134
137
|
function convertQuestionPlaceholders(query) {
|
|
135
138
|
let index = 0;
|
|
136
139
|
return query.replace(/\?/gu, () => `$${++index}`);
|
|
@@ -311,20 +314,27 @@ class PlatformOperationStore {
|
|
|
311
314
|
const leaseSeconds = Math.max(30, Math.min(Number(input.leaseSeconds ?? 300), 3600));
|
|
312
315
|
const now = isoNow(this.now);
|
|
313
316
|
const leaseExpiresAt = new Date(this.now().getTime() + leaseSeconds * 1e3).toISOString();
|
|
317
|
+
const capabilities = normalizeOperationCapabilities(input.capabilities);
|
|
318
|
+
const capabilityWhere = capabilities.length > 0 ? ` AND (${capabilities.map(() => `(namespace || ':' || operation) = ?`).join(" OR ")})` : "";
|
|
319
|
+
const capabilityParams = capabilities;
|
|
314
320
|
const rows = input.operationId ? await this.database.all(
|
|
315
321
|
`SELECT * FROM platform_operations
|
|
316
322
|
WHERE id = ? AND (
|
|
317
323
|
status = 'queued'
|
|
318
324
|
OR (status = 'leased' AND lease_expires_at IS NOT NULL AND lease_expires_at < ?)
|
|
319
325
|
)
|
|
326
|
+
${capabilityWhere}
|
|
320
327
|
ORDER BY created_at ASC LIMIT 1`,
|
|
321
|
-
[input.operationId, now]
|
|
328
|
+
[input.operationId, now, ...capabilityParams]
|
|
322
329
|
) : await this.database.all(
|
|
323
330
|
`SELECT * FROM platform_operations
|
|
324
|
-
WHERE
|
|
331
|
+
WHERE (
|
|
332
|
+
status = 'queued'
|
|
325
333
|
OR (status = 'leased' AND lease_expires_at IS NOT NULL AND lease_expires_at < ?)
|
|
334
|
+
)
|
|
335
|
+
${capabilityWhere}
|
|
326
336
|
ORDER BY created_at ASC LIMIT 1`,
|
|
327
|
-
[now]
|
|
337
|
+
[now, ...capabilityParams]
|
|
328
338
|
);
|
|
329
339
|
const row = rows[0];
|
|
330
340
|
if (!row) return { ok: true, operation: null };
|
|
@@ -424,6 +434,22 @@ class PlatformOperationStore {
|
|
|
424
434
|
});
|
|
425
435
|
return this.getOperation(operationId);
|
|
426
436
|
}
|
|
437
|
+
async cancel(operationId, request) {
|
|
438
|
+
await this.assertRunnerUpdate(operationId, request.runnerId);
|
|
439
|
+
const timestamp = isoNow(this.now);
|
|
440
|
+
await this.database.run(
|
|
441
|
+
`UPDATE platform_operations
|
|
442
|
+
SET status = 'cancelled', error_json = ?, lease_expires_at = NULL, cancelled_at = COALESCE(cancelled_at, ?), updated_at = ?, finished_at = COALESCE(finished_at, ?)
|
|
443
|
+
WHERE id = ?`,
|
|
444
|
+
[JSON.stringify(request.error ?? { message: "Platform operation was cancelled." }), timestamp, timestamp, timestamp, operationId]
|
|
445
|
+
);
|
|
446
|
+
await this.appendPlatformOperationEvent(operationId, request.event?.kind ?? "runner.cancelled", request.event?.data ?? {});
|
|
447
|
+
await this.releaseRepositoryClaimsForRunner(request.runnerId, {
|
|
448
|
+
claimState: "released",
|
|
449
|
+
metadata: { operationId, status: "cancelled" }
|
|
450
|
+
});
|
|
451
|
+
return this.getOperation(operationId);
|
|
452
|
+
}
|
|
427
453
|
async upsertRepositoryClaim(input) {
|
|
428
454
|
const repositoryKeyValue = repositoryKey(input.repository);
|
|
429
455
|
const timestamp = isoNow(this.now);
|
|
@@ -154,6 +154,10 @@ export interface PlatformOperationRunnerCoreClient {
|
|
|
154
154
|
ok: true;
|
|
155
155
|
operation: PlatformOperation;
|
|
156
156
|
}>;
|
|
157
|
+
cancel?(operationId: string, request: PlatformRunnerJobUpdateRequest): Promise<{
|
|
158
|
+
ok: true;
|
|
159
|
+
operation: PlatformOperation;
|
|
160
|
+
}>;
|
|
157
161
|
}
|
|
158
162
|
export interface PlatformOperationRunnerCoreOptions {
|
|
159
163
|
client: PlatformOperationRunnerCoreClient;
|
|
@@ -262,4 +266,8 @@ export declare class PlatformRunnerClient {
|
|
|
262
266
|
ok: true;
|
|
263
267
|
operation: PlatformOperation;
|
|
264
268
|
}>;
|
|
269
|
+
cancel(operationId: string, request: PlatformRunnerJobUpdateRequest): Promise<{
|
|
270
|
+
ok: true;
|
|
271
|
+
operation: PlatformOperation;
|
|
272
|
+
}>;
|
|
265
273
|
}
|
|
@@ -190,6 +190,7 @@ async function runPlatformOperationOnce(options) {
|
|
|
190
190
|
const claimed = await options.client.claimJob({
|
|
191
191
|
runnerId: options.runnerId,
|
|
192
192
|
operationId: options.operationId ?? void 0,
|
|
193
|
+
capabilities: registry.keys(),
|
|
193
194
|
limit: options.limit ?? 1,
|
|
194
195
|
leaseSeconds: options.leaseSeconds ?? 300
|
|
195
196
|
});
|
|
@@ -259,6 +260,14 @@ async function runPlatformOperationOnce(options) {
|
|
|
259
260
|
message: error instanceof Error ? error.message : String(error)
|
|
260
261
|
};
|
|
261
262
|
const eventKind = failure.message.toLowerCase().includes("cancel") ? "runner.cancelled" : "runner.retry_safe_failure";
|
|
263
|
+
if (eventKind === "runner.cancelled" && options.client.cancel) {
|
|
264
|
+
const cancelled = await options.client.cancel(operation.id, {
|
|
265
|
+
runnerId: options.runnerId,
|
|
266
|
+
error: failure,
|
|
267
|
+
event: { kind: eventKind, data: failure }
|
|
268
|
+
});
|
|
269
|
+
return { ok: false, claimed: true, operation: cancelled.operation, error: failure };
|
|
270
|
+
}
|
|
262
271
|
if (eventKind === "runner.cancelled" && options.client.getOperation) {
|
|
263
272
|
await options.client.appendEvent(operation.id, {
|
|
264
273
|
runnerId: options.runnerId,
|
|
@@ -399,6 +408,16 @@ class PlatformRunnerClient {
|
|
|
399
408
|
return response;
|
|
400
409
|
});
|
|
401
410
|
}
|
|
411
|
+
cancel(operationId, request) {
|
|
412
|
+
return this.requestJson(`${PLATFORM_OPERATION_ENDPOINTS.runnerJob(operationId)}/cancel`, {
|
|
413
|
+
method: "POST",
|
|
414
|
+
body: { ...request, marketId: this.marketId }
|
|
415
|
+
}).then((response) => {
|
|
416
|
+
assertPlatformOperationOkEnvelope(response, "Platform operation cancellation response");
|
|
417
|
+
assertPlatformOperation(response.operation);
|
|
418
|
+
return response;
|
|
419
|
+
});
|
|
420
|
+
}
|
|
402
421
|
}
|
|
403
422
|
export {
|
|
404
423
|
PLATFORM_OPERATION_ENDPOINTS,
|
package/dist/remote.js
CHANGED
|
@@ -56,10 +56,10 @@ class RemoteTreeseedClient {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
class RemoteTreeseedAuthClient {
|
|
59
|
+
client;
|
|
59
60
|
constructor(client) {
|
|
60
61
|
this.client = client;
|
|
61
62
|
}
|
|
62
|
-
client;
|
|
63
63
|
startDeviceFlow(request) {
|
|
64
64
|
return this.client.requestJson("/auth/device/start", {
|
|
65
65
|
method: "POST",
|
|
@@ -85,10 +85,10 @@ class RemoteTreeseedAuthClient {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
class RemoteTreeseedSdkClient {
|
|
88
|
+
client;
|
|
88
89
|
constructor(client) {
|
|
89
90
|
this.client = client;
|
|
90
91
|
}
|
|
91
|
-
client;
|
|
92
92
|
execute(operation, request) {
|
|
93
93
|
return this.client.requestJson(`/sdk/${encodeURIComponent(operation)}`, {
|
|
94
94
|
method: "POST",
|
|
@@ -182,10 +182,10 @@ class CloudflareQueuePushClient {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
class RemoteTreeseedOperationsClient {
|
|
185
|
+
client;
|
|
185
186
|
constructor(client) {
|
|
186
187
|
this.client = client;
|
|
187
188
|
}
|
|
188
|
-
client;
|
|
189
189
|
execute(operation, request) {
|
|
190
190
|
return this.client.requestJson(`/operations/${encodeURIComponent(operation)}`, {
|
|
191
191
|
method: "POST",
|
|
@@ -195,10 +195,10 @@ class RemoteTreeseedOperationsClient {
|
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
class RemoteTreeseedDispatchClient {
|
|
198
|
+
client;
|
|
198
199
|
constructor(client) {
|
|
199
200
|
this.client = client;
|
|
200
201
|
}
|
|
201
|
-
client;
|
|
202
202
|
dispatch(projectId, request) {
|
|
203
203
|
return this.client.requestJson(`/v1/projects/${encodeURIComponent(projectId)}/dispatch`, {
|
|
204
204
|
method: "POST",
|
|
@@ -208,10 +208,10 @@ class RemoteTreeseedDispatchClient {
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
class RemoteTreeseedJobsClient {
|
|
211
|
+
client;
|
|
211
212
|
constructor(client) {
|
|
212
213
|
this.client = client;
|
|
213
214
|
}
|
|
214
|
-
client;
|
|
215
215
|
get(jobId) {
|
|
216
216
|
return this.client.requestJson(`/v1/jobs/${encodeURIComponent(jobId)}`, {
|
|
217
217
|
requireAuth: true
|
|
@@ -230,10 +230,10 @@ class RemoteTreeseedJobsClient {
|
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
class RemoteTreeseedRunnerClient {
|
|
233
|
+
client;
|
|
233
234
|
constructor(client) {
|
|
234
235
|
this.client = client;
|
|
235
236
|
}
|
|
236
|
-
client;
|
|
237
237
|
pull(projectId, request = {}) {
|
|
238
238
|
return this.client.requestJson(`/v1/projects/${encodeURIComponent(projectId)}/runner/jobs/pull`, {
|
|
239
239
|
method: "POST",
|
|
@@ -386,7 +386,9 @@ function resolveRepositorySlug(repoDir) {
|
|
|
386
386
|
return parseGitHubRepositoryFromRemote(remote);
|
|
387
387
|
}
|
|
388
388
|
function isProductionLikeTarget(repository, siteUrl) {
|
|
389
|
-
|
|
389
|
+
const productionRepositories = new Set(['knowledge-coop/market', 'treeseed-ai/market']);
|
|
390
|
+
const normalizedSiteUrl = String(siteUrl ?? '').replace(/\/+$/u, '').toLowerCase();
|
|
391
|
+
return productionRepositories.has(repository) || ['https://treeseed.ai', 'https://www.treeseed.ai'].includes(normalizedSiteUrl);
|
|
390
392
|
}
|
|
391
393
|
async function waitForGitHubWorkflow(repository, headSha, { timeoutMs = 900000 } = {}) {
|
|
392
394
|
const startedAt = Date.now();
|
package/dist/sdk-types.d.ts
CHANGED
|
@@ -15,7 +15,9 @@ export declare const PROJECT_EXECUTION_OWNERS: readonly ["project_api", "project
|
|
|
15
15
|
export declare const REMOTE_JOB_STATUSES: readonly ["pending", "claimed", "running", "completed", "failed", "cancelled"];
|
|
16
16
|
export declare const PROJECT_ENVIRONMENT_NAMES: readonly ["local", "staging", "prod"];
|
|
17
17
|
export declare const PROJECT_DEPLOYMENT_KINDS: readonly ["provision", "code", "content", "mixed"];
|
|
18
|
-
export declare const
|
|
18
|
+
export declare const PROJECT_WEB_DEPLOYMENT_ACTIONS: readonly ["deploy_web", "publish_content", "monitor"];
|
|
19
|
+
export declare const PROJECT_DEPLOYMENT_ENVIRONMENTS: readonly ["staging", "prod"];
|
|
20
|
+
export declare const PROJECT_DEPLOYMENT_STATUSES: readonly ["pending", "queued", "claimed", "dispatching", "running", "monitoring", "succeeded", "failed", "cancelled", "timed_out"];
|
|
19
21
|
export declare const PROJECT_INFRA_RESOURCE_PROVIDERS: readonly ["cloudflare", "railway", "github", "market"];
|
|
20
22
|
export declare const PROJECT_INFRA_RESOURCE_KINDS: readonly ["pages", "worker", "r2", "d1", "queue", "dlq", "railway_project", "railway_service", "railway_schedule"];
|
|
21
23
|
export declare const AGENT_POOL_STATUSES: readonly ["pending", "active", "degraded", "offline"];
|
|
@@ -37,7 +39,12 @@ export type ProjectExecutionOwner = (typeof PROJECT_EXECUTION_OWNERS)[number];
|
|
|
37
39
|
export type RemoteJobStatus = (typeof REMOTE_JOB_STATUSES)[number];
|
|
38
40
|
export type ProjectEnvironmentName = (typeof PROJECT_ENVIRONMENT_NAMES)[number];
|
|
39
41
|
export type ProjectDeploymentKind = (typeof PROJECT_DEPLOYMENT_KINDS)[number];
|
|
42
|
+
export type ProjectWebDeploymentAction = (typeof PROJECT_WEB_DEPLOYMENT_ACTIONS)[number];
|
|
43
|
+
export type ProjectDeploymentEnvironment = (typeof PROJECT_DEPLOYMENT_ENVIRONMENTS)[number];
|
|
40
44
|
export type ProjectDeploymentStatus = (typeof PROJECT_DEPLOYMENT_STATUSES)[number];
|
|
45
|
+
export type ProjectWebMonitorStatus = 'healthy' | 'degraded' | 'failed' | 'unknown';
|
|
46
|
+
export type ProjectWebMonitorCheckStatus = 'passed' | 'warning' | 'failed' | 'skipped';
|
|
47
|
+
export type ProjectWebMonitorCheckSource = 'market' | 'github' | 'cloudflare' | 'http' | 'sdk';
|
|
41
48
|
export type ProjectInfrastructureResourceProvider = (typeof PROJECT_INFRA_RESOURCE_PROVIDERS)[number];
|
|
42
49
|
export type ProjectInfrastructureResourceKind = (typeof PROJECT_INFRA_RESOURCE_KINDS)[number];
|
|
43
50
|
export type AgentPoolStatus = (typeof AGENT_POOL_STATUSES)[number];
|
|
@@ -194,20 +201,108 @@ export interface ProjectInfrastructureResource {
|
|
|
194
201
|
}
|
|
195
202
|
export interface ProjectDeployment {
|
|
196
203
|
id: string;
|
|
204
|
+
teamId: string | null;
|
|
197
205
|
projectId: string;
|
|
198
206
|
environment: ProjectEnvironmentName;
|
|
199
207
|
deploymentKind: ProjectDeploymentKind;
|
|
208
|
+
action: ProjectWebDeploymentAction | string;
|
|
200
209
|
status: ProjectDeploymentStatus;
|
|
210
|
+
platformOperationId: string | null;
|
|
211
|
+
retryOfDeploymentId: string | null;
|
|
212
|
+
resumedFromDeploymentId: string | null;
|
|
213
|
+
idempotencyKey: string | null;
|
|
214
|
+
requestedByUserId: string | null;
|
|
201
215
|
sourceRef: string | null;
|
|
202
216
|
releaseTag: string | null;
|
|
203
217
|
commitSha: string | null;
|
|
204
218
|
triggeredByType: string | null;
|
|
205
219
|
triggeredById: string | null;
|
|
220
|
+
repository?: Record<string, unknown>;
|
|
221
|
+
externalWorkflow?: Record<string, unknown>;
|
|
222
|
+
target?: Record<string, unknown>;
|
|
223
|
+
monitor?: Record<string, unknown>;
|
|
224
|
+
summary: string | null;
|
|
225
|
+
error?: Record<string, unknown>;
|
|
206
226
|
metadata?: Record<string, unknown>;
|
|
207
227
|
startedAt: string | null;
|
|
208
228
|
finishedAt: string | null;
|
|
209
229
|
createdAt: string;
|
|
210
230
|
updatedAt: string;
|
|
231
|
+
completedAt: string | null;
|
|
232
|
+
}
|
|
233
|
+
export interface ProjectWebMonitorCheck {
|
|
234
|
+
key: string;
|
|
235
|
+
label: string;
|
|
236
|
+
status: ProjectWebMonitorCheckStatus;
|
|
237
|
+
summary: string;
|
|
238
|
+
source: ProjectWebMonitorCheckSource;
|
|
239
|
+
url?: string;
|
|
240
|
+
inspectCommand?: string;
|
|
241
|
+
}
|
|
242
|
+
export interface ProjectWebMonitorResult {
|
|
243
|
+
environment: ProjectDeploymentEnvironment;
|
|
244
|
+
status: ProjectWebMonitorStatus;
|
|
245
|
+
checkedAt: string;
|
|
246
|
+
checks: ProjectWebMonitorCheck[];
|
|
247
|
+
urls: string[];
|
|
248
|
+
warnings: string[];
|
|
249
|
+
}
|
|
250
|
+
export interface ProjectDeploymentEvent {
|
|
251
|
+
id: string;
|
|
252
|
+
deploymentId: string;
|
|
253
|
+
projectId: string;
|
|
254
|
+
teamId: string;
|
|
255
|
+
operationId: string | null;
|
|
256
|
+
kind: string;
|
|
257
|
+
message: string;
|
|
258
|
+
status: string | null;
|
|
259
|
+
severity: string;
|
|
260
|
+
sequence: number;
|
|
261
|
+
payload?: Record<string, unknown>;
|
|
262
|
+
createdAt: string;
|
|
263
|
+
}
|
|
264
|
+
export interface ProjectDeploymentActionAvailability {
|
|
265
|
+
environment: ProjectDeploymentEnvironment;
|
|
266
|
+
action: ProjectWebDeploymentAction;
|
|
267
|
+
available: boolean;
|
|
268
|
+
blockedBy: Array<{
|
|
269
|
+
code: string;
|
|
270
|
+
message: string;
|
|
271
|
+
href?: string;
|
|
272
|
+
}>;
|
|
273
|
+
}
|
|
274
|
+
export interface ProjectDeploymentReadiness {
|
|
275
|
+
ready: boolean;
|
|
276
|
+
blockers: Array<{
|
|
277
|
+
code: string;
|
|
278
|
+
message: string;
|
|
279
|
+
href?: string;
|
|
280
|
+
}>;
|
|
281
|
+
checks: Array<{
|
|
282
|
+
code: string;
|
|
283
|
+
label: string;
|
|
284
|
+
ready: boolean;
|
|
285
|
+
message: string;
|
|
286
|
+
href?: string;
|
|
287
|
+
}>;
|
|
288
|
+
}
|
|
289
|
+
export interface CreateProjectWebDeploymentRequest {
|
|
290
|
+
environment: ProjectDeploymentEnvironment;
|
|
291
|
+
action: ProjectWebDeploymentAction;
|
|
292
|
+
source?: 'market_ui' | 'market_api' | 'cli' | 'launch_flow';
|
|
293
|
+
reason?: string;
|
|
294
|
+
idempotencyKey?: string;
|
|
295
|
+
previewId?: string | null;
|
|
296
|
+
dryRun?: boolean;
|
|
297
|
+
confirmProduction?: boolean;
|
|
298
|
+
}
|
|
299
|
+
export interface CreateProjectWebDeploymentResponse {
|
|
300
|
+
ok: true;
|
|
301
|
+
deployment: ProjectDeployment;
|
|
302
|
+
operation: Record<string, unknown>;
|
|
303
|
+
pollUrl: string;
|
|
304
|
+
eventsUrl: string;
|
|
305
|
+
stateUrl: string;
|
|
211
306
|
}
|
|
212
307
|
export interface AgentPoolAutoscalePolicy {
|
|
213
308
|
minWorkers: number;
|
|
@@ -1909,14 +2004,27 @@ export interface CreateProjectDeploymentRequest {
|
|
|
1909
2004
|
environment: ProjectEnvironmentName;
|
|
1910
2005
|
deploymentKind: ProjectDeploymentKind;
|
|
1911
2006
|
status?: ProjectDeploymentStatus;
|
|
2007
|
+
action?: ProjectWebDeploymentAction | string;
|
|
2008
|
+
platformOperationId?: string | null;
|
|
2009
|
+
retryOfDeploymentId?: string | null;
|
|
2010
|
+
resumedFromDeploymentId?: string | null;
|
|
2011
|
+
idempotencyKey?: string | null;
|
|
2012
|
+
requestedByUserId?: string | null;
|
|
1912
2013
|
sourceRef?: string | null;
|
|
1913
2014
|
releaseTag?: string | null;
|
|
1914
2015
|
commitSha?: string | null;
|
|
1915
2016
|
triggeredByType?: string | null;
|
|
1916
2017
|
triggeredById?: string | null;
|
|
2018
|
+
repository?: Record<string, unknown> | null;
|
|
2019
|
+
externalWorkflow?: Record<string, unknown> | null;
|
|
2020
|
+
target?: Record<string, unknown> | null;
|
|
2021
|
+
monitor?: Record<string, unknown> | null;
|
|
2022
|
+
summary?: string | null;
|
|
2023
|
+
error?: Record<string, unknown> | null;
|
|
1917
2024
|
metadata?: Record<string, unknown> | null;
|
|
1918
2025
|
startedAt?: string | null;
|
|
1919
2026
|
finishedAt?: string | null;
|
|
2027
|
+
completedAt?: string | null;
|
|
1920
2028
|
}
|
|
1921
2029
|
export interface UpsertAgentPoolRequest {
|
|
1922
2030
|
id?: string;
|
package/dist/sdk-types.js
CHANGED
|
@@ -41,7 +41,9 @@ const PROJECT_EXECUTION_OWNERS = ["project_api", "project_runner", "market"];
|
|
|
41
41
|
const REMOTE_JOB_STATUSES = ["pending", "claimed", "running", "completed", "failed", "cancelled"];
|
|
42
42
|
const PROJECT_ENVIRONMENT_NAMES = ["local", "staging", "prod"];
|
|
43
43
|
const PROJECT_DEPLOYMENT_KINDS = ["provision", "code", "content", "mixed"];
|
|
44
|
-
const
|
|
44
|
+
const PROJECT_WEB_DEPLOYMENT_ACTIONS = ["deploy_web", "publish_content", "monitor"];
|
|
45
|
+
const PROJECT_DEPLOYMENT_ENVIRONMENTS = ["staging", "prod"];
|
|
46
|
+
const PROJECT_DEPLOYMENT_STATUSES = ["pending", "queued", "claimed", "dispatching", "running", "monitoring", "succeeded", "failed", "cancelled", "timed_out"];
|
|
45
47
|
const PROJECT_INFRA_RESOURCE_PROVIDERS = ["cloudflare", "railway", "github", "market"];
|
|
46
48
|
const PROJECT_INFRA_RESOURCE_KINDS = [
|
|
47
49
|
"pages",
|
|
@@ -67,6 +69,7 @@ function projectConnectionModeFromHosting(kind, registration = "none") {
|
|
|
67
69
|
export {
|
|
68
70
|
AGENT_POOL_STATUSES,
|
|
69
71
|
PROJECT_CONNECTION_MODES,
|
|
72
|
+
PROJECT_DEPLOYMENT_ENVIRONMENTS,
|
|
70
73
|
PROJECT_DEPLOYMENT_KINDS,
|
|
71
74
|
PROJECT_DEPLOYMENT_STATUSES,
|
|
72
75
|
PROJECT_ENVIRONMENT_NAMES,
|
|
@@ -74,6 +77,7 @@ export {
|
|
|
74
77
|
PROJECT_INFRA_RESOURCE_KINDS,
|
|
75
78
|
PROJECT_INFRA_RESOURCE_PROVIDERS,
|
|
76
79
|
PROJECT_RUNNER_REGISTRATION_STATES,
|
|
80
|
+
PROJECT_WEB_DEPLOYMENT_ACTIONS,
|
|
77
81
|
REMOTE_JOB_STATUSES,
|
|
78
82
|
SDK_DISPATCH_EXECUTION_CLASSES,
|
|
79
83
|
SDK_DISPATCH_NAMESPACES,
|
|
@@ -135,20 +135,20 @@ CREATE TABLE IF NOT EXISTS "better_auth_account" (
|
|
|
135
135
|
"accessToken" text,
|
|
136
136
|
"refreshToken" text,
|
|
137
137
|
"idToken" text,
|
|
138
|
-
"accessTokenExpiresAt"
|
|
139
|
-
"refreshTokenExpiresAt"
|
|
138
|
+
"accessTokenExpiresAt" bigint,
|
|
139
|
+
"refreshTokenExpiresAt" bigint,
|
|
140
140
|
"scope" text,
|
|
141
141
|
"password" text,
|
|
142
|
-
"createdAt"
|
|
143
|
-
"updatedAt"
|
|
142
|
+
"createdAt" bigint NOT NULL,
|
|
143
|
+
"updatedAt" bigint NOT NULL
|
|
144
144
|
);
|
|
145
145
|
|
|
146
146
|
CREATE TABLE IF NOT EXISTS "better_auth_session" (
|
|
147
147
|
"id" text PRIMARY KEY NOT NULL,
|
|
148
|
-
"expiresAt"
|
|
148
|
+
"expiresAt" bigint NOT NULL,
|
|
149
149
|
"token" text NOT NULL,
|
|
150
|
-
"createdAt"
|
|
151
|
-
"updatedAt"
|
|
150
|
+
"createdAt" bigint NOT NULL,
|
|
151
|
+
"updatedAt" bigint NOT NULL,
|
|
152
152
|
"ipAddress" text,
|
|
153
153
|
"userAgent" text,
|
|
154
154
|
"userId" text NOT NULL,
|
|
@@ -161,8 +161,8 @@ CREATE TABLE IF NOT EXISTS "better_auth_user" (
|
|
|
161
161
|
"email" text NOT NULL,
|
|
162
162
|
"emailVerified" integer DEFAULT 0 NOT NULL,
|
|
163
163
|
"image" text,
|
|
164
|
-
"createdAt"
|
|
165
|
-
"updatedAt"
|
|
164
|
+
"createdAt" bigint NOT NULL,
|
|
165
|
+
"updatedAt" bigint NOT NULL,
|
|
166
166
|
"username" text,
|
|
167
167
|
"firstName" text,
|
|
168
168
|
"lastName" text,
|
|
@@ -173,9 +173,9 @@ CREATE TABLE IF NOT EXISTS "better_auth_verification" (
|
|
|
173
173
|
"id" text PRIMARY KEY NOT NULL,
|
|
174
174
|
"identifier" text NOT NULL,
|
|
175
175
|
"value" text NOT NULL,
|
|
176
|
-
"expiresAt"
|
|
177
|
-
"createdAt"
|
|
178
|
-
"updatedAt"
|
|
176
|
+
"expiresAt" bigint NOT NULL,
|
|
177
|
+
"createdAt" bigint NOT NULL,
|
|
178
|
+
"updatedAt" bigint NOT NULL
|
|
179
179
|
);
|
|
180
180
|
|
|
181
181
|
CREATE TABLE IF NOT EXISTS "capacity_grants" (
|
|
@@ -844,22 +844,51 @@ CREATE TABLE IF NOT EXISTS "project_connections" (
|
|
|
844
844
|
CONSTRAINT "project_connections_project_id_unique" UNIQUE("project_id")
|
|
845
845
|
);
|
|
846
846
|
|
|
847
|
+
CREATE TABLE IF NOT EXISTS "project_deployment_events" (
|
|
848
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
849
|
+
"deployment_id" text NOT NULL,
|
|
850
|
+
"project_id" text NOT NULL,
|
|
851
|
+
"team_id" text NOT NULL,
|
|
852
|
+
"operation_id" text,
|
|
853
|
+
"kind" text NOT NULL,
|
|
854
|
+
"message" text NOT NULL,
|
|
855
|
+
"status" text,
|
|
856
|
+
"severity" text DEFAULT 'info' NOT NULL,
|
|
857
|
+
"sequence" integer NOT NULL,
|
|
858
|
+
"payload_json" text DEFAULT '{}' NOT NULL,
|
|
859
|
+
"created_at" text NOT NULL
|
|
860
|
+
);
|
|
861
|
+
|
|
847
862
|
CREATE TABLE IF NOT EXISTS "project_deployments" (
|
|
848
863
|
"id" text PRIMARY KEY NOT NULL,
|
|
864
|
+
"team_id" text NOT NULL,
|
|
849
865
|
"project_id" text NOT NULL,
|
|
850
866
|
"environment" text NOT NULL,
|
|
851
867
|
"deployment_kind" text NOT NULL,
|
|
868
|
+
"action" text DEFAULT 'deploy_web' NOT NULL,
|
|
852
869
|
"status" text NOT NULL,
|
|
870
|
+
"platform_operation_id" text,
|
|
871
|
+
"retry_of_deployment_id" text,
|
|
872
|
+
"resumed_from_deployment_id" text,
|
|
873
|
+
"idempotency_key" text,
|
|
874
|
+
"requested_by_user_id" text,
|
|
853
875
|
"source_ref" text,
|
|
854
876
|
"release_tag" text,
|
|
855
877
|
"commit_sha" text,
|
|
856
878
|
"triggered_by_type" text,
|
|
857
879
|
"triggered_by_id" text,
|
|
880
|
+
"repository_json" text DEFAULT '{}' NOT NULL,
|
|
881
|
+
"external_workflow_json" text DEFAULT '{}' NOT NULL,
|
|
882
|
+
"target_json" text DEFAULT '{}' NOT NULL,
|
|
883
|
+
"monitor_json" text DEFAULT '{}' NOT NULL,
|
|
884
|
+
"summary" text,
|
|
885
|
+
"error_json" text DEFAULT '{}' NOT NULL,
|
|
858
886
|
"metadata_json" text,
|
|
859
887
|
"started_at" text,
|
|
860
888
|
"finished_at" text,
|
|
861
889
|
"created_at" text NOT NULL,
|
|
862
|
-
"updated_at" text NOT NULL
|
|
890
|
+
"updated_at" text NOT NULL,
|
|
891
|
+
"completed_at" text
|
|
863
892
|
);
|
|
864
893
|
|
|
865
894
|
CREATE TABLE IF NOT EXISTS "project_environments" (
|
|
@@ -1397,6 +1426,20 @@ CREATE TABLE IF NOT EXISTS "teams" (
|
|
|
1397
1426
|
CONSTRAINT "teams_slug_unique" UNIQUE("slug")
|
|
1398
1427
|
);
|
|
1399
1428
|
|
|
1429
|
+
CREATE TABLE IF NOT EXISTS "user_email_addresses" (
|
|
1430
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
1431
|
+
"user_id" text NOT NULL,
|
|
1432
|
+
"email" text NOT NULL,
|
|
1433
|
+
"normalized_email" text NOT NULL,
|
|
1434
|
+
"status" text DEFAULT 'pending' NOT NULL,
|
|
1435
|
+
"is_primary" integer DEFAULT 0 NOT NULL,
|
|
1436
|
+
"verification_requested_at" text,
|
|
1437
|
+
"verified_at" text,
|
|
1438
|
+
"created_at" text NOT NULL,
|
|
1439
|
+
"updated_at" text NOT NULL,
|
|
1440
|
+
CONSTRAINT "user_email_addresses_normalized_email_unique" UNIQUE("normalized_email")
|
|
1441
|
+
);
|
|
1442
|
+
|
|
1400
1443
|
CREATE TABLE IF NOT EXISTS "user_identities" (
|
|
1401
1444
|
"id" text PRIMARY KEY NOT NULL,
|
|
1402
1445
|
"user_id" text NOT NULL,
|
|
@@ -1539,7 +1582,6 @@ CREATE TABLE IF NOT EXISTS "worker_runners" (
|
|
|
1539
1582
|
"updated_at" text NOT NULL
|
|
1540
1583
|
);
|
|
1541
1584
|
|
|
1542
|
-
|
|
1543
1585
|
-- Treeseed Market schema adoption columns
|
|
1544
1586
|
ALTER TABLE "agent_messages" ADD COLUMN IF NOT EXISTS "id" integer;
|
|
1545
1587
|
ALTER TABLE "agent_messages" ADD COLUMN IF NOT EXISTS "type" text;
|
|
@@ -1680,6 +1722,9 @@ ALTER TABLE "better_auth_verification" ADD COLUMN IF NOT EXISTS "value" text;
|
|
|
1680
1722
|
ALTER TABLE "better_auth_verification" ADD COLUMN IF NOT EXISTS "expiresAt" integer;
|
|
1681
1723
|
ALTER TABLE "better_auth_verification" ADD COLUMN IF NOT EXISTS "createdAt" integer;
|
|
1682
1724
|
ALTER TABLE "better_auth_verification" ADD COLUMN IF NOT EXISTS "updatedAt" integer;
|
|
1725
|
+
ALTER TABLE "better_auth_verification" ALTER COLUMN "expiresAt" TYPE bigint;
|
|
1726
|
+
ALTER TABLE "better_auth_verification" ALTER COLUMN "createdAt" TYPE bigint;
|
|
1727
|
+
ALTER TABLE "better_auth_verification" ALTER COLUMN "updatedAt" TYPE bigint;
|
|
1683
1728
|
ALTER TABLE "capacity_grants" ADD COLUMN IF NOT EXISTS "id" text;
|
|
1684
1729
|
ALTER TABLE "capacity_grants" ADD COLUMN IF NOT EXISTS "capacity_provider_id" text;
|
|
1685
1730
|
ALTER TABLE "capacity_grants" ADD COLUMN IF NOT EXISTS "lane_id" text;
|
|
@@ -2751,6 +2796,17 @@ ALTER TABLE "worker_runners" ADD COLUMN IF NOT EXISTS "created_at" text;
|
|
|
2751
2796
|
ALTER TABLE "worker_runners" ADD COLUMN IF NOT EXISTS "updated_at" text;
|
|
2752
2797
|
-- End Treeseed Market schema adoption columns
|
|
2753
2798
|
|
|
2799
|
+
-- Backfill verified account emails from existing active credential rows.
|
|
2800
|
+
INSERT INTO user_email_addresses (
|
|
2801
|
+
id, user_id, email, normalized_email, status, is_primary, verification_requested_at, verified_at, created_at, updated_at
|
|
2802
|
+
)
|
|
2803
|
+
SELECT 'email_' || md5(user_id || ':' || LOWER(email)), user_id, email, LOWER(email), 'verified', 1, created_at, COALESCE(updated_at, created_at), created_at, updated_at
|
|
2804
|
+
FROM market_auth_credentials
|
|
2805
|
+
WHERE email IS NOT NULL
|
|
2806
|
+
AND email != ''
|
|
2807
|
+
AND status = 'active'
|
|
2808
|
+
ON CONFLICT (normalized_email) DO NOTHING;
|
|
2809
|
+
|
|
2754
2810
|
CREATE INDEX IF NOT EXISTS "idx_agent_pool_registrations_pool_heartbeat" ON "agent_pool_registrations" USING btree ("pool_id","heartbeat_at");
|
|
2755
2811
|
CREATE INDEX IF NOT EXISTS "idx_agent_pool_scale_decisions_pool_created" ON "agent_pool_scale_decisions" USING btree ("pool_id","created_at");
|
|
2756
2812
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_agent_pools_project_environment_name" ON "agent_pools" USING btree ("project_id","environment","name");
|
|
@@ -2813,7 +2869,15 @@ CREATE INDEX IF NOT EXISTS "idx_platform_repository_claims_runner" ON "platform_
|
|
|
2813
2869
|
CREATE INDEX IF NOT EXISTS "idx_priority_overrides_project_priority" ON "priority_overrides" USING btree ("project_id","priority","updated_at");
|
|
2814
2870
|
CREATE INDEX IF NOT EXISTS "idx_priority_snapshots_project_generated" ON "priority_snapshots" USING btree ("project_id","generated_at");
|
|
2815
2871
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_project_capability_grants_project_operation" ON "project_capability_grants" USING btree ("project_id","namespace","operation");
|
|
2872
|
+
CREATE INDEX IF NOT EXISTS "idx_project_deployment_events_deployment_sequence" ON "project_deployment_events" USING btree ("deployment_id","sequence");
|
|
2873
|
+
CREATE INDEX IF NOT EXISTS "idx_project_deployment_events_project_created" ON "project_deployment_events" USING btree ("project_id","created_at");
|
|
2874
|
+
CREATE INDEX IF NOT EXISTS "idx_project_deployment_events_operation" ON "project_deployment_events" USING btree ("operation_id");
|
|
2875
|
+
CREATE INDEX IF NOT EXISTS "idx_project_deployments_project_created" ON "project_deployments" USING btree ("project_id","created_at");
|
|
2816
2876
|
CREATE INDEX IF NOT EXISTS "idx_project_deployments_project_environment" ON "project_deployments" USING btree ("project_id","environment","created_at");
|
|
2877
|
+
CREATE INDEX IF NOT EXISTS "idx_project_deployments_project_status" ON "project_deployments" USING btree ("project_id","status","updated_at");
|
|
2878
|
+
CREATE INDEX IF NOT EXISTS "idx_project_deployments_operation" ON "project_deployments" USING btree ("platform_operation_id");
|
|
2879
|
+
CREATE INDEX IF NOT EXISTS "idx_project_deployments_team_created" ON "project_deployments" USING btree ("team_id","created_at");
|
|
2880
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "idx_project_deployments_idempotency" ON "project_deployments" USING btree ("project_id","idempotency_key");
|
|
2817
2881
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_project_environments_project_environment" ON "project_environments" USING btree ("project_id","environment");
|
|
2818
2882
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_project_infrastructure_resource_unique" ON "project_infrastructure_resources" USING btree ("project_id","environment","provider","resource_kind","logical_name");
|
|
2819
2883
|
CREATE INDEX IF NOT EXISTS "idx_project_summary_snapshots_team_generated" ON "project_summary_snapshots" USING btree ("team_id","generated_at");
|
|
@@ -2853,6 +2917,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS "idx_team_memberships_team_user" ON "team_memb
|
|
|
2853
2917
|
CREATE INDEX IF NOT EXISTS "idx_team_web_hosts_team_provider" ON "team_web_hosts" USING btree ("team_id","provider","status");
|
|
2854
2918
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_team_web_hosts_team_provider_name" ON "team_web_hosts" USING btree ("team_id","provider","name");
|
|
2855
2919
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_teams_name" ON "teams" USING btree ("name");
|
|
2920
|
+
CREATE INDEX IF NOT EXISTS "idx_user_email_addresses_user" ON "user_email_addresses" USING btree ("user_id","status","is_primary");
|
|
2921
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "idx_user_email_addresses_normalized" ON "user_email_addresses" USING btree ("normalized_email");
|
|
2856
2922
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_user_identities_provider_subject" ON "user_identities" USING btree ("provider","provider_subject");
|
|
2857
2923
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_user_role_bindings_user_role" ON "user_role_bindings" USING btree ("user_id","role_id");
|
|
2858
2924
|
CREATE UNIQUE INDEX IF NOT EXISTS "idx_users_username" ON "users" USING btree ("username");
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS "user_email_addresses" (
|
|
2
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
3
|
+
"user_id" text NOT NULL,
|
|
4
|
+
"email" text NOT NULL,
|
|
5
|
+
"normalized_email" text NOT NULL,
|
|
6
|
+
"status" text DEFAULT 'pending' NOT NULL,
|
|
7
|
+
"is_primary" integer DEFAULT 0 NOT NULL,
|
|
8
|
+
"verification_requested_at" text,
|
|
9
|
+
"verified_at" text,
|
|
10
|
+
"created_at" text NOT NULL,
|
|
11
|
+
"updated_at" text NOT NULL,
|
|
12
|
+
CONSTRAINT "user_email_addresses_normalized_email_unique" UNIQUE("normalized_email")
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE INDEX IF NOT EXISTS "idx_user_email_addresses_user" ON "user_email_addresses" USING btree ("user_id","status","is_primary");
|
|
16
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "idx_user_email_addresses_normalized" ON "user_email_addresses" USING btree ("normalized_email");
|
|
17
|
+
|
|
18
|
+
INSERT INTO user_email_addresses (
|
|
19
|
+
id, user_id, email, normalized_email, status, is_primary, verification_requested_at, verified_at, created_at, updated_at
|
|
20
|
+
)
|
|
21
|
+
SELECT 'email_' || md5(user_id || ':' || LOWER(email)), user_id, email, LOWER(email), 'verified', 1, created_at, COALESCE(updated_at, created_at), created_at, updated_at
|
|
22
|
+
FROM market_auth_credentials
|
|
23
|
+
WHERE email IS NOT NULL
|
|
24
|
+
AND email != ''
|
|
25
|
+
AND status = 'active'
|
|
26
|
+
ON CONFLICT (normalized_email) DO NOTHING;
|