refactor: eliminate remaining 15 any warnings and ratchet rule to error

- TaskCard: four catch((err: any) => err.message) promise handlers in
  archive/unarchive/delete/move → catch((err) => getErrorMessage(err)).
- InlineCreateCard + QuickEntryBox: .catch((err: any)) model-load handlers
  → getErrorMessage(err) with existing @fusion/core import.
- TerminalModal: drop (navigator as any).maxTouchPoints — modern lib.dom
  types already expose the property.
- serve.ts: remove unused any annotation on OpenRouter model mapper; the
  array element type is already inferred from json.data.
- pi.js, runtime-resolution.ts, dashboard.ts, serve.ts, dev-server-port-
  detect.ts, devserver-manager.ts: drop now-stale eslint-disable comments
  that the cleanup made redundant.

Fix a prompt-builder regression surfaced by agent's `any` cleanup: toolCall
with a raw string `arguments` field must be preserved verbatim (JSON-quoted)
rather than coerced to `{}`; restores a previously-passing test.

Then promote @typescript-eslint/no-explicit-any from warn → error. Future
new anys must either come with a one-line disable + justification or use a
real type. Workspace is now lint-clean (0 problems).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-23 19:01:54 -07:00
parent 4cabe7f613
commit 4101af8547
12 changed files with 37 additions and 32 deletions

View File

@@ -866,8 +866,6 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
//
// Create the skills adapter using the same DefaultPackageManager instance
// that was set up earlier for extension resolution.
//
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const skillsAdapter = packageManager
? createSkillsAdapter({
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- dashboard's resolve() uses a looser onMissing signature than pi's DefaultPackageManager

View File

@@ -524,7 +524,7 @@ export async function runServe(
};
}>;
};
const orModels = (json.data || []).map((m: any) => {
const orModels = (json.data || []).map((m) => {
const id = (m.id || "").toLowerCase();
const name = (m.name || "").toLowerCase();
const reasoning =
@@ -615,8 +615,6 @@ export async function runServe(
//
// Create the skills adapter using the same DefaultPackageManager instance
// that was set up earlier for extension resolution.
//
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const skillsAdapter = packageManager
? createSkillsAdapter({
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- dashboard's resolve() uses a looser onMissing signature than pi's DefaultPackageManager

View File

@@ -189,9 +189,9 @@ export function InlineCreateCard({
setFavoriteModels(response.favoriteModels);
}
})
.catch((err: any) => {
.catch((err) => {
if (!cancelled) {
setModelsError(err?.message || "Failed to load models");
setModelsError(getErrorMessage(err) || "Failed to load models");
}
})
.finally(() => {

View File

@@ -175,9 +175,9 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
}
}
})
.catch((err: any) => {
.catch((err) => {
if (!cancelled) {
setModelsError(err?.message || "Failed to load models");
setModelsError(getErrorMessage(err) || "Failed to load models");
}
})
.finally(() => {

View File

@@ -702,8 +702,8 @@ function TaskCardComponent({
void onArchiveTask(task.id).then(() => {
addToast(`Archived ${task.id}`, "success");
}).catch((err: any) => {
addToast(`Failed to archive ${task.id}: ${err.message}`, "error");
}).catch((err) => {
addToast(`Failed to archive ${task.id}: ${getErrorMessage(err)}`, "error");
});
}, [addToast, onArchiveTask, task.id]);
@@ -713,8 +713,8 @@ function TaskCardComponent({
void onUnarchiveTask(task.id).then(() => {
addToast(`Unarchived ${task.id}`, "success");
}).catch((err: any) => {
addToast(`Failed to unarchive ${task.id}: ${err.message}`, "error");
}).catch((err) => {
addToast(`Failed to unarchive ${task.id}: ${getErrorMessage(err)}`, "error");
});
}, [addToast, onUnarchiveTask, task.id]);
@@ -725,8 +725,8 @@ function TaskCardComponent({
if (window.confirm(`Delete ${task.id}?`)) {
void onDeleteTask(task.id).then(() => {
addToast(`Deleted ${task.id}`, "success");
}).catch((err: any) => {
addToast(`Failed to delete ${task.id}: ${err.message}`, "error");
}).catch((err) => {
addToast(`Failed to delete ${task.id}: ${getErrorMessage(err)}`, "error");
});
}
}, [addToast, onDeleteTask, task.id]);
@@ -760,8 +760,8 @@ function TaskCardComponent({
void onMoveTask(task.id, column).then(() => {
addToast(`Moved ${task.id} to ${COLUMN_LABELS[column]}`, "success");
}).catch((err: any) => {
addToast(`Failed to move ${task.id}: ${err.message}`, "error");
}).catch((err) => {
addToast(`Failed to move ${task.id}: ${getErrorMessage(err)}`, "error");
});
}, [addToast, onMoveTask, task.id]);

View File

@@ -71,7 +71,7 @@ export async function retryDynamicImport<T>(
function isMobileDevice(): boolean {
if (typeof window === "undefined") return false;
const hasTouchScreen =
"ontouchstart" in window || (navigator as any).maxTouchPoints > 0;
"ontouchstart" in window || navigator.maxTouchPoints > 0;
const isNarrow = window.innerWidth <= 768;
return hasTouchScreen && isNarrow;
}

View File

@@ -235,7 +235,6 @@ export async function probeFallbackPorts(host = DEFAULT_PROBE_HOST, timeoutMs =
}
// Probe sequentially so first responsive common port wins deterministically.
// eslint-disable-next-line no-await-in-loop
const isOpen = await probePort(safeHost, port, safeTimeout);
if (isOpen) {
return {

View File

@@ -312,7 +312,6 @@ export class DevServerManager extends EventEmitter<DevServerManagerEvents> {
private async findFirstReachablePort(ports: number[]): Promise<number | null> {
for (const port of ports) {
// eslint-disable-next-line no-await-in-loop
const reachable = await probePort(port);
if (reachable) {
return port;

View File

@@ -4,7 +4,6 @@
* Uses Fusion auth for writes and legacy pi auth as a read-only fallback.
* Provides factory functions for creating triage and executor agent sessions.
*/
/* eslint-disable @typescript-eslint/no-explicit-any */
import { existsSync, readFileSync } from "node:fs";
import { exec } from "node:child_process";
import { promisify } from "node:util";

View File

@@ -78,7 +78,6 @@ export class DefaultPiRuntime implements AgentRuntime {
readonly name = "Default PI Runtime";
// Synchronous cached describeModel function
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private static describeModelFn: ((session: AgentSession) => string) | null = null;
/**
@@ -223,7 +222,6 @@ function wrapPluginRuntime(
describeModel: (session: AgentSession) => {
const adapter = instance as Record<string, unknown>;
if (typeof adapter.describeModel === "function") {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (adapter.describeModel as (s: AgentSession) => string)(session);
}
// Fallback to default pi describeModel - use cached sync function

View File

@@ -438,19 +438,30 @@ function contentToText(content: string | unknown[]): string {
if (block.type === "thinking") return ""; // Skip thinking — internal reasoning, not conversation
if (block.type === "toolCall") {
const name = typeof block.name === "string" ? block.name : "";
const args = block.arguments && typeof block.arguments === "object"
? (block.arguments as Record<string, unknown>)
: undefined;
const rawArgs = block.arguments;
// A toolCall may carry either parsed args (object) or the raw unparsed
// string that pi produced — preserve the raw string verbatim so callers
// can see what the model actually sent.
const argsObject =
rawArgs && typeof rawArgs === "object" ? (rawArgs as Record<string, unknown>) : undefined;
const isCustom = isCustomToolName(name);
if (isCustom) {
// Custom tools: don't reference the MCP tool name — Claude might try to re-call it.
// Just note what was done. The result follows as a TOOL RESULT message.
const argsStr = args ? JSON.stringify(args) : "{}";
const argsStr = argsObject
? JSON.stringify(argsObject)
: typeof rawArgs === "string"
? JSON.stringify(rawArgs)
: "{}";
return `[Used ${name} tool with args: ${argsStr}]`;
}
const claudeName = mapPiToolNameToClaude(name);
const claudeArgs = args ? translatePiArgsToClaude(name, args) : undefined;
const argsStr = claudeArgs ? JSON.stringify(claudeArgs) : "{}";
const claudeArgs = argsObject ? translatePiArgsToClaude(name, argsObject) : undefined;
const argsStr = claudeArgs
? JSON.stringify(claudeArgs)
: typeof rawArgs === "string"
? JSON.stringify(rawArgs)
: "{}";
return `Historical tool call (non-executable): ${claudeName} args=${argsStr}`;
}
// Unknown block types are represented as a placeholder