From 4202cedfd273780c70817d77ceb7e6e4459e7fdd Mon Sep 17 00:00:00 2001 From: suryaiyer95 Date: Wed, 18 Mar 2026 13:52:50 -0700 Subject: [PATCH 1/2] fix: surface project context in system prompt for connection discovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inject a `` block into the system prompt based on the workspace fingerprint, so the LLM agent knows how to handle SQL connections appropriately for the open project. - dbt project detected: try dbt connection first (profiles.yml), fall back to configured warehouse, then ask user for credentials — with the detected adapter type (e.g. snowflake, bigquery) pre-filled in the prompt - No dbt project: check for existing warehouse connection, ask user for adapter-scoped credentials if none is configured The LLM is explicitly told not to assume the dbt connection will succeed, ensuring graceful fallback and correct credential prompting when it fails. Co-Authored-By: Claude Sonnet 4.6 --- packages/opencode/src/session/system.ts | 34 ++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts index 6e1e4c45e3..c22b6643d6 100644 --- a/packages/opencode/src/session/system.ts +++ b/packages/opencode/src/session/system.ts @@ -36,7 +36,7 @@ export namespace SystemPrompt { export async function environment(model: Provider.Model) { const project = Instance.project - return [ + const parts: string[] = [ [ `You are powered by the model named ${model.api.id}. The exact model ID is ${model.providerID}/${model.api.id}`, `Here is some useful information about the environment you are running in:`, @@ -59,6 +59,38 @@ export namespace SystemPrompt { ``, ].join("\n"), ] + + // altimate_change start - inject project context to guide connection discovery + const fingerprint = Fingerprint.get() ?? await Fingerprint.detect(Instance.directory, Instance.worktree) + if (fingerprint.tags.length > 0) { + const isDbt = fingerprint.tags.includes("dbt") + const adapterTags = ["snowflake", "bigquery", "redshift", "databricks", "postgres", "mysql", "duckdb", "trino", "spark", "clickhouse"] + const detectedAdapter = fingerprint.tags.find(t => adapterTags.includes(t)) + + parts.push( + [ + ``, + ` Detected project tags: ${fingerprint.tags.join(", ")}`, + ...(isDbt ? [ + ``, + ` This workspace contains a dbt project. When executing SQL queries:`, + ` 1. Attempt to use the dbt connection first (configured via profiles.yml${detectedAdapter ? `, adapter: ${detectedAdapter}` : ""}).`, + ` 2. If the dbt connection is unavailable or fails, fall back to a configured warehouse connection.`, + ` 3. If neither works, ask the user for the credentials needed to connect${detectedAdapter ? ` to ${detectedAdapter}` : ""}.`, + ` Do not assume the dbt connection will always succeed — be prepared to ask for credentials.`, + ] : [ + ``, + ` No dbt project detected. When SQL execution is needed:`, + ` 1. Check if a warehouse connection is already configured.`, + ` 2. If not, ask the user for the connection credentials appropriate to this project${detectedAdapter ? ` (detected: ${detectedAdapter})` : ""}.`, + ]), + ``, + ].join("\n"), + ) + } + // altimate_change end + + return parts } export async function skills(agent: Agent.Info) { From bdf7ebf5a6ed93b3557cda5e5e51b29b5da98113 Mon Sep 17 00:00:00 2001 From: suryaiyer95 Date: Wed, 18 Mar 2026 14:06:07 -0700 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20address=20PR=20review=20=E2=80=94=20?= =?UTF-8?q?error=20safety,=20stale=20cache,=20and=20adapter=20list=20drift?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Wrap fingerprint detection in try/catch so a failure never blocks session startup (addresses Sentry MEDIUM bug report) - Call `Fingerprint.detect()` directly instead of `get() ?? detect()`: `detect()` already caches per-cwd, so this is equivalent but avoids injecting stale tags when the cwd changes (addresses Copilot comment) - Export `ADAPTER_TAGS` from fingerprint module as the single source of truth; reuse it in both `detectDir` (replacing the hardcoded regex) and the system prompt builder — fixes the missing `sqlite` and prevents future drift (addresses Copilot comment) Co-Authored-By: Claude Sonnet 4.6 --- .../src/altimate/fingerprint/index.ts | 8 ++- packages/opencode/src/session/system.ts | 56 ++++++++++--------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/packages/opencode/src/altimate/fingerprint/index.ts b/packages/opencode/src/altimate/fingerprint/index.ts index fcbb9911fc..8241a96af2 100644 --- a/packages/opencode/src/altimate/fingerprint/index.ts +++ b/packages/opencode/src/altimate/fingerprint/index.ts @@ -6,6 +6,12 @@ import path from "path" const log = Log.create({ service: "fingerprint" }) +/** Canonical list of warehouse adapter identifiers, shared with system prompt builder. */ +export const ADAPTER_TAGS = [ + "snowflake", "bigquery", "redshift", "databricks", "postgres", + "mysql", "sqlite", "duckdb", "trino", "spark", "clickhouse", +] as const + export namespace Fingerprint { export interface Result { tags: string[] @@ -102,7 +108,7 @@ export namespace Fingerprint { try { const content = await Filesystem.readText(path.join(dir, "profiles.yml")) const adapterMatch = content.match( - /type:\s*(snowflake|bigquery|redshift|databricks|postgres|mysql|sqlite|duckdb|trino|spark|clickhouse)/i, + new RegExp(`type:\\s*(${ADAPTER_TAGS.join("|")})`, "i"), ) if (adapterMatch) { tags.push(adapterMatch[1]!.toLowerCase()) diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts index c22b6643d6..120e3ea29b 100644 --- a/packages/opencode/src/session/system.ts +++ b/packages/opencode/src/session/system.ts @@ -14,7 +14,7 @@ import type { Agent } from "@/agent/agent" import { PermissionNext } from "@/permission/next" import { Skill } from "@/skill" // altimate_change start - import for env-based skill selection -import { Fingerprint } from "../altimate/fingerprint" +import { Fingerprint, ADAPTER_TAGS } from "../altimate/fingerprint" import { Config } from "../config/config" import { selectSkillsWithLLM } from "../altimate/skill-selector" // altimate_change end @@ -61,32 +61,36 @@ export namespace SystemPrompt { ] // altimate_change start - inject project context to guide connection discovery - const fingerprint = Fingerprint.get() ?? await Fingerprint.detect(Instance.directory, Instance.worktree) - if (fingerprint.tags.length > 0) { - const isDbt = fingerprint.tags.includes("dbt") - const adapterTags = ["snowflake", "bigquery", "redshift", "databricks", "postgres", "mysql", "duckdb", "trino", "spark", "clickhouse"] - const detectedAdapter = fingerprint.tags.find(t => adapterTags.includes(t)) + try { + // detect() caches per-cwd, so calling it directly is both correct and cheap + const fingerprint = await Fingerprint.detect(Instance.directory, Instance.worktree) + if (fingerprint.tags.length > 0) { + const isDbt = fingerprint.tags.includes("dbt") + const detectedAdapter = fingerprint.tags.find(t => (ADAPTER_TAGS as readonly string[]).includes(t)) - parts.push( - [ - ``, - ` Detected project tags: ${fingerprint.tags.join(", ")}`, - ...(isDbt ? [ - ``, - ` This workspace contains a dbt project. When executing SQL queries:`, - ` 1. Attempt to use the dbt connection first (configured via profiles.yml${detectedAdapter ? `, adapter: ${detectedAdapter}` : ""}).`, - ` 2. If the dbt connection is unavailable or fails, fall back to a configured warehouse connection.`, - ` 3. If neither works, ask the user for the credentials needed to connect${detectedAdapter ? ` to ${detectedAdapter}` : ""}.`, - ` Do not assume the dbt connection will always succeed — be prepared to ask for credentials.`, - ] : [ - ``, - ` No dbt project detected. When SQL execution is needed:`, - ` 1. Check if a warehouse connection is already configured.`, - ` 2. If not, ask the user for the connection credentials appropriate to this project${detectedAdapter ? ` (detected: ${detectedAdapter})` : ""}.`, - ]), - ``, - ].join("\n"), - ) + parts.push( + [ + ``, + ` Detected project tags: ${fingerprint.tags.join(", ")}`, + ...(isDbt ? [ + ``, + ` This workspace contains a dbt project. When executing SQL queries:`, + ` 1. Attempt to use the dbt connection first (configured via profiles.yml${detectedAdapter ? `, adapter: ${detectedAdapter}` : ""}).`, + ` 2. If the dbt connection is unavailable or fails, fall back to a configured warehouse connection.`, + ` 3. If neither works, ask the user for the credentials needed to connect${detectedAdapter ? ` to ${detectedAdapter}` : ""}.`, + ` Do not assume the dbt connection will always succeed — be prepared to ask for credentials.`, + ] : [ + ``, + ` No dbt project detected. When SQL execution is needed:`, + ` 1. Check if a warehouse connection is already configured.`, + ` 2. If not, ask the user for the connection credentials appropriate to this project${detectedAdapter ? ` (detected: ${detectedAdapter})` : ""}.`, + ]), + ``, + ].join("\n"), + ) + } + } catch { + // fingerprint detection is best-effort — never block session startup } // altimate_change end