feat: add space functions to center, remove space remote template
This commit is contained in:
1 parent
e9956bd34f
commit
953976cfc1
9 files changed
+79
-21
No files matched your search
@@ -0,0 +1,38 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const spec = {
|
||||
name: 'create-function',
|
||||
description: 'Create a new function on this remote by writing a function module.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Function identifier.' },
|
||||
description: { type: 'string', description: 'Description shown to the AI.' },
|
||||
parameters: { type: 'object', description: 'OpenAI tool parameter schema for the function arguments.' },
|
||||
code: { type: 'string', description: 'JavaScript statements forming the function body; `args` and `ctx` are in scope.' },
|
||||
},
|
||||
required: ['name', 'description', 'parameters', 'code'],
|
||||
},
|
||||
};
|
||||
|
||||
export default async function (args, ctx) {
|
||||
const name = args.name;
|
||||
if (typeof name !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(name)) {
|
||||
throw new Error(`Invalid function name: ${JSON.stringify(name)}`);
|
||||
}
|
||||
const functionsDir = path.join(ctx.dir, '.remote', 'functions');
|
||||
fs.mkdirSync(functionsDir, { recursive: true });
|
||||
const moduleSource = `export const spec = ${JSON.stringify({
|
||||
name,
|
||||
description: args.description,
|
||||
parameters: args.parameters,
|
||||
}, null, 2)};
|
||||
|
||||
export default async function (args, ctx) {
|
||||
${args.code}
|
||||
}
|
||||
`;
|
||||
fs.writeFileSync(path.join(functionsDir, `${name}.mjs`), moduleSource);
|
||||
return { created: name };
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const spec = {
|
||||
name: 'delete-file',
|
||||
description: 'Delete a file (or directory) in the space.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
path: { type: 'string', description: 'Path relative to the space directory.' },
|
||||
},
|
||||
required: ['path'],
|
||||
},
|
||||
};
|
||||
|
||||
function resolveIn(base, relPath) {
|
||||
const resolved = path.resolve(base, relPath);
|
||||
if (resolved !== base && !resolved.startsWith(base + path.sep)) {
|
||||
throw new Error('Path escapes the space directory');
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
export default async function (args, ctx) {
|
||||
const file = resolveIn(ctx.dir, args.path);
|
||||
if (!fs.existsSync(file)) throw new Error(`No such file: ${args.path}`);
|
||||
fs.rmSync(file, { recursive: true });
|
||||
return { deleted: args.path };
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const spec = {
|
||||
name: 'delete-function',
|
||||
description: 'Delete a function module from this remote.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Name of the function to delete.' },
|
||||
},
|
||||
required: ['name'],
|
||||
},
|
||||
};
|
||||
|
||||
export default async function (args, ctx) {
|
||||
const functionsDir = path.join(ctx.dir, '.remote', 'functions');
|
||||
for (const ext of ['.mjs', '.js']) {
|
||||
const file = path.join(functionsDir, `${args.name}${ext}`);
|
||||
if (fs.existsSync(file)) {
|
||||
fs.unlinkSync(file);
|
||||
return { deleted: args.name };
|
||||
}
|
||||
}
|
||||
throw new Error(`No such function: ${args.name}`);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const spec = {
|
||||
name: 'list-files',
|
||||
description: 'List every file in the space, as paths relative to the space directory.',
|
||||
parameters: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export default async function (args, ctx) {
|
||||
const files = [];
|
||||
const walk = (dir, prefix) => {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
||||
if (entry.isDirectory()) walk(path.join(dir, entry.name), rel);
|
||||
else files.push(rel);
|
||||
}
|
||||
};
|
||||
walk(ctx.dir, '');
|
||||
return { files };
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const spec = {
|
||||
name: 'read-file',
|
||||
description: 'Read the text content of a file in the space.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
path: { type: 'string', description: 'File path relative to the space directory.' },
|
||||
},
|
||||
required: ['path'],
|
||||
},
|
||||
};
|
||||
|
||||
function resolveIn(base, relPath) {
|
||||
const resolved = path.resolve(base, relPath);
|
||||
if (resolved !== base && !resolved.startsWith(base + path.sep)) {
|
||||
throw new Error('Path escapes the space directory');
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
export default async function (args, ctx) {
|
||||
return { content: fs.readFileSync(resolveIn(ctx.dir, args.path), 'utf8') };
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const spec = {
|
||||
name: 'write-file',
|
||||
description: 'Write text content to a file in the space, creating parent directories as needed.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
path: { type: 'string', description: 'File path relative to the space directory.' },
|
||||
content: { type: 'string', description: 'Text content to write.' },
|
||||
},
|
||||
required: ['path', 'content'],
|
||||
},
|
||||
};
|
||||
|
||||
function resolveIn(base, relPath) {
|
||||
const resolved = path.resolve(base, relPath);
|
||||
if (resolved !== base && !resolved.startsWith(base + path.sep)) {
|
||||
throw new Error('Path escapes the space directory');
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
export default async function (args, ctx) {
|
||||
const file = resolveIn(ctx.dir, args.path);
|
||||
fs.mkdirSync(path.dirname(file), { recursive: true });
|
||||
fs.writeFileSync(file, args.content ?? '');
|
||||
return { written: args.path };
|
||||
}
|
||||
Reference in new issue
Block a user