feat(pi): materialize effective plugin worker tools
This commit is contained in:
@@ -14,19 +14,22 @@ const MUTATION_TOOLS = new Set([
|
||||
'write',
|
||||
'game_asset_browser',
|
||||
'game_asset_review',
|
||||
'data_service_configure',
|
||||
'data_service_put_document',
|
||||
'data_service_delete_document',
|
||||
'data_service_remove_collection',
|
||||
'data_service_reset',
|
||||
'data_service_remove_project',
|
||||
]);
|
||||
const WORKER_ROLE = process.env.MAKELORE_PI_WORKER_ROLE || 'parent';
|
||||
const leases = new Map();
|
||||
const touchedPaths = new Map();
|
||||
let dynamicLeaseTools = new Set();
|
||||
|
||||
async function readWorkerContext() {
|
||||
const value = JSON.parse(await readFile(process.env.MAKELORE_PI_CONTEXT_FILE, 'utf8'));
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
throw new Error('Makelore worker context is invalid');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
async function runtimeContext() {
|
||||
const value = JSON.parse(await readFile(process.env.MAKELORE_PI_CONTEXT_FILE, 'utf8'));
|
||||
const value = await readWorkerContext();
|
||||
if (!value.runId) throw new Error('Makelore run context is unavailable');
|
||||
return value;
|
||||
}
|
||||
@@ -131,7 +134,47 @@ function registerProductTool(pi, name, label, description, parameters) {
|
||||
});
|
||||
}
|
||||
|
||||
export default function makeloreRuntime(pi) {
|
||||
function isRecord(value) {
|
||||
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function isToolDeclaration(value) {
|
||||
return isRecord(value)
|
||||
&& typeof value.name === 'string'
|
||||
&& typeof value.label === 'string'
|
||||
&& typeof value.description === 'string'
|
||||
&& isRecord(value.inputSchema);
|
||||
}
|
||||
|
||||
async function registerDynamicProductTools(pi) {
|
||||
if (WORKER_ROLE !== 'parent') return;
|
||||
const context = await readWorkerContext();
|
||||
const allowedToolNames = new Set(
|
||||
Array.isArray(context.allowedToolNames)
|
||||
? context.allowedToolNames.filter((name) => typeof name === 'string')
|
||||
: [],
|
||||
);
|
||||
const declarations = Array.isArray(context.tools) ? context.tools : [];
|
||||
dynamicLeaseTools = new Set(
|
||||
declarations
|
||||
.filter((declaration) => isToolDeclaration(declaration)
|
||||
&& declaration.projectWriteLease === true
|
||||
&& allowedToolNames.has(declaration.name))
|
||||
.map((declaration) => declaration.name),
|
||||
);
|
||||
for (const declaration of declarations) {
|
||||
if (!isToolDeclaration(declaration) || !allowedToolNames.has(declaration.name)) continue;
|
||||
registerProductTool(
|
||||
pi,
|
||||
declaration.name,
|
||||
declaration.label,
|
||||
declaration.description,
|
||||
declaration.inputSchema,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default async function makeloreRuntime(pi) {
|
||||
if (WORKER_ROLE === 'parent') pi.registerTool({
|
||||
name: 'ask_user',
|
||||
label: 'Ask user',
|
||||
@@ -290,139 +333,11 @@ export default function makeloreRuntime(pi) {
|
||||
'Read the safe selected-skill and command catalog for this managed worker.',
|
||||
{ type: 'object', additionalProperties: false, properties: {} },
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_configure',
|
||||
'Data Service configure',
|
||||
'Configure collections for the active Makelore project Data Service instance.',
|
||||
{
|
||||
type: 'object', additionalProperties: false, required: ['collections'],
|
||||
properties: {
|
||||
collections: {
|
||||
type: 'array', minItems: 0, maxItems: 20,
|
||||
items: { type: 'string', minLength: 1, maxLength: 48, pattern: '^[a-z][a-z0-9_-]{0,47}$' },
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_inspect',
|
||||
'Data Service inspect',
|
||||
'Inspect the active Makelore project Data Service instance.',
|
||||
{ type: 'object', additionalProperties: false, properties: {} },
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_list_projects',
|
||||
'Data Service projects',
|
||||
'List Data Service instances available to the signed-in account.',
|
||||
{ type: 'object', additionalProperties: false, properties: {} },
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_get_document',
|
||||
'Data Service get document',
|
||||
'Read one document from a collection in the active Makelore project.',
|
||||
{
|
||||
type: 'object', additionalProperties: false, required: ['collection', 'document_id'],
|
||||
properties: {
|
||||
collection: { type: 'string', minLength: 1, maxLength: 48, pattern: '^[a-z][a-z0-9_-]{0,47}$' },
|
||||
document_id: {
|
||||
type: 'string', minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9._~-]{1,128}$',
|
||||
not: { enum: ['.', '..'] },
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_list_documents',
|
||||
'Data Service list documents',
|
||||
'List documents from a collection in the active Makelore project.',
|
||||
{
|
||||
type: 'object', additionalProperties: false, required: ['collection'],
|
||||
properties: {
|
||||
collection: { type: 'string', minLength: 1, maxLength: 48, pattern: '^[a-z][a-z0-9_-]{0,47}$' },
|
||||
limit: { type: 'integer', minimum: 1, maximum: 100 },
|
||||
cursor: { type: 'string', minLength: 1, maxLength: 1024 },
|
||||
},
|
||||
},
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_put_document',
|
||||
'Data Service put document',
|
||||
'Create or update one document in a collection in the active Makelore project.',
|
||||
{
|
||||
type: 'object', additionalProperties: false,
|
||||
required: ['collection', 'document_id', 'data'],
|
||||
properties: {
|
||||
collection: { type: 'string', minLength: 1, maxLength: 48, pattern: '^[a-z][a-z0-9_-]{0,47}$' },
|
||||
document_id: {
|
||||
type: 'string', minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9._~-]{1,128}$',
|
||||
not: { enum: ['.', '..'] },
|
||||
},
|
||||
data: { type: 'object' },
|
||||
if_revision: { type: 'integer', minimum: 1, maximum: 9007199254740991 },
|
||||
},
|
||||
},
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_delete_document',
|
||||
'Data Service delete document',
|
||||
'Delete one document from the active Makelore project after explicit confirmation.',
|
||||
{
|
||||
type: 'object', additionalProperties: false,
|
||||
required: ['collection', 'document_id', 'confirmed'],
|
||||
properties: {
|
||||
collection: { type: 'string', minLength: 1, maxLength: 48, pattern: '^[a-z][a-z0-9_-]{0,47}$' },
|
||||
document_id: {
|
||||
type: 'string', minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9._~-]{1,128}$',
|
||||
not: { enum: ['.', '..'] },
|
||||
},
|
||||
if_revision: { type: 'integer', minimum: 1, maximum: 9007199254740991 },
|
||||
confirmed: { type: 'boolean', const: true },
|
||||
},
|
||||
},
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_remove_collection',
|
||||
'Data Service remove collection',
|
||||
'Remove a collection from the active Makelore project after explicit confirmation.',
|
||||
{
|
||||
type: 'object', additionalProperties: false, required: ['collection', 'confirmed'],
|
||||
properties: {
|
||||
collection: { type: 'string', minLength: 1, maxLength: 48, pattern: '^[a-z][a-z0-9_-]{0,47}$' },
|
||||
confirmed: { type: 'boolean', const: true },
|
||||
},
|
||||
},
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_reset',
|
||||
'Data Service reset',
|
||||
'Reset all collections in the active Makelore project after explicit confirmation.',
|
||||
{
|
||||
type: 'object', additionalProperties: false, required: ['confirmed'],
|
||||
properties: { confirmed: { type: 'boolean', const: true } },
|
||||
},
|
||||
);
|
||||
if (WORKER_ROLE === 'parent') registerProductTool(
|
||||
pi,
|
||||
'data_service_remove_project',
|
||||
'Data Service remove project',
|
||||
'Remove the active Makelore project Data Service instance after explicit confirmation.',
|
||||
{
|
||||
type: 'object', additionalProperties: false, required: ['confirmed'],
|
||||
properties: { confirmed: { type: 'boolean', const: true } },
|
||||
},
|
||||
);
|
||||
|
||||
await registerDynamicProductTools(pi);
|
||||
|
||||
pi.on('tool_call', async (event, ctx) => {
|
||||
if (!MUTATION_TOOLS.has(event.toolName)) return;
|
||||
if (!MUTATION_TOOLS.has(event.toolName) && !dynamicLeaseTools.has(event.toolName)) return;
|
||||
const input = event.input || event.arguments || event.args || {};
|
||||
const touchedPath = (event.toolName === 'write' || event.toolName === 'edit')
|
||||
? projectRelativePath(input.path) : undefined;
|
||||
|
||||
Reference in New Issue
Block a user