feat(coding): add bundled plugin package selection
This commit is contained in:
407
shared/coding-plugins.ts
Normal file
407
shared/coding-plugins.ts
Normal file
@@ -0,0 +1,407 @@
|
||||
/**
|
||||
* 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 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>>;
|
||||
}
|
||||
|
||||
export interface CodingPluginDefinition {
|
||||
id: string;
|
||||
version: string;
|
||||
contractVersion: number;
|
||||
displayName: string;
|
||||
description: string;
|
||||
scope: 'project';
|
||||
adapterId: string;
|
||||
requiresBackend: boolean;
|
||||
skills: readonly CodingPluginSkillDefinition[];
|
||||
tools: readonly CodingPluginToolDefinition[];
|
||||
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 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_PLUGIN_DEFINITION = freezeDeep({
|
||||
id: DATA_SERVICE_PLUGIN_ID,
|
||||
version: '1.0.0',
|
||||
contractVersion: 1,
|
||||
displayName: '开发数据服务',
|
||||
description: '为当前项目提供受控的开发期 JSON 数据存储。',
|
||||
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,
|
||||
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[]);
|
||||
Reference in New Issue
Block a user