feat(FN-5102): complete Step 2 — prefill agent github tracking
Fusion-Task-Id: FN-5102 Fusion-Task-Lineage: 13be2941-176e-4a6e-b6fc-2bb644f7444a
This commit is contained in:
committed by
gsxdsm
parent
13977f4682
commit
000fa3d6bb
@@ -86,6 +86,7 @@ describe("agent tool github tracking end-to-end", () => {
|
|||||||
|
|
||||||
const persisted = await store.getTask(taskId);
|
const persisted = await store.getTask(taskId);
|
||||||
expect(persisted).toBeTruthy();
|
expect(persisted).toBeTruthy();
|
||||||
|
expect(persisted?.githubTracking?.enabled).toBe(true);
|
||||||
const resolvedTracking = resolveTaskGithubTracking(
|
const resolvedTracking = resolveTaskGithubTracking(
|
||||||
persisted!,
|
persisted!,
|
||||||
depsArg?.projectSettings as never,
|
depsArg?.projectSettings as never,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { rm } from "node:fs/promises";
|
|||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { TaskStore, setTaskCreatedHook, type Task } from "@fusion/core";
|
import { TaskStore, setTaskCreatedHook, type Task } from "@fusion/core";
|
||||||
import { createTaskCreateTool, createDelegateTaskTool } from "../agent-tools.js";
|
import { createAgentTask, createTaskCreateTool, createDelegateTaskTool } from "../agent-tools.js";
|
||||||
|
|
||||||
function makeTmpDir(prefix: string): string {
|
function makeTmpDir(prefix: string): string {
|
||||||
return mkdtempSync(join(tmpdir(), prefix));
|
return mkdtempSync(join(tmpdir(), prefix));
|
||||||
@@ -75,3 +75,88 @@ describe("agent task creation github-tracking hook integration", () => {
|
|||||||
await expect(run()).resolves.toBeTruthy();
|
await expect(run()).resolves.toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("createAgentTask githubTracking prefill", () => {
|
||||||
|
let rootDir: string;
|
||||||
|
let globalDir: string;
|
||||||
|
let store: TaskStore;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
setTaskCreatedHook(undefined);
|
||||||
|
rootDir = makeTmpDir("kb-engine-agent-tools-gh-track-prefill-");
|
||||||
|
globalDir = makeTmpDir("kb-engine-agent-tools-gh-track-prefill-global-");
|
||||||
|
store = new TaskStore(rootDir, globalDir, { inMemoryDb: true });
|
||||||
|
await store.init();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
setTaskCreatedHook(undefined);
|
||||||
|
store.close();
|
||||||
|
await rm(rootDir, { recursive: true, force: true });
|
||||||
|
await rm(globalDir, { recursive: true, force: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
async function createViaAgentTask(params: Record<string, unknown> = {}): Promise<{ githubTracking?: { enabled?: boolean; repoOverride?: string } }> {
|
||||||
|
const created = await createAgentTask(store, {
|
||||||
|
description: "tracking defaults task",
|
||||||
|
source: { sourceType: "api" },
|
||||||
|
...(params as never),
|
||||||
|
});
|
||||||
|
const task = await store.getTask(created.task.id);
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
it("prefills enabled=true from project defaults", async () => {
|
||||||
|
await store.updateSettings({
|
||||||
|
githubTrackingEnabledByDefault: true,
|
||||||
|
githubTrackingDefaultRepo: "owner/repo",
|
||||||
|
});
|
||||||
|
|
||||||
|
const task = await createViaAgentTask();
|
||||||
|
expect(task.githubTracking?.enabled).toBe(true);
|
||||||
|
expect(task.githubTracking?.repoOverride).toBe("owner/repo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not prefill when project defaults disabled", async () => {
|
||||||
|
await store.updateSettings({
|
||||||
|
githubTrackingEnabledByDefault: false,
|
||||||
|
githubTrackingDefaultRepo: "owner/repo",
|
||||||
|
});
|
||||||
|
|
||||||
|
const task = await createViaAgentTask();
|
||||||
|
expect(task.githubTracking).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves explicit opt-out enabled=false", async () => {
|
||||||
|
await store.updateSettings({
|
||||||
|
githubTrackingEnabledByDefault: true,
|
||||||
|
githubTrackingDefaultRepo: "owner/repo",
|
||||||
|
});
|
||||||
|
|
||||||
|
const task = await createViaAgentTask({ githubTracking: { enabled: false } });
|
||||||
|
expect(task.githubTracking?.enabled).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets enabled=true even when no repo is configured", async () => {
|
||||||
|
await store.updateSettings({
|
||||||
|
githubTrackingEnabledByDefault: true,
|
||||||
|
githubTrackingDefaultRepo: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const task = await createViaAgentTask();
|
||||||
|
expect(task.githubTracking?.enabled).toBe(true);
|
||||||
|
expect(task.githubTracking?.repoOverride).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses global-only defaults when project settings are empty", async () => {
|
||||||
|
await store.getGlobalSettingsStore().updateSettings({
|
||||||
|
githubTrackingDefaultEnabledForNewTasks: true,
|
||||||
|
githubTrackingDefaultRepo: "global/repo",
|
||||||
|
});
|
||||||
|
vi.spyOn(store, "getSettings").mockResolvedValue({} as never);
|
||||||
|
|
||||||
|
const task = await createViaAgentTask();
|
||||||
|
expect(task.githubTracking?.enabled).toBe(true);
|
||||||
|
expect(task.githubTracking?.repoOverride).toBe("global/repo");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { existsSync } from "node:fs";
|
|||||||
import { createHash } from "node:crypto";
|
import { createHash } from "node:crypto";
|
||||||
import { join, relative, resolve } from "node:path";
|
import { join, relative, resolve } from "node:path";
|
||||||
import type { AgentStore, AgentState, AgentCapability, AgentUpdateInput, TaskDocument, TaskDocumentCreateInput, TaskStore, RunMutationContext, MessageStore, Message, SourceType, Settings, ResearchRun, ResearchRunStatus, TaskCreateInput, ReflectionStore, ApprovalRequestStore, ProjectSettings, ChatStore } from "@fusion/core";
|
import type { AgentStore, AgentState, AgentCapability, AgentUpdateInput, TaskDocument, TaskDocumentCreateInput, TaskStore, RunMutationContext, MessageStore, Message, SourceType, Settings, ResearchRun, ResearchRunStatus, TaskCreateInput, ReflectionStore, ApprovalRequestStore, ProjectSettings, ChatStore } from "@fusion/core";
|
||||||
import { DASHBOARD_USER_ID, canAgentTakeImplementationTaskForExplicitRouting, dailyMemoryPath, ensureOpenClawMemoryFiles, extractAgentProvisioningRequest, formatRoleMismatchReason, getMemoryBackendCapabilities, getProjectMemory, isEphemeralAgent, memoryLongTermPath, normalizeMessageParticipant, reconcileDeterministicDuplicate, resolveAgentProvisioningPolicy, resolveMemoryBackend, resolveResearchSettings, resolveTitleSummarizerSettingsModel, runDeterministicDuplicateGuard, scheduleQmdProjectMemoryRefresh, searchProjectMemory, shouldSkipBackgroundQmdRefresh, summarizeTitle } from "@fusion/core";
|
import { DASHBOARD_USER_ID, canAgentTakeImplementationTaskForExplicitRouting, dailyMemoryPath, ensureOpenClawMemoryFiles, extractAgentProvisioningRequest, formatRoleMismatchReason, getMemoryBackendCapabilities, getProjectMemory, isEphemeralAgent, memoryLongTermPath, normalizeMessageParticipant, reconcileDeterministicDuplicate, resolveAgentProvisioningPolicy, resolveMemoryBackend, resolveResearchSettings, resolveTaskGithubTracking, resolveTitleSummarizerSettingsModel, runDeterministicDuplicateGuard, scheduleQmdProjectMemoryRefresh, searchProjectMemory, shouldSkipBackgroundQmdRefresh, summarizeTitle } from "@fusion/core";
|
||||||
import { ResearchOrchestrator } from "./research-orchestrator.js";
|
import { ResearchOrchestrator } from "./research-orchestrator.js";
|
||||||
import { ResearchProviderRegistry } from "./research/provider-registry.js";
|
import { ResearchProviderRegistry } from "./research/provider-registry.js";
|
||||||
import { ResearchStepRunner } from "./research-step-runner.js";
|
import { ResearchStepRunner } from "./research-step-runner.js";
|
||||||
@@ -634,10 +634,31 @@ export async function createAgentTask(
|
|||||||
}
|
}
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const createdTask = await store.createTask({
|
const globalSettings =
|
||||||
|
(await store.getGlobalSettingsStore?.()?.getSettings?.()) ?? {};
|
||||||
|
const resolvedTracking = resolveTaskGithubTracking(
|
||||||
|
{ githubTracking: input.githubTracking },
|
||||||
|
settings,
|
||||||
|
globalSettings,
|
||||||
|
);
|
||||||
|
|
||||||
|
const shouldPrefillGithubTrackingEnabled =
|
||||||
|
input.githubTracking?.enabled !== false && resolvedTracking.enabled;
|
||||||
|
const createInput: TaskCreateInput = {
|
||||||
...input,
|
...input,
|
||||||
source: nextSource,
|
source: nextSource,
|
||||||
}, {
|
githubTracking: shouldPrefillGithubTrackingEnabled
|
||||||
|
? {
|
||||||
|
...(input.githubTracking ?? {}),
|
||||||
|
enabled: true,
|
||||||
|
...(input.githubTracking?.repoOverride || !resolvedTracking.repo
|
||||||
|
? {}
|
||||||
|
: { repoOverride: `${resolvedTracking.repo.owner}/${resolvedTracking.repo.repo}` }),
|
||||||
|
}
|
||||||
|
: input.githubTracking,
|
||||||
|
};
|
||||||
|
|
||||||
|
const createdTask = await store.createTask(createInput, {
|
||||||
settings: { autoSummarizeTitles: settings.autoSummarizeTitles === true },
|
settings: { autoSummarizeTitles: settings.autoSummarizeTitles === true },
|
||||||
onSummarize: rootDir
|
onSummarize: rootDir
|
||||||
? async (description: string) => {
|
? async (description: string) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user