Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,17 @@ export function importLegacyCredentials(tx: Parameters<DatabaseMigration.Migrati

const credential =
value.type === "api"
? Credential.Key.make({ type: "key", key: value.key, metadata: value.metadata })
? Credential.Key.make({
type: "key",
key: value.key,
// A legacy `server` value is file-controlled text and no first-party
// writer sets one on a key credential. Carrying it through would let
// an imported file point the stored key at an arbitrary host, so drop
// it here: imported keys use the configured default server.
metadata: value.metadata
? Object.fromEntries(Object.entries(value.metadata).filter(([name]) => name !== "server"))
: undefined,
})
: value.type === "wellknown"
? Credential.Key.make({ type: "key", key: value.token })
: Credential.OAuth.make({
Expand Down
21 changes: 19 additions & 2 deletions packages/core/src/plugin/provider/mars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,22 @@ import { Credential } from "../../credential.js"
import { Integration } from "../../integration.js"
import { Provider } from "../../provider.js"

const defaultServer = (process.env.MARSAI_URL ?? "https://marsai.click").replace(/\/+$/, "").replace(/\/v1$/i, "")
const fallbackServer = "https://marsai.click"

function normalizeServer(raw: string) {
try {
const url = new URL(raw)
const loopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1" || url.hostname === "[::1]"
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) return undefined
return `${url.origin}${url.pathname.replace(/\/+$/, "").replace(/\/v1$/i, "")}`
} catch {
return undefined
}
}

// MARSAI_URL gets the same check as a credential server. Without it the
// fallback itself could point the key at a remote host over plaintext http.
const defaultServer = (process.env.MARSAI_URL ? normalizeServer(process.env.MARSAI_URL) : undefined) ?? fallbackServer
const integrationID = Integration.ID.make("marsai")
const providerID = Provider.ID.make("marsai")
const ModelsResponse = Schema.Struct({
Expand All @@ -27,7 +42,9 @@ const ModelsResponse = Schema.Struct({
})

function serverUrl(value: Credential.Key) {
return typeof value.metadata?.server === "string" ? value.metadata.server : defaultServer
const raw = value.metadata?.server
if (typeof raw !== "string") return defaultServer
return normalizeServer(raw) ?? defaultServer
}

function modelsFor(http: HttpClient.HttpClient, value: Credential.Key) {
Expand Down
Loading