@mindstudio-ai/agent 0.1.99 → 0.1.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -0
- package/dist/cli.js +387 -52
- package/dist/index.d.ts +520 -23
- package/dist/index.js +479 -42
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +387 -52
- package/llms.txt +12 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3134,28 +3134,28 @@ var stepMetadata = {
|
|
|
3134
3134
|
"scrapeUrl": {
|
|
3135
3135
|
stepType: "scrapeUrl",
|
|
3136
3136
|
description: "Extract text, HTML, or structured content from one or more web pages.",
|
|
3137
|
-
usageNotes: '- Accepts a single URL or multiple URLs (as a JSON array, comma-separated, or newline-separated).\n- Output format controls the result shape: "text" returns markdown, "html" returns raw HTML, "json" returns structured scraper data.\n- Can optionally capture a screenshot of each page.',
|
|
3138
|
-
inputSchema: { "type": "object", "properties": { "url": { "type": "string", "description": "URL(s) to scrape. Accepts a single URL, JSON array, or comma/newline-separated list" }, "service": { "enum": ["default", "firecrawl"], "type": "string", "description": "Scraping service to use" }, "autoEnhance": { "type": "boolean", "description": "
|
|
3139
|
-
outputSchema: { "type": "object", "properties": { "content": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "object", "properties": { "text": { "type": "string", "description": "Markdown/plain-text content of the scraped page" }, "html": { "type": "string", "description": "Raw HTML content of the scraped page" }, "json": { "type": "object", "properties": {}, "required": [], "description": "Structured data extracted from the page" }, "screenshotUrl": { "type": "string", "description": "Screenshot URL of the page (if requested)" }, "metadata": { "type": "object", "properties": { "title": { "type": "string", "description": "Page title" }, "description": { "type": "string", "description": "Page meta description" }, "url": { "type": "string", "description": "Canonical URL" }, "image": { "type": "string", "description": "Open Graph image URL" } }, "required": ["title", "description", "url", "image"], "description": "Page metadata (Open Graph / meta tags)" }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": ["code", "message"], "description": "Set when the scrape failed. `text`/`html` still carry the human-readable error so existing callers behave as before, but callers that care \u2014 billing, in particular \u2014 can tell a failure from real page content." } }, "required": ["text", "html"] }, { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string", "description": "Markdown/plain-text content of the scraped page" }, "html": { "type": "string", "description": "Raw HTML content of the scraped page" }, "json": { "type": "object", "properties": {}, "required": [], "description": "Structured data extracted from the page" }, "screenshotUrl": { "type": "string", "description": "Screenshot URL of the page (if requested)" }, "metadata": { "type": "object", "properties": { "title": { "type": "string", "description": "Page title" }, "description": { "type": "string", "description": "Page meta description" }, "url": { "type": "string", "description": "Canonical URL" }, "image": { "type": "string", "description": "Open Graph image URL" } }, "required": ["title", "description", "url", "image"], "description": "Page metadata (Open Graph / meta tags)" }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": ["code", "message"], "description": "Set when the scrape failed. `text`/`html` still carry the human-readable error so existing callers behave as before, but callers that care \u2014 billing, in particular \u2014 can tell a failure from real page content." } }, "required": ["text", "html"] } }] }, "screenshot": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] } }, "required": ["content"] }
|
|
3137
|
+
usageNotes: '- Accepts a single URL or multiple URLs (as a JSON array, comma-separated, or newline-separated).\n- Output format controls the result shape: "text" returns markdown, "html" returns raw HTML, "json" returns structured scraper data, "summary" returns a model-written summary and requires the "firecrawl" service.\n- Can optionally capture a screenshot of each page.\n- Handles bot protection automatically; no proxy or rendering configuration is needed.',
|
|
3138
|
+
inputSchema: { "type": "object", "properties": { "url": { "type": "string", "description": "URL(s) to scrape. Accepts a single URL, JSON array, or comma/newline-separated list" }, "service": { "enum": ["default", "firecrawl"], "type": "string", "description": "Scraping service to use" }, "autoEnhance": { "type": "boolean", "description": "No longer selects a provider \u2014 the default service's anti-bot engine decides per request how hard to work. Retained because existing workflows set it and the builder still renders it." }, "outputFormat": { "enum": ["text", "json", "html", "summary"], "type": "string", "description": "Output format: text returns markdown, html returns raw HTML, json returns structured scraper data, summary returns a model-written summary (Firecrawl only)" }, "pageOptions": { "type": "object", "properties": { "onlyMainContent": { "type": "boolean", "description": "Whether to extract only the main content of the page, excluding navigation, footers, etc." }, "screenshot": { "type": "boolean", "description": "Whether to capture a screenshot of the page" }, "waitFor": { "type": "number", "description": "Milliseconds to wait before scraping (0 for immediate)" }, "replaceAllPathsWithAbsolutePaths": { "type": "boolean", "description": "Whether to convert relative URLs to absolute URLs in the result" }, "headers": { "type": "object", "properties": {}, "required": [], "description": "Custom HTTP request headers as key-value pairs" }, "removeTags": { "type": "array", "items": { "type": "string" }, "description": "HTML tags to remove from the scraped result" }, "mobile": { "type": "boolean", "description": "Whether to scrape using a mobile user-agent" } }, "required": ["onlyMainContent", "screenshot", "waitFor", "replaceAllPathsWithAbsolutePaths", "headers", "removeTags", "mobile"], "description": "Page-level scraping options (content filtering, screenshots, headers, etc.)" } }, "required": ["url"] },
|
|
3139
|
+
outputSchema: { "type": "object", "properties": { "content": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "object", "properties": { "text": { "type": "string", "description": "Markdown/plain-text content of the scraped page" }, "html": { "type": "string", "description": "Raw HTML content of the scraped page" }, "json": { "type": "object", "properties": {}, "required": [], "description": "Structured data extracted from the page" }, "screenshotUrl": { "type": "string", "description": "Screenshot URL of the page (if requested)" }, "metadata": { "type": "object", "properties": { "title": { "type": "string", "description": "Page title" }, "description": { "type": "string", "description": "Page meta description" }, "url": { "type": "string", "description": "Canonical URL" }, "image": { "type": "string", "description": "Open Graph image URL" } }, "required": ["title", "description", "url", "image"], "description": "Page metadata (Open Graph / meta tags)" }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": ["code", "message"], "description": "Set when the scrape failed. `text`/`html` still carry the human-readable error so existing callers behave as before, but callers that care \u2014 billing, in particular \u2014 can tell a failure from real page content." }, "costUnits": { "type": "number", "description": "What the provider actually charged, when it tells us. Scrapfly returns an exact per-request credit total that varies with how hard the target fought back (6 for an unprotected page, 80 for Glassdoor), so billing a flat rate would either overcharge the easy case or eat the hard one. Providers that report nothing leave this undefined and fall back to the route's estimate.\n\nIncludes every attempt made on the caller's behalf, not just the last one." } }, "required": ["text", "html"] }, { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string", "description": "Markdown/plain-text content of the scraped page" }, "html": { "type": "string", "description": "Raw HTML content of the scraped page" }, "json": { "type": "object", "properties": {}, "required": [], "description": "Structured data extracted from the page" }, "screenshotUrl": { "type": "string", "description": "Screenshot URL of the page (if requested)" }, "metadata": { "type": "object", "properties": { "title": { "type": "string", "description": "Page title" }, "description": { "type": "string", "description": "Page meta description" }, "url": { "type": "string", "description": "Canonical URL" }, "image": { "type": "string", "description": "Open Graph image URL" } }, "required": ["title", "description", "url", "image"], "description": "Page metadata (Open Graph / meta tags)" }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": ["code", "message"], "description": "Set when the scrape failed. `text`/`html` still carry the human-readable error so existing callers behave as before, but callers that care \u2014 billing, in particular \u2014 can tell a failure from real page content." }, "costUnits": { "type": "number", "description": "What the provider actually charged, when it tells us. Scrapfly returns an exact per-request credit total that varies with how hard the target fought back (6 for an unprotected page, 80 for Glassdoor), so billing a flat rate would either overcharge the easy case or eat the hard one. Providers that report nothing leave this undefined and fall back to the route's estimate.\n\nIncludes every attempt made on the caller's behalf, not just the last one." } }, "required": ["text", "html"] } }] }, "screenshot": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] } }, "required": ["content"] }
|
|
3140
3140
|
},
|
|
3141
3141
|
"scrapeXPost": {
|
|
3142
3142
|
stepType: "scrapeXPost",
|
|
3143
3143
|
description: "Scrape data from a single X (Twitter) post by URL.",
|
|
3144
3144
|
usageNotes: "- Returns structured post data (text, html, optional json/screenshot/metadata).\n- Optionally saves the text content to a variable.",
|
|
3145
3145
|
inputSchema: { "type": "object", "properties": { "url": { "type": "string", "description": "Full URL to the X post (e.g. https://x.com/elonmusk/status/1655608985058267139)" } }, "required": ["url"] },
|
|
3146
|
-
outputSchema: { "type": "object", "properties": { "post": { "type": "object", "properties": { "text": { "type": "string", "description": "Markdown/plain-text content of the scraped page" }, "html": { "type": "string", "description": "Raw HTML content of the scraped page" }, "json": { "type": "object", "properties": {}, "required": [], "description": "Structured data extracted from the page" }, "screenshotUrl": { "type": "string", "description": "Screenshot URL of the page (if requested)" }, "metadata": { "type": "object", "properties": { "title": { "type": "string", "description": "Page title" }, "description": { "type": "string", "description": "Page meta description" }, "url": { "type": "string", "description": "Canonical URL" }, "image": { "type": "string", "description": "Open Graph image URL" } }, "required": ["title", "description", "url", "image"], "description": "Page metadata (Open Graph / meta tags)" }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": ["code", "message"], "description": "Set when the scrape failed. `text`/`html` still carry the human-readable error so existing callers behave as before, but callers that care \u2014 billing, in particular \u2014 can tell a failure from real page content." } }, "required": ["text", "html"], "description": "Scraped post data including text, HTML, and optional structured JSON" } }, "required": ["post"] }
|
|
3146
|
+
outputSchema: { "type": "object", "properties": { "post": { "type": "object", "properties": { "text": { "type": "string", "description": "Markdown/plain-text content of the scraped page" }, "html": { "type": "string", "description": "Raw HTML content of the scraped page" }, "json": { "type": "object", "properties": {}, "required": [], "description": "Structured data extracted from the page" }, "screenshotUrl": { "type": "string", "description": "Screenshot URL of the page (if requested)" }, "metadata": { "type": "object", "properties": { "title": { "type": "string", "description": "Page title" }, "description": { "type": "string", "description": "Page meta description" }, "url": { "type": "string", "description": "Canonical URL" }, "image": { "type": "string", "description": "Open Graph image URL" } }, "required": ["title", "description", "url", "image"], "description": "Page metadata (Open Graph / meta tags)" }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": ["code", "message"], "description": "Set when the scrape failed. `text`/`html` still carry the human-readable error so existing callers behave as before, but callers that care \u2014 billing, in particular \u2014 can tell a failure from real page content." }, "costUnits": { "type": "number", "description": "What the provider actually charged, when it tells us. Scrapfly returns an exact per-request credit total that varies with how hard the target fought back (6 for an unprotected page, 80 for Glassdoor), so billing a flat rate would either overcharge the easy case or eat the hard one. Providers that report nothing leave this undefined and fall back to the route's estimate.\n\nIncludes every attempt made on the caller's behalf, not just the last one." } }, "required": ["text", "html"], "description": "Scraped post data including text, HTML, and optional structured JSON" } }, "required": ["post"] }
|
|
3147
3147
|
},
|
|
3148
3148
|
"scrapeXProfile": {
|
|
3149
3149
|
stepType: "scrapeXProfile",
|
|
3150
3150
|
description: "Scrape public profile data from an X (Twitter) account by URL.",
|
|
3151
3151
|
usageNotes: "- Returns structured profile data.\n- Optionally saves the result to a variable.",
|
|
3152
3152
|
inputSchema: { "type": "object", "properties": { "url": { "type": "string", "description": "Full URL or username for the X profile (e.g. https://x.com/elonmusk)" } }, "required": ["url"] },
|
|
3153
|
-
outputSchema: { "type": "object", "properties": { "profile": { "type": "object", "properties": { "text": { "type": "string", "description": "Markdown/plain-text content of the scraped page" }, "html": { "type": "string", "description": "Raw HTML content of the scraped page" }, "json": { "type": "object", "properties": {}, "required": [], "description": "Structured data extracted from the page" }, "screenshotUrl": { "type": "string", "description": "Screenshot URL of the page (if requested)" }, "metadata": { "type": "object", "properties": { "title": { "type": "string", "description": "Page title" }, "description": { "type": "string", "description": "Page meta description" }, "url": { "type": "string", "description": "Canonical URL" }, "image": { "type": "string", "description": "Open Graph image URL" } }, "required": ["title", "description", "url", "image"], "description": "Page metadata (Open Graph / meta tags)" }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": ["code", "message"], "description": "Set when the scrape failed. `text`/`html` still carry the human-readable error so existing callers behave as before, but callers that care \u2014 billing, in particular \u2014 can tell a failure from real page content." } }, "required": ["text", "html"], "description": "Scraped profile data including text, HTML, and optional structured JSON" } }, "required": ["profile"] }
|
|
3153
|
+
outputSchema: { "type": "object", "properties": { "profile": { "type": "object", "properties": { "text": { "type": "string", "description": "Markdown/plain-text content of the scraped page" }, "html": { "type": "string", "description": "Raw HTML content of the scraped page" }, "json": { "type": "object", "properties": {}, "required": [], "description": "Structured data extracted from the page" }, "screenshotUrl": { "type": "string", "description": "Screenshot URL of the page (if requested)" }, "metadata": { "type": "object", "properties": { "title": { "type": "string", "description": "Page title" }, "description": { "type": "string", "description": "Page meta description" }, "url": { "type": "string", "description": "Canonical URL" }, "image": { "type": "string", "description": "Open Graph image URL" } }, "required": ["title", "description", "url", "image"], "description": "Page metadata (Open Graph / meta tags)" }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": ["code", "message"], "description": "Set when the scrape failed. `text`/`html` still carry the human-readable error so existing callers behave as before, but callers that care \u2014 billing, in particular \u2014 can tell a failure from real page content." }, "costUnits": { "type": "number", "description": "What the provider actually charged, when it tells us. Scrapfly returns an exact per-request credit total that varies with how hard the target fought back (6 for an unprotected page, 80 for Glassdoor), so billing a flat rate would either overcharge the easy case or eat the hard one. Providers that report nothing leave this undefined and fall back to the route's estimate.\n\nIncludes every attempt made on the caller's behalf, not just the last one." } }, "required": ["text", "html"], "description": "Scraped profile data including text, HTML, and optional structured JSON" } }, "required": ["profile"] }
|
|
3154
3154
|
},
|
|
3155
3155
|
"screenshotUrl": {
|
|
3156
3156
|
stepType: "screenshotUrl",
|
|
3157
3157
|
description: "Capture a screenshot of a web page as a PNG image.",
|
|
3158
|
-
usageNotes: "- Takes a viewport or full-page screenshot of the given URL.\n- Returns a CDN-hosted PNG image URL.\n- Viewport mode captures only the visible area; fullPage captures the entire scrollable page.\n-
|
|
3158
|
+
usageNotes: "- Takes a viewport or full-page screenshot of the given URL.\n- Returns a CDN-hosted PNG image URL.\n- Viewport mode captures only the visible area; fullPage captures the entire scrollable page, scrolling it first so lazy-loaded content is included.\n- Works on sites behind bot protection (Cloudflare and similar).\n- Cookie-consent banners and similar overlays are suppressed automatically.\n- `width` and `height` are the exact output pixel dimensions.\n- You can add a delay or wait for a CSS selector before capturing. A selector that never appears fails the step rather than capturing early.",
|
|
3159
3159
|
inputSchema: { "type": "object", "properties": { "url": { "type": "string", "description": "URL to screenshot" }, "mode": { "enum": ["viewport", "fullPage"], "type": "string", "description": "Screenshot mode: viewport captures visible area, fullPage captures entire page" }, "width": { "type": "number", "description": "Viewport width in pixels (default: 1280)" }, "height": { "type": "number", "description": "Viewport height in pixels (default: 800, ignored for fullPage mode)" }, "delay": { "type": "number", "description": "Milliseconds to wait before capturing (default: 0)" }, "waitFor": { "type": "string", "description": "CSS selector to wait for before capturing" } }, "required": ["url"] },
|
|
3160
3160
|
outputSchema: { "type": "object", "properties": { "screenshotUrl": { "type": "string" } }, "required": ["screenshotUrl"] }
|
|
3161
3161
|
},
|
|
@@ -3525,6 +3525,178 @@ var stepMetadata = {
|
|
|
3525
3525
|
}
|
|
3526
3526
|
};
|
|
3527
3527
|
|
|
3528
|
+
// src/task/schema.ts
|
|
3529
|
+
function describe(value) {
|
|
3530
|
+
if (value === void 0) return "undefined";
|
|
3531
|
+
const json = JSON.stringify(value);
|
|
3532
|
+
if (json === void 0) return String(value);
|
|
3533
|
+
return json.length > 60 ? `${json.slice(0, 57)}...` : json;
|
|
3534
|
+
}
|
|
3535
|
+
function matchesTypeName(value, name) {
|
|
3536
|
+
switch (name) {
|
|
3537
|
+
case "null":
|
|
3538
|
+
return value === null;
|
|
3539
|
+
case "string":
|
|
3540
|
+
return typeof value === "string";
|
|
3541
|
+
case "number":
|
|
3542
|
+
return typeof value === "number";
|
|
3543
|
+
case "integer":
|
|
3544
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
3545
|
+
case "boolean":
|
|
3546
|
+
return typeof value === "boolean";
|
|
3547
|
+
case "array":
|
|
3548
|
+
return Array.isArray(value);
|
|
3549
|
+
case "object":
|
|
3550
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
function validateAgainstSchema(value, schema) {
|
|
3554
|
+
const errors = [];
|
|
3555
|
+
walk(value, schema, "$", errors);
|
|
3556
|
+
return errors;
|
|
3557
|
+
}
|
|
3558
|
+
function walk(value, schema, path, errors) {
|
|
3559
|
+
if (schema.const !== void 0) {
|
|
3560
|
+
if (value !== schema.const) {
|
|
3561
|
+
errors.push({
|
|
3562
|
+
path,
|
|
3563
|
+
message: `expected the constant ${describe(schema.const)}, got ${describe(value)}`
|
|
3564
|
+
});
|
|
3565
|
+
}
|
|
3566
|
+
return;
|
|
3567
|
+
}
|
|
3568
|
+
if (schema.enum !== void 0) {
|
|
3569
|
+
if (!schema.enum.includes(value)) {
|
|
3570
|
+
errors.push({
|
|
3571
|
+
path,
|
|
3572
|
+
message: `expected one of ${schema.enum.map(describe).join(" | ")}, got ${describe(value)}`
|
|
3573
|
+
});
|
|
3574
|
+
}
|
|
3575
|
+
return;
|
|
3576
|
+
}
|
|
3577
|
+
if (schema.type !== void 0) {
|
|
3578
|
+
const names = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
3579
|
+
if (!names.some((name) => matchesTypeName(value, name))) {
|
|
3580
|
+
errors.push({
|
|
3581
|
+
path,
|
|
3582
|
+
message: `expected type ${names.join(" | ")}, got ${describe(value)}`
|
|
3583
|
+
});
|
|
3584
|
+
return;
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
if (matchesTypeName(value, "object")) {
|
|
3588
|
+
const record = value;
|
|
3589
|
+
if (schema.required) {
|
|
3590
|
+
for (const key of schema.required) {
|
|
3591
|
+
if (!(key in record) || record[key] === void 0) {
|
|
3592
|
+
errors.push({
|
|
3593
|
+
path,
|
|
3594
|
+
message: `missing required property "${key}"`
|
|
3595
|
+
});
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
if (schema.properties) {
|
|
3600
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
3601
|
+
if (key in record && record[key] !== void 0) {
|
|
3602
|
+
walk(record[key], propSchema, `${path}.${key}`, errors);
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
if (schema.additionalProperties === false) {
|
|
3606
|
+
for (const key of Object.keys(record)) {
|
|
3607
|
+
if (!(key in schema.properties)) {
|
|
3608
|
+
errors.push({
|
|
3609
|
+
path,
|
|
3610
|
+
message: `unexpected property "${key}" (additionalProperties is false)`
|
|
3611
|
+
});
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
if (Array.isArray(value) && schema.items) {
|
|
3618
|
+
value.forEach((item, index) => {
|
|
3619
|
+
walk(item, schema.items, `${path}[${index}]`, errors);
|
|
3620
|
+
});
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
function formatValidationErrors(errors) {
|
|
3624
|
+
return errors.map((e) => `- at ${e.path}: ${e.message}`).join("\n");
|
|
3625
|
+
}
|
|
3626
|
+
var SUPPORTED_KEYWORDS = /* @__PURE__ */ new Set([
|
|
3627
|
+
"type",
|
|
3628
|
+
"properties",
|
|
3629
|
+
"required",
|
|
3630
|
+
"additionalProperties",
|
|
3631
|
+
"items",
|
|
3632
|
+
"enum",
|
|
3633
|
+
"const",
|
|
3634
|
+
// Harmless annotations — ignored by the validator, allowed to pass through.
|
|
3635
|
+
"description",
|
|
3636
|
+
"title",
|
|
3637
|
+
"examples",
|
|
3638
|
+
"default"
|
|
3639
|
+
]);
|
|
3640
|
+
function assertSupportedSchema(schema) {
|
|
3641
|
+
assertSupportedNode(schema, "$");
|
|
3642
|
+
}
|
|
3643
|
+
function assertSupportedNode(schema, path) {
|
|
3644
|
+
for (const key of Object.keys(schema)) {
|
|
3645
|
+
if (SUPPORTED_KEYWORDS.has(key)) continue;
|
|
3646
|
+
const hint = key === "nullable" ? ' Use a type array instead: type: ["string", "null"].' : key === "oneOf" || key === "anyOf" || key === "allOf" ? " Model alternatives with an enum, a type array, or a discriminating property instead." : "";
|
|
3647
|
+
throw new MindStudioError(
|
|
3648
|
+
`[task] Unsupported JSON Schema keyword "${key}" at ${path} in outputSchema. Supported: type, properties, required, additionalProperties, items, enum, const.${hint}`,
|
|
3649
|
+
"task_output_schema_unsupported",
|
|
3650
|
+
400
|
|
3651
|
+
);
|
|
3652
|
+
}
|
|
3653
|
+
if (schema.properties) {
|
|
3654
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
3655
|
+
assertSupportedNode(propSchema, `${path}.${key}`);
|
|
3656
|
+
}
|
|
3657
|
+
}
|
|
3658
|
+
if (schema.items) {
|
|
3659
|
+
assertSupportedNode(schema.items, `${path}[]`);
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
function buildExampleFromSchema(schema) {
|
|
3663
|
+
if (schema.const !== void 0) return schema.const;
|
|
3664
|
+
if (schema.enum !== void 0 && schema.enum.length > 0)
|
|
3665
|
+
return schema.enum[0];
|
|
3666
|
+
const names = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
3667
|
+
const name = names.find((n) => n !== "null") ?? names[0];
|
|
3668
|
+
switch (name) {
|
|
3669
|
+
case "object": {
|
|
3670
|
+
const example = {};
|
|
3671
|
+
for (const [key, propSchema] of Object.entries(
|
|
3672
|
+
schema.properties ?? {}
|
|
3673
|
+
)) {
|
|
3674
|
+
example[key] = buildExampleFromSchema(propSchema);
|
|
3675
|
+
}
|
|
3676
|
+
return example;
|
|
3677
|
+
}
|
|
3678
|
+
case "array":
|
|
3679
|
+
return schema.items ? [buildExampleFromSchema(schema.items)] : [];
|
|
3680
|
+
case "string":
|
|
3681
|
+
return "...";
|
|
3682
|
+
case "number":
|
|
3683
|
+
case "integer":
|
|
3684
|
+
return 0;
|
|
3685
|
+
case "boolean":
|
|
3686
|
+
return true;
|
|
3687
|
+
case "null":
|
|
3688
|
+
return null;
|
|
3689
|
+
default:
|
|
3690
|
+
return null;
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
function stripCodeFences(text) {
|
|
3694
|
+
const match = /^```[a-zA-Z]*[ \t]*\r?\n([\s\S]*?)\r?\n?```$/.exec(
|
|
3695
|
+
text.trim()
|
|
3696
|
+
);
|
|
3697
|
+
return match ? match[1] : text;
|
|
3698
|
+
}
|
|
3699
|
+
|
|
3528
3700
|
// src/task/index.ts
|
|
3529
3701
|
function resolveStepType(name) {
|
|
3530
3702
|
const meta = stepMetadata[name];
|
|
@@ -3550,7 +3722,11 @@ function buildTaskRequestBody(options) {
|
|
|
3550
3722
|
prompt: options.prompt,
|
|
3551
3723
|
input: options.input,
|
|
3552
3724
|
tools: mapTools(options.tools),
|
|
3553
|
-
|
|
3725
|
+
// The legacy whole-task route requires structuredOutputExample and
|
|
3726
|
+
// composes its own prompt server-side, so in schema mode we synthesize a
|
|
3727
|
+
// skeleton example from the schema. Validation still happens client-side
|
|
3728
|
+
// after the result comes back (see _runTaskInner).
|
|
3729
|
+
structuredOutputExample: options.outputSchema ? JSON.stringify(buildExampleFromSchema(options.outputSchema)) : typeof options.structuredOutputExample === "string" ? options.structuredOutputExample : JSON.stringify(options.structuredOutputExample),
|
|
3554
3730
|
model: options.model,
|
|
3555
3731
|
...options.maxTurns != null && { maxTurns: options.maxTurns },
|
|
3556
3732
|
...options.appId != null && { appId: options.appId },
|
|
@@ -3751,6 +3927,7 @@ async function runTaskStream(httpConfig, body, onEvent) {
|
|
|
3751
3927
|
// src/task/local.ts
|
|
3752
3928
|
var DEFAULT_MAX_TURNS = 20;
|
|
3753
3929
|
var MAX_TURNS_LIMIT = 100;
|
|
3930
|
+
var MAX_SCHEMA_REPAIR_ATTEMPTS = 3;
|
|
3754
3931
|
var MAX_TOOL_OUTPUT_CHARS = 5e4;
|
|
3755
3932
|
var MAX_TURN_ATTEMPTS = 5;
|
|
3756
3933
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
@@ -3946,12 +4123,23 @@ async function runTurnWithRetry(httpConfig, body) {
|
|
|
3946
4123
|
async function runTaskLocal(deps, options) {
|
|
3947
4124
|
const { httpConfig } = deps;
|
|
3948
4125
|
const onEvent = options.onEvent;
|
|
3949
|
-
const
|
|
3950
|
-
|
|
4126
|
+
const outputSchema = options.outputSchema;
|
|
4127
|
+
if (outputSchema) assertSupportedSchema(outputSchema);
|
|
4128
|
+
let system;
|
|
4129
|
+
if (outputSchema) {
|
|
4130
|
+
system = `${options.prompt}
|
|
4131
|
+
|
|
4132
|
+
When you have completed the task, respond with your final output as a single JSON object that conforms to this JSON Schema. Respond with the JSON object itself \u2014 NOT the schema, no prose, no code fences:
|
|
4133
|
+
${JSON.stringify(outputSchema)}
|
|
4134
|
+
<!-- cache_breakpoint -->`;
|
|
4135
|
+
} else {
|
|
4136
|
+
const structuredOutputExample = typeof options.structuredOutputExample === "string" ? options.structuredOutputExample : JSON.stringify(options.structuredOutputExample);
|
|
4137
|
+
system = `${options.prompt}
|
|
3951
4138
|
|
|
3952
4139
|
When you have completed the task, respond with your final output as JSON matching this example:
|
|
3953
4140
|
${structuredOutputExample}
|
|
3954
4141
|
<!-- cache_breakpoint -->`;
|
|
4142
|
+
}
|
|
3955
4143
|
const wireTools = mapTools(options.tools);
|
|
3956
4144
|
const toolKinds = /* @__PURE__ */ new Map();
|
|
3957
4145
|
const toolDefaults = /* @__PURE__ */ new Map();
|
|
@@ -3972,6 +4160,7 @@ ${structuredOutputExample}
|
|
|
3972
4160
|
{ role: "user", content: JSON.stringify(options.input) }
|
|
3973
4161
|
];
|
|
3974
4162
|
let loopCount = 0;
|
|
4163
|
+
let schemaRepairCount = 0;
|
|
3975
4164
|
const toolCallLog = [];
|
|
3976
4165
|
const totalUsage = {
|
|
3977
4166
|
inputTokens: 0,
|
|
@@ -4003,11 +4192,38 @@ ${structuredOutputExample}
|
|
|
4003
4192
|
logTaskResult(result);
|
|
4004
4193
|
return result;
|
|
4005
4194
|
};
|
|
4195
|
+
const schemaMismatch = (outputRaw, errors) => {
|
|
4196
|
+
onEvent?.({
|
|
4197
|
+
type: "error",
|
|
4198
|
+
error: "Output did not conform to outputSchema.",
|
|
4199
|
+
errors
|
|
4200
|
+
});
|
|
4201
|
+
return new MindStudioError(
|
|
4202
|
+
"[task] Output did not conform to outputSchema after all repair attempts.",
|
|
4203
|
+
"task_output_schema_mismatch",
|
|
4204
|
+
422,
|
|
4205
|
+
{
|
|
4206
|
+
outputRaw,
|
|
4207
|
+
errors,
|
|
4208
|
+
turns: loopCount,
|
|
4209
|
+
usage: totalUsage,
|
|
4210
|
+
toolCalls: toolCallLog
|
|
4211
|
+
}
|
|
4212
|
+
);
|
|
4213
|
+
};
|
|
4006
4214
|
const turnFailure = (err) => {
|
|
4007
4215
|
if (err instanceof TurnError && err.phase === "model") {
|
|
4008
4216
|
if (isDevMode()) {
|
|
4009
4217
|
console.error(`[task] Model call failed: ${err.message}`);
|
|
4010
4218
|
}
|
|
4219
|
+
if (outputSchema) {
|
|
4220
|
+
throw new MindStudioError(
|
|
4221
|
+
`[task] ${err.message}`,
|
|
4222
|
+
"task_execution_error",
|
|
4223
|
+
500,
|
|
4224
|
+
{ turns: loopCount, usage: totalUsage, toolCalls: toolCallLog }
|
|
4225
|
+
);
|
|
4226
|
+
}
|
|
4011
4227
|
return finish(buildResult(null, "", false, loopCount));
|
|
4012
4228
|
}
|
|
4013
4229
|
if (err instanceof TurnError) {
|
|
@@ -4066,11 +4282,11 @@ ${structuredOutputExample}
|
|
|
4066
4282
|
return { toolCall, ...result };
|
|
4067
4283
|
})
|
|
4068
4284
|
);
|
|
4069
|
-
for (const { toolCall, output:
|
|
4285
|
+
for (const { toolCall, output: output3, billingCost, isError } of results) {
|
|
4070
4286
|
if (billingCost) {
|
|
4071
4287
|
totalUsage.totalBillingCost += billingCost;
|
|
4072
4288
|
}
|
|
4073
|
-
const truncated = truncateToolOutput(
|
|
4289
|
+
const truncated = truncateToolOutput(output3);
|
|
4074
4290
|
messages.push({
|
|
4075
4291
|
role: "user",
|
|
4076
4292
|
content: JSON.stringify(truncated),
|
|
@@ -4089,17 +4305,43 @@ ${structuredOutputExample}
|
|
|
4089
4305
|
continue;
|
|
4090
4306
|
}
|
|
4091
4307
|
messages.push({ role: "assistant", content: turn.text });
|
|
4308
|
+
let output2;
|
|
4309
|
+
let parseOk = true;
|
|
4092
4310
|
try {
|
|
4093
|
-
|
|
4094
|
-
return finish(buildResult(output2, turn.text, true, loopCount));
|
|
4311
|
+
output2 = JSON.parse(outputSchema ? stripCodeFences(turn.text) : turn.text);
|
|
4095
4312
|
} catch {
|
|
4096
|
-
|
|
4313
|
+
parseOk = false;
|
|
4314
|
+
}
|
|
4315
|
+
if (parseOk) {
|
|
4316
|
+
if (!outputSchema) {
|
|
4317
|
+
return finish(buildResult(output2, turn.text, true, loopCount));
|
|
4318
|
+
}
|
|
4319
|
+
const errors = validateAgainstSchema(output2, outputSchema);
|
|
4320
|
+
if (errors.length === 0) {
|
|
4321
|
+
return finish(buildResult(output2, turn.text, true, loopCount));
|
|
4322
|
+
}
|
|
4323
|
+
if (loopCount < maxTurns && schemaRepairCount < MAX_SCHEMA_REPAIR_ATTEMPTS) {
|
|
4324
|
+
schemaRepairCount++;
|
|
4097
4325
|
messages.push({
|
|
4098
4326
|
role: "user",
|
|
4099
|
-
content:
|
|
4327
|
+
content: `Your JSON output did not conform to the required schema. Fix these problems and respond again with ONLY the corrected JSON:
|
|
4328
|
+
${formatValidationErrors(errors)}`
|
|
4100
4329
|
});
|
|
4101
4330
|
continue;
|
|
4102
4331
|
}
|
|
4332
|
+
throw schemaMismatch(turn.text, errors);
|
|
4333
|
+
}
|
|
4334
|
+
if (loopCount < maxTurns) {
|
|
4335
|
+
messages.push({
|
|
4336
|
+
role: "user",
|
|
4337
|
+
content: "Your response was not valid JSON. Please respond with ONLY the JSON output, no other text."
|
|
4338
|
+
});
|
|
4339
|
+
continue;
|
|
4340
|
+
}
|
|
4341
|
+
if (outputSchema) {
|
|
4342
|
+
throw schemaMismatch(turn.text, [
|
|
4343
|
+
{ path: "$", message: "output was not valid JSON" }
|
|
4344
|
+
]);
|
|
4103
4345
|
}
|
|
4104
4346
|
return finish(buildResult(turn.text, turn.text, false, loopCount));
|
|
4105
4347
|
}
|
|
@@ -4129,11 +4371,22 @@ ${structuredOutputExample}
|
|
|
4129
4371
|
let parsedSuccessfully = true;
|
|
4130
4372
|
let output;
|
|
4131
4373
|
try {
|
|
4132
|
-
output = JSON.parse(finalText);
|
|
4374
|
+
output = JSON.parse(outputSchema ? stripCodeFences(finalText) : finalText);
|
|
4133
4375
|
} catch {
|
|
4134
4376
|
output = finalText;
|
|
4135
4377
|
parsedSuccessfully = false;
|
|
4136
4378
|
}
|
|
4379
|
+
if (outputSchema) {
|
|
4380
|
+
if (!parsedSuccessfully) {
|
|
4381
|
+
throw schemaMismatch(finalText, [
|
|
4382
|
+
{ path: "$", message: "output was not valid JSON" }
|
|
4383
|
+
]);
|
|
4384
|
+
}
|
|
4385
|
+
const errors = validateAgainstSchema(output, outputSchema);
|
|
4386
|
+
if (errors.length > 0) {
|
|
4387
|
+
throw schemaMismatch(finalText, errors);
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4137
4390
|
return finish(
|
|
4138
4391
|
buildResult(output, finalText, parsedSuccessfully, loopCount + 1)
|
|
4139
4392
|
);
|
|
@@ -5150,29 +5403,6 @@ var MindStudioAgent = class {
|
|
|
5150
5403
|
};
|
|
5151
5404
|
}
|
|
5152
5405
|
}
|
|
5153
|
-
/**
|
|
5154
|
-
* Run a task agent — a multi-step tool-use loop that composes SDK actions
|
|
5155
|
-
* to produce structured output. The model receives the prompt and tools,
|
|
5156
|
-
* calls actions as needed, and returns JSON matching the output example.
|
|
5157
|
-
*
|
|
5158
|
-
* Tools can be SDK actions, your own app's methods, or both. App methods run
|
|
5159
|
-
* as the user who invoked the method that started the task, with their roles.
|
|
5160
|
-
*
|
|
5161
|
-
* ```ts
|
|
5162
|
-
* const result = await agent.runTask<{ name: string; url: string }>({
|
|
5163
|
-
* prompt: 'Find canonical info for this restaurant, then save it.',
|
|
5164
|
-
* input: { restaurantName: 'Tartine Bakery SF' },
|
|
5165
|
-
* tools: [
|
|
5166
|
-
* 'searchGoogle',
|
|
5167
|
-
* 'fetchUrl',
|
|
5168
|
-
* { appMethod: 'saveRestaurant', description: 'Persist the researched restaurant.' },
|
|
5169
|
-
* ],
|
|
5170
|
-
* structuredOutputExample: JSON.stringify({ name: 'Tartine Bakery', url: 'https://tartinebakery.com' }),
|
|
5171
|
-
* model: 'claude-4-6-sonnet',
|
|
5172
|
-
* });
|
|
5173
|
-
* console.log(result.output.name); // 'Tartine Bakery'
|
|
5174
|
-
* ```
|
|
5175
|
-
*/
|
|
5176
5406
|
async runTask(options) {
|
|
5177
5407
|
const taskPromise = this._runTaskInner(options);
|
|
5178
5408
|
const hook = globalThis.__msWaitUntil;
|
|
@@ -5296,10 +5526,25 @@ var MindStudioAgent = class {
|
|
|
5296
5526
|
} catch (err) {
|
|
5297
5527
|
if (err instanceof MindStudioError && err.code === TURN_UNAVAILABLE_CODE) {
|
|
5298
5528
|
const body = buildTaskRequestBody(options);
|
|
5299
|
-
|
|
5300
|
-
|
|
5529
|
+
const result = options.onEvent ? await runTaskStream(httpConfig, body, options.onEvent) : await runTaskPoll(httpConfig, body);
|
|
5530
|
+
if (options.outputSchema) {
|
|
5531
|
+
const errors = result.parsedSuccessfully ? validateAgainstSchema(result.output, options.outputSchema) : [{ path: "$", message: "output was not valid JSON" }];
|
|
5532
|
+
if (errors.length > 0) {
|
|
5533
|
+
throw new MindStudioError(
|
|
5534
|
+
"[task] Output did not conform to outputSchema (legacy task route, no repair turns).",
|
|
5535
|
+
"task_output_schema_mismatch",
|
|
5536
|
+
422,
|
|
5537
|
+
{
|
|
5538
|
+
outputRaw: result.outputRaw,
|
|
5539
|
+
errors,
|
|
5540
|
+
turns: result.turns,
|
|
5541
|
+
usage: result.usage,
|
|
5542
|
+
toolCalls: result.toolCalls
|
|
5543
|
+
}
|
|
5544
|
+
);
|
|
5545
|
+
}
|
|
5301
5546
|
}
|
|
5302
|
-
return
|
|
5547
|
+
return result;
|
|
5303
5548
|
}
|
|
5304
5549
|
throw err;
|
|
5305
5550
|
}
|
|
@@ -5713,6 +5958,79 @@ var MindStudioAgent = class {
|
|
|
5713
5958
|
get files() {
|
|
5714
5959
|
return this._files ??= createFiles(this._filesRequest.bind(this));
|
|
5715
5960
|
}
|
|
5961
|
+
/**
|
|
5962
|
+
* Jewel surfaces: arrival-shaped triggers (`propose`) and the app-native
|
|
5963
|
+
* approval queue (`queue.list` / `queue.resolve`). See {@link JewelsApi}.
|
|
5964
|
+
*/
|
|
5965
|
+
get jewels() {
|
|
5966
|
+
return {
|
|
5967
|
+
propose: (methodId, subject, opts) => {
|
|
5968
|
+
if (!methodId || typeof methodId !== "string") {
|
|
5969
|
+
throw new MindStudioError(
|
|
5970
|
+
"methodId is required",
|
|
5971
|
+
"missing_method_id",
|
|
5972
|
+
400
|
|
5973
|
+
);
|
|
5974
|
+
}
|
|
5975
|
+
return this._jewelsRequest("propose", {
|
|
5976
|
+
methodId,
|
|
5977
|
+
subject,
|
|
5978
|
+
...opts?.idempotencyKey !== void 0 && {
|
|
5979
|
+
idempotencyKey: opts.idempotencyKey
|
|
5980
|
+
}
|
|
5981
|
+
});
|
|
5982
|
+
},
|
|
5983
|
+
queue: {
|
|
5984
|
+
list: (opts) => this._jewelsRequest("queue/list", {
|
|
5985
|
+
...opts?.methodId !== void 0 && { methodId: opts.methodId },
|
|
5986
|
+
...opts?.limit !== void 0 && { limit: opts.limit }
|
|
5987
|
+
}),
|
|
5988
|
+
resolve: (itemId, opts) => this._jewelsRequest("queue/resolve", {
|
|
5989
|
+
itemId,
|
|
5990
|
+
action: opts.action,
|
|
5991
|
+
...opts.input !== void 0 && { input: opts.input }
|
|
5992
|
+
})
|
|
5993
|
+
}
|
|
5994
|
+
};
|
|
5995
|
+
}
|
|
5996
|
+
/**
|
|
5997
|
+
* Raw hook-token call shared by the jewels surfaces (mirrors reportIssue).
|
|
5998
|
+
* No retries: propose holds the request for the jewel run and is idempotent
|
|
5999
|
+
* by key anyway; resolve applies a method and must never double-fire.
|
|
6000
|
+
*/
|
|
6001
|
+
async _jewelsRequest(path, body) {
|
|
6002
|
+
const rctx = getRequestContext();
|
|
6003
|
+
if (this._authType !== "internal" && !rctx?.callbackToken) {
|
|
6004
|
+
throw new MindStudioError(
|
|
6005
|
+
`jewels.${path.replace("/", ".")} requires an app execution context (hook token) \u2014 it cannot be called with an API key.`,
|
|
6006
|
+
"jewels_requires_app_context",
|
|
6007
|
+
400
|
|
6008
|
+
);
|
|
6009
|
+
}
|
|
6010
|
+
const url = `${this._currentHttpConfig.baseUrl}/_internal/v2/jewels/${path}`;
|
|
6011
|
+
const res = await fetch(url, {
|
|
6012
|
+
method: "POST",
|
|
6013
|
+
headers: {
|
|
6014
|
+
"Content-Type": "application/json",
|
|
6015
|
+
Authorization: this._token
|
|
6016
|
+
},
|
|
6017
|
+
body: JSON.stringify(body)
|
|
6018
|
+
});
|
|
6019
|
+
if (!res.ok) {
|
|
6020
|
+
let code = "jewels_error";
|
|
6021
|
+
let message = `jewels.${path.replace("/", ".")} failed: ${res.status} ${res.statusText}`;
|
|
6022
|
+
let details;
|
|
6023
|
+
try {
|
|
6024
|
+
const errBody = await res.json();
|
|
6025
|
+
details = errBody;
|
|
6026
|
+
if (typeof errBody.errorString === "string") code = errBody.errorString;
|
|
6027
|
+
message = typeof errBody.errorMessage === "string" && errBody.errorMessage || typeof errBody.errorString === "string" && errBody.errorString || message;
|
|
6028
|
+
} catch {
|
|
6029
|
+
}
|
|
6030
|
+
throw new MindStudioError(message, code, res.status, details);
|
|
6031
|
+
}
|
|
6032
|
+
return await res.json();
|
|
6033
|
+
}
|
|
5716
6034
|
/**
|
|
5717
6035
|
* Searchable document corpora.
|
|
5718
6036
|
*
|
|
@@ -6274,6 +6592,124 @@ function resolveToken(provided, config) {
|
|
|
6274
6592
|
);
|
|
6275
6593
|
}
|
|
6276
6594
|
|
|
6595
|
+
// src/jewel/index.ts
|
|
6596
|
+
function errorInfo(e) {
|
|
6597
|
+
if (e instanceof Error) return { message: e.message, stack: e.stack };
|
|
6598
|
+
return { message: String(e) };
|
|
6599
|
+
}
|
|
6600
|
+
function deepEqual(a, b) {
|
|
6601
|
+
if (a === b) return true;
|
|
6602
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object") {
|
|
6603
|
+
return false;
|
|
6604
|
+
}
|
|
6605
|
+
const aIsArray = Array.isArray(a);
|
|
6606
|
+
if (aIsArray !== Array.isArray(b)) return false;
|
|
6607
|
+
if (aIsArray) {
|
|
6608
|
+
const aa = a;
|
|
6609
|
+
const ba = b;
|
|
6610
|
+
return aa.length === ba.length && aa.every((v, i) => deepEqual(v, ba[i]));
|
|
6611
|
+
}
|
|
6612
|
+
const ao = a;
|
|
6613
|
+
const bo = b;
|
|
6614
|
+
const aKeys = Object.keys(ao).filter((k) => ao[k] !== void 0);
|
|
6615
|
+
const bKeys = Object.keys(bo).filter((k) => bo[k] !== void 0);
|
|
6616
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
6617
|
+
return aKeys.every((k) => deepEqual(ao[k], bo[k]));
|
|
6618
|
+
}
|
|
6619
|
+
var VERDICTS = /* @__PURE__ */ new Set(["agree", "disagree", "skip"]);
|
|
6620
|
+
function normalizeVerdict(v) {
|
|
6621
|
+
if (!v || !VERDICTS.has(v.verdict)) {
|
|
6622
|
+
return {
|
|
6623
|
+
verdict: "skip",
|
|
6624
|
+
notes: `grade returned invalid verdict: ${JSON.stringify(v)}`
|
|
6625
|
+
};
|
|
6626
|
+
}
|
|
6627
|
+
return v.notes === void 0 ? { verdict: v.verdict } : { verdict: v.verdict, notes: v.notes };
|
|
6628
|
+
}
|
|
6629
|
+
function defineJewel(method, config) {
|
|
6630
|
+
const runGrade = async (proposed, actual) => {
|
|
6631
|
+
if (config.grade) {
|
|
6632
|
+
try {
|
|
6633
|
+
return normalizeVerdict(await config.grade({ proposed, actual }));
|
|
6634
|
+
} catch (e) {
|
|
6635
|
+
return { verdict: "skip", notes: `grade threw: ${errorInfo(e).message}` };
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
6638
|
+
return deepEqual(proposed, actual) ? { verdict: "agree" } : { verdict: "disagree" };
|
|
6639
|
+
};
|
|
6640
|
+
const run = async (params) => {
|
|
6641
|
+
const startedAt = Date.now();
|
|
6642
|
+
const customGrade = config.grade !== void 0;
|
|
6643
|
+
const done = (rest) => ({
|
|
6644
|
+
v: 1,
|
|
6645
|
+
customGrade,
|
|
6646
|
+
startedAt,
|
|
6647
|
+
durationMs: Date.now() - startedAt,
|
|
6648
|
+
...rest
|
|
6649
|
+
});
|
|
6650
|
+
if (Object.prototype.hasOwnProperty.call(params, "grade")) {
|
|
6651
|
+
const ctx = params.grade;
|
|
6652
|
+
const verdict2 = await runGrade(ctx.proposed, ctx.actual);
|
|
6653
|
+
return done({
|
|
6654
|
+
mode: "grade",
|
|
6655
|
+
proposed: ctx.proposed,
|
|
6656
|
+
actual: ctx.actual,
|
|
6657
|
+
verdict: verdict2.verdict,
|
|
6658
|
+
...verdict2.notes !== void 0 ? { notes: verdict2.notes } : {}
|
|
6659
|
+
});
|
|
6660
|
+
}
|
|
6661
|
+
const isShadow = Object.prototype.hasOwnProperty.call(params, "humanInput");
|
|
6662
|
+
const mode = isShadow ? "shadow" : "eval";
|
|
6663
|
+
const actual = isShadow ? params.humanInput : void 0;
|
|
6664
|
+
let subject;
|
|
6665
|
+
if (isShadow) {
|
|
6666
|
+
try {
|
|
6667
|
+
subject = config.subject(actual);
|
|
6668
|
+
} catch (e) {
|
|
6669
|
+
return done({ mode, actual, error: { phase: "subject", ...errorInfo(e) } });
|
|
6670
|
+
}
|
|
6671
|
+
} else {
|
|
6672
|
+
subject = params.subject;
|
|
6673
|
+
}
|
|
6674
|
+
let proposal;
|
|
6675
|
+
try {
|
|
6676
|
+
proposal = await config.propose(subject);
|
|
6677
|
+
} catch (e) {
|
|
6678
|
+
return done({
|
|
6679
|
+
mode,
|
|
6680
|
+
subject,
|
|
6681
|
+
actual,
|
|
6682
|
+
error: { phase: "propose", ...errorInfo(e) }
|
|
6683
|
+
});
|
|
6684
|
+
}
|
|
6685
|
+
if (!isShadow) {
|
|
6686
|
+
return done({
|
|
6687
|
+
mode,
|
|
6688
|
+
subject,
|
|
6689
|
+
proposed: proposal.input,
|
|
6690
|
+
reasoning: proposal.reasoning
|
|
6691
|
+
});
|
|
6692
|
+
}
|
|
6693
|
+
const verdict = await runGrade(proposal.input, actual);
|
|
6694
|
+
return done({
|
|
6695
|
+
mode,
|
|
6696
|
+
subject,
|
|
6697
|
+
proposed: proposal.input,
|
|
6698
|
+
reasoning: proposal.reasoning,
|
|
6699
|
+
actual,
|
|
6700
|
+
verdict: verdict.verdict,
|
|
6701
|
+
...verdict.notes !== void 0 ? { notes: verdict.notes } : {}
|
|
6702
|
+
});
|
|
6703
|
+
};
|
|
6704
|
+
return Object.assign(run, {
|
|
6705
|
+
kind: "jewel",
|
|
6706
|
+
method,
|
|
6707
|
+
subject: config.subject,
|
|
6708
|
+
propose: config.propose,
|
|
6709
|
+
grade: config.grade
|
|
6710
|
+
});
|
|
6711
|
+
}
|
|
6712
|
+
|
|
6277
6713
|
// src/generated/snippets.ts
|
|
6278
6714
|
var monacoSnippets = {
|
|
6279
6715
|
"activeCampaignAddNote": { fields: [["contactId", "string"], ["note", "string"]], outputKeys: [] },
|
|
@@ -6525,6 +6961,7 @@ export {
|
|
|
6525
6961
|
dataSources,
|
|
6526
6962
|
db,
|
|
6527
6963
|
index_default as default,
|
|
6964
|
+
defineJewel,
|
|
6528
6965
|
files,
|
|
6529
6966
|
getRequestContext,
|
|
6530
6967
|
mindstudio,
|