Add agent workflows & stuff
This commit is contained in:
@@ -104,6 +104,30 @@ const applicationTables = {
|
||||
lastCheckedAt: v.optional(v.number()),
|
||||
lastUpstreamCommit: v.optional(v.string()),
|
||||
lastForkCommit: v.optional(v.string()),
|
||||
connectionId: v.optional(v.id('gitConnections')),
|
||||
githubInstallationId: v.optional(v.string()),
|
||||
githubRepositoryId: v.optional(v.number()),
|
||||
upstreamRepositoryId: v.optional(v.number()),
|
||||
syncStatus: v.optional(
|
||||
v.union(
|
||||
v.literal('unknown'),
|
||||
v.literal('up_to_date'),
|
||||
v.literal('behind'),
|
||||
v.literal('ahead'),
|
||||
v.literal('diverged'),
|
||||
v.literal('checking'),
|
||||
v.literal('conflict'),
|
||||
v.literal('error'),
|
||||
),
|
||||
),
|
||||
upstreamAheadBy: v.optional(v.number()),
|
||||
forkAheadBy: v.optional(v.number()),
|
||||
lastMergeBaseCommit: v.optional(v.string()),
|
||||
lastSyncRunId: v.optional(v.id('syncRuns')),
|
||||
lastAiReviewId: v.optional(v.id('aiReviews')),
|
||||
lastGithubRefreshAt: v.optional(v.number()),
|
||||
lastSuccessfulRefreshAt: v.optional(v.number()),
|
||||
lastError: v.optional(v.string()),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
@@ -111,6 +135,87 @@ const applicationTables = {
|
||||
.index('by_owner_status', ['ownerId', 'status'])
|
||||
.index('by_owner_provider', ['ownerId', 'provider'])
|
||||
.index('by_upstream', ['provider', 'upstreamOwner', 'upstreamRepo']),
|
||||
spoonRepositoryStates: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
upstreamFullName: v.string(),
|
||||
forkFullName: v.string(),
|
||||
upstreamDefaultBranch: v.string(),
|
||||
forkDefaultBranch: v.string(),
|
||||
upstreamHeadSha: v.optional(v.string()),
|
||||
forkHeadSha: v.optional(v.string()),
|
||||
mergeBaseSha: v.optional(v.string()),
|
||||
upstreamAheadBy: v.number(),
|
||||
forkAheadBy: v.number(),
|
||||
status: v.union(
|
||||
v.literal('up_to_date'),
|
||||
v.literal('behind'),
|
||||
v.literal('ahead'),
|
||||
v.literal('diverged'),
|
||||
v.literal('unknown'),
|
||||
),
|
||||
openForkPullRequestCount: v.number(),
|
||||
openUpstreamPullRequestCount: v.number(),
|
||||
lastCommitAt: v.optional(v.number()),
|
||||
rawCompareUrl: v.optional(v.string()),
|
||||
refreshedAt: v.number(),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner', ['ownerId'])
|
||||
.index('by_status', ['ownerId', 'status']),
|
||||
spoonCommits: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
sha: v.string(),
|
||||
side: v.union(v.literal('upstream'), v.literal('fork')),
|
||||
message: v.string(),
|
||||
authorName: v.optional(v.string()),
|
||||
authorEmail: v.optional(v.string()),
|
||||
authorLogin: v.optional(v.string()),
|
||||
committedAt: v.optional(v.number()),
|
||||
htmlUrl: v.optional(v.string()),
|
||||
filesChanged: v.optional(v.number()),
|
||||
additions: v.optional(v.number()),
|
||||
deletions: v.optional(v.number()),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_spoon_side', ['spoonId', 'side'])
|
||||
.index('by_owner', ['ownerId'])
|
||||
.index('by_sha', ['spoonId', 'sha'])
|
||||
.index('by_committed', ['spoonId', 'committedAt']),
|
||||
spoonPullRequests: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
githubId: v.number(),
|
||||
number: v.number(),
|
||||
repoFullName: v.string(),
|
||||
scope: v.union(
|
||||
v.literal('fork'),
|
||||
v.literal('upstream'),
|
||||
v.literal('from_fork_to_upstream'),
|
||||
),
|
||||
title: v.string(),
|
||||
state: v.union(v.literal('open'), v.literal('closed'), v.literal('merged')),
|
||||
draft: v.boolean(),
|
||||
authorLogin: v.optional(v.string()),
|
||||
baseRef: v.string(),
|
||||
headRef: v.string(),
|
||||
headRepoFullName: v.optional(v.string()),
|
||||
htmlUrl: v.string(),
|
||||
createdAtGithub: v.optional(v.number()),
|
||||
updatedAtGithub: v.optional(v.number()),
|
||||
mergedAtGithub: v.optional(v.number()),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_spoon_scope', ['spoonId', 'scope'])
|
||||
.index('by_owner', ['ownerId'])
|
||||
.index('by_github_id', ['githubId'])
|
||||
.index('by_state', ['spoonId', 'state']),
|
||||
syncRuns: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
@@ -143,10 +248,113 @@ const applicationTables = {
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner_status', ['ownerId', 'status'])
|
||||
.index('by_created', ['createdAt']),
|
||||
aiReviews: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
syncRunId: v.optional(v.id('syncRuns')),
|
||||
model: v.string(),
|
||||
status: v.union(
|
||||
v.literal('queued'),
|
||||
v.literal('running'),
|
||||
v.literal('completed'),
|
||||
v.literal('failed'),
|
||||
),
|
||||
reviewType: v.union(
|
||||
v.literal('upstream_update'),
|
||||
v.literal('manual_prompt'),
|
||||
v.literal('merge_safety'),
|
||||
),
|
||||
inputSummary: v.string(),
|
||||
outputSummary: v.optional(v.string()),
|
||||
risk: v.union(
|
||||
v.literal('unknown'),
|
||||
v.literal('low'),
|
||||
v.literal('medium'),
|
||||
v.literal('high'),
|
||||
),
|
||||
compatible: v.boolean(),
|
||||
requiresHumanReview: v.boolean(),
|
||||
recommendedAction: v.union(
|
||||
v.literal('sync'),
|
||||
v.literal('open_review_pr'),
|
||||
v.literal('manual_review'),
|
||||
v.literal('do_not_sync'),
|
||||
v.literal('unknown'),
|
||||
),
|
||||
potentialConflicts: v.optional(v.array(v.string())),
|
||||
importantFiles: v.optional(v.array(v.string())),
|
||||
reasoningSummary: v.optional(v.string()),
|
||||
error: v.optional(v.string()),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
completedAt: v.optional(v.number()),
|
||||
})
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner', ['ownerId'])
|
||||
.index('by_status', ['ownerId', 'status'])
|
||||
.index('by_sync_run', ['syncRunId'])
|
||||
.index('by_created', ['createdAt']),
|
||||
spoonSettings: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
autoRefreshEnabled: v.boolean(),
|
||||
autoReviewEnabled: v.boolean(),
|
||||
autoSyncEnabled: v.boolean(),
|
||||
requireAiLowRiskForSync: v.boolean(),
|
||||
requireCleanCompareForSync: v.boolean(),
|
||||
ignoredFilePatterns: v.optional(v.array(v.string())),
|
||||
importantFilePatterns: v.optional(v.array(v.string())),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner', ['ownerId']),
|
||||
spoonRemotes: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
label: v.string(),
|
||||
url: v.string(),
|
||||
remoteName: v.optional(v.string()),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner', ['ownerId']),
|
||||
userAiSettings: defineTable({
|
||||
userId: v.id('users'),
|
||||
provider: v.literal('openai'),
|
||||
encryptedApiKey: v.optional(v.string()),
|
||||
apiKeyPreview: v.optional(v.string()),
|
||||
model: v.string(),
|
||||
reasoningEffort: v.union(
|
||||
v.literal('none'),
|
||||
v.literal('minimal'),
|
||||
v.literal('low'),
|
||||
v.literal('medium'),
|
||||
v.literal('high'),
|
||||
v.literal('xhigh'),
|
||||
),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_user', ['userId'])
|
||||
.index('by_user_provider', ['userId', 'provider']),
|
||||
agentRequests: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
agentJobId: v.optional(v.id('agentJobs')),
|
||||
prompt: v.string(),
|
||||
requestType: v.optional(
|
||||
v.union(
|
||||
v.literal('manual_prompt'),
|
||||
v.literal('upstream_review'),
|
||||
v.literal('future_code_change'),
|
||||
),
|
||||
),
|
||||
priority: v.optional(
|
||||
v.union(v.literal('low'), v.literal('normal'), v.literal('high')),
|
||||
),
|
||||
source: v.optional(v.union(v.literal('user'), v.literal('system'))),
|
||||
status: v.union(
|
||||
v.literal('draft'),
|
||||
v.literal('queued'),
|
||||
@@ -157,6 +365,9 @@ const applicationTables = {
|
||||
v.literal('cancelled'),
|
||||
),
|
||||
targetBranch: v.optional(v.string()),
|
||||
selectedSecretIds: v.optional(v.array(v.id('spoonSecrets'))),
|
||||
baseBranch: v.optional(v.string()),
|
||||
requestedBranchName: v.optional(v.string()),
|
||||
mergeRequestUrl: v.optional(v.string()),
|
||||
summary: v.optional(v.string()),
|
||||
error: v.optional(v.string()),
|
||||
@@ -167,6 +378,151 @@ const applicationTables = {
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner_status', ['ownerId', 'status'])
|
||||
.index('by_created', ['createdAt']),
|
||||
spoonSecrets: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
name: v.string(),
|
||||
encryptedValue: v.string(),
|
||||
valuePreview: v.optional(v.string()),
|
||||
description: v.optional(v.string()),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner', ['ownerId'])
|
||||
.index('by_name', ['spoonId', 'name']),
|
||||
spoonAgentSettings: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
enabled: v.boolean(),
|
||||
defaultBaseBranch: v.optional(v.string()),
|
||||
branchPrefix: v.string(),
|
||||
installCommand: v.optional(v.string()),
|
||||
checkCommand: v.optional(v.string()),
|
||||
testCommand: v.optional(v.string()),
|
||||
agentModel: v.string(),
|
||||
reasoningEffort: v.union(
|
||||
v.literal('none'),
|
||||
v.literal('minimal'),
|
||||
v.literal('low'),
|
||||
v.literal('medium'),
|
||||
v.literal('high'),
|
||||
v.literal('xhigh'),
|
||||
),
|
||||
maxJobDurationMs: v.number(),
|
||||
maxOutputBytes: v.number(),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner', ['ownerId']),
|
||||
agentJobs: defineTable({
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
agentRequestId: v.id('agentRequests'),
|
||||
status: v.union(
|
||||
v.literal('queued'),
|
||||
v.literal('claimed'),
|
||||
v.literal('preparing'),
|
||||
v.literal('running'),
|
||||
v.literal('checks_running'),
|
||||
v.literal('changes_ready'),
|
||||
v.literal('draft_pr_opened'),
|
||||
v.literal('failed'),
|
||||
v.literal('cancelled'),
|
||||
v.literal('timed_out'),
|
||||
),
|
||||
prompt: v.string(),
|
||||
baseBranch: v.string(),
|
||||
workBranch: v.string(),
|
||||
githubInstallationId: v.optional(v.string()),
|
||||
forkOwner: v.string(),
|
||||
forkRepo: v.string(),
|
||||
forkUrl: v.string(),
|
||||
upstreamOwner: v.string(),
|
||||
upstreamRepo: v.string(),
|
||||
selectedSecretIds: v.array(v.id('spoonSecrets')),
|
||||
model: v.string(),
|
||||
reasoningEffort: v.union(
|
||||
v.literal('none'),
|
||||
v.literal('minimal'),
|
||||
v.literal('low'),
|
||||
v.literal('medium'),
|
||||
v.literal('high'),
|
||||
v.literal('xhigh'),
|
||||
),
|
||||
commitSha: v.optional(v.string()),
|
||||
pullRequestUrl: v.optional(v.string()),
|
||||
pullRequestNumber: v.optional(v.number()),
|
||||
summary: v.optional(v.string()),
|
||||
error: v.optional(v.string()),
|
||||
claimedBy: v.optional(v.string()),
|
||||
claimedAt: v.optional(v.number()),
|
||||
startedAt: v.optional(v.number()),
|
||||
completedAt: v.optional(v.number()),
|
||||
createdAt: v.number(),
|
||||
updatedAt: v.number(),
|
||||
})
|
||||
.index('by_owner', ['ownerId'])
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_request', ['agentRequestId'])
|
||||
.index('by_status', ['status'])
|
||||
.index('by_claim', ['status', 'createdAt']),
|
||||
agentJobEvents: defineTable({
|
||||
jobId: v.id('agentJobs'),
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
level: v.union(
|
||||
v.literal('debug'),
|
||||
v.literal('info'),
|
||||
v.literal('warn'),
|
||||
v.literal('error'),
|
||||
),
|
||||
phase: v.union(
|
||||
v.literal('queued'),
|
||||
v.literal('clone'),
|
||||
v.literal('plan'),
|
||||
v.literal('edit'),
|
||||
v.literal('install'),
|
||||
v.literal('check'),
|
||||
v.literal('test'),
|
||||
v.literal('commit'),
|
||||
v.literal('push'),
|
||||
v.literal('pr'),
|
||||
v.literal('cleanup'),
|
||||
),
|
||||
message: v.string(),
|
||||
metadata: v.optional(v.string()),
|
||||
createdAt: v.number(),
|
||||
})
|
||||
.index('by_job', ['jobId'])
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner', ['ownerId']),
|
||||
agentJobArtifacts: defineTable({
|
||||
jobId: v.id('agentJobs'),
|
||||
spoonId: v.id('spoons'),
|
||||
ownerId: v.id('users'),
|
||||
kind: v.union(
|
||||
v.literal('plan'),
|
||||
v.literal('diff'),
|
||||
v.literal('test_output'),
|
||||
v.literal('summary'),
|
||||
v.literal('error'),
|
||||
v.literal('pr_body'),
|
||||
),
|
||||
title: v.string(),
|
||||
content: v.string(),
|
||||
contentType: v.union(
|
||||
v.literal('text/markdown'),
|
||||
v.literal('text/plain'),
|
||||
v.literal('application/json'),
|
||||
v.literal('text/x-diff'),
|
||||
),
|
||||
createdAt: v.number(),
|
||||
})
|
||||
.index('by_job', ['jobId'])
|
||||
.index('by_spoon', ['spoonId'])
|
||||
.index('by_owner', ['ownerId']),
|
||||
};
|
||||
|
||||
export default defineSchema({
|
||||
|
||||
Reference in New Issue
Block a user