/** * The small, code-owned vocabulary shared by the Main plugin registry and the * renderer-facing product contracts. Package manifests are untrusted input; * the values below are the only first-party adapter, surface, permission and * Data Service identifiers that the P0 registry accepts. */ export type PluginBillingMode = | 'included' | 'platform_metered' | 'external_account'; export type PluginToolMutation = 'read' | 'write' | 'destructive'; export type CodingPluginRuntimeKind = | 'bundled_typed' | 'skill_only' | 'platform_hosted'; export type CodingPluginAcquisitionMode = | 'system_included' | 'user_acquired'; export type CodingPluginExecutionMode = 'synchronous' | 'job'; export interface CodingPluginPackageProvenance { readonly source: 'bundled' | 'marketplace'; /** A trusted Package Store root, never a manifest-provided value. */ readonly packageRoot: string; } export interface CodingPluginSkillDefinition { id: string; entryPath: string; grants: readonly string[]; } export interface CodingPluginToolDefinition { name: string; label: string; description: string; capabilityId: string; operation: string; roles: readonly ['parent']; mutation: PluginToolMutation; projectWriteLease: boolean; permissions: readonly string[]; inputSchema: Readonly>; outputSchema?: Readonly>; executionMode?: CodingPluginExecutionMode; } export interface CodingPluginOperationDefinition { capabilityId: string; operation: string; toolName?: string; } export interface CodingPluginDefinition { id: string; version: string; contractVersion: number; displayName: string; description: string; runtimeKind: CodingPluginRuntimeKind; acquisitionMode: CodingPluginAcquisitionMode; releaseId: string | null; provenance: CodingPluginPackageProvenance; scope: 'project'; adapterId: string; requiresBackend: boolean; skills: readonly CodingPluginSkillDefinition[]; tools: readonly CodingPluginToolDefinition[]; operations: readonly CodingPluginOperationDefinition[]; surfaces: Readonly<{ projectSettings?: string; previewRuntime?: string; }>; } export interface AgentPluginsAuthorManifest { name: string; } export interface AgentPluginsRootManifest { $schema: string; name: string; version: string; description: string; author: AgentPluginsAuthorManifest; extensions: Readonly<{ 'com.makelore': Readonly<{ capabilityManifest: string }>; }>; } export const AGENT_PLUGINS_SCHEMA_URL = 'https://agent-plugins.org/schemas/1.0.0/plugin.schema.json' as const; export const DATA_SERVICE_PLUGIN_ID = 'makelore.data-service' as const; export const DATA_SERVICE_ADAPTER_ID = 'data-service' as const; export const DATA_SERVICE_PROJECT_SETTINGS_SURFACE = 'data-service' as const; export const DATA_SERVICE_PREVIEW_RUNTIME_SURFACE = 'data-service-v1' as const; export const GAME_RESOURCE_PLUGIN_ID = 'makelore.game-resource' as const; export const GAME_RESOURCE_BUNDLED_RELEASE_ID = '00000000-0000-4000-8000-000000000105' as const; export const WEB_SEARCH_PLUGIN_ID = 'makelore.web-search' as const; export const WEB_SEARCH_BUNDLED_RELEASE_ID = '00000000-0000-4000-8000-000000000204' as const; export const CODE_OWNED_OPTIONAL_BUNDLED_RELEASES = Object.freeze({ [GAME_RESOURCE_PLUGIN_ID]: Object.freeze({ releaseId: GAME_RESOURCE_BUNDLED_RELEASE_ID, version: '1.0.0', channel: 'stable' as const, }), [WEB_SEARCH_PLUGIN_ID]: Object.freeze({ releaseId: WEB_SEARCH_BUNDLED_RELEASE_ID, version: '1.0.0', channel: 'stable' as const, }), }); export function isCodeOwnedOptionalBundledPluginId(pluginId: string): boolean { return Object.prototype.hasOwnProperty.call(CODE_OWNED_OPTIONAL_BUNDLED_RELEASES, pluginId); } export const DATA_SERVICE_CAPABILITY_IDS = Object.freeze([ 'data-service.control', 'data-service.documents', 'data-service.preview', ] as const); export const DATA_SERVICE_TOOL_NAMES = Object.freeze([ 'data_service_configure', 'data_service_inspect', 'data_service_list_projects', 'data_service_get_document', 'data_service_list_documents', 'data_service_put_document', 'data_service_delete_document', 'data_service_remove_collection', 'data_service_reset', 'data_service_remove_project', ] as const); export const CODE_OWNED_PLUGIN_ADAPTER_IDS = Object.freeze([ DATA_SERVICE_ADAPTER_ID, ] as const); export const CODE_OWNED_PLUGIN_SETTINGS_SURFACES = Object.freeze([ DATA_SERVICE_PROJECT_SETTINGS_SURFACE, ] as const); export const CODE_OWNED_PLUGIN_PREVIEW_SURFACES = Object.freeze([ DATA_SERVICE_PREVIEW_RUNTIME_SURFACE, ] as const); export const CODE_OWNED_PLUGIN_PERMISSION_IDS = Object.freeze([ 'project.data.admin', 'project.data.configure', 'project.data.read', 'project.data.write', ] as const); // Descriptive aliases keep the allowlist vocabulary discoverable to callers // without creating a second source of truth. export const BUNDLED_CODING_PLUGIN_ADAPTER_IDS = CODE_OWNED_PLUGIN_ADAPTER_IDS; export const BUNDLED_CODING_PLUGIN_SETTINGS_SURFACES = CODE_OWNED_PLUGIN_SETTINGS_SURFACES; export const BUNDLED_CODING_PLUGIN_PREVIEW_SURFACES = CODE_OWNED_PLUGIN_PREVIEW_SURFACES; export const BUNDLED_CODING_PLUGIN_PERMISSION_IDS = CODE_OWNED_PLUGIN_PERMISSION_IDS; const EMPTY_OBJECT_SCHEMA = Object.freeze({ type: 'object', additionalProperties: false, properties: {}, } as const); const COLLECTION_SCHEMA = Object.freeze({ type: 'string', pattern: '^[a-z][a-z0-9_-]{0,47}$', } as const); const DOCUMENT_ID_SCHEMA = Object.freeze({ type: 'string', pattern: '^[A-Za-z0-9._~-]{1,128}$', } as const); const REVISION_SCHEMA = Object.freeze({ type: 'integer', minimum: 1, } as const); const DATA_SCHEMA = Object.freeze({ type: 'object', } as const); const LIST_LIMIT_SCHEMA = Object.freeze({ type: 'integer', minimum: 1, maximum: 100, } as const); const CURSOR_SCHEMA = Object.freeze({ type: 'string', minLength: 1, maxLength: 1024, } as const); const CONFIRMED_SCHEMA = Object.freeze({ type: 'boolean', const: true, } as const); const CONFIGURE_SCHEMA = Object.freeze({ type: 'object', additionalProperties: false, required: ['collections'], properties: { collections: { type: 'array', maxItems: 20, items: COLLECTION_SCHEMA, }, }, } as const); const GET_DOCUMENT_SCHEMA = Object.freeze({ type: 'object', additionalProperties: false, required: ['collection', 'document_id'], properties: { collection: COLLECTION_SCHEMA, document_id: DOCUMENT_ID_SCHEMA, }, } as const); const LIST_DOCUMENTS_SCHEMA = Object.freeze({ type: 'object', additionalProperties: false, required: ['collection'], properties: { collection: COLLECTION_SCHEMA, limit: LIST_LIMIT_SCHEMA, cursor: CURSOR_SCHEMA, }, } as const); const PUT_DOCUMENT_SCHEMA = Object.freeze({ type: 'object', additionalProperties: false, required: ['collection', 'document_id', 'data'], properties: { collection: COLLECTION_SCHEMA, document_id: DOCUMENT_ID_SCHEMA, data: DATA_SCHEMA, if_revision: REVISION_SCHEMA, }, } as const); const DELETE_DOCUMENT_SCHEMA = Object.freeze({ type: 'object', additionalProperties: false, required: ['collection', 'document_id', 'confirmed'], properties: { collection: COLLECTION_SCHEMA, document_id: DOCUMENT_ID_SCHEMA, if_revision: REVISION_SCHEMA, confirmed: CONFIRMED_SCHEMA, }, } as const); const REMOVE_COLLECTION_SCHEMA = Object.freeze({ type: 'object', additionalProperties: false, required: ['collection', 'confirmed'], properties: { collection: COLLECTION_SCHEMA, confirmed: CONFIRMED_SCHEMA, }, } as const); const CONFIRMATION_SCHEMA = Object.freeze({ type: 'object', additionalProperties: false, required: ['confirmed'], properties: { confirmed: CONFIRMED_SCHEMA }, } as const); function freezeDeep(value: T): T { if (value && typeof value === 'object' && !Object.isFrozen(value)) { for (const child of Object.values(value as Record)) freezeDeep(child); Object.freeze(value); } return value; } function tool( name: (typeof DATA_SERVICE_TOOL_NAMES)[number], label: string, description: string, capabilityId: string, operation: string, mutation: PluginToolMutation, projectWriteLease: boolean, permissions: readonly string[], inputSchema: Readonly>, ): CodingPluginToolDefinition { return { name, label, description, capabilityId, operation, roles: ['parent'], mutation, projectWriteLease, permissions, inputSchema, }; } export const DATA_SERVICE_TOOL_DEFINITIONS = freezeDeep([ tool( 'data_service_configure', 'Data Service configure', 'Configure collections for the active project.', 'data-service.control', 'configure', 'write', true, ['project.data.configure'], CONFIGURE_SCHEMA, ), tool( 'data_service_inspect', 'Data Service inspect', 'Inspect the active project data instance.', 'data-service.control', 'inspect', 'read', false, ['project.data.read'], EMPTY_OBJECT_SCHEMA, ), tool( 'data_service_list_projects', 'Data Service list projects', 'List the authenticated projects with Data Service instances.', 'data-service.control', 'list_projects', 'read', false, ['project.data.read'], EMPTY_OBJECT_SCHEMA, ), tool( 'data_service_get_document', 'Data Service get document', 'Read a document from the active project.', 'data-service.documents', 'get_document', 'read', false, ['project.data.read'], GET_DOCUMENT_SCHEMA, ), tool( 'data_service_list_documents', 'Data Service list documents', 'List documents from a collection in the active project.', 'data-service.documents', 'list_documents', 'read', false, ['project.data.read'], LIST_DOCUMENTS_SCHEMA, ), tool( 'data_service_put_document', 'Data Service put document', 'Create or replace a document in the active project.', 'data-service.documents', 'put_document', 'write', true, ['project.data.write'], PUT_DOCUMENT_SCHEMA, ), tool( 'data_service_delete_document', 'Data Service delete document', 'Delete a document after explicit confirmation.', 'data-service.documents', 'delete_document', 'destructive', true, ['project.data.write'], DELETE_DOCUMENT_SCHEMA, ), tool( 'data_service_remove_collection', 'Data Service remove collection', 'Remove a collection after explicit confirmation.', 'data-service.control', 'remove_collection', 'destructive', true, ['project.data.admin'], REMOVE_COLLECTION_SCHEMA, ), tool( 'data_service_reset', 'Data Service reset', 'Reset all active project data after explicit confirmation.', 'data-service.control', 'reset', 'destructive', true, ['project.data.admin'], CONFIRMATION_SCHEMA, ), tool( 'data_service_remove_project', 'Data Service remove project', 'Remove the active project data instance after explicit confirmation.', 'data-service.control', 'remove_project', 'destructive', true, ['project.data.admin'], CONFIRMATION_SCHEMA, ), ] as const satisfies readonly CodingPluginToolDefinition[]); export const DATA_SERVICE_OPERATION_DEFINITIONS = freezeDeep([ ...DATA_SERVICE_TOOL_DEFINITIONS.map(({ capabilityId, operation, name }) => ({ capabilityId, operation, toolName: name, })), ...['get', 'list', 'put', 'delete'].map((operation) => ({ capabilityId: 'data-service.preview', operation, })), ] as const satisfies readonly CodingPluginOperationDefinition[]); export const DATA_SERVICE_PLUGIN_DEFINITION = freezeDeep({ id: DATA_SERVICE_PLUGIN_ID, version: '1.0.0', contractVersion: 1, displayName: '开发数据服务', description: '为当前项目提供受控的开发期 JSON 数据存储。', runtimeKind: 'bundled_typed', acquisitionMode: 'system_included', releaseId: null, provenance: { source: 'bundled', packageRoot: 'data-service', }, scope: 'project', adapterId: DATA_SERVICE_ADAPTER_ID, requiresBackend: true, skills: [ { id: 'data-service', entryPath: 'skills/data-service/SKILL.md', grants: ['data-service.control', 'data-service.documents'], }, ], tools: DATA_SERVICE_TOOL_DEFINITIONS, operations: DATA_SERVICE_OPERATION_DEFINITIONS, surfaces: { projectSettings: DATA_SERVICE_PROJECT_SETTINGS_SURFACE, previewRuntime: DATA_SERVICE_PREVIEW_RUNTIME_SURFACE, }, } as const satisfies CodingPluginDefinition); export const BUNDLED_CODING_PLUGIN_DEFINITIONS = freezeDeep([ DATA_SERVICE_PLUGIN_DEFINITION, ] as const satisfies readonly CodingPluginDefinition[]);