u
This commit is contained in:
@@ -197,6 +197,32 @@ function runInWorker({ code, timeoutMs, vfsRoot, googleAuthId, appletInput, appl
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the applet description header.
|
||||
*
|
||||
* Accepts either a quoted string (e.g. `"Lorem ipsum"` or `'Lorem ipsum'`) or bare text.
|
||||
* Strips surrounding quotes if present and trims whitespace.
|
||||
*
|
||||
* @param {string} header raw text after the `// @applet-description ` marker
|
||||
* @returns {string}
|
||||
*/
|
||||
function parseAppletDescription(header) {
|
||||
const text = String(header || '').trim();
|
||||
if (!text) {
|
||||
throw new ToolError('Applet description cannot be empty.');
|
||||
}
|
||||
if ((text.startsWith('"') && text.endsWith('"')) || (text.startsWith("'") && text.endsWith("'"))) {
|
||||
try {
|
||||
const parsed = JSON.parse(text);
|
||||
if (typeof parsed === 'string' && parsed.trim()) return parsed.trim();
|
||||
} catch {
|
||||
const unquoted = text.slice(1, -1).trim();
|
||||
if (unquoted) return unquoted;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function readApplet(vfsRoot, appletvfsfile) {
|
||||
if (typeof appletvfsfile !== 'string' || !appletvfsfile.trim()) {
|
||||
throw new ToolError('"appletvfsfile" must be a non-empty VFS-relative file path.');
|
||||
@@ -228,14 +254,16 @@ function readApplet(vfsRoot, appletvfsfile) {
|
||||
throw new ToolError(`Unable to read applet "${appletPath}" from the VFS: ${err.message}`);
|
||||
}
|
||||
|
||||
const lines = source.replace(/^\uFEFF/, '').split(/\r?\n/, 3);
|
||||
const lines = source.replace(/^\uFEFF/, '').split(/\r?\n/, 4);
|
||||
const inputHeader = lines[0]?.match(/^\/\/ @applet-input-schema (.+)$/);
|
||||
const outputHeader = lines[1]?.match(/^\/\/ @applet-output-schema (.+)$/);
|
||||
if (!inputHeader || !outputHeader) {
|
||||
const descHeader = lines[2]?.match(/^\/\/ @applet-description (.+)$/);
|
||||
if (!inputHeader || !outputHeader || !descHeader) {
|
||||
throw new ToolError(
|
||||
'Applet metadata must be on the first two lines: ' +
|
||||
'Applet metadata must be on the first three lines: ' +
|
||||
'`// @applet-input-schema {JSON Schema}` followed by ' +
|
||||
'`// @applet-output-schema name:type;name:type` (typed CSV columns).'
|
||||
'`// @applet-output-schema name:type;name:type` (typed CSV columns) and ' +
|
||||
'`// @applet-description "description"`.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -251,8 +279,9 @@ function readApplet(vfsRoot, appletvfsfile) {
|
||||
}
|
||||
|
||||
const outputColumns = parseTypedCsvColumns(outputHeader[1]);
|
||||
const description = parseAppletDescription(descHeader[1]);
|
||||
|
||||
return { source, outputColumns };
|
||||
return { source, outputColumns, description, inputSchema };
|
||||
}
|
||||
|
||||
function formatSandboxError(code, report) {
|
||||
@@ -401,6 +430,7 @@ export function createJavascriptExecuteTool({ googleAuthId }) {
|
||||
result.result = table.csv;
|
||||
result.rows = table.rows;
|
||||
result.columns = table.columns;
|
||||
result.description = applet.description;
|
||||
if (table.warnings.length) result.warnings = table.warnings;
|
||||
}
|
||||
if (truncated) {
|
||||
|
||||
@@ -48,7 +48,7 @@ export const TOOL_DESCRIPTIONS = {
|
||||
|
||||
javascript_execute:
|
||||
'Execute JS in an isolated sandbox via inline `code` (assign to `module.exports`) or `appletvfsfile` ' +
|
||||
'(.applet.js returning typed CSV per @applet-input-schema and @applet-output-schema; details in applet.SKILL). ' +
|
||||
'(.applet.js returning typed CSV per @applet-input-schema, @applet-output-schema, and @applet-description; details in applet.SKILL). ' +
|
||||
'Pre-injected globals: fs/vfs, sharp, ExcelJS, PDFDocument, crypto, and fetch("/path"). No require/import.',
|
||||
|
||||
find_files:
|
||||
|
||||
Reference in New Issue
Block a user