fix(POSTV1-02): 接通真实AI生成链路
Dada P0-A isolated Windows CI / validate-and-package (push) Waiting to run
Dada P0-A isolated Windows CI / validate-and-package (push) Waiting to run
This commit is contained in:
@@ -16,7 +16,7 @@ import { MockResendAdapter } from "./resend-adapter.js";
|
||||
import { readSecureConfigCandidate } from "./secure-config.js";
|
||||
import { StructuredJsonlLogger } from "./structured-log.js";
|
||||
import { attachApiSupervisorControl, initializeApiCredentialClients, receiveApiCredentials } from "./supervisor-channel.js";
|
||||
import { ModelConfigurationService } from "./model-configuration.js";
|
||||
import { ModelConfigurationService, portableRuntimeModelCandidates } from "./model-configuration.js";
|
||||
import { MockAmapAdapter, type AmapAdapter } from "./amap-adapter.js";
|
||||
import { StickerReleaseService } from "./sticker-releases.js";
|
||||
import { createAdminDiagnosticsProvider, createAdminServicesStorageProvider } from "./admin-state.js";
|
||||
@@ -56,7 +56,7 @@ if (credentialChannelEnabled) {
|
||||
storage = new ManagedStorage({ dataRoot, databasePath });
|
||||
stickers = new StickerReleaseService({ databasePath, storage });
|
||||
latestExports = new LatestExportService({ databasePath, storage });
|
||||
models = new ModelConfigurationService({ database: registration.database });
|
||||
models = new ModelConfigurationService({ database: registration.database, seedCandidates: portableRuntimeModelCandidates });
|
||||
recentAssets = new RecentAssetService({ database: registration.database });
|
||||
registration.applySecureConfig(readSecureConfigCandidate(instanceConfigPath));
|
||||
} catch (error) {
|
||||
|
||||
@@ -111,7 +111,7 @@ const defaultErrorMapping: Record<string, string> = {
|
||||
upstream_timeout: "upstream_timeout",
|
||||
};
|
||||
|
||||
const seedCandidates: ModelConfigCandidate[] = [
|
||||
const defaultSeedCandidates: ModelConfigCandidate[] = [
|
||||
{
|
||||
model_id: modelIds[0], display_name: "Gemini 3.1 Flash Image Preview", enabled: true, is_default: true,
|
||||
recommendation_priority: 1, route_profile: { endpoint: "https://mock.invalid/v1/images", mode: "sync" },
|
||||
@@ -138,6 +138,42 @@ const seedCandidates: ModelConfigCandidate[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const portableRuntimeModelCandidates: ModelConfigCandidate[] = [
|
||||
{
|
||||
...defaultSeedCandidates[0]!,
|
||||
display_name: "Gemini 3.1 Flash Image",
|
||||
route_profile: {
|
||||
endpoint: "https://oneapi.intelligrow.cn/v1/chat/completions",
|
||||
mode: "sync",
|
||||
protocol_version: "gemini-openai-chat-v1",
|
||||
provider_model_id: "gemini-3.1-flash-image",
|
||||
},
|
||||
gateway_account_ref: "oneapi-intelligrow-test",
|
||||
contract_validation_status: "verified",
|
||||
contract_evidence_ref: "contract:wp7-02:gemini-3.1-flash-image:v7",
|
||||
},
|
||||
{
|
||||
...defaultSeedCandidates[1]!,
|
||||
enabled: false,
|
||||
route_profile: { endpoint: "https://oneapi.intelligrow.cn/unsupported", mode: "disabled" },
|
||||
gateway_account_ref: "oneapi-intelligrow-test",
|
||||
contract_validation_status: "unverified",
|
||||
contract_evidence_ref: null,
|
||||
},
|
||||
{
|
||||
...defaultSeedCandidates[2]!,
|
||||
route_profile: {
|
||||
endpoint: "https://oneapi.intelligrow.cn/v1/images/generations",
|
||||
mode: "sync",
|
||||
protocol_version: "openai-images-v1",
|
||||
reference_endpoint: "https://oneapi.intelligrow.cn/v1/images/edits",
|
||||
},
|
||||
gateway_account_ref: "oneapi-intelligrow-test",
|
||||
contract_validation_status: "verified",
|
||||
contract_evidence_ref: "contract:wp7-02:gpt-image-2:v2",
|
||||
},
|
||||
];
|
||||
|
||||
function stableJson(value: unknown): string {
|
||||
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
||||
if (value && typeof value === "object") {
|
||||
@@ -207,17 +243,20 @@ export interface ModelConfigurationServiceOptions {
|
||||
clock?: () => number;
|
||||
database: BetterSqlite3.Database;
|
||||
onChanged?: (configSetVersion: number) => void;
|
||||
seedCandidates?: ModelConfigCandidate[];
|
||||
}
|
||||
|
||||
export class ModelConfigurationService {
|
||||
readonly database: BetterSqlite3.Database;
|
||||
readonly #clock: () => number;
|
||||
readonly #onChanged: ((configSetVersion: number) => void) | undefined;
|
||||
readonly #seedCandidates: ModelConfigCandidate[];
|
||||
|
||||
constructor(options: ModelConfigurationServiceOptions) {
|
||||
this.database = options.database;
|
||||
this.#clock = options.clock ?? Date.now;
|
||||
this.#onChanged = options.onChanged;
|
||||
this.#seedCandidates = structuredClone(options.seedCandidates ?? defaultSeedCandidates);
|
||||
this.ensureSchema();
|
||||
}
|
||||
|
||||
@@ -503,7 +542,7 @@ export class ModelConfigurationService {
|
||||
const current = this.database.prepare("SELECT config_set_id FROM model_config_current WHERE singleton = 1").get() as { config_set_id: string } | undefined;
|
||||
if (current) return;
|
||||
const seed = this.database.transaction(() => {
|
||||
validateModelConfigurationCandidateSet(seedCandidates);
|
||||
validateModelConfigurationCandidateSet(this.#seedCandidates);
|
||||
const now = this.#clock();
|
||||
const setId = randomUUID();
|
||||
this.database.prepare("INSERT INTO model_config_sets (config_set_id, config_set_version, created_at, created_by) VALUES (?, 1, ?, 'system_seed')")
|
||||
@@ -520,7 +559,9 @@ export class ModelConfigurationService {
|
||||
INSERT INTO model_config_set_members (config_set_id, model_id, config_version, enabled, is_default, recommendation_priority)
|
||||
VALUES (?, ?, 1, ?, ?, ?)
|
||||
`);
|
||||
for (const candidate of seedCandidates) {
|
||||
for (const candidate of this.#seedCandidates) {
|
||||
const contractStatus = candidate.contract_validation_status ?? "unverified";
|
||||
const contractEvidenceRef = contractStatus === "unverified" ? null : candidate.contract_evidence_ref ?? null;
|
||||
const routeProfileId = profileRef("route", candidate.route_profile);
|
||||
const errorMappingProfileId = profileRef("error", candidate.error_mapping_profile);
|
||||
this.database.prepare("INSERT OR IGNORE INTO gateway_route_profiles (route_profile_id, profile_json, created_at) VALUES (?, ?, ?)")
|
||||
@@ -530,12 +571,14 @@ export class ModelConfigurationService {
|
||||
insertVersion.run(candidate.model_id, candidate.display_name, candidate.enabled ? 1 : 0, candidate.is_default ? 1 : 0,
|
||||
candidate.recommendation_priority, routeProfileId, stableJson(candidate.route_profile), candidate.gateway_account_ref,
|
||||
errorMappingProfileId, stableJson(candidate.error_mapping_profile), candidate.credit_cost, stableJson(candidate.supported_ratios), stableJson(candidate.reference_limits),
|
||||
candidate.prompt_max_length, candidate.safety_source, "unverified", null, fingerprint(candidate), now);
|
||||
candidate.prompt_max_length, candidate.safety_source, contractStatus, contractEvidenceRef, fingerprint(candidate), now);
|
||||
insertMember.run(setId, candidate.model_id, candidate.enabled ? 1 : 0, candidate.is_default ? 1 : 0, candidate.recommendation_priority);
|
||||
const available = candidate.enabled && contractStatus === "verified";
|
||||
const runtimeReason = !candidate.enabled ? "configured_disabled" : available ? "available" : "contract_unverified";
|
||||
this.database.prepare(`
|
||||
INSERT INTO model_runtime_availability (model_id, available_for_new_jobs, reason, checked_at, runtime_availability_version)
|
||||
VALUES (?, 0, 'contract_unverified', ?, 0)
|
||||
`).run(candidate.model_id, now);
|
||||
VALUES (?, ?, ?, ?, 0)
|
||||
`).run(candidate.model_id, available ? 1 : 0, runtimeReason, now);
|
||||
}
|
||||
this.database.prepare("INSERT INTO model_config_current (singleton, config_set_id) VALUES (1, ?)").run(setId);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user