mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 02:26:12 +02:00
fix(heartbeat): keep source-free project policy stable across turns (#17447)
This commit is contained in:
1 parent
0eb2c964a7
commit
988fe0180b
2 files changed
+26
-2
No files matched your search
@@ -1,9 +1,10 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import { agents, agentTaskSessions, authUsers, companies, companyMemberships, createDb, heartbeatRuns, issues } from "@paperclipai/db";
|
||||
import { agents, agentTaskSessions, authUsers, companies, companyMemberships, createDb, heartbeatRuns, issues, plugins, projects } from "@paperclipai/db";
|
||||
import { registerServerAdapter, unregisterServerAdapter, type AdapterExecutionContext } from "../adapters/index.js";
|
||||
import { heartbeatService } from "../services/heartbeat.js";
|
||||
import { createPluginWorkspaceFixture } from "./helpers/plugin-workspaces.js";
|
||||
import { getEmbeddedPostgresTestSupport, startEmbeddedPostgresTestDatabase } from "./helpers/embedded-postgres.js";
|
||||
|
||||
const support = await getEmbeddedPostgresTestSupport();
|
||||
@@ -81,6 +82,29 @@ describePostgres("heartbeat session preparation through adapter dispatch", () =>
|
||||
expect(resumed.finished.sessionIdBefore).toBe("saved-session");
|
||||
});
|
||||
|
||||
it("keeps inherited project policy stable after binding a repository-free workspace", async () => {
|
||||
const f = await seed();
|
||||
const storage = await createPluginWorkspaceFixture(db, f.companyId);
|
||||
const [plugin] = await db.select().from(plugins).where(eq(plugins.id, storage.pluginId));
|
||||
await db.update(plugins).set({ manifestJson: { ...plugin.manifestJson, workspaceProvider: {
|
||||
...plugin.manifestJson.workspaceProvider!, defaultForProjects: { mode: "isolated_workspace", strategy: "git_worktree" },
|
||||
} } }).where(eq(plugins.id, storage.pluginId));
|
||||
const [project] = await db.insert(projects).values({ companyId: f.companyId, name: "Directory project" }).returning();
|
||||
await db.update(issues).set({ projectId: project.id }).where(eq(issues.id, f.issueId));
|
||||
try {
|
||||
const first = await execute(f);
|
||||
const [bound] = await db.select().from(issues).where(eq(issues.id, f.issueId));
|
||||
expect(bound.executionWorkspaceId).toEqual(expect.any(String));
|
||||
const next = await execute(f);
|
||||
expect(next.input.runtime.sessionId).toBe("saved-session");
|
||||
expect(next.input.config.workspaceStrategy).toEqual(first.input.config.workspaceStrategy);
|
||||
expect(next.finished.resultJson).toMatchObject({ configFreshness: {
|
||||
session: { reset: false, taskSessionReused: true, changedCategories: [] },
|
||||
workspace: { action: "reuse", workspaceReused: true, changedCategories: [], activeWorkspaceId: bound.executionWorkspaceId },
|
||||
} });
|
||||
} finally { await db.delete(plugins).where(eq(plugins.id, storage.pluginId)); }
|
||||
});
|
||||
|
||||
it("starts fresh when effective model configuration changes and persists the reason", async () => {
|
||||
const f = await seed();
|
||||
await execute(f);
|
||||
|
||||
@@ -2371,7 +2371,7 @@ export function heartbeatService(
|
||||
!boundSourceWorkspace && !taskWorkspaceIntentRow?.intent && !issueContext?.projectWorkspaceId
|
||||
? taskProjectContext : null
|
||||
);
|
||||
const parsedProjectExecutionWorkspacePolicy = workspacePolicyContext && !boundSourceWorkspace
|
||||
const parsedProjectExecutionWorkspacePolicy = workspacePolicyContext?.hasWorkspace && !boundSourceWorkspace
|
||||
? await effectiveProjectWorkspacePolicy(db, agent.companyId, workspacePolicyContext.executionWorkspacePolicy, workspacePolicyContext.hasGitSource)
|
||||
: parseProjectExecutionWorkspacePolicy(workspacePolicyContext?.executionWorkspacePolicy);
|
||||
const projectExecutionWorkspacePolicy =
|
||||
|
||||
Reference in new issue
Block a user