refactor(server): add getErrorMessage helper and fix error-related type-aware lint errors (#704)
* refactor(server): add getErrorMessage helper and fix error-related type-aware lint errors in session.ts * fix build: correct parseClientCapabilities type handling
This commit is contained in:
@@ -78,6 +78,7 @@ import { spawnWorkspaceScript } from "./worktree-bootstrap.js";
|
|||||||
import type { WorkspaceScriptRuntimeStore } from "./workspace-script-runtime-store.js";
|
import type { WorkspaceScriptRuntimeStore } from "./workspace-script-runtime-store.js";
|
||||||
import type { DaemonConfigStore } from "./daemon-config-store.js";
|
import type { DaemonConfigStore } from "./daemon-config-store.js";
|
||||||
import { applyMutableProviderConfigToOverrides } from "./daemon-config-store.js";
|
import { applyMutableProviderConfigToOverrides } from "./daemon-config-store.js";
|
||||||
|
import { getErrorMessage, getErrorMessageOr } from "../shared/error-utils.js";
|
||||||
import type { WorkspaceGitRuntimeSnapshot, WorkspaceGitService } from "./workspace-git-service.js";
|
import type { WorkspaceGitRuntimeSnapshot, WorkspaceGitService } from "./workspace-git-service.js";
|
||||||
|
|
||||||
import { buildProviderRegistry } from "./agent/provider-registry.js";
|
import { buildProviderRegistry } from "./agent/provider-registry.js";
|
||||||
@@ -733,11 +734,13 @@ function parseClientCapabilities(
|
|||||||
return new Set();
|
return new Set();
|
||||||
}
|
}
|
||||||
const known = new Set<ClientCapability>(Object.values(CLIENT_CAPS));
|
const known = new Set<ClientCapability>(Object.values(CLIENT_CAPS));
|
||||||
return new Set(
|
const result: ClientCapability[] = [];
|
||||||
Object.entries(capabilities).flatMap(([key, value]) =>
|
for (const [key, value] of Object.entries(capabilities)) {
|
||||||
value === true && known.has(key as ClientCapability) ? [key as ClientCapability] : [],
|
if (value === true && known.has(key as ClientCapability)) {
|
||||||
),
|
result.push(key as ClientCapability);
|
||||||
);
|
}
|
||||||
|
}
|
||||||
|
return new Set(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1692,7 +1695,8 @@ export class Session {
|
|||||||
const err = error instanceof Error ? error : new Error(String(error));
|
const err = error instanceof Error ? error : new Error(String(error));
|
||||||
this.sessionLogger.error({ err }, "Error handling message");
|
this.sessionLogger.error({ err }, "Error handling message");
|
||||||
|
|
||||||
const requestId = (msg as { requestId?: unknown }).requestId;
|
const requestId =
|
||||||
|
"requestId" in msg && typeof msg.requestId === "string" ? msg.requestId : undefined;
|
||||||
if (typeof requestId === "string") {
|
if (typeof requestId === "string") {
|
||||||
try {
|
try {
|
||||||
this.emit({
|
this.emit({
|
||||||
@@ -2493,7 +2497,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Failed to update agent: ${(error as Error).message}`,
|
content: `Failed to update agent: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.emit({
|
this.emit({
|
||||||
@@ -2502,9 +2506,7 @@ export class Session {
|
|||||||
requestId,
|
requestId,
|
||||||
agentId,
|
agentId,
|
||||||
accepted: false,
|
accepted: false,
|
||||||
error: (error as Error | undefined)?.message
|
error: getErrorMessageOr(error, "Failed to update agent"),
|
||||||
? String((error as Error).message)
|
|
||||||
: "Failed to update agent",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -3168,7 +3170,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Failed to resume agent: ${(error as Error).message}`,
|
content: `Failed to resume agent: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -3321,7 +3323,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Failed to refresh agent: ${(error as Error).message}`,
|
content: `Failed to refresh agent: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -3497,7 +3499,7 @@ export class Session {
|
|||||||
type: "list_provider_models_response",
|
type: "list_provider_models_response",
|
||||||
payload: {
|
payload: {
|
||||||
provider: msg.provider,
|
provider: msg.provider,
|
||||||
error: (error as Error)?.message ?? String(error),
|
error: getErrorMessage(error),
|
||||||
fetchedAt,
|
fetchedAt,
|
||||||
requestId: msg.requestId,
|
requestId: msg.requestId,
|
||||||
},
|
},
|
||||||
@@ -3645,7 +3647,7 @@ export class Session {
|
|||||||
type: "list_provider_modes_response",
|
type: "list_provider_modes_response",
|
||||||
payload: {
|
payload: {
|
||||||
provider: msg.provider,
|
provider: msg.provider,
|
||||||
error: (error as Error)?.message ?? String(error),
|
error: getErrorMessage(error),
|
||||||
fetchedAt,
|
fetchedAt,
|
||||||
requestId: msg.requestId,
|
requestId: msg.requestId,
|
||||||
},
|
},
|
||||||
@@ -3722,7 +3724,7 @@ export class Session {
|
|||||||
type: "list_provider_features_response",
|
type: "list_provider_features_response",
|
||||||
payload: {
|
payload: {
|
||||||
provider: msg.draftConfig.provider,
|
provider: msg.draftConfig.provider,
|
||||||
error: (error as Error)?.message ?? String(error),
|
error: getErrorMessage(error),
|
||||||
fetchedAt,
|
fetchedAt,
|
||||||
requestId: msg.requestId,
|
requestId: msg.requestId,
|
||||||
},
|
},
|
||||||
@@ -3753,7 +3755,7 @@ export class Session {
|
|||||||
type: "list_available_providers_response",
|
type: "list_available_providers_response",
|
||||||
payload: {
|
payload: {
|
||||||
providers: [],
|
providers: [],
|
||||||
error: (error as Error)?.message ?? String(error),
|
error: getErrorMessage(error),
|
||||||
fetchedAt,
|
fetchedAt,
|
||||||
requestId: msg.requestId,
|
requestId: msg.requestId,
|
||||||
},
|
},
|
||||||
@@ -3999,7 +4001,7 @@ export class Session {
|
|||||||
const snapshot = await this.workspaceGitService.getSnapshot(cwd);
|
const snapshot = await this.workspaceGitService.getSnapshot(cwd);
|
||||||
return snapshot.git.isDirty === true;
|
return snapshot.git.isDirty === true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Unable to inspect git status for ${cwd}: ${(error as Error).message}`, {
|
throw new Error(`Unable to inspect git status for ${cwd}: ${getErrorMessage(error)}`, {
|
||||||
cause: error,
|
cause: error,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -4103,7 +4105,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Failed to set agent mode: ${(error as Error).message}`,
|
content: `Failed to set agent mode: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.emit({
|
this.emit({
|
||||||
@@ -4112,9 +4114,7 @@ export class Session {
|
|||||||
requestId,
|
requestId,
|
||||||
agentId,
|
agentId,
|
||||||
accepted: false,
|
accepted: false,
|
||||||
error: (error as Error | undefined)?.message
|
error: getErrorMessageOr(error, "Failed to set agent mode"),
|
||||||
? String((error as Error).message)
|
|
||||||
: "Failed to set agent mode",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -4148,7 +4148,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Failed to set agent model: ${(error as Error).message}`,
|
content: `Failed to set agent model: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.emit({
|
this.emit({
|
||||||
@@ -4157,9 +4157,7 @@ export class Session {
|
|||||||
requestId,
|
requestId,
|
||||||
agentId,
|
agentId,
|
||||||
accepted: false,
|
accepted: false,
|
||||||
error: (error as Error | undefined)?.message
|
error: getErrorMessageOr(error, "Failed to set agent model"),
|
||||||
? String((error as Error).message)
|
|
||||||
: "Failed to set agent model",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -4197,7 +4195,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Failed to set agent feature: ${(error as Error).message}`,
|
content: `Failed to set agent feature: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.emit({
|
this.emit({
|
||||||
@@ -4206,9 +4204,7 @@ export class Session {
|
|||||||
requestId,
|
requestId,
|
||||||
agentId,
|
agentId,
|
||||||
accepted: false,
|
accepted: false,
|
||||||
error: (error as Error | undefined)?.message
|
error: getErrorMessageOr(error, "Failed to set agent feature"),
|
||||||
? String((error as Error).message)
|
|
||||||
: "Failed to set agent feature",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -4245,7 +4241,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Failed to set agent thinking option: ${(error as Error).message}`,
|
content: `Failed to set agent thinking option: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.emit({
|
this.emit({
|
||||||
@@ -4254,9 +4250,7 @@ export class Session {
|
|||||||
requestId,
|
requestId,
|
||||||
agentId,
|
agentId,
|
||||||
accepted: false,
|
accepted: false,
|
||||||
error: (error as Error | undefined)?.message
|
error: getErrorMessageOr(error, "Failed to set agent thinking option"),
|
||||||
? String((error as Error).message)
|
|
||||||
: "Failed to set agent thinking option",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -4397,7 +4391,7 @@ export class Session {
|
|||||||
payload: {
|
payload: {
|
||||||
agentId,
|
agentId,
|
||||||
commands: [],
|
commands: [],
|
||||||
error: (error as Error).message,
|
error: getErrorMessage(error),
|
||||||
requestId,
|
requestId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -4439,7 +4433,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Failed to respond to permission: ${(error as Error).message}`,
|
content: `Failed to respond to permission: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
@@ -4534,7 +4528,7 @@ export class Session {
|
|||||||
return;
|
return;
|
||||||
default: {
|
default: {
|
||||||
const exhaustiveCheck: never = resolution;
|
const exhaustiveCheck: never = resolution;
|
||||||
throw new Error(`Unhandled branch resolution: ${exhaustiveCheck}`);
|
throw new Error(`Unhandled branch resolution: ${getErrorMessage(exhaustiveCheck)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -5563,7 +5557,7 @@ export class Session {
|
|||||||
mode,
|
mode,
|
||||||
directory: null,
|
directory: null,
|
||||||
file: null,
|
file: null,
|
||||||
error: (error as Error).message,
|
error: getErrorMessage(error),
|
||||||
requestId,
|
requestId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -5595,7 +5589,7 @@ export class Session {
|
|||||||
payload: {
|
payload: {
|
||||||
cwd,
|
cwd,
|
||||||
icon: null,
|
icon: null,
|
||||||
error: (error as Error).message,
|
error: getErrorMessage(error),
|
||||||
requestId,
|
requestId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -5671,7 +5665,7 @@ export class Session {
|
|||||||
fileName: null,
|
fileName: null,
|
||||||
mimeType: null,
|
mimeType: null,
|
||||||
size: null,
|
size: null,
|
||||||
error: (error as Error).message,
|
error: getErrorMessage(error),
|
||||||
requestId,
|
requestId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -5966,7 +5960,7 @@ export class Session {
|
|||||||
defaultSort: [{ key: "updated_at", direction: "desc" }],
|
defaultSort: [{ key: "updated_at", direction: "desc" }],
|
||||||
label: "fetch_agents",
|
label: "fetch_agents",
|
||||||
getId: (agent) => agent.id,
|
getId: (agent) => agent.id,
|
||||||
getSortValue: (agent, key) => {
|
getSortValue: (agent, key): number | string => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "status_priority":
|
case "status_priority":
|
||||||
return this.getStatusPriority(agent);
|
return this.getStatusPriority(agent);
|
||||||
@@ -6007,7 +6001,7 @@ export class Session {
|
|||||||
return {
|
return {
|
||||||
id: workspace.workspaceId,
|
id: workspace.workspaceId,
|
||||||
projectId: workspace.projectId,
|
projectId: workspace.projectId,
|
||||||
projectDisplayName: resolvedProjectRecord?.displayName ?? String(workspace.projectId),
|
projectDisplayName: resolvedProjectRecord?.displayName ?? workspace.projectId,
|
||||||
projectRootPath: resolvedProjectRecord?.rootPath ?? workspace.cwd,
|
projectRootPath: resolvedProjectRecord?.rootPath ?? workspace.cwd,
|
||||||
workspaceDirectory: workspace.cwd,
|
workspaceDirectory: workspace.cwd,
|
||||||
projectKind: (resolvedProjectRecord?.kind ?? "directory") === "git" ? "git" : "non_git",
|
projectKind: (resolvedProjectRecord?.kind ?? "directory") === "git" ? "git" : "non_git",
|
||||||
@@ -6095,7 +6089,7 @@ export class Session {
|
|||||||
return {
|
return {
|
||||||
id: result.workspace.workspaceId,
|
id: result.workspace.workspaceId,
|
||||||
projectId: result.workspace.projectId,
|
projectId: result.workspace.projectId,
|
||||||
projectDisplayName: projectRecord?.displayName ?? String(result.workspace.projectId),
|
projectDisplayName: projectRecord?.displayName ?? result.workspace.projectId,
|
||||||
projectRootPath: projectRecord?.rootPath ?? result.repoRoot,
|
projectRootPath: projectRecord?.rootPath ?? result.repoRoot,
|
||||||
workspaceDirectory: result.workspace.cwd,
|
workspaceDirectory: result.workspace.cwd,
|
||||||
projectKind: "git",
|
projectKind: "git",
|
||||||
@@ -7779,7 +7773,7 @@ export class Session {
|
|||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
type: "error",
|
type: "error",
|
||||||
content: `Transcription error: ${(error as Error).message}`,
|
content: `Transcription error: ${getErrorMessage(error)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Extracts a human-readable error message from an unknown error value.
|
||||||
|
* Handles Error instances, string errors, and other types safely.
|
||||||
|
*/
|
||||||
|
export function getErrorMessage(error: unknown): string {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return error.message;
|
||||||
|
}
|
||||||
|
if (typeof error === "string") {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
return String(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts an error message from an unknown error value, with a fallback
|
||||||
|
* for when no message can be extracted.
|
||||||
|
*/
|
||||||
|
export function getErrorMessageOr(error: unknown, fallback: string): string {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return error.message;
|
||||||
|
}
|
||||||
|
if (typeof error === "string" && error.length > 0) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user