Skip to content
Merged
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
9 changes: 9 additions & 0 deletions packages/opencode/src/provider/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,9 @@ export namespace Provider {
return {
models: languages,
providers,
// altimate_change start — expose full provider database (including unauthenticated custom providers)
database,
// altimate_change end
sdk,
modelLoaders,
varsLoaders,
Expand All @@ -1257,6 +1260,12 @@ export namespace Provider {
return state().then((state) => state.providers)
}

// altimate_change start — expose full provider database (including unauthenticated custom providers)
export async function all() {
return state().then((state) => state.database)
}
// altimate_change end

async function getSDK(model: Model) {
try {
using _ = log.time("getSDK", {
Expand Down
11 changes: 11 additions & 0 deletions packages/opencode/src/server/routes/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,19 @@ export const ProviderRoutes = lazy(() =>
}

const connected = await Provider.list()
// altimate_change start — include custom providers (e.g. Snowflake Cortex) even when not yet authenticated
const allDatabase = await Provider.all()
const customProviders: Record<string, Provider.Info> = {}
for (const [key, value] of Object.entries(allDatabase)) {
if (key in filteredProviders || key in connected) continue
if ((enabled ? enabled.has(key) : true) && !disabled.has(key)) {
customProviders[key] = value
}
}
// altimate_change end
const providers = Object.assign(
mapValues(filteredProviders, (x) => Provider.fromModelsDevProvider(x)),
customProviders,
connected,
)
return c.json({
Expand Down
108 changes: 108 additions & 0 deletions packages/opencode/test/provider/snowflake.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,3 +606,111 @@ describe("snowflake-cortex provider", () => {
}
})
})

// ---------------------------------------------------------------------------
// Provider.all() — unauthenticated discoverability
// ---------------------------------------------------------------------------

describe("Provider.all() discoverability", () => {
test("includes snowflake-cortex even without oauth auth", async () => {
const savedAuth = await Auth.get("snowflake-cortex")
if (savedAuth) await Auth.remove("snowflake-cortex")
try {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "opencode.json"), JSON.stringify({ $schema: "https://altimate.ai/config.json" }))
},
})
await Instance.provide({
directory: tmp.path,
init: async () => {
Env.remove("SNOWFLAKE_ACCOUNT")
},
fn: async () => {
const allProviders = await Provider.all()
expect(allProviders["snowflake-cortex"]).toBeDefined()
expect(allProviders["snowflake-cortex"].name).toBe("Snowflake Cortex")
// list() still returns nothing (not authenticated)
const connected = await Provider.list()
expect(connected["snowflake-cortex"]).toBeUndefined()
},
})
} finally {
if (savedAuth) await Auth.set("snowflake-cortex", savedAuth)
}
})

test("all() includes snowflake-cortex models", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "opencode.json"), JSON.stringify({ $schema: "https://altimate.ai/config.json" }))
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const allProviders = await Provider.all()
const models = allProviders["snowflake-cortex"]?.models
expect(models).toBeDefined()
expect(models["claude-sonnet-4-6"]).toBeDefined()
expect(models["deepseek-r1"]).toBeDefined()
},
})
})

test("disabled_providers config suppresses snowflake-cortex from all()", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(
path.join(dir, "opencode.json"),
JSON.stringify({ $schema: "https://altimate.ai/config.json", disabled_providers: ["snowflake-cortex"] }),
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
// Provider.all() returns raw database, config filtering happens at the route level.
// Verify the route-level filtering logic: a disabled provider should not appear
// in the merged provider list used by GET /provider.
const allProviders = await Provider.all()
const connected = await Provider.list()
// Simulate the route filtering (same logic as routes/provider.ts)
const disabled = new Set(["snowflake-cortex"])
const customProviders: Record<string, (typeof allProviders)[string]> = {}
for (const [key, value] of Object.entries(allProviders)) {
if (key in connected) continue
if (!disabled.has(key)) customProviders[key] = value
}
expect(customProviders["snowflake-cortex"]).toBeUndefined()
},
})
})

test("enabled_providers config suppresses snowflake-cortex when not listed", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(
path.join(dir, "opencode.json"),
JSON.stringify({ $schema: "https://altimate.ai/config.json", enabled_providers: ["anthropic"] }),
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const allProviders = await Provider.all()
const connected = await Provider.list()
// Simulate route filtering with enabled_providers
// (snowflake-cortex is not in the enabled list, so it should be excluded)
const enabled = new Set(["anthropic"])
const customProviders: Record<string, (typeof allProviders)[string]> = {}
for (const [key, value] of Object.entries(allProviders)) {
if (key in connected) continue
if (enabled.has(key)) customProviders[key] = value
}
expect(customProviders["snowflake-cortex"]).toBeUndefined()
},
})
})
})
Loading