feat(FN-2294): merge fusion/fn-2294

This commit is contained in:
Fusion
2026-04-23 08:07:53 -07:00
committed by gsxdsm
parent e520ba0439
commit a196d3b1b7
16 changed files with 96 additions and 53 deletions

View File

@@ -1,10 +1,12 @@
/* eslint-env node */
import { existsSync, readFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import { AuthStorage } from "@mariozechner/pi-coding-agent";
import { getOAuthProvider } from "@mariozechner/pi-ai/oauth";
function getHomeDir() {
return process.env.HOME || process.env.USERPROFILE || homedir();
return globalThis.process.env.HOME || globalThis.process.env.USERPROFILE || homedir();
}
export function getFusionAuthPath(home = getHomeDir()) {
return join(home, ".fusion", "agent", "auth.json");
@@ -52,7 +54,7 @@ function readLegacyCredentials(authPaths = getLegacyAuthPaths()) {
function resolveStoredApiKey(key) {
if (!key)
return undefined;
return process.env[key] ?? key;
return globalThis.process.env[key] ?? key;
}
function resolveOAuthApiKey(providerId, credential) {
if (credential.type !== "oauth" ||

View File

@@ -7085,7 +7085,6 @@ describe("Workflow Steps Execution", () => {
currentStep: 0,
taskDoneRetryCount: 3,
log: [],
prompt: "# test\n## Steps\n### Step 0: Preflight\n- [ ] check",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});

View File

@@ -1,3 +1,5 @@
/* eslint-env node */
/**
* Lightweight structured logger for the `@fusion/engine` package.
*
@@ -27,13 +29,13 @@ export function createLogger(prefix) {
const tag = `[${prefix}]`;
return {
log(message, ...args) {
console.error(`${tag} ${message}`, ...args);
globalThis.console.error(`${tag} ${message}`, ...args);
},
warn(message, ...args) {
console.warn(`${tag} ${message}`, ...args);
globalThis.console.warn(`${tag} ${message}`, ...args);
},
error(message, ...args) {
console.error(`${tag} ${message}`, ...args);
globalThis.console.error(`${tag} ${message}`, ...args);
},
};
}

View File

@@ -311,8 +311,8 @@ function createReadOnlyPiSettingsView(cwd, agentDir) {
const fusionProjectSettings = readJsonObject(join(projectRoot, ".fusion", "settings.json"));
const mergedSettings = { ...globalSettings, ...fusionProjectSettings };
return {
getGlobalSettings: () => structuredClone(globalSettings),
getProjectSettings: () => structuredClone(fusionProjectSettings),
getGlobalSettings: () => globalThis.structuredClone(globalSettings),
getProjectSettings: () => globalThis.structuredClone(fusionProjectSettings),
getNpmCommand: () => Array.isArray(mergedSettings.npmCommand)
? [...mergedSettings.npmCommand]
: undefined,
@@ -481,9 +481,7 @@ export function wrapToolsWithBoundary(tools, worktreePath, projectRoot) {
return {
...tool,
execute: async (...args) => {
const _toolCallId = args[0];
const params = args[1];
const _signal = args[2];
// Check path argument for file operations
const pathArg = params.path;
if (pathArg && !isWorktreeAllowedPath(worktreePath, projectRoot, pathArg)) {

View File

@@ -1397,7 +1397,8 @@ describe("Engine pause/unpause cycle", () => {
store.getTask.mockResolvedValue(makeTaskDetail("FN-EP1", "in-progress"));
// Agent triggers engine pause mid-flight but continues normally (soft pause)
mockedCreateFnAgent.mockImplementation(async () => ({
mockedCreateFnAgent.mockImplementation((async (opts: any) => ({
session: {
prompt: vi.fn().mockImplementation(async () => {
// Trigger engine pause — session should NOT be terminated
@@ -1405,11 +1406,16 @@ describe("Engine pause/unpause cycle", () => {
settings: { enginePaused: true },
previous: { enginePaused: false },
});
// Session continues normally
// Session continues normally and completes by calling task_done
const taskDoneTool = opts?.customTools?.find((t: any) => t.name === "task_done");
if (taskDoneTool) {
await taskDoneTool.execute("tool-1", {});
}
}),
dispose: vi.fn(),
},
} as any));
}) as any));
const executor = new TaskExecutor(store, "/tmp/test");
await executor.execute(task);

View File

@@ -257,7 +257,6 @@ export function createSkillsOverrideFromSelection(selection, options = {}) {
}
// Log diagnostics if any
if (newDiagnostics.length > 0) {
const _purpose = sessionPurpose ? `[${sessionPurpose}]` : "skills";
for (const diag of newDiagnostics) {
piLog.warn(`[skills] ${diag.type}: ${diag.message}`);
}