@cortexkit/opencode-magic-context 0.14.1 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,12 +37,45 @@ export interface DiagnosticReport {
37
37
  historianDumps: {
38
38
  dir: string;
39
39
  count: number;
40
- recent: {
41
- name: string;
42
- ageMinutes: number;
43
- sizeKb: number;
44
- }[];
40
+ recent: HistorianDumpSummary[];
45
41
  };
42
+ /** Most recent historian-failure rows from session_meta across all sessions. */
43
+ historianFailures: HistorianFailureSummary[];
44
+ }
45
+ export interface HistorianDumpSummary {
46
+ name: string;
47
+ ageMinutes: number;
48
+ sizeKb: number;
49
+ /** Parsed metadata — only structural fields, never raw XML content. */
50
+ meta?: HistorianDumpMeta;
51
+ /** If the XML could not be parsed, reason for failure. */
52
+ parseError?: string;
53
+ }
54
+ export interface HistorianDumpMeta {
55
+ /** Number of <compartment> elements found. */
56
+ compartmentCount: number;
57
+ /** Smallest start ordinal across compartments, or null if none. */
58
+ minStart: number | null;
59
+ /** Largest end ordinal across compartments, or null if none. */
60
+ maxEnd: number | null;
61
+ /** Value of <unprocessed_from> tag, if present. */
62
+ unprocessedFrom: number | null;
63
+ /** Number of <fact> items grouped by category. */
64
+ factCountByCategory: Record<string, number>;
65
+ /** Number of <user_observations> items. */
66
+ userObservationCount: number;
67
+ /** Total number of compartment ordinal gaps (missing ranges between consecutive compartments). */
68
+ ordinalGapCount: number;
69
+ /** Total number of overlapping compartment ranges. */
70
+ ordinalOverlapCount: number;
71
+ }
72
+ export interface HistorianFailureSummary {
73
+ sessionId: string;
74
+ failureCount: number;
75
+ /** Sanitized truncated last-error text. May be empty if never set. */
76
+ lastError: string;
77
+ /** ISO timestamp of last failure, or empty if never failed. */
78
+ lastFailureAt: string;
46
79
  }
47
80
  export declare function collectDiagnostics(): Promise<DiagnosticReport>;
48
81
  export declare function renderDiagnosticsMarkdown(report: DiagnosticReport): string;
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/cli/diagnostics.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,gBAAgB,CAAC;AAMrE,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,uBAAuB,EAAE,OAAO,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,EAAE;QAChB,MAAM,EAAE,OAAO,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,CAAC;IACF,WAAW,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,kBAAkB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,SAAS,EAAE;QACP,WAAW,EAAE,OAAO,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,OAAO,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,cAAc,EAAE;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAClE,CAAC;CACL;AAgKD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CA+CpE;AASD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAwE1E"}
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/cli/diagnostics.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,gBAAgB,CAAC;AAMrE,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,uBAAuB,EAAE,OAAO,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,EAAE;QAChB,MAAM,EAAE,OAAO,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,CAAC;IACF,WAAW,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,kBAAkB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,SAAS,EAAE;QACP,WAAW,EAAE,OAAO,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,OAAO,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,cAAc,EAAE;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,oBAAoB,EAAE,CAAC;KAClC,CAAC;IACF,gFAAgF;IAChF,iBAAiB,EAAE,uBAAuB,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAC9B,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mDAAmD;IACnD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kDAAkD;IAClD,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,2CAA2C;IAC3C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kGAAkG;IAClG,eAAe,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,mBAAmB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,uBAAuB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,aAAa,EAAE,MAAM,CAAC;CACzB;AA+OD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAgDpE;AASD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CA8E1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/cli/logs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,gBAAgB,EAA6B,MAAM,eAAe,CAAC;AAMjF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAe1D;AAeD,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CACnC,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAsC7B"}
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/cli/logs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,gBAAgB,EAA6B,MAAM,eAAe,CAAC;AAMjF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAe1D;AAeD,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACxB;AA0CD,wBAAsB,iBAAiB,CACnC,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAkD7B"}
package/dist/cli.js CHANGED
@@ -8656,11 +8656,59 @@ function detectConfigPaths() {
8656
8656
 
8657
8657
  // src/cli/diagnostics.ts
8658
8658
  var import_comment_json2 = __toESM(require_src2(), 1);
8659
+ import { Database } from "bun:sqlite";
8659
8660
  import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync4, statSync } from "node:fs";
8660
8661
  import { createRequire as createRequire2 } from "node:module";
8661
8662
  import { homedir as homedir4, tmpdir as tmpdir2, userInfo } from "node:os";
8662
8663
  import { join as join7 } from "node:path";
8663
8664
 
8665
+ // src/hooks/magic-context/compartment-parser.ts
8666
+ var COMPARTMENT_REGEX = /<compartment\s+(?:id="[^"]*"\s+)?start="(\d+)"\s+end="(\d+)"\s+title="([^"]+)"\s*>(.*?)<\/compartment>/gs;
8667
+ var CATEGORY_BLOCK_REGEX = /<(WORKFLOW_RULES|ARCHITECTURE_DECISIONS|CONSTRAINTS|CONFIG_DEFAULTS|KNOWN_ISSUES|ENVIRONMENT|NAMING|USER_PREFERENCES|USER_DIRECTIVES)>(.*?)<\/\1>/gs;
8668
+ var FACT_ITEM_REGEX = /^\s*\*\s*(.+)$/gm;
8669
+ var UNPROCESSED_REGEX = /<unprocessed_from>(\d+)<\/unprocessed_from>/;
8670
+ var USER_OBSERVATIONS_REGEX = /<user_observations>(.*?)<\/user_observations>/s;
8671
+ var USER_OBS_ITEM_REGEX = /^\s*\*\s*(.+)$/gm;
8672
+ function parseCompartmentOutput(text) {
8673
+ const compartments = [];
8674
+ const facts = [];
8675
+ for (const match of text.matchAll(COMPARTMENT_REGEX)) {
8676
+ const startMessage = parseInt(match[1], 10);
8677
+ const endMessage = parseInt(match[2], 10);
8678
+ const title = unescapeXml(match[3]);
8679
+ const content = unescapeXml(match[4].trim());
8680
+ if (!Number.isNaN(startMessage) && !Number.isNaN(endMessage) && title && content) {
8681
+ compartments.push({ startMessage, endMessage, title, content });
8682
+ }
8683
+ }
8684
+ for (const categoryMatch of text.matchAll(CATEGORY_BLOCK_REGEX)) {
8685
+ const category = categoryMatch[1];
8686
+ const blockContent = categoryMatch[2];
8687
+ for (const itemMatch of blockContent.matchAll(FACT_ITEM_REGEX)) {
8688
+ const content = unescapeXml(itemMatch[1].trim());
8689
+ if (content) {
8690
+ facts.push({ category, content });
8691
+ }
8692
+ }
8693
+ }
8694
+ const unprocessedMatch = text.match(UNPROCESSED_REGEX);
8695
+ const unprocessedFrom = unprocessedMatch ? parseInt(unprocessedMatch[1], 10) : null;
8696
+ const userObservations = [];
8697
+ const userObsMatch = text.match(USER_OBSERVATIONS_REGEX);
8698
+ if (userObsMatch) {
8699
+ for (const itemMatch of userObsMatch[1].matchAll(USER_OBS_ITEM_REGEX)) {
8700
+ const obs = unescapeXml(itemMatch[1].trim());
8701
+ if (obs)
8702
+ userObservations.push(obs);
8703
+ }
8704
+ }
8705
+ compartments.sort((a, b) => a.startMessage - b.startMessage);
8706
+ return { compartments, facts, unprocessedFrom, userObservations };
8707
+ }
8708
+ function unescapeXml(s) {
8709
+ return s.replace(/&amp;/g, "&").replace(/&apos;/g, "'").replace(/&quot;/g, '"').replace(/&lt;/g, "<").replace(/&gt;/g, ">");
8710
+ }
8711
+
8664
8712
  // src/cli/opencode-helpers.ts
8665
8713
  import { execSync } from "node:child_process";
8666
8714
  function isOpenCodeInstalled() {
@@ -8840,6 +8888,40 @@ function configHasPluginEntry(config) {
8840
8888
  return false;
8841
8889
  });
8842
8890
  }
8891
+ function parseHistorianDumpMeta(path2) {
8892
+ try {
8893
+ const xml = readFileSync4(path2, "utf-8");
8894
+ const parsed = parseCompartmentOutput(xml);
8895
+ const factCountByCategory = {};
8896
+ for (const fact of parsed.facts) {
8897
+ factCountByCategory[fact.category] = (factCountByCategory[fact.category] ?? 0) + 1;
8898
+ }
8899
+ const starts = parsed.compartments.map((c) => c.startMessage);
8900
+ const ends = parsed.compartments.map((c) => c.endMessage);
8901
+ let gaps = 0;
8902
+ let overlaps = 0;
8903
+ for (let i = 1;i < parsed.compartments.length; i++) {
8904
+ const prev = parsed.compartments[i - 1];
8905
+ const curr = parsed.compartments[i];
8906
+ if (curr.startMessage > prev.endMessage + 1)
8907
+ gaps += 1;
8908
+ else if (curr.startMessage <= prev.endMessage)
8909
+ overlaps += 1;
8910
+ }
8911
+ return {
8912
+ compartmentCount: parsed.compartments.length,
8913
+ minStart: starts.length > 0 ? Math.min(...starts) : null,
8914
+ maxEnd: ends.length > 0 ? Math.max(...ends) : null,
8915
+ unprocessedFrom: parsed.unprocessedFrom,
8916
+ factCountByCategory,
8917
+ userObservationCount: parsed.userObservations.length,
8918
+ ordinalGapCount: gaps,
8919
+ ordinalOverlapCount: overlaps
8920
+ };
8921
+ } catch (error) {
8922
+ return { error: error instanceof Error ? error.message : String(error) };
8923
+ }
8924
+ }
8843
8925
  function collectHistorianDumps() {
8844
8926
  const dir = join7(tmpdir2(), "magic-context-historian");
8845
8927
  if (!existsSync6(dir)) {
@@ -8855,16 +8937,49 @@ function collectHistorianDumps() {
8855
8937
  };
8856
8938
  }).sort((a, b) => b.mtime - a.mtime);
8857
8939
  const now = Date.now();
8858
- const recent = entries.slice(0, 3).map((entry) => ({
8859
- name: entry.name,
8860
- ageMinutes: Math.round((now - entry.mtime) / 60000),
8861
- sizeKb: entry.sizeKb
8862
- }));
8940
+ const recent = entries.slice(0, 5).map((entry) => {
8941
+ const meta = parseHistorianDumpMeta(join7(dir, entry.name));
8942
+ const summary = {
8943
+ name: entry.name,
8944
+ ageMinutes: Math.round((now - entry.mtime) / 60000),
8945
+ sizeKb: entry.sizeKb
8946
+ };
8947
+ if ("error" in meta) {
8948
+ summary.parseError = meta.error;
8949
+ } else {
8950
+ summary.meta = meta;
8951
+ }
8952
+ return summary;
8953
+ });
8863
8954
  return { dir, count: entries.length, recent };
8864
8955
  } catch {
8865
8956
  return { dir, count: 0, recent: [] };
8866
8957
  }
8867
8958
  }
8959
+ function collectHistorianFailures(storageDirPath) {
8960
+ const contextDbPath = join7(storageDirPath, "context.db");
8961
+ if (!existsSync6(contextDbPath))
8962
+ return [];
8963
+ let db = null;
8964
+ try {
8965
+ db = new Database(contextDbPath, { readonly: true });
8966
+ const rows = db.prepare("SELECT session_id, historian_failure_count, historian_last_error, historian_last_failure_at FROM session_meta WHERE historian_failure_count > 0 ORDER BY historian_last_failure_at DESC LIMIT 10").all();
8967
+ return rows.map((row) => {
8968
+ const sessionId = typeof row.session_id === "string" ? row.session_id : "<unknown>";
8969
+ const failureCount = typeof row.historian_failure_count === "number" ? row.historian_failure_count : 0;
8970
+ const rawError = typeof row.historian_last_error === "string" ? row.historian_last_error : "";
8971
+ const lastAt = typeof row.historian_last_failure_at === "number" ? new Date(row.historian_last_failure_at).toISOString() : "";
8972
+ const lastError = sanitizeString(rawError.replace(/\s+/g, " ").trim().slice(0, 400));
8973
+ return { sessionId, failureCount, lastError, lastFailureAt: lastAt };
8974
+ });
8975
+ } catch {
8976
+ return [];
8977
+ } finally {
8978
+ try {
8979
+ db?.close();
8980
+ } catch {}
8981
+ }
8982
+ }
8868
8983
  async function collectDiagnostics() {
8869
8984
  const pluginVersion = getSelfVersion();
8870
8985
  const configPaths = detectConfigPaths();
@@ -8907,7 +9022,8 @@ async function collectDiagnostics() {
8907
9022
  exists: existsSync6(logPath),
8908
9023
  sizeKb: Math.round(logFileSize / 1024)
8909
9024
  },
8910
- historianDumps: collectHistorianDumps()
9025
+ historianDumps: collectHistorianDumps(),
9026
+ historianFailures: collectHistorianFailures(storageDirPath)
8911
9027
  };
8912
9028
  }
8913
9029
  function formatBytes(bytes) {
@@ -8976,9 +9092,14 @@ function renderDiagnosticsMarkdown(report) {
8976
9092
  "```",
8977
9093
  "",
8978
9094
  "### Historian dumps",
9095
+ "(Metadata only — XML content is not included in this report.)",
8979
9096
  "```json",
8980
9097
  JSON.stringify(historianDumps, null, 2),
8981
9098
  "```",
9099
+ "",
9100
+ "### Historian failures (session_meta)",
9101
+ report.historianFailures.length === 0 ? "_No sessions with historian failures._" : ["```json", JSON.stringify(report.historianFailures, null, 2), "```"].join(`
9102
+ `),
8982
9103
  "",
8983
9104
  "### Log file",
8984
9105
  `- Path: ${sanitizeString(report.logFile.path)}`,
@@ -9022,11 +9143,36 @@ function formatTimestamp(date) {
9022
9143
  pad(date.getSeconds())
9023
9144
  ].join("");
9024
9145
  }
9146
+ var HISTORIAN_LOG_PATTERNS = [
9147
+ /historian failure:/,
9148
+ /historian failure recorded:/,
9149
+ /historian prompt failed:/,
9150
+ /## Historian alert/,
9151
+ /historian alert suppressed/,
9152
+ /EMERGENCY: aborting session/,
9153
+ /historian: prompt attempt \d+ failed:/
9154
+ ];
9155
+ function isHistorianLogLine(line) {
9156
+ return HISTORIAN_LOG_PATTERNS.some((rx) => rx.test(line));
9157
+ }
9158
+ function extractHistorianFailureLines(sanitized, limit = 30) {
9159
+ const matches = [];
9160
+ const lines = sanitized.split(/\r?\n/);
9161
+ for (let i = lines.length - 1;i >= 0 && matches.length < limit; i -= 1) {
9162
+ if (isHistorianLogLine(lines[i])) {
9163
+ matches.push(lines[i]);
9164
+ }
9165
+ }
9166
+ return matches.reverse();
9167
+ }
9025
9168
  async function bundleIssueReport(report, description, _title) {
9026
- const LOG_TAIL_LINES = 200;
9169
+ const LOG_TAIL_LINES = 400;
9027
9170
  const logLines = report.logFile.exists ? readFileSync5(report.logFile.path, "utf-8").split(/\r?\n/) : [];
9028
9171
  const recentLog = sanitizeLogContent(logLines.slice(-LOG_TAIL_LINES).join(`
9029
9172
  `)).trim();
9173
+ const historianScanWindow = sanitizeLogContent(logLines.slice(-4000).join(`
9174
+ `));
9175
+ const historianFailureLines = extractHistorianFailureLines(historianScanWindow, 30);
9030
9176
  const configBody = JSON.stringify(report.magicContextConfig.flags, null, 2);
9031
9177
  const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(homedir5(), "~");
9032
9178
  const bodyMarkdown = [
@@ -9047,6 +9193,11 @@ async function bundleIssueReport(report, description, _title) {
9047
9193
  "",
9048
9194
  "## Diagnostics",
9049
9195
  renderDiagnosticsMarkdown(report),
9196
+ "",
9197
+ "## Historian failure signals (log, sanitized)",
9198
+ historianFailureLines.length === 0 ? "_No historian failure log lines found in recent history._" : ["```", historianFailureLines.join(`
9199
+ `), "```"].join(`
9200
+ `),
9050
9201
  "",
9051
9202
  `## Log (last ${LOG_TAIL_LINES} lines, sanitized)`,
9052
9203
  "```",
@@ -1 +1 @@
1
- {"version":3,"file":"storage-meta-persisted.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/storage-meta-persisted.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage-meta-persisted.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/storage-meta-persisted.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"compartment-runner-incremental.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/compartment-runner-incremental.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAoBxE,+DAA+D;AAC/D,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEhE;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0OpF"}
1
+ {"version":3,"file":"compartment-runner-incremental.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/compartment-runner-incremental.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAoBxE,+DAA+D;AAC/D,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEhE;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoQpF"}
@@ -1,4 +1,4 @@
1
- import { getOrCreateSessionMeta, getTopNBySize } from "../../features/magic-context/storage";
1
+ import { getOrCreateSessionMeta, type getTopNBySize } from "../../features/magic-context/storage";
2
2
  import type { ContextUsage, SessionMeta, TagEntry } from "../../features/magic-context/types";
3
3
  type ContextDatabase = Parameters<typeof getOrCreateSessionMeta>[0];
4
4
  export type ContextNudge = {
@@ -1 +1 @@
1
- {"version":3,"file":"nudger.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/nudger.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EAGtB,aAAa,EAEhB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAY9F,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAC/D,eAAO,MAAM,2BAA2B,QAAgB,CAAC;AA+BzD,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,yBAAyB,EAAE,MAAM,CAAC;IAClC,4BAA4B,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/C,IAIO,WAAW,MAAM,EACjB,cAAc,YAAY,EAC1B,IAAI,eAAe,EACnB,QAAQ,OAAO,aAAa,EAC5B,gBAAgB,QAAQ,EAAE,EAC1B,wBAAwB,MAAM,EAC9B,uBAAuB,WAAW,KACnC,YAAY,GAAG,IAAI,CAyIzB"}
1
+ {"version":3,"file":"nudger.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/nudger.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EAGtB,KAAK,aAAa,EAErB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAY9F,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAC/D,eAAO,MAAM,2BAA2B,QAAgB,CAAC;AA+BzD,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,yBAAyB,EAAE,MAAM,CAAC;IAClC,4BAA4B,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/C,IAIO,WAAW,MAAM,EACjB,cAAc,YAAY,EAC1B,IAAI,eAAe,EACnB,QAAQ,OAAO,aAAa,EAC5B,gBAAgB,QAAQ,EAAE,EAC1B,wBAAwB,MAAM,EAC9B,uBAAuB,WAAW,KACnC,YAAY,GAAG,IAAI,CAyIzB"}
package/dist/index.js CHANGED
@@ -15615,6 +15615,77 @@ var init_data_path = () => {};
15615
15615
  function getErrorMessage(error48) {
15616
15616
  return error48 instanceof Error ? error48.message : String(error48);
15617
15617
  }
15618
+ function readString(value) {
15619
+ if (typeof value === "string" && value.length > 0)
15620
+ return value;
15621
+ if (typeof value === "number")
15622
+ return String(value);
15623
+ return;
15624
+ }
15625
+ function clip(value, max) {
15626
+ if (value.length <= max)
15627
+ return value;
15628
+ return `${value.slice(0, max)}\u2026`;
15629
+ }
15630
+ function describeError(error48) {
15631
+ const stringForm = clip(safeString(error48), 400);
15632
+ if (!(error48 instanceof Error) && !(error48 && typeof error48 === "object")) {
15633
+ return {
15634
+ name: typeof error48,
15635
+ message: "",
15636
+ stringForm,
15637
+ brief: stringForm || "<empty>"
15638
+ };
15639
+ }
15640
+ const obj = error48;
15641
+ const nameFromField = readString(obj.name);
15642
+ const nameFromCtor = error48?.constructor?.name;
15643
+ const name = nameFromField ?? nameFromCtor ?? "Error";
15644
+ const message = readString(obj.message) ?? "";
15645
+ const status = readString(obj.status) ?? readString(obj.statusCode);
15646
+ const code = readString(obj.code);
15647
+ let causeName;
15648
+ const cause = obj.cause;
15649
+ if (cause && typeof cause === "object") {
15650
+ const causeRecord = cause;
15651
+ causeName = readString(causeRecord.name) ?? cause.constructor?.name;
15652
+ }
15653
+ const stack = readString(obj.stack);
15654
+ const stackHead = stack ? stack.split(`
15655
+ `).slice(0, 4).map((l) => l.trim()).filter((l) => l.length > 0).join(" | ") : undefined;
15656
+ const briefParts = [];
15657
+ if (name)
15658
+ briefParts.push(name);
15659
+ if (message)
15660
+ briefParts.push(`message="${clip(message, 200)}"`);
15661
+ if (status)
15662
+ briefParts.push(`status=${status}`);
15663
+ if (code)
15664
+ briefParts.push(`code=${code}`);
15665
+ if (causeName)
15666
+ briefParts.push(`cause=${causeName}`);
15667
+ if (!message && stringForm && stringForm !== name) {
15668
+ briefParts.push(`str="${clip(stringForm, 200)}"`);
15669
+ }
15670
+ const brief = briefParts.join(" ") || stringForm || name;
15671
+ return {
15672
+ name,
15673
+ message,
15674
+ ...status ? { status } : {},
15675
+ ...code ? { code } : {},
15676
+ ...causeName ? { causeName } : {},
15677
+ ...stackHead ? { stackHead } : {},
15678
+ stringForm,
15679
+ brief
15680
+ };
15681
+ }
15682
+ function safeString(value) {
15683
+ try {
15684
+ return String(value);
15685
+ } catch {
15686
+ return "<unstringifiable>";
15687
+ }
15688
+ }
15618
15689
 
15619
15690
  // src/features/magic-context/memory/storage-memory-embeddings.ts
15620
15691
  function isEmbeddingBlob(value) {
@@ -151183,7 +151254,10 @@ function incrementHistorianFailure(db, sessionId, error48) {
151183
151254
  db.transaction(() => {
151184
151255
  ensureSessionMetaRow(db, sessionId);
151185
151256
  const current = getHistorianFailureState(db, sessionId);
151186
- db.prepare("UPDATE session_meta SET historian_failure_count = ?, historian_last_error = ?, historian_last_failure_at = ? WHERE session_id = ?").run(current.failureCount + 1, error48, Date.now(), sessionId);
151257
+ const nextCount = current.failureCount + 1;
151258
+ db.prepare("UPDATE session_meta SET historian_failure_count = ?, historian_last_error = ?, historian_last_failure_at = ? WHERE session_id = ?").run(nextCount, error48, Date.now(), sessionId);
151259
+ const reason = error48.replace(/\s+/g, " ").trim().slice(0, 300);
151260
+ sessionLog(sessionId, `historian failure recorded: count=${nextCount} reason="${reason}"`);
151187
151261
  })();
151188
151262
  }
151189
151263
  function clearHistorianFailureState(db, sessionId) {
@@ -151267,6 +151341,7 @@ function removeStrippedPlaceholderId(db, sessionId, messageId) {
151267
151341
  return true;
151268
151342
  }
151269
151343
  var init_storage_meta_persisted = __esm(() => {
151344
+ init_logger();
151270
151345
  init_storage_meta_shared();
151271
151346
  });
151272
151347
 
@@ -152157,14 +152232,12 @@ async function runHistorianPrompt(args) {
152157
152232
  const dumpPath = dumpHistorianResponse(parentSessionId, dumpLabel ?? "historian-response", result);
152158
152233
  return { ok: true, result, dumpPath };
152159
152234
  } catch (modelError) {
152160
- const modelMsg = getErrorMessage(modelError);
152161
- const modelStack = modelError instanceof Error ? modelError.stack : undefined;
152162
- sessionLog(parentSessionId, "compartment agent: historian attempt failed", {
152163
- error: modelMsg,
152164
- promptLength: prompt.length,
152165
- stack: modelStack
152166
- });
152167
- return { ok: false, error: `Historian failed while processing this session: ${modelMsg}` };
152235
+ const desc = describeError(modelError);
152236
+ sessionLog(parentSessionId, `historian prompt failed: ${desc.brief} promptLength=${prompt.length}${desc.stackHead ? ` stackHead="${desc.stackHead}"` : ""}`);
152237
+ return {
152238
+ ok: false,
152239
+ error: `Historian failed while processing this session: ${desc.brief}`
152240
+ };
152168
152241
  } finally {
152169
152242
  if (agentSessionId) {
152170
152243
  await client.session.delete({ path: { id: agentSessionId }, query: { directory: sessionDirectory } }).catch((e) => {
@@ -154317,6 +154390,7 @@ async function runCompartmentAgent(deps) {
154317
154390
  const priorFacts = existingFacts;
154318
154391
  const existingValidationError = validateStoredCompartments(priorCompartments);
154319
154392
  if (existingValidationError) {
154393
+ sessionLog(sessionId, `historian failure: source=existing-validation reason="${existingValidationError}"`);
154320
154394
  await notifyHistorianIssue(`## Historian alert
154321
154395
 
154322
154396
  Historian skipped this session because existing stored compartments are invalid: ${existingValidationError}
@@ -154335,6 +154409,7 @@ No new compartments or facts were written. Rebuild or clear the broken compartme
154335
154409
  }
154336
154410
  const chunkCoverageError = validateChunkCoverage(chunk);
154337
154411
  if (chunkCoverageError) {
154412
+ sessionLog(sessionId, `historian failure: source=chunk-coverage reason="${chunkCoverageError}" chunkRange=${chunk.startIndex}-${chunk.endIndex}`);
154338
154413
  await notifyHistorianIssue(`## Historian alert
154339
154414
 
154340
154415
  Historian skipped this session because the raw chunk could not be represented safely: ${chunkCoverageError}
@@ -154370,6 +154445,7 @@ ${chunk.text}`);
154370
154445
  twoPass: deps.historianTwoPass
154371
154446
  });
154372
154447
  if (!validatedPass.ok) {
154448
+ sessionLog(sessionId, `historian failure: source=validation reason="${validatedPass.error}" chunkRange=${chunk.startIndex}-${chunk.endIndex} fallbackModel=${deps.fallbackModelId ?? "<none>"} twoPass=${deps.historianTwoPass ? "true" : "false"}`);
154373
154449
  incrementHistorianFailure(db, sessionId, validatedPass.error);
154374
154450
  await notifyHistorianIssue(`## Historian alert
154375
154451
 
@@ -154381,6 +154457,8 @@ No new compartments or facts were written. Check the historian model/output and
154381
154457
  const newCompartments = validatedPass.compartments;
154382
154458
  const lastNewEnd = newCompartments[newCompartments.length - 1]?.endMessage ?? 0;
154383
154459
  if (lastNewEnd + 1 <= offset) {
154460
+ sessionLog(sessionId, `historian failure: source=no-progress reason="historian returned compartments that did not advance past raw message ${offset - 1}" newCompartmentCount=${newCompartments.length} lastNewEnd=${lastNewEnd} priorEnd=${offset - 1}`);
154461
+ incrementHistorianFailure(db, sessionId, `no forward progress beyond raw message ${offset - 1}`);
154384
154462
  await notifyHistorianIssue(`## Historian alert
154385
154463
 
154386
154464
  Historian returned compartments that made no forward progress beyond raw message ${offset - 1}.
@@ -154434,11 +154512,13 @@ No new compartments or facts were written. Check the historian model/output and
154434
154512
  }
154435
154513
  }
154436
154514
  } catch (error48) {
154437
- const msg = getErrorMessage(error48);
154515
+ const desc = describeError(error48);
154516
+ sessionLog(sessionId, `historian failure: source=exception ${desc.brief}${desc.stackHead ? ` stackHead="${desc.stackHead}"` : ""}`);
154438
154517
  if (!issueNotified) {
154518
+ incrementHistorianFailure(db, sessionId, desc.brief);
154439
154519
  await notifyHistorianIssue(`## Historian alert
154440
154520
 
154441
- Historian failed unexpectedly: ${msg}
154521
+ Historian failed unexpectedly: ${desc.brief}
154442
154522
 
154443
154523
  No new compartments or facts were written. Check the historian model/output and try again.`);
154444
154524
  }
@@ -1,2 +1,32 @@
1
1
  export declare function getErrorMessage(error: unknown): string;
2
+ /**
3
+ * Produce a rich, safe-to-log description of any thrown value.
4
+ *
5
+ * Motivated by SDK errors whose `.message` is empty while `.name`/`toString()`
6
+ * carry the actual signal (e.g. `NotFoundError` with no message on OpenCode
7
+ * session-delete races). Using {@link getErrorMessage} alone erases that signal.
8
+ *
9
+ * Captures:
10
+ * - `name` from the Error (defaults to `constructor.name`)
11
+ * - `message` (may be empty)
12
+ * - first few stack frames
13
+ * - `String(error)` so objects and custom toString surfaces are visible
14
+ * - Common HTTP-shape fields (`status`, `statusCode`, `code`)
15
+ * - `cause` chain summary (first level only)
16
+ *
17
+ * Returns a compact, single-line-friendly string suitable for log lines,
18
+ * plus a structured object for callers that want individual fields.
19
+ */
20
+ export interface ErrorDescription {
21
+ name: string;
22
+ message: string;
23
+ status?: string;
24
+ code?: string;
25
+ causeName?: string;
26
+ stackHead?: string;
27
+ stringForm: string;
28
+ /** Best short summary for human-readable logs. Never empty. */
29
+ brief: string;
30
+ }
31
+ export declare function describeError(error: unknown): ErrorDescription;
2
32
  //# sourceMappingURL=error-message.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-message.d.ts","sourceRoot":"","sources":["../../src/shared/error-message.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD"}
1
+ {"version":3,"file":"error-message.d.ts","sourceRoot":"","sources":["../../src/shared/error-message.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CA6D9D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,94 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import { describeError, getErrorMessage } from "./error-message";
3
+
4
+ describe("describeError", () => {
5
+ it("extracts name and message from standard Error", () => {
6
+ const err = new TypeError("boom");
7
+ const desc = describeError(err);
8
+ expect(desc.name).toBe("TypeError");
9
+ expect(desc.message).toBe("boom");
10
+ expect(desc.brief).toContain("TypeError");
11
+ expect(desc.brief).toContain('message="boom"');
12
+ });
13
+
14
+ it("surfaces class name when message is empty (NotFoundError case)", () => {
15
+ class NotFoundError extends Error {
16
+ constructor() {
17
+ super("");
18
+ this.name = "NotFoundError";
19
+ }
20
+ }
21
+ const err = new NotFoundError();
22
+ const desc = describeError(err);
23
+ expect(desc.name).toBe("NotFoundError");
24
+ expect(desc.message).toBe("");
25
+ // brief must still carry a useful signal even with empty message
26
+ expect(desc.brief).toContain("NotFoundError");
27
+ });
28
+
29
+ it("falls back to constructor.name when .name is missing", () => {
30
+ // Simulate an SDK-shaped object where .name is an empty string
31
+ const err = Object.assign(new Error("x"), { name: "" });
32
+ const desc = describeError(err);
33
+ // Falls back to constructor.name ("Error")
34
+ expect(desc.name).toBe("Error");
35
+ });
36
+
37
+ it("extracts status/code fields from HTTP-style errors", () => {
38
+ const err = Object.assign(new Error("not found"), {
39
+ status: 404,
40
+ code: "ENOTFOUND",
41
+ });
42
+ const desc = describeError(err);
43
+ expect(desc.status).toBe("404");
44
+ expect(desc.code).toBe("ENOTFOUND");
45
+ expect(desc.brief).toContain("status=404");
46
+ expect(desc.brief).toContain("code=ENOTFOUND");
47
+ });
48
+
49
+ it("captures first stack frames in stackHead", () => {
50
+ const err = new Error("with stack");
51
+ const desc = describeError(err);
52
+ expect(desc.stackHead).toBeDefined();
53
+ expect(desc.stackHead?.length).toBeGreaterThan(0);
54
+ });
55
+
56
+ it("handles non-Error thrown values", () => {
57
+ const desc = describeError("plain string");
58
+ expect(desc.brief).toContain("plain string");
59
+ expect(desc.stringForm).toContain("plain string");
60
+ });
61
+
62
+ it("handles objects without .message", () => {
63
+ const desc = describeError({ name: "WeirdError" });
64
+ expect(desc.name).toBe("WeirdError");
65
+ expect(desc.message).toBe("");
66
+ expect(desc.brief).toContain("WeirdError");
67
+ });
68
+
69
+ it("handles undefined/null", () => {
70
+ expect(describeError(undefined).brief).toBeTruthy();
71
+ expect(describeError(null).brief).toBeTruthy();
72
+ });
73
+
74
+ it("surfaces cause name when present", () => {
75
+ const cause = new TypeError("inner");
76
+ const outer = new Error("outer");
77
+ (outer as unknown as { cause: unknown }).cause = cause;
78
+ const desc = describeError(outer);
79
+ expect(desc.causeName).toBe("TypeError");
80
+ expect(desc.brief).toContain("cause=TypeError");
81
+ });
82
+
83
+ it("clips very long messages in brief", () => {
84
+ const long = "x".repeat(1000);
85
+ const err = new Error(long);
86
+ const desc = describeError(err);
87
+ expect(desc.brief.length).toBeLessThan(500);
88
+ });
89
+
90
+ it("getErrorMessage still works as before", () => {
91
+ expect(getErrorMessage(new Error("foo"))).toBe("foo");
92
+ expect(getErrorMessage("bar")).toBe("bar");
93
+ });
94
+ });
@@ -1,3 +1,115 @@
1
1
  export function getErrorMessage(error: unknown): string {
2
2
  return error instanceof Error ? error.message : String(error);
3
3
  }
4
+
5
+ /**
6
+ * Produce a rich, safe-to-log description of any thrown value.
7
+ *
8
+ * Motivated by SDK errors whose `.message` is empty while `.name`/`toString()`
9
+ * carry the actual signal (e.g. `NotFoundError` with no message on OpenCode
10
+ * session-delete races). Using {@link getErrorMessage} alone erases that signal.
11
+ *
12
+ * Captures:
13
+ * - `name` from the Error (defaults to `constructor.name`)
14
+ * - `message` (may be empty)
15
+ * - first few stack frames
16
+ * - `String(error)` so objects and custom toString surfaces are visible
17
+ * - Common HTTP-shape fields (`status`, `statusCode`, `code`)
18
+ * - `cause` chain summary (first level only)
19
+ *
20
+ * Returns a compact, single-line-friendly string suitable for log lines,
21
+ * plus a structured object for callers that want individual fields.
22
+ */
23
+ export interface ErrorDescription {
24
+ name: string;
25
+ message: string;
26
+ status?: string;
27
+ code?: string;
28
+ causeName?: string;
29
+ stackHead?: string;
30
+ stringForm: string;
31
+ /** Best short summary for human-readable logs. Never empty. */
32
+ brief: string;
33
+ }
34
+
35
+ function readString(value: unknown): string | undefined {
36
+ if (typeof value === "string" && value.length > 0) return value;
37
+ if (typeof value === "number") return String(value);
38
+ return undefined;
39
+ }
40
+
41
+ function clip(value: string, max: number): string {
42
+ if (value.length <= max) return value;
43
+ return `${value.slice(0, max)}…`;
44
+ }
45
+
46
+ export function describeError(error: unknown): ErrorDescription {
47
+ const stringForm = clip(safeString(error), 400);
48
+
49
+ if (!(error instanceof Error) && !(error && typeof error === "object")) {
50
+ return {
51
+ name: typeof error,
52
+ message: "",
53
+ stringForm,
54
+ brief: stringForm || "<empty>",
55
+ };
56
+ }
57
+
58
+ const obj = error as Record<string, unknown>;
59
+ const nameFromField = readString(obj.name);
60
+ const nameFromCtor = error?.constructor?.name;
61
+ const name = nameFromField ?? nameFromCtor ?? "Error";
62
+
63
+ const message = readString(obj.message) ?? "";
64
+ const status = readString(obj.status) ?? readString(obj.statusCode);
65
+ const code = readString(obj.code);
66
+
67
+ let causeName: string | undefined;
68
+ const cause = obj.cause;
69
+ if (cause && typeof cause === "object") {
70
+ const causeRecord = cause as Record<string, unknown>;
71
+ causeName =
72
+ readString(causeRecord.name) ??
73
+ (cause as { constructor?: { name?: string } }).constructor?.name;
74
+ }
75
+
76
+ const stack = readString(obj.stack);
77
+ const stackHead = stack
78
+ ? stack
79
+ .split("\n")
80
+ .slice(0, 4)
81
+ .map((l) => l.trim())
82
+ .filter((l) => l.length > 0)
83
+ .join(" | ")
84
+ : undefined;
85
+
86
+ const briefParts: string[] = [];
87
+ if (name) briefParts.push(name);
88
+ if (message) briefParts.push(`message="${clip(message, 200)}"`);
89
+ if (status) briefParts.push(`status=${status}`);
90
+ if (code) briefParts.push(`code=${code}`);
91
+ if (causeName) briefParts.push(`cause=${causeName}`);
92
+ if (!message && stringForm && stringForm !== name) {
93
+ briefParts.push(`str="${clip(stringForm, 200)}"`);
94
+ }
95
+ const brief = briefParts.join(" ") || stringForm || name;
96
+
97
+ return {
98
+ name,
99
+ message,
100
+ ...(status ? { status } : {}),
101
+ ...(code ? { code } : {}),
102
+ ...(causeName ? { causeName } : {}),
103
+ ...(stackHead ? { stackHead } : {}),
104
+ stringForm,
105
+ brief,
106
+ };
107
+ }
108
+
109
+ function safeString(value: unknown): string {
110
+ try {
111
+ return String(value);
112
+ } catch {
113
+ return "<unstringifiable>";
114
+ }
115
+ }