feat(agent): per-upstream pi Models with isolated credential stores

- PiUpstreamClient: one Models per upstream holding only its provider; credential
  store adapter maps to that upstream's secret, so several accounts of one provider
  coexist; host env is only read for authKind none (ambient cloud creds)
- provider catalog from builtinProviders() plus static oauth modes, env fields and
  subscription terms notes; openai-compatible custom endpoints
- fake upstream provider with mock OAuth (browser paste / device approval)
- PiAgentRuntime accepts an upstream; thinking level clamped to the model

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 02:23:09 +08:00
1 parent b9dbd54e37
commit 743fe2486d
8 files changed
+1085 -5

No files matched your search

+6 -1
View File
@@ -8,9 +8,11 @@ import type { ResolvedAgentSettings } from "../settings.ts";
export interface ResolvedPiModel {
models: MutableModels;
model: Model<Api>;
/** 夹到模型支持范围后的思考档位;缺省用设置值 */
thinkingLevel?: ResolvedAgentSettings["thinkingLevel"];
}
export type PiModelResolver = (settings: ResolvedAgentSettings) => ResolvedPiModel;
export type PiModelResolver = (settings: ResolvedAgentSettings) => ResolvedPiModel | Promise<ResolvedPiModel>;
const ANTHROPIC_DEFAULT_BASE = "https://api.anthropic.com";
const PROVIDER_ID = { anthropic: "umt-anthropic", "openai-compatible": "umt-openai-compatible" } as const;
@@ -20,6 +22,9 @@ const PROVIDER_ID = { anthropic: "umt-anthropic", "openai-compatible": "umt-open
* Anthropic baseUrl 不带 /v1;OpenAI 兼容 baseUrl 带 /v1(与 spike 抓包结论一致)。
*/
export function resolveModelFromSettings(settings: ResolvedAgentSettings): ResolvedPiModel {
if (settings.provider !== "anthropic" && settings.provider !== "openai-compatible")
throw new Error(`provider ${settings.provider} 需要按上游装配(PiAgentRuntimeOptions.upstream)`);
if (!settings.apiKey) throw new Error("未配置上游密钥");
const providerId = PROVIDER_ID[settings.provider];
const common = {
id: settings.model,