480 lines
13 KiB
TypeScript
480 lines
13 KiB
TypeScript
/**
|
|
* 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<Record<string, unknown>>;
|
|
outputSchema?: Readonly<Record<string, unknown>>;
|
|
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<T>(value: T): T {
|
|
if (value && typeof value === 'object' && !Object.isFrozen(value)) {
|
|
for (const child of Object.values(value as Record<string, unknown>)) 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<Record<string, unknown>>,
|
|
): 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[]);
|