mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-17 14:01:25 +00:00
Merge remote-tracking branch 'origin/main' into test-dev-webhooks-flow
# Conflicts: # factory/packages/backend/src/actors/project/actions.ts # factory/packages/backend/src/actors/workspace/actions.ts # factory/packages/frontend/src/components/mock-layout.tsx
This commit is contained in:
commit
c8a095b69f
302 changed files with 11419 additions and 9952 deletions
|
|
@ -2,24 +2,9 @@
|
|||
import { randomUUID } from "node:crypto";
|
||||
import { and, desc, eq, isNotNull, ne } from "drizzle-orm";
|
||||
import { Loop } from "rivetkit/workflow";
|
||||
import type {
|
||||
AgentType,
|
||||
HandoffRecord,
|
||||
HandoffSummary,
|
||||
ProviderId,
|
||||
RepoOverview,
|
||||
RepoStackAction,
|
||||
RepoStackActionResult
|
||||
} from "@openhandoff/shared";
|
||||
import type { AgentType, HandoffRecord, HandoffSummary, ProviderId, RepoOverview, RepoStackAction, RepoStackActionResult } from "@openhandoff/shared";
|
||||
import { getActorRuntimeContext } from "../context.js";
|
||||
import {
|
||||
getHandoff,
|
||||
getOrCreateHandoff,
|
||||
getOrCreateHistory,
|
||||
getOrCreateProjectBranchSync,
|
||||
getOrCreateProjectPrSync,
|
||||
selfProject
|
||||
} from "../handles.js";
|
||||
import { getHandoff, getOrCreateHandoff, getOrCreateHistory, getOrCreateProjectBranchSync, getOrCreateProjectPrSync, selfProject } from "../handles.js";
|
||||
import { isActorNotFoundError, logActorWarning, resolveErrorMessage } from "../logging.js";
|
||||
import { openhandoffRepoClonePath } from "../../services/openhandoff-paths.js";
|
||||
import { expectQueueResponse } from "../../services/queue.js";
|
||||
|
|
@ -164,11 +149,7 @@ async function ensureHandoffIndexHydrated(c: any): Promise<void> {
|
|||
return;
|
||||
}
|
||||
|
||||
const existing = await c.db
|
||||
.select({ handoffId: handoffIndex.handoffId })
|
||||
.from(handoffIndex)
|
||||
.limit(1)
|
||||
.get();
|
||||
const existing = await c.db.select({ handoffId: handoffIndex.handoffId }).from(handoffIndex).limit(1).get();
|
||||
|
||||
if (existing) {
|
||||
c.state.handoffIndexHydrated = true;
|
||||
|
|
@ -205,7 +186,7 @@ async function ensureHandoffIndexHydrated(c: any): Promise<void> {
|
|||
handoffId: row.handoffId,
|
||||
branchName: row.branchName,
|
||||
createdAt: row.createdAt,
|
||||
updatedAt: row.createdAt
|
||||
updatedAt: row.createdAt,
|
||||
})
|
||||
.onConflictDoNothing()
|
||||
.run();
|
||||
|
|
@ -215,14 +196,14 @@ async function ensureHandoffIndexHydrated(c: any): Promise<void> {
|
|||
logActorWarning("project", "skipped missing handoffs while hydrating index", {
|
||||
workspaceId: c.state.workspaceId,
|
||||
repoId: c.state.repoId,
|
||||
skippedMissingHandoffActors
|
||||
skippedMissingHandoffActors,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logActorWarning("project", "handoff index hydration from history failed", {
|
||||
workspaceId: c.state.workspaceId,
|
||||
repoId: c.state.repoId,
|
||||
error: resolveErrorMessage(error)
|
||||
error: resolveErrorMessage(error),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -284,7 +265,7 @@ async function enrichHandoffRecord(c: any, record: HandoffRecord): Promise<Hando
|
|||
diffStat: branches.diffStat,
|
||||
hasUnpushed: branches.hasUnpushed,
|
||||
conflictsWithMain: branches.conflictsWithMain,
|
||||
parentBranch: branches.parentBranch
|
||||
parentBranch: branches.parentBranch,
|
||||
})
|
||||
.from(branches)
|
||||
.where(eq(branches.branchName, branchName))
|
||||
|
|
@ -299,7 +280,7 @@ async function enrichHandoffRecord(c: any, record: HandoffRecord): Promise<Hando
|
|||
prAuthor: prCache.prAuthor,
|
||||
ciStatus: prCache.ciStatus,
|
||||
reviewStatus: prCache.reviewStatus,
|
||||
reviewer: prCache.reviewer
|
||||
reviewer: prCache.reviewer,
|
||||
})
|
||||
.from(prCache)
|
||||
.where(eq(prCache.branchName, branchName))
|
||||
|
|
@ -316,7 +297,7 @@ async function enrichHandoffRecord(c: any, record: HandoffRecord): Promise<Hando
|
|||
prAuthor: pr?.prAuthor ?? null,
|
||||
ciStatus: pr?.ciStatus ?? null,
|
||||
reviewStatus: pr?.reviewStatus ?? null,
|
||||
reviewer: pr?.reviewer ?? null
|
||||
reviewer: pr?.reviewer ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -329,14 +310,14 @@ async function ensureProjectMutation(c: any, cmd: EnsureProjectCommand): Promise
|
|||
.values({
|
||||
id: 1,
|
||||
remoteUrl: cmd.remoteUrl,
|
||||
updatedAt: Date.now()
|
||||
updatedAt: Date.now(),
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: repoMeta.id,
|
||||
set: {
|
||||
remoteUrl: cmd.remoteUrl,
|
||||
updatedAt: Date.now()
|
||||
}
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
})
|
||||
.run();
|
||||
|
||||
|
|
@ -358,11 +339,7 @@ async function createHandoffMutation(c: any, cmd: CreateHandoffCommand): Promise
|
|||
if (onBranch) {
|
||||
await forceProjectSync(c, localPath);
|
||||
|
||||
const branchRow = await c.db
|
||||
.select({ branchName: branches.branchName })
|
||||
.from(branches)
|
||||
.where(eq(branches.branchName, onBranch))
|
||||
.get();
|
||||
const branchRow = await c.db.select({ branchName: branches.branchName }).from(branches).where(eq(branches.branchName, onBranch)).get();
|
||||
if (!branchRow) {
|
||||
throw new Error(`Branch not found in repo snapshot: ${onBranch}`);
|
||||
}
|
||||
|
|
@ -370,7 +347,7 @@ async function createHandoffMutation(c: any, cmd: CreateHandoffCommand): Promise
|
|||
await registerHandoffBranchMutation(c, {
|
||||
handoffId,
|
||||
branchName: onBranch,
|
||||
requireExistingRemote: true
|
||||
requireExistingRemote: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -393,7 +370,11 @@ async function createHandoffMutation(c: any, cmd: CreateHandoffCommand): Promise
|
|||
});
|
||||
} catch (error) {
|
||||
if (onBranch) {
|
||||
await c.db.delete(handoffIndex).where(eq(handoffIndex.handoffId, handoffId)).run().catch(() => {});
|
||||
await c.db
|
||||
.delete(handoffIndex)
|
||||
.where(eq(handoffIndex.handoffId, handoffId))
|
||||
.run()
|
||||
.catch(() => {});
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -406,7 +387,7 @@ async function createHandoffMutation(c: any, cmd: CreateHandoffCommand): Promise
|
|||
handoffId,
|
||||
branchName: initialBranchName,
|
||||
createdAt: now,
|
||||
updatedAt: now
|
||||
updatedAt: now,
|
||||
})
|
||||
.onConflictDoNothing()
|
||||
.run();
|
||||
|
|
@ -420,17 +401,14 @@ async function createHandoffMutation(c: any, cmd: CreateHandoffCommand): Promise
|
|||
handoffId,
|
||||
payload: {
|
||||
repoId: c.state.repoId,
|
||||
providerId: cmd.providerId
|
||||
}
|
||||
providerId: cmd.providerId,
|
||||
},
|
||||
});
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
async function registerHandoffBranchMutation(
|
||||
c: any,
|
||||
cmd: RegisterHandoffBranchCommand,
|
||||
): Promise<{ branchName: string; headSha: string }> {
|
||||
async function registerHandoffBranchMutation(c: any, cmd: RegisterHandoffBranchCommand): Promise<{ branchName: string; headSha: string }> {
|
||||
const localPath = await ensureProjectReady(c);
|
||||
|
||||
const branchName = cmd.branchName.trim();
|
||||
|
|
@ -460,7 +438,7 @@ async function registerHandoffBranchMutation(
|
|||
workspaceId: c.state.workspaceId,
|
||||
repoId: c.state.repoId,
|
||||
handoffId: existingOwner.handoffId,
|
||||
branchName
|
||||
branchName,
|
||||
});
|
||||
} else {
|
||||
throw error;
|
||||
|
|
@ -510,7 +488,7 @@ async function registerHandoffBranchMutation(
|
|||
workspaceId: c.state.workspaceId,
|
||||
repoId: c.state.repoId,
|
||||
branchName,
|
||||
error: resolveErrorMessage(error)
|
||||
error: resolveErrorMessage(error),
|
||||
});
|
||||
}
|
||||
stackRows = await driver.stack.listStack(localPath).catch(() => []);
|
||||
|
|
@ -532,7 +510,7 @@ async function registerHandoffBranchMutation(
|
|||
trackedInStack: trackedInStack ? 1 : 0,
|
||||
firstSeenAt: now,
|
||||
lastSeenAt: now,
|
||||
updatedAt: now
|
||||
updatedAt: now,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: branches.branchName,
|
||||
|
|
@ -541,8 +519,8 @@ async function registerHandoffBranchMutation(
|
|||
parentBranch,
|
||||
trackedInStack: trackedInStack ? 1 : 0,
|
||||
lastSeenAt: now,
|
||||
updatedAt: now
|
||||
}
|
||||
updatedAt: now,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
|
||||
|
|
@ -552,14 +530,14 @@ async function registerHandoffBranchMutation(
|
|||
handoffId: cmd.handoffId,
|
||||
branchName,
|
||||
createdAt: now,
|
||||
updatedAt: now
|
||||
updatedAt: now,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: handoffIndex.handoffId,
|
||||
set: {
|
||||
branchName,
|
||||
updatedAt: now
|
||||
}
|
||||
updatedAt: now,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
|
||||
|
|
@ -581,7 +559,7 @@ async function runRepoStackActionMutation(c: any, cmd: RunRepoStackActionCommand
|
|||
action,
|
||||
executed: false,
|
||||
message: "git-spice is not available for this repo",
|
||||
at
|
||||
at,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -595,11 +573,7 @@ async function runRepoStackActionMutation(c: any, cmd: RunRepoStackActionCommand
|
|||
await forceProjectSync(c, localPath);
|
||||
|
||||
if (branchName) {
|
||||
const row = await c.db
|
||||
.select({ branchName: branches.branchName })
|
||||
.from(branches)
|
||||
.where(eq(branches.branchName, branchName))
|
||||
.get();
|
||||
const row = await c.db.select({ branchName: branches.branchName }).from(branches).where(eq(branches.branchName, branchName)).get();
|
||||
if (!row) {
|
||||
throw new Error(`Branch not found in repo snapshot: ${branchName}`);
|
||||
}
|
||||
|
|
@ -612,11 +586,7 @@ async function runRepoStackActionMutation(c: any, cmd: RunRepoStackActionCommand
|
|||
if (parentBranch === branchName) {
|
||||
throw new Error("parentBranch must be different from branchName");
|
||||
}
|
||||
const parentRow = await c.db
|
||||
.select({ branchName: branches.branchName })
|
||||
.from(branches)
|
||||
.where(eq(branches.branchName, parentBranch))
|
||||
.get();
|
||||
const parentRow = await c.db.select({ branchName: branches.branchName }).from(branches).where(eq(branches.branchName, parentBranch)).get();
|
||||
if (!parentRow) {
|
||||
throw new Error(`Parent branch not found in repo snapshot: ${parentBranch}`);
|
||||
}
|
||||
|
|
@ -648,15 +618,15 @@ async function runRepoStackActionMutation(c: any, cmd: RunRepoStackActionCommand
|
|||
payload: {
|
||||
action,
|
||||
branchName: branchName ?? null,
|
||||
parentBranch: parentBranch ?? null
|
||||
}
|
||||
parentBranch: parentBranch ?? null,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
logActorWarning("project", "failed appending repo stack history event", {
|
||||
workspaceId: c.state.workspaceId,
|
||||
repoId: c.state.repoId,
|
||||
action,
|
||||
error: resolveErrorMessage(error)
|
||||
error: resolveErrorMessage(error),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -664,7 +634,7 @@ async function runRepoStackActionMutation(c: any, cmd: RunRepoStackActionCommand
|
|||
action,
|
||||
executed: true,
|
||||
message: `stack action executed: ${action}`,
|
||||
at
|
||||
at,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -686,7 +656,7 @@ async function applyPrSyncResultMutation(c: any, body: PrSyncResult): Promise<vo
|
|||
reviewStatus: item.reviewStatus ?? null,
|
||||
reviewer: item.reviewer ?? null,
|
||||
fetchedAt: body.at,
|
||||
updatedAt: body.at
|
||||
updatedAt: body.at,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: prCache.branchName,
|
||||
|
|
@ -701,8 +671,8 @@ async function applyPrSyncResultMutation(c: any, body: PrSyncResult): Promise<vo
|
|||
reviewStatus: item.reviewStatus ?? null,
|
||||
reviewer: item.reviewer ?? null,
|
||||
fetchedAt: body.at,
|
||||
updatedAt: body.at
|
||||
}
|
||||
updatedAt: body.at,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
|
@ -712,11 +682,7 @@ async function applyPrSyncResultMutation(c: any, body: PrSyncResult): Promise<vo
|
|||
continue;
|
||||
}
|
||||
|
||||
const row = await c.db
|
||||
.select({ handoffId: handoffIndex.handoffId })
|
||||
.from(handoffIndex)
|
||||
.where(eq(handoffIndex.branchName, item.headRefName))
|
||||
.get();
|
||||
const row = await c.db.select({ handoffId: handoffIndex.handoffId }).from(handoffIndex).where(eq(handoffIndex.branchName, item.headRefName)).get();
|
||||
if (!row) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -732,7 +698,7 @@ async function applyPrSyncResultMutation(c: any, body: PrSyncResult): Promise<vo
|
|||
repoId: c.state.repoId,
|
||||
handoffId: row.handoffId,
|
||||
branchName: item.headRefName,
|
||||
prState: item.state
|
||||
prState: item.state,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
@ -742,7 +708,7 @@ async function applyPrSyncResultMutation(c: any, body: PrSyncResult): Promise<vo
|
|||
handoffId: row.handoffId,
|
||||
branchName: item.headRefName,
|
||||
prState: item.state,
|
||||
error: resolveErrorMessage(error)
|
||||
error: resolveErrorMessage(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -754,7 +720,7 @@ async function applyBranchSyncResultMutation(c: any, body: BranchSyncResult): Pr
|
|||
for (const item of body.items) {
|
||||
const existing = await c.db
|
||||
.select({
|
||||
firstSeenAt: branches.firstSeenAt
|
||||
firstSeenAt: branches.firstSeenAt,
|
||||
})
|
||||
.from(branches)
|
||||
.where(eq(branches.branchName, item.branchName))
|
||||
|
|
@ -772,7 +738,7 @@ async function applyBranchSyncResultMutation(c: any, body: BranchSyncResult): Pr
|
|||
conflictsWithMain: item.conflictsWithMain ? 1 : 0,
|
||||
firstSeenAt: existing?.firstSeenAt ?? body.at,
|
||||
lastSeenAt: body.at,
|
||||
updatedAt: body.at
|
||||
updatedAt: body.at,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: branches.branchName,
|
||||
|
|
@ -785,16 +751,13 @@ async function applyBranchSyncResultMutation(c: any, body: BranchSyncResult): Pr
|
|||
conflictsWithMain: item.conflictsWithMain ? 1 : 0,
|
||||
firstSeenAt: existing?.firstSeenAt ?? body.at,
|
||||
lastSeenAt: body.at,
|
||||
updatedAt: body.at
|
||||
}
|
||||
updatedAt: body.at,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
const existingRows = await c.db
|
||||
.select({ branchName: branches.branchName })
|
||||
.from(branches)
|
||||
.all();
|
||||
const existingRows = await c.db.select({ branchName: branches.branchName }).from(branches).all();
|
||||
|
||||
for (const row of existingRows) {
|
||||
if (incoming.has(row.branchName)) {
|
||||
|
|
@ -824,62 +787,60 @@ export async function runProjectWorkflow(ctx: any): Promise<void> {
|
|||
return Loop.continue(undefined);
|
||||
}
|
||||
|
||||
if (msg.name === "project.command.hydrateHandoffIndex") {
|
||||
await loopCtx.step("project-hydrate-handoff-index", async () =>
|
||||
hydrateHandoffIndexMutation(loopCtx, msg.body as HydrateHandoffIndexCommand),
|
||||
);
|
||||
await msg.complete({ ok: true });
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
if (msg.name === "project.command.hydrateHandoffIndex") {
|
||||
await loopCtx.step("project-hydrate-handoff-index", async () => hydrateHandoffIndexMutation(loopCtx, msg.body as HydrateHandoffIndexCommand));
|
||||
await msg.complete({ ok: true });
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
|
||||
if (msg.name === "project.command.createHandoff") {
|
||||
const result = await loopCtx.step({
|
||||
name: "project-create-handoff",
|
||||
timeout: 12 * 60_000,
|
||||
run: async () => createHandoffMutation(loopCtx, msg.body as CreateHandoffCommand),
|
||||
});
|
||||
await msg.complete(result);
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
if (msg.name === "project.command.createHandoff") {
|
||||
const result = await loopCtx.step({
|
||||
name: "project-create-handoff",
|
||||
timeout: 12 * 60_000,
|
||||
run: async () => createHandoffMutation(loopCtx, msg.body as CreateHandoffCommand),
|
||||
});
|
||||
await msg.complete(result);
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
|
||||
if (msg.name === "project.command.registerHandoffBranch") {
|
||||
const result = await loopCtx.step({
|
||||
name: "project-register-handoff-branch",
|
||||
timeout: 5 * 60_000,
|
||||
run: async () => registerHandoffBranchMutation(loopCtx, msg.body as RegisterHandoffBranchCommand),
|
||||
});
|
||||
await msg.complete(result);
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
if (msg.name === "project.command.registerHandoffBranch") {
|
||||
const result = await loopCtx.step({
|
||||
name: "project-register-handoff-branch",
|
||||
timeout: 5 * 60_000,
|
||||
run: async () => registerHandoffBranchMutation(loopCtx, msg.body as RegisterHandoffBranchCommand),
|
||||
});
|
||||
await msg.complete(result);
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
|
||||
if (msg.name === "project.command.runRepoStackAction") {
|
||||
const result = await loopCtx.step({
|
||||
name: "project-run-repo-stack-action",
|
||||
timeout: 12 * 60_000,
|
||||
run: async () => runRepoStackActionMutation(loopCtx, msg.body as RunRepoStackActionCommand),
|
||||
});
|
||||
await msg.complete(result);
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
if (msg.name === "project.command.runRepoStackAction") {
|
||||
const result = await loopCtx.step({
|
||||
name: "project-run-repo-stack-action",
|
||||
timeout: 12 * 60_000,
|
||||
run: async () => runRepoStackActionMutation(loopCtx, msg.body as RunRepoStackActionCommand),
|
||||
});
|
||||
await msg.complete(result);
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
|
||||
if (msg.name === "project.command.applyPrSyncResult") {
|
||||
await loopCtx.step({
|
||||
name: "project-apply-pr-sync-result",
|
||||
timeout: 60_000,
|
||||
run: async () => applyPrSyncResultMutation(loopCtx, msg.body as PrSyncResult),
|
||||
});
|
||||
await msg.complete({ ok: true });
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
if (msg.name === "project.command.applyPrSyncResult") {
|
||||
await loopCtx.step({
|
||||
name: "project-apply-pr-sync-result",
|
||||
timeout: 60_000,
|
||||
run: async () => applyPrSyncResultMutation(loopCtx, msg.body as PrSyncResult),
|
||||
});
|
||||
await msg.complete({ ok: true });
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
|
||||
if (msg.name === "project.command.applyBranchSyncResult") {
|
||||
await loopCtx.step({
|
||||
name: "project-apply-branch-sync-result",
|
||||
timeout: 60_000,
|
||||
run: async () => applyBranchSyncResultMutation(loopCtx, msg.body as BranchSyncResult),
|
||||
});
|
||||
await msg.complete({ ok: true });
|
||||
}
|
||||
if (msg.name === "project.command.applyBranchSyncResult") {
|
||||
await loopCtx.step({
|
||||
name: "project-apply-branch-sync-result",
|
||||
timeout: 60_000,
|
||||
run: async () => applyBranchSyncResultMutation(loopCtx, msg.body as BranchSyncResult),
|
||||
});
|
||||
await msg.complete({ ok: true });
|
||||
}
|
||||
|
||||
return Loop.continue(undefined);
|
||||
});
|
||||
|
|
@ -909,15 +870,9 @@ export const projectActions = {
|
|||
async listReservedBranches(c: any, _cmd?: ListReservedBranchesCommand): Promise<string[]> {
|
||||
await ensureHandoffIndexHydratedForRead(c);
|
||||
|
||||
const rows = await c.db
|
||||
.select({ branchName: handoffIndex.branchName })
|
||||
.from(handoffIndex)
|
||||
.where(isNotNull(handoffIndex.branchName))
|
||||
.all();
|
||||
const rows = await c.db.select({ branchName: handoffIndex.branchName }).from(handoffIndex).where(isNotNull(handoffIndex.branchName)).all();
|
||||
|
||||
return rows
|
||||
.map((row) => row.branchName)
|
||||
.filter((name): name is string => typeof name === "string" && name.trim().length > 0);
|
||||
return rows.map((row) => row.branchName).filter((name): name is string => typeof name === "string" && name.trim().length > 0);
|
||||
},
|
||||
|
||||
async registerHandoffBranch(c: any, cmd: RegisterHandoffBranchCommand): Promise<{ branchName: string; headSha: string }> {
|
||||
|
|
@ -944,11 +899,7 @@ export const projectActions = {
|
|||
|
||||
await ensureHandoffIndexHydratedForRead(c);
|
||||
|
||||
const handoffRows = await c.db
|
||||
.select({ handoffId: handoffIndex.handoffId })
|
||||
.from(handoffIndex)
|
||||
.orderBy(desc(handoffIndex.updatedAt))
|
||||
.all();
|
||||
const handoffRows = await c.db.select({ handoffId: handoffIndex.handoffId }).from(handoffIndex).orderBy(desc(handoffIndex.updatedAt)).all();
|
||||
|
||||
for (const row of handoffRows) {
|
||||
try {
|
||||
|
|
@ -966,7 +917,7 @@ export const projectActions = {
|
|||
branchName: record.branchName,
|
||||
title: record.title,
|
||||
status: record.status,
|
||||
updatedAt: record.updatedAt
|
||||
updatedAt: record.updatedAt,
|
||||
});
|
||||
} catch (error) {
|
||||
if (isStaleHandoffReferenceError(error)) {
|
||||
|
|
@ -974,7 +925,7 @@ export const projectActions = {
|
|||
logActorWarning("project", "pruned stale handoff index row during summary listing", {
|
||||
workspaceId: c.state.workspaceId,
|
||||
repoId: c.state.repoId,
|
||||
handoffId: row.handoffId
|
||||
handoffId: row.handoffId,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
@ -982,7 +933,7 @@ export const projectActions = {
|
|||
workspaceId: c.state.workspaceId,
|
||||
repoId: c.state.repoId,
|
||||
handoffId: row.handoffId,
|
||||
error: resolveErrorMessage(error)
|
||||
error: resolveErrorMessage(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -994,11 +945,7 @@ export const projectActions = {
|
|||
async getHandoffEnriched(c: any, cmd: GetHandoffEnrichedCommand): Promise<HandoffRecord> {
|
||||
await ensureHandoffIndexHydratedForRead(c);
|
||||
|
||||
const row = await c.db
|
||||
.select({ handoffId: handoffIndex.handoffId })
|
||||
.from(handoffIndex)
|
||||
.where(eq(handoffIndex.handoffId, cmd.handoffId))
|
||||
.get();
|
||||
const row = await c.db.select({ handoffId: handoffIndex.handoffId }).from(handoffIndex).where(eq(handoffIndex.handoffId, cmd.handoffId)).get();
|
||||
if (!row) {
|
||||
throw new Error(`Unknown handoff in repo ${c.state.repoId}: ${cmd.handoffId}`);
|
||||
}
|
||||
|
|
@ -1037,7 +984,7 @@ export const projectActions = {
|
|||
conflictsWithMain: branches.conflictsWithMain,
|
||||
firstSeenAt: branches.firstSeenAt,
|
||||
lastSeenAt: branches.lastSeenAt,
|
||||
updatedAt: branches.updatedAt
|
||||
updatedAt: branches.updatedAt,
|
||||
})
|
||||
.from(branches)
|
||||
.all();
|
||||
|
|
@ -1046,15 +993,12 @@ export const projectActions = {
|
|||
.select({
|
||||
handoffId: handoffIndex.handoffId,
|
||||
branchName: handoffIndex.branchName,
|
||||
updatedAt: handoffIndex.updatedAt
|
||||
updatedAt: handoffIndex.updatedAt,
|
||||
})
|
||||
.from(handoffIndex)
|
||||
.all();
|
||||
|
||||
const handoffMetaByBranch = new Map<
|
||||
string,
|
||||
{ handoffId: string; title: string | null; status: HandoffRecord["status"] | null; updatedAt: number }
|
||||
>();
|
||||
const handoffMetaByBranch = new Map<string, { handoffId: string; title: string | null; status: HandoffRecord["status"] | null; updatedAt: number }>();
|
||||
|
||||
for (const row of handoffRows) {
|
||||
if (!row.branchName) {
|
||||
|
|
@ -1067,7 +1011,7 @@ export const projectActions = {
|
|||
handoffId: row.handoffId,
|
||||
title: record.title ?? null,
|
||||
status: record.status,
|
||||
updatedAt: record.updatedAt
|
||||
updatedAt: record.updatedAt,
|
||||
});
|
||||
} catch (error) {
|
||||
if (isStaleHandoffReferenceError(error)) {
|
||||
|
|
@ -1076,7 +1020,7 @@ export const projectActions = {
|
|||
workspaceId: c.state.workspaceId,
|
||||
repoId: c.state.repoId,
|
||||
handoffId: row.handoffId,
|
||||
branchName: row.branchName
|
||||
branchName: row.branchName,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1085,7 +1029,7 @@ export const projectActions = {
|
|||
repoId: c.state.repoId,
|
||||
handoffId: row.handoffId,
|
||||
branchName: row.branchName,
|
||||
error: resolveErrorMessage(error)
|
||||
error: resolveErrorMessage(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1098,7 +1042,7 @@ export const projectActions = {
|
|||
prUrl: prCache.prUrl,
|
||||
ciStatus: prCache.ciStatus,
|
||||
reviewStatus: prCache.reviewStatus,
|
||||
reviewer: prCache.reviewer
|
||||
reviewer: prCache.reviewer,
|
||||
})
|
||||
.from(prCache)
|
||||
.all();
|
||||
|
|
@ -1108,8 +1052,8 @@ export const projectActions = {
|
|||
branchRowsRaw.map((row) => ({
|
||||
branchName: row.branchName,
|
||||
parentBranch: row.parentBranch ?? null,
|
||||
updatedAt: row.updatedAt
|
||||
}))
|
||||
updatedAt: row.updatedAt,
|
||||
})),
|
||||
);
|
||||
|
||||
const detailByBranch = new Map(branchRowsRaw.map((row) => [row.branchName, row]));
|
||||
|
|
@ -1137,7 +1081,7 @@ export const projectActions = {
|
|||
reviewer: pr?.reviewer ?? null,
|
||||
firstSeenAt: row.firstSeenAt ?? null,
|
||||
lastSeenAt: row.lastSeenAt ?? null,
|
||||
updatedAt: Math.max(row.updatedAt, handoffMeta?.updatedAt ?? 0)
|
||||
updatedAt: Math.max(row.updatedAt, handoffMeta?.updatedAt ?? 0),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -1148,14 +1092,11 @@ export const projectActions = {
|
|||
baseRef,
|
||||
stackAvailable,
|
||||
fetchedAt: now,
|
||||
branches: branchRows
|
||||
branches: branchRows,
|
||||
};
|
||||
},
|
||||
|
||||
async getPullRequestForBranch(
|
||||
c: any,
|
||||
cmd: GetPullRequestForBranchCommand,
|
||||
): Promise<{ number: number; status: "draft" | "ready" } | null> {
|
||||
async getPullRequestForBranch(c: any, cmd: GetPullRequestForBranchCommand): Promise<{ number: number; status: "draft" | "ready" } | null> {
|
||||
const branchName = cmd.branchName?.trim();
|
||||
if (!branchName) {
|
||||
return null;
|
||||
|
|
@ -1204,5 +1145,5 @@ export const projectActions = {
|
|||
wait: true,
|
||||
timeout: 5 * 60_000,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,4 +4,3 @@ export default defineConfig({
|
|||
out: "./src/actors/project/db/drizzle",
|
||||
schema: "./src/actors/project/db/schema.ts",
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -189,4 +189,4 @@
|
|||
"internal": {
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,4 +213,4 @@
|
|||
"internal": {
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,4 +251,4 @@
|
|||
"internal": {
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,32 +3,32 @@
|
|||
// Do not hand-edit this file.
|
||||
|
||||
const journal = {
|
||||
"entries": [
|
||||
entries: [
|
||||
{
|
||||
"idx": 0,
|
||||
"when": 1770924376062,
|
||||
"tag": "0000_stormy_the_hunter",
|
||||
"breakpoints": true
|
||||
idx: 0,
|
||||
when: 1770924376062,
|
||||
tag: "0000_stormy_the_hunter",
|
||||
breakpoints: true,
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"when": 1770947252449,
|
||||
"tag": "0001_wild_carlie_cooper",
|
||||
"breakpoints": true
|
||||
idx: 1,
|
||||
when: 1770947252449,
|
||||
tag: "0001_wild_carlie_cooper",
|
||||
breakpoints: true,
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"when": 1771276338465,
|
||||
"tag": "0002_far_war_machine",
|
||||
"breakpoints": true
|
||||
idx: 2,
|
||||
when: 1771276338465,
|
||||
tag: "0002_far_war_machine",
|
||||
breakpoints: true,
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"when": 1771369000000,
|
||||
"tag": "0003_busy_legacy",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
idx: 3,
|
||||
when: 1771369000000,
|
||||
tag: "0003_busy_legacy",
|
||||
breakpoints: true,
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
export default {
|
||||
|
|
@ -77,5 +77,5 @@ ALTER TABLE \`branches\` DROP COLUMN \`worktree_path\`;`,
|
|||
);
|
||||
`,
|
||||
m0003: `ALTER TABLE \`branches\` ADD \`tracked_in_stack\` integer;`,
|
||||
} as const
|
||||
} as const,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,5 +40,5 @@ export const handoffIndex = sqliteTable("handoff_index", {
|
|||
handoffId: text("handoff_id").notNull().primaryKey(),
|
||||
branchName: text("branch_name"),
|
||||
createdAt: integer("created_at").notNull(),
|
||||
updatedAt: integer("updated_at").notNull()
|
||||
updatedAt: integer("updated_at").notNull(),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const project = actor({
|
|||
remoteUrl: input.remoteUrl,
|
||||
localPath: null as string | null,
|
||||
syncActorsStarted: false,
|
||||
handoffIndexHydrated: false
|
||||
handoffIndexHydrated: false,
|
||||
}),
|
||||
actions: projectActions,
|
||||
run: workflow(runProjectWorkflow),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue