Skip to content

Commit 1eafc40

Browse files
committed
fix: seed default model on catalog import and gate MCP management
Seed default_model when unset after models.dev/registry import. Return an empty plugin marketplace when no URL is configured. Reject MCP management RPCs while the experimental flag is off.
1 parent 43ccd2c commit 1eafc40

5 files changed

Lines changed: 47 additions & 9 deletions

File tree

‎packages/agent-core-v2/src/app/kosongConfig/modelsDevImportService.ts‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { IModelService, modelRecordProviderId, type ModelsSection } from '#/koso
1616
import { type ProviderConfig, type ProvidersSection } from '#/kosong/provider/provider';
1717
import { modelsDevProviderModels, resolveModelsDevImport } from './modelsDev';
1818

19-
import { MODELS_SECTION, PROVIDERS_SECTION } from './configSection';
19+
import { DEFAULT_MODEL_SECTION, MODELS_SECTION, PROVIDERS_SECTION } from './configSection';
2020
import { ModelsDevImportErrors } from './errors';
2121
import { IKosongConfigService } from './kosongConfig';
2222
import {
@@ -86,6 +86,12 @@ export class ModelsDevImportService implements IModelsDevImportService {
8686
return this.enqueueWrite(() => this.doImportCustomRegistry(options));
8787
}
8888

89+
private async seedDefaultModelWhenUnset(config: IConfigService, alias: string): Promise<void> {
90+
const current = config.inspect<string>(DEFAULT_MODEL_SECTION).userValue;
91+
if (current !== undefined && current.trim() !== '') return;
92+
await config.replace(DEFAULT_MODEL_SECTION, alias);
93+
}
94+
8995
private enqueueWrite<T>(task: () => Promise<T>): Promise<T> {
9096
const run = this.writeChain.then(task, task);
9197
this.writeChain = run.then(
@@ -165,6 +171,11 @@ export class ModelsDevImportService implements IModelsDevImportService {
165171
}
166172
await config.replace(MODELS_SECTION, nextModels);
167173

174+
const firstModel = models[0];
175+
if (firstModel !== undefined) {
176+
await this.seedDefaultModelWhenUnset(config, `${targetId}/${firstModel.id}`);
177+
}
178+
168179
await this.models.settled;
169180
const imported = await this.modelCatalog.getProvider(targetId);
170181
return { provider: imported, modelsImported: models.length };
@@ -239,6 +250,14 @@ export class ModelsDevImportService implements IModelsDevImportService {
239250
await config.replace(PROVIDERS_SECTION, applied.providers as ProvidersSection);
240251
await config.replace(MODELS_SECTION, (applied.models ?? {}) as ModelsSection);
241252

253+
const firstEntry = Object.values(entries)[0];
254+
if (firstEntry !== undefined) {
255+
const firstModelId = Object.keys(firstEntry.models)[0];
256+
if (firstModelId !== undefined) {
257+
await this.seedDefaultModelWhenUnset(config, `${firstEntry.id}/${firstModelId}`);
258+
}
259+
}
260+
242261
await this.models.settled;
243262
const imported = [];
244263
for (const entry of Object.values(entries)) {

‎packages/agent-core-v2/src/app/mcpManagement/mcpManagementService.ts‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Disposable } from '#/_base/di/lifecycle';
66
import { LifecycleScope } from '#/app/scopes';
77
import { ScopeActivation, registerScopedService } from '#/_base/di/scope';
88
import { ILogService } from '#/_base/log/log';
9+
import { IFlagService } from '#/app/flag/flag';
910

1011
import { ErrorCodes, Error2 } from '#/errors';
1112
import { McpConnectionManager } from '#/mcpCore/connection-manager';
@@ -52,6 +53,7 @@ import {
5253
type McpServerTestResult,
5354
type McpServerTestTarget,
5455
} from './mcpManagement';
56+
import { MCP_MANAGEMENT_FLAG_ID } from './flag';
5557

5658
const DEFAULT_AUTH_TIMEOUT_MS = 15 * 60_000;
5759
const AUTH_FLOW_IDLE_TIMEOUT_MS = 15 * 60_000;
@@ -76,15 +78,27 @@ export class McpManagementService extends Disposable implements IMcpManagementSe
7678
@IHostEnvironment private readonly hostEnvironment: IHostEnvironment,
7779
@IHostProcessService private readonly hostProcess: IHostProcessService,
7880
@ILogService private readonly log: ILogService,
81+
@IFlagService private readonly flags: IFlagService,
7982
) {
8083
super();
8184
}
8285

86+
private assertManagementEnabled(): void {
87+
if (!this.flags.enabled(MCP_MANAGEMENT_FLAG_ID)) {
88+
throw new Error2(
89+
ErrorCodes.REQUEST_INVALID,
90+
'MCP management is disabled; enable the mcp-management experimental flag',
91+
);
92+
}
93+
}
94+
8395
async listServers(query: McpRegistryQuery = {}): Promise<readonly McpManagedServer[]> {
96+
this.assertManagementEnabled();
8497
return (await this.registry.list(query)).map(toManagedServer);
8598
}
8699

87100
async getServer(name: string, query: McpRegistryQuery = {}): Promise<McpManagedServer> {
101+
this.assertManagementEnabled();
88102
return toManagedServer(await this.registry.get(name, query));
89103
}
90104

‎packages/agent-core-v2/test/app/mcpManagement/mcpManagement.test.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from 'vite
1010

1111
import { DisposableStore } from '#/_base/di/lifecycle';
1212
import { createServices } from '#/_base/di/test';
13+
import { IFlagService } from '#/app/flag/flag';
1314
import { ILogService } from '#/_base/log/log';
1415
import { IBootstrapService } from '#/app/bootstrap/bootstrap';
1516
import {
@@ -154,6 +155,9 @@ describe('McpManagementService', () => {
154155
});
155156
reg.definePartialInstance(IWorkspaceInstanceManager, { findContaining, getOrCreate });
156157
reg.defineInstance(ILogService, stubLog());
158+
reg.definePartialInstance(IFlagService, {
159+
enabled: () => true,
160+
});
157161
reg.define(IMcpManagementService, McpManagementService);
158162
},
159163
});

‎packages/agent-gateway/src/routes/plugins.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,16 @@ export function registerPluginsRoutes(
124124
operationId: 'listPluginMarketplace',
125125
},
126126
async (req, reply) => {
127+
const source = opts.marketplaceUrl().trim();
128+
if (source.length === 0) {
129+
reply.send(okEnvelope({ entries: [] }, req.id));
130+
return;
131+
}
127132
const fetchImpl = opts.fetchImpl ?? fetchWithTimeout;
128133
let read: { raw: string; location: MarketplaceLocation };
129134
try {
130135
read = await readPluginMarketplace({
131-
source: opts.marketplaceUrl(),
136+
source,
132137
workDir: process.cwd(),
133138
fetchImpl,
134139
sourceCheckoutLocation:

‎packages/agent-gateway/src/start.ts‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -439,14 +439,10 @@ export async function startServer(opts: ServerStartOptions): Promise<RunningServ
439439
guiStore,
440440
pluginMarketplaceUrl: (() => {
441441
const configured = opts.pluginMarketplaceUrl ?? process.env['PYTHINKER_CODE_PLUGIN_MARKETPLACE_URL'];
442-
if (configured !== undefined) return () => configured;
443-
return () =>
444-
'https://code.pythinker.com/pythinker-code/plugins/marketplace.json';
442+
if (configured !== undefined && configured.trim() !== '') return () => configured;
443+
return () => '';
445444
})(),
446-
pluginMarketplaceIsDefault:
447-
opts.pluginMarketplaceUrl === undefined &&
448-
(process.env['PYTHINKER_CODE_PLUGIN_MARKETPLACE_URL'] === undefined ||
449-
process.env['PYTHINKER_CODE_PLUGIN_MARKETPLACE_FROM_DEV_SERVER'] === '1'),
445+
pluginMarketplaceIsDefault: false,
450446
remoteControl: {
451447
service: remoteControlManager,
452448
staticEnableError:

0 commit comments

Comments
 (0)