fix(pi-claude-cli): unblock parameterless MCP tool calls in triage
Triage with claude-sonnet-4-6 via pi-claude-cli kept looping on
fn_review_spec calls that were rejected by pi's validator with
"root: must be object". Parameterless MCP tools (schema
{type:"object", properties:{}}) emit zero input_json_delta events,
so partialJson stayed "" and the catch fell through to
finalArgs = "" — a string, which TypeBox's Type.Object({}) rightly
refuses. Default empty partialJson to {} so the call lands.
Also:
- Add a 2-step reminder loop in triage before swapping to the
fallback planning model — primary models that wrote PROMPT.md
but forgot fn_review_spec recover from a nudge, no need to pay
the cold-start tax of a new triage on a different model.
- Inject @runfusion/fusion's own pi extension into dashboard/
daemon/serve sessions and propagate the path to createFnAgent
via setHostExtensionPaths so fn_* tools register globally
without requiring `pi install npm:@runfusion/fusion`.
- Drop the "historical" qualifier from replayed tool labels —
Claude was reading "TOOL RESULT (historical Read):" as
"previous session, ignore" and looping on verification.
- Remove subprocess-lifecycle stderr debug logs that landed for
hang diagnosis — root cause is fixed, the noise can go.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,7 @@ import {
|
||||
} from "@fusion/core";
|
||||
import type { AutomationRunResult, ScheduledTask } from "@fusion/core";
|
||||
import { createServer, GitHubClient, createSkillsAdapter, getProjectSettingsPath, loadTlsCredentialsFromEnv } from "@fusion/dashboard";
|
||||
import { ProjectEngineManager, PeerExchangeService } from "@fusion/engine";
|
||||
import { ProjectEngineManager, PeerExchangeService, setHostExtensionPaths } from "@fusion/engine";
|
||||
import {
|
||||
AuthStorage,
|
||||
DefaultPackageManager,
|
||||
@@ -49,6 +49,7 @@ import {
|
||||
resolveClaudeCliExtensionPaths,
|
||||
setCachedClaudeCliResolution,
|
||||
} from "./claude-cli-extension.js";
|
||||
import { resolveSelfExtension } from "./self-extension.js";
|
||||
import { createReadOnlyAuthFileStorage, mergeAuthStorageReads, wrapAuthStorageWithApiKeyProviders } from "./provider-auth.js";
|
||||
import { getFusionAuthPath, getLegacyAuthPaths, getModelRegistryModelsPath, getPackageManagerAgentDir } from "./auth-paths.js";
|
||||
import { resolveProject } from "../project-context.js";
|
||||
@@ -416,8 +417,17 @@ export async function runDaemon(opts: DaemonOptions = {}) {
|
||||
// external `pi-claude-cli` install. Drops shadowing externals (e.g. a
|
||||
// global `npm install -g pi-claude-cli`) so the upstream's once-and-lock
|
||||
// MCP-config bug can't poison sessions.
|
||||
// Inject the cli's own extension (@runfusion/fusion) so fn_* tools
|
||||
// register globally without requiring `pi install npm:@runfusion/fusion`.
|
||||
const selfExtension = resolveSelfExtension();
|
||||
const selfExtensionPaths = selfExtension.status === "ok" ? [selfExtension.path] : [];
|
||||
if (selfExtension.status !== "ok") {
|
||||
console.warn(`[extensions] self: ${selfExtension.reason}`);
|
||||
}
|
||||
setHostExtensionPaths(selfExtensionPaths);
|
||||
|
||||
const reconciledExtensionPaths = reconcileClaudeCliPaths(
|
||||
[...getEnabledPiExtensionPaths(cwd), ...packageExtensionPaths, ...claudeCliPaths],
|
||||
[...selfExtensionPaths, ...getEnabledPiExtensionPaths(cwd), ...packageExtensionPaths, ...claudeCliPaths],
|
||||
claudeCliPaths[0] ?? null,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user