refactor(web): unify form controls, one notification rule, dedupe i18n copy (#54)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c7465625a4
commit
3f868ac385
50 files changed
+2391
-1190
No files matched your search
@@ -701,6 +701,35 @@ export function translateEvents(
|
||||
// Retry policy
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A fuller error string than `err.message` for the LLM request outcome. Node's `fetch`
|
||||
* wraps the real transport failure as `TypeError: terminated` and puts the actual reason
|
||||
* on `err.cause` (a socket close, `ECONNRESET`, a provider stream abort, …); taking only
|
||||
* `.message` throws that away and leaves a bare, unactionable "terminated". This walks the
|
||||
* `cause` chain and appends each level's message and error `code`, so it surfaces as e.g.
|
||||
* "terminated: other side closed (UND_ERR_SOCKET)". Segments are de-duplicated and the
|
||||
* chain walk guards against cycles; a non-Error cause tail (string/number) is still kept.
|
||||
*/
|
||||
export function describeError(error: unknown): string {
|
||||
if (!(error instanceof Error)) return String(error);
|
||||
const parts: string[] = [];
|
||||
const seen = new Set<unknown>();
|
||||
let cur: unknown = error;
|
||||
while (cur instanceof Error && !seen.has(cur)) {
|
||||
seen.add(cur);
|
||||
const code = (cur as { code?: unknown }).code;
|
||||
let piece = cur.message || cur.name;
|
||||
if (typeof code === "string" && code && !piece.includes(code)) piece = `${piece} (${code})`;
|
||||
if (piece && !parts.includes(piece)) parts.push(piece);
|
||||
cur = (cur as { cause?: unknown }).cause;
|
||||
}
|
||||
if (cur != null && !(cur instanceof Error)) {
|
||||
const tail = String(cur);
|
||||
if (tail && !parts.includes(tail)) parts.push(tail);
|
||||
}
|
||||
return parts.join(": ") || error.message || String(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether an error is an AgentHub / Provider "response delivered but unusable"
|
||||
* parse or validation error. Two shapes (@prismshadow/agenthub 0.4.x):
|
||||
@@ -906,7 +935,7 @@ export class GenerativeModel implements LLMInterface {
|
||||
} catch (err) {
|
||||
return {
|
||||
status: "failed",
|
||||
message: err instanceof Error ? err.message : String(err),
|
||||
message: describeError(err),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -984,7 +1013,7 @@ export class GenerativeModel implements LLMInterface {
|
||||
// malformed to reconnect and retry — must not be classified as failed.
|
||||
outcome = {
|
||||
status: "malformed",
|
||||
message: error instanceof Error ? error.message : String(error),
|
||||
message: describeError(error),
|
||||
};
|
||||
} else if (isRetryableError(error)) {
|
||||
outcome = { status: "timeout" }; // Network drop/network error -> needs reconnection
|
||||
@@ -993,7 +1022,7 @@ export class GenerativeModel implements LLMInterface {
|
||||
} else {
|
||||
outcome = {
|
||||
status: "failed",
|
||||
message: error instanceof Error ? error.message : String(error),
|
||||
message: describeError(error),
|
||||
};
|
||||
}
|
||||
} finally {
|
||||
|
||||
Reference in new issue
Block a user