Skip to content

Commit 56194d7

Browse files
suryaiyer95claude
andcommitted
fix: [AI-5975] propagate actual error messages to telemetry instead of "unknown error"
Root cause: 6,905+ telemetry entries showed "unknown error" because tools did not set `metadata.error` on failure paths. The telemetry layer in `tool.ts` reads `metadata.error` — when missing, it logs "unknown error". Changes: - Add `error` field to `metadata` on all failure paths across 12 failing tools: `altimate_core_validate`, `altimate_core_fix`, `altimate_core_correct`, `altimate_core_semantics`, `altimate_core_equivalence`, `sql_explain`, `sql_analyze`, `finops_query_history`, `finops_expensive_queries`, `finops_analyze_credits`, `finops_unused_resources`, `finops_warehouse_advice` - Add error extraction functions for nested napi-rs response structures: `extractValidationErrors()` (data.errors[]), `extractFixErrors()` (data.unfixable_errors[]), `extractCorrectErrors()` (data.final_validation.errors[]), `extractSemanticsErrors()` (data.validation_errors[]), `extractEquivalenceErrors()` (data.validation_errors[]) - Wire `schema_path`/`schema_context` params through `sql_analyze` tool to dispatcher (were completely disconnected — handler expected them) - Add `schema_path` to `SqlAnalyzeParams` type - Surface `unfixable_errors` from `sql.fix` handler in `register.ts` - Clean up tool descriptions: remove "Rust-based altimate-core engine" boilerplate, add schema guidance where applicable - Add `error?: string` to `Tool.Metadata` interface in `tool.ts` - Add 18 regression tests using mock dispatcher with real failure shapes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent df24e73 commit 56194d7

52 files changed

Lines changed: 545 additions & 83 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/opencode/src/altimate/native/sql/register.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,18 @@ register("sql.fix", async (params) => {
215215
fixed_sql: f.fixed_sql ?? f.rewritten_sql,
216216
}))
217217

218+
const unfixableError = !result.fixed && Array.isArray(result.unfixable_errors) && result.unfixable_errors.length > 0
219+
? result.unfixable_errors.map((e: any) => e.error?.message ?? e.reason ?? String(e)).join("; ")
220+
: undefined
221+
218222
return {
219223
success: result.fixed ?? true,
220224
original_sql: result.original_sql ?? params.sql,
221225
fixed_sql: result.fixed_sql ?? params.sql,
222226
error_message: params.error_message ?? "",
223227
suggestions,
224228
suggestion_count: suggestions.length,
229+
...(unfixableError && { error: unfixableError }),
225230
}
226231
} catch (e) {
227232
return {

packages/opencode/src/altimate/native/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface SqlExecuteResult {
2424
export interface SqlAnalyzeParams {
2525
sql: string
2626
dialect?: string
27+
schema_path?: string
2728
schema_context?: Record<string, any>
2829
}
2930

@@ -385,6 +386,7 @@ export interface SqlFixResult {
385386
error_message: string
386387
suggestions: SqlFixSuggestion[]
387388
suggestion_count: number
389+
error?: string
388390
}
389391

390392
// --- SQL Autocomplete ---

packages/opencode/src/altimate/tools/altimate-core-check.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dispatcher } from "../native"
44

55
export const AltimateCoreCheckTool = Tool.define("altimate_core_check", {
66
description:
7-
"Run full analysis pipeline: validate + lint + safety scan + PII check using the Rust-based altimate-core engine. Single call for comprehensive SQL analysis.",
7+
"Run full analysis pipeline: validate + lint + safety scan + PII check. Single call for comprehensive SQL analysis. Provide schema_context or schema_path for accurate table/column resolution.",
88
parameters: z.object({
99
sql: z.string().describe("SQL query to analyze"),
1010
schema_path: z.string().optional().describe("Path to YAML/JSON schema file"),

packages/opencode/src/altimate/tools/altimate-core-classify-pii.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dispatcher } from "../native"
44

55
export const AltimateCoreClassifyPiiTool = Tool.define("altimate_core_classify_pii", {
66
description:
7-
"Classify PII columns in a schema using the Rust-based altimate-core engine. Identifies columns likely containing personal identifiable information by name patterns and data types.",
7+
"Classify PII columns in a schema. Identifies columns likely containing personal identifiable information by name patterns and data types. Provide schema_context or schema_path for accurate table/column resolution.",
88
parameters: z.object({
99
schema_path: z.string().optional().describe("Path to YAML/JSON schema file"),
1010
schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"),

packages/opencode/src/altimate/tools/altimate-core-column-lineage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dispatcher } from "../native"
44

55
export const AltimateCoreColumnLineageTool = Tool.define("altimate_core_column_lineage", {
66
description:
7-
"Trace schema-aware column lineage using the Rust-based altimate-core engine. Maps how columns flow through a query from source tables to output. Requires altimate_core.init() with API key.",
7+
"Trace schema-aware column lineage. Maps how columns flow through a query from source tables to output. Requires altimate_core.init() with API key. Provide schema_context or schema_path for accurate table/column resolution.",
88
parameters: z.object({
99
sql: z.string().describe("SQL query to trace lineage for"),
1010
dialect: z.string().optional().describe("SQL dialect (e.g. snowflake, bigquery)"),

packages/opencode/src/altimate/tools/altimate-core-compare.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dispatcher } from "../native"
44

55
export const AltimateCoreCompareTool = Tool.define("altimate_core_compare", {
66
description:
7-
"Structurally compare two SQL queries using the Rust-based altimate-core engine. Identifies differences in table references, join conditions, filters, projections, and aggregations.",
7+
"Structurally compare two SQL queries. Identifies differences in table references, join conditions, filters, projections, and aggregations.",
88
parameters: z.object({
99
left_sql: z.string().describe("First SQL query"),
1010
right_sql: z.string().describe("Second SQL query"),

packages/opencode/src/altimate/tools/altimate-core-complete.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dispatcher } from "../native"
44

55
export const AltimateCoreCompleteTool = Tool.define("altimate_core_complete", {
66
description:
7-
"Get cursor-aware SQL completion suggestions using the Rust-based altimate-core engine. Returns table names, column names, functions, and keywords relevant to the cursor position.",
7+
"Get cursor-aware SQL completion suggestions. Returns table names, column names, functions, and keywords relevant to the cursor position. Provide schema_context or schema_path for accurate table/column resolution.",
88
parameters: z.object({
99
sql: z.string().describe("Partial SQL query"),
1010
cursor_pos: z.number().describe("Cursor position (0-indexed character offset)"),
@@ -23,12 +23,12 @@ export const AltimateCoreCompleteTool = Tool.define("altimate_core_complete", {
2323
const count = data.items?.length ?? data.suggestions?.length ?? 0
2424
return {
2525
title: `Complete: ${count} suggestion(s)`,
26-
metadata: { success: result.success, suggestion_count: count },
26+
metadata: { success: result.success, suggestion_count: count, error: result.error ?? (data as any).error },
2727
output: formatComplete(data),
2828
}
2929
} catch (e) {
3030
const msg = e instanceof Error ? e.message : String(e)
31-
return { title: "Complete: ERROR", metadata: { success: false, suggestion_count: 0 }, output: `Failed: ${msg}` }
31+
return { title: "Complete: ERROR", metadata: { success: false, suggestion_count: 0, error: msg }, output: `Failed: ${msg}` }
3232
}
3333
},
3434
})

packages/opencode/src/altimate/tools/altimate-core-correct.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dispatcher } from "../native"
44

55
export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", {
66
description:
7-
"Iteratively correct SQL using a propose-verify-refine loop via the Rust-based altimate-core engine. More thorough than fix — applies multiple correction rounds to produce valid SQL.",
7+
"Iteratively correct SQL using a propose-verify-refine loop. More thorough than fix — applies multiple correction rounds to produce valid SQL. Provide schema_context or schema_path for accurate table/column resolution.",
88
parameters: z.object({
99
sql: z.string().describe("SQL query to correct"),
1010
schema_path: z.string().optional().describe("Path to YAML/JSON schema file"),
@@ -18,18 +18,29 @@ export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", {
1818
schema_context: args.schema_context,
1919
})
2020
const data = result.data as Record<string, any>
21+
const error = result.error ?? data.error ?? extractCorrectErrors(data)
2122
return {
2223
title: `Correct: ${data.success ? "CORRECTED" : "COULD NOT CORRECT"}`,
23-
metadata: { success: result.success, iterations: data.iterations },
24-
output: formatCorrect(data),
24+
metadata: { success: result.success, iterations: data.iterations, error },
25+
output: error ? `Error: ${error}` : formatCorrect(data),
2526
}
2627
} catch (e) {
2728
const msg = e instanceof Error ? e.message : String(e)
28-
return { title: "Correct: ERROR", metadata: { success: false, iterations: 0 }, output: `Failed: ${msg}` }
29+
return { title: "Correct: ERROR", metadata: { success: false, iterations: 0, error: msg }, output: `Failed: ${msg}` }
2930
}
3031
},
3132
})
3233

34+
function extractCorrectErrors(data: Record<string, any>): string | undefined {
35+
if (data.final_validation?.errors?.length > 0) {
36+
return data.final_validation.errors.map((e: any) => e.message ?? String(e)).join("; ")
37+
}
38+
if (Array.isArray(data.errors) && data.errors.length > 0) {
39+
return data.errors.map((e: any) => e.message ?? String(e)).join("; ")
40+
}
41+
return undefined
42+
}
43+
3344
function formatCorrect(data: Record<string, any>): string {
3445
if (data.error) return `Error: ${data.error}`
3546
const lines: string[] = []

packages/opencode/src/altimate/tools/altimate-core-equivalence.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dispatcher } from "../native"
44

55
export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalence", {
66
description:
7-
"Check semantic equivalence of two SQL queries using the Rust-based altimate-core engine. Determines if two queries produce the same result set regardless of syntactic differences.",
7+
"Check semantic equivalence of two SQL queries. Determines if two queries produce the same result set regardless of syntactic differences. Provide schema_context or schema_path for accurate table/column resolution.",
88
parameters: z.object({
99
sql1: z.string().describe("First SQL query"),
1010
sql2: z.string().describe("Second SQL query"),
@@ -20,18 +20,26 @@ export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalenc
2020
schema_context: args.schema_context,
2121
})
2222
const data = result.data as Record<string, any>
23+
const error = result.error ?? data.error ?? extractEquivalenceErrors(data)
2324
return {
2425
title: `Equivalence: ${data.equivalent ? "EQUIVALENT" : "DIFFERENT"}`,
25-
metadata: { success: result.success, equivalent: data.equivalent },
26+
metadata: { success: result.success, equivalent: data.equivalent, error },
2627
output: formatEquivalence(data),
2728
}
2829
} catch (e) {
2930
const msg = e instanceof Error ? e.message : String(e)
30-
return { title: "Equivalence: ERROR", metadata: { success: false, equivalent: false }, output: `Failed: ${msg}` }
31+
return { title: "Equivalence: ERROR", metadata: { success: false, equivalent: false, error: msg }, output: `Failed: ${msg}` }
3132
}
3233
},
3334
})
3435

36+
function extractEquivalenceErrors(data: Record<string, any>): string | undefined {
37+
if (Array.isArray(data.validation_errors) && data.validation_errors.length > 0) {
38+
return data.validation_errors.join("; ")
39+
}
40+
return undefined
41+
}
42+
3543
function formatEquivalence(data: Record<string, any>): string {
3644
if (data.error) return `Error: ${data.error}`
3745
const lines: string[] = []

packages/opencode/src/altimate/tools/altimate-core-export-ddl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dispatcher } from "../native"
44

55
export const AltimateCoreExportDdlTool = Tool.define("altimate_core_export_ddl", {
66
description:
7-
"Export a YAML/JSON schema as CREATE TABLE DDL statements using the Rust-based altimate-core engine.",
7+
"Export a YAML/JSON schema as CREATE TABLE DDL statements. Provide schema_context or schema_path for accurate table/column resolution.",
88
parameters: z.object({
99
schema_path: z.string().optional().describe("Path to YAML/JSON schema file"),
1010
schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"),

0 commit comments

Comments
 (0)