From 2eddd03307e5d03750adef9b8fa6fd94dfdd120f Mon Sep 17 00:00:00 2001 From: Melissa Barca Date: Wed, 15 Jul 2026 16:19:32 -0400 Subject: [PATCH 1/3] Add snowflake.home to the providers.json schema --- packages/ai-config/providers.schema.json | 6 ++++++ packages/ai-config/src/__tests__/schema.test.ts | 12 ++++++++++++ packages/ai-config/src/schema.ts | 7 +++++++ 3 files changed, 25 insertions(+) diff --git a/packages/ai-config/providers.schema.json b/packages/ai-config/providers.schema.json index 850e9ad..ddd053d 100644 --- a/packages/ai-config/providers.schema.json +++ b/packages/ai-config/providers.schema.json @@ -1431,6 +1431,9 @@ "account": { "type": "string" }, + "home": { + "type": "string" + }, "host": { "type": "string" } @@ -5431,6 +5434,9 @@ "account": { "type": "string" }, + "home": { + "type": "string" + }, "host": { "type": "string" } diff --git a/packages/ai-config/src/__tests__/schema.test.ts b/packages/ai-config/src/__tests__/schema.test.ts index dc785ec..0c735da 100644 --- a/packages/ai-config/src/__tests__/schema.test.ts +++ b/packages/ai-config/src/__tests__/schema.test.ts @@ -89,6 +89,18 @@ describe("providersConfigSchema", () => { expect(result.success).toBe(true); }); + it("accepts snowflake.home on built-in and custom snowflake providers", () => { + const result = providersConfigSchema.safeParse({ + providers: { + "snowflake-cortex": { snowflake: { account: "MYORG-MYACCT", home: "/opt/snowflake" } }, + custom: { + "snowflake-2": { type: "snowflake", snowflake: { home: "/opt/snowflake" } }, + }, + }, + }); + expect(result.success).toBe(true); + }); + it("accepts baseUrl in model overrides", () => { const result = providersConfigSchema.safeParse({ providers: { diff --git a/packages/ai-config/src/schema.ts b/packages/ai-config/src/schema.ts index d7b10c9..12ae1ae 100644 --- a/packages/ai-config/src/schema.ts +++ b/packages/ai-config/src/schema.ts @@ -139,6 +139,13 @@ export const snowflakeConfigSchema = z .object({ account: z.string().optional(), host: z.string().optional(), + /** + * Directory containing `connections.toml` (the `SNOWFLAKE_HOME` override). + * Points Snowflake credential discovery at a non-default location — e.g. + * Workbench Managed Credentials, which place `connections.toml` in a + * managed directory. Non-secret. + */ + home: z.string().optional(), }) .strict(); From 6c3cac0ca91e1ca7372ca21f426ce13ee13a6ae3 Mon Sep 17 00:00:00 2001 From: Melissa Barca Date: Wed, 15 Jul 2026 16:21:24 -0400 Subject: [PATCH 2/3] Carry snowflake.home through ResolvedConnection --- .../src/__tests__/resolve-catalog.test.ts | 22 +++++++++++++++++++ packages/ai-config/src/types.ts | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/ai-config/src/__tests__/resolve-catalog.test.ts b/packages/ai-config/src/__tests__/resolve-catalog.test.ts index 6c6233b..1425f05 100644 --- a/packages/ai-config/src/__tests__/resolve-catalog.test.ts +++ b/packages/ai-config/src/__tests__/resolve-catalog.test.ts @@ -339,6 +339,28 @@ describe("resolveProviderCatalog — host layer merge semantics (Phase 6)", () = }); }); + it("snowflake home merges across user + host like the other snowflake keys", () => { + // host (e.g. the transitional authentication.* layer) supplies home; user + // supplies account → the merged connection carries both. + const catalog = resolveProviderCatalog({ + sources: [ + source("user", { + providers: { "snowflake-cortex": { snowflake: { account: "user-acct" } } }, + }), + source("host", { + providers: { "snowflake-cortex": { snowflake: { home: "/managed/snowflake" } } }, + }), + ], + baseline: STANDALONE, + envVars: {}, + }); + // Typed access to `.home` is the point: it fails check-types until + // ResolvedConnection.snowflake carries the field. + const resolved = find(catalog, "snowflake-cortex")?.connection.snowflake; + expect(resolved?.home).toBe("/managed/snowflake"); + expect(resolved?.account).toBe("user-acct"); + }); + it("AWS region ordering: env > host authentication setting > us-east-1 default", () => { // host setting beats the us-east-1 default (revival of the previously-dead // authentication.aws.credentials.AWS_REGION). diff --git a/packages/ai-config/src/types.ts b/packages/ai-config/src/types.ts index f6405ec..8202457 100644 --- a/packages/ai-config/src/types.ts +++ b/packages/ai-config/src/types.ts @@ -125,7 +125,7 @@ export interface ResolvedConnection { positaiLogin?: { host?: string; clientId?: string; scope?: string }; aws?: { region?: string; profile?: string }; googleCloud?: { project?: string; location?: string }; - snowflake?: { account?: string; host?: string }; + snowflake?: { account?: string; host?: string; home?: string }; } /** From 419a6af0d4e61ab969eb378067bec68d4b3c1fe0 Mon Sep 17 00:00:00 2001 From: Melissa Barca Date: Wed, 15 Jul 2026 16:22:58 -0400 Subject: [PATCH 3/3] Read SNOWFLAKE_HOME in the Positron authentication host source --- .../src/__tests__/positron-source.test.ts | 16 +++++++++++++++- .../src/positron/authentication-fragment.ts | 15 +++++++++------ packages/ai-config/src/positron/index.ts | 3 ++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/packages/ai-config/src/__tests__/positron-source.test.ts b/packages/ai-config/src/__tests__/positron-source.test.ts index bb65262..35459f5 100644 --- a/packages/ai-config/src/__tests__/positron-source.test.ts +++ b/packages/ai-config/src/__tests__/positron-source.test.ts @@ -21,7 +21,7 @@ function fakeReader( baseUrls?: Record; customHeaders?: Record>; awsRegion?: string; - snowflake?: { host?: string; account?: string }; + snowflake?: { host?: string; account?: string; home?: string }; } = {}, ): PositronAuthSettingReader { return { @@ -142,6 +142,20 @@ describe("buildAuthenticationFragment", () => { }); }); + it("emits snowflake.home under snowflake-cortex", () => { + const reader = fakeReader({ + snowflake: { host: "h.snowflakecomputing.com", home: "/managed/snowflake" }, + }); + const fragment = buildAuthenticationFragment(reader, [SNOWFLAKE]); + expect(fragment).toEqual({ + providers: { + "snowflake-cortex": { + snowflake: { host: "h.snowflakecomputing.com", home: "/managed/snowflake" }, + }, + }, + }); + }); + it("applies the descriptor's normalizeBaseUrl to a set base URL", () => { const normalizeBaseUrl = (url: string) => url === "https://bare.example" ? "https://bare.example/v1" : url; diff --git a/packages/ai-config/src/positron/authentication-fragment.ts b/packages/ai-config/src/positron/authentication-fragment.ts index 4bea878..c9e280d 100644 --- a/packages/ai-config/src/positron/authentication-fragment.ts +++ b/packages/ai-config/src/positron/authentication-fragment.ts @@ -38,10 +38,10 @@ export interface PositronAuthSettingReader { /** AWS region (`authentication.aws.credentials.AWS_REGION`, `process.env` fallback). */ getAwsRegion(): string | undefined; /** - * Snowflake host/account (`authentication.snowflake.credentials.{SNOWFLAKE_HOST, - * SNOWFLAKE_ACCOUNT}`, `process.env` fallback). + * Snowflake host/account/home (`authentication.snowflake.credentials.{SNOWFLAKE_HOST, + * SNOWFLAKE_ACCOUNT,SNOWFLAKE_HOME}`, `process.env` fallback). */ - getSnowflake(): { host?: string; account?: string } | undefined; + getSnowflake(): { host?: string; account?: string; home?: string } | undefined; } /** @@ -59,8 +59,8 @@ export interface PositronAuthSettingDescriptor { * - `"api-key-connection"`: reads BOTH `baseUrl` and `customHeaders` (they * share the `authentication.` namespace). * - `"aws-region"`: reads `authentication.aws.credentials.AWS_REGION`. - * - `"snowflake"`: reads `snowflake.credentials.{SNOWFLAKE_HOST,SNOWFLAKE_ACCOUNT}` - * (+ `snowflake.customHeaders`), with `process.env` fallback for host/account. + * - `"snowflake"`: reads `snowflake.credentials.{SNOWFLAKE_HOST,SNOWFLAKE_ACCOUNT, + * SNOWFLAKE_HOME}` (+ `snowflake.customHeaders`), with `process.env` fallback. */ readonly read: "api-key-connection" | "aws-region" | "snowflake"; /** @@ -160,13 +160,16 @@ function buildSnowflakeBlock( const block: BuiltinProviderBlock = {}; const snow = reader.getSnowflake(); - const snowflake: { host?: string; account?: string } = {}; + const snowflake: { host?: string; account?: string; home?: string } = {}; if (snow?.host) { snowflake.host = snow.host; } if (snow?.account) { snowflake.account = snow.account; } + if (snow?.home) { + snowflake.home = snow.home; + } if (hasKeys(snowflake)) { block.snowflake = snowflake; } diff --git a/packages/ai-config/src/positron/index.ts b/packages/ai-config/src/positron/index.ts index fa5b018..5189a5b 100644 --- a/packages/ai-config/src/positron/index.ts +++ b/packages/ai-config/src/positron/index.ts @@ -35,7 +35,7 @@ export type { PositronAuthSettingDescriptor, PositronAuthSettingReader }; /** * A reader over `vscode.workspace.getConfiguration("authentication")`, with - * `process.env` fallbacks for the Snowflake host/account (host environments — + * `process.env` fallbacks for the Snowflake host/account/home (host environments — * TUI / node — set them there). Mirrors the bridge's `createVscodeCredentialConfig`. */ function createVscodeAuthReader(): PositronAuthSettingReader { @@ -59,6 +59,7 @@ function createVscodeAuthReader(): PositronAuthSettingReader { return { host: snowflakeConfig?.SNOWFLAKE_HOST || process.env.SNOWFLAKE_HOST, account: snowflakeConfig?.SNOWFLAKE_ACCOUNT || process.env.SNOWFLAKE_ACCOUNT, + home: snowflakeConfig?.SNOWFLAKE_HOME || process.env.SNOWFLAKE_HOME, }; }, };