Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/opencode/src/altimate/fingerprint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
Expand Down Expand Up @@ -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())
Expand Down
40 changes: 38 additions & 2 deletions packages/opencode/src/session/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:`,
Expand All @@ -59,6 +59,42 @@ export namespace SystemPrompt {
`</directories>`,
].join("\n"),
]

// altimate_change start - inject project context to guide connection discovery
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(
[
`<project-context>`,
` 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})` : ""}.`,
]),
`</project-context>`,
].join("\n"),
)
}
} catch {
// fingerprint detection is best-effort — never block session startup
}
// altimate_change end

return parts
}

export async function skills(agent: Agent.Info) {
Expand Down
Loading