Files
jerapah-flow/packages/web/src/components/ScriptMetaPanel.jsx
T
nsrb 43e9370638 feat(scripts): enhance script return structure and context handling
- Introduced a new contract for script returns, requiring an object with `output`, `context`, and `skipRemaining` fields.
- Refactored existing scripts to align with the new return structure, ensuring compatibility with the updated context management.
- Added utility functions for normalizing context and step results, improving the handling of script execution context.
- Updated various scripts (e.g., fetch-binary, fetch-html, fetch-http) to return structured output and context, enhancing data flow and usability.
- Improved error handling for script returns, ensuring clearer feedback when invalid structures are returned.

This update significantly enhances the flexibility and clarity of script interactions within workflows.
2026-08-15 22:32:42 +07:00

86 lines
2.9 KiB
React

import { scriptTags, scriptReadsCtx } from "../lib/script.js";
import { TagBadge } from "./TagBadge.jsx";
function FieldTable({ title, fields }) {
const entries = Object.entries(fields ?? {});
if (entries.length === 0) return null;
return (
<div>
<h3 className="mb-1 text-xs font-semibold uppercase tracking-wide opacity-60">{title}</h3>
<div className="overflow-x-auto">
<table className="table table-xs">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
{entries.map(([name, spec]) => {
const field = spec && typeof spec === "object" ? spec : { description: String(spec) };
const notes = [
field.required ? "required" : null,
field.default !== undefined ? `default ${JSON.stringify(field.default)}` : null,
Array.isArray(field.enum)
? `enum ${field.enum.map((x) => (x && typeof x === "object" ? x.value : x)).join(", ")}`
: Array.isArray(field.options)
? `enum ${field.options.map((x) => (x && typeof x === "object" ? x.value : x)).join(", ")}`
: null,
field.description,
]
.filter(Boolean)
.join(" · ");
return (
<tr key={name}>
<td className="font-mono">{name}</td>
<td className="opacity-70">{field.type ?? ""}</td>
<td className="opacity-80">{notes}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}
export function ScriptMetaPanel({ meta, metaError, className = "" }) {
if (metaError) {
return <p className={`text-error text-sm ${className}`}>Meta: {metaError}</p>;
}
if (!meta) {
return (
<p className={`text-sm opacity-50 ${className}`}>
No script.meta on the default export
</p>
);
}
const tags = scriptTags(meta);
return (
<div className={`space-y-3 ${className}`}>
{meta.description ? <p className="text-sm">{meta.description}</p> : null}
{(tags.length || scriptReadsCtx(meta)) ? (
<div className="flex flex-wrap gap-1">
{tags.map((tag) => (
<TagBadge key={tag} tag={tag} />
))}
{scriptReadsCtx(meta) ? (
<span className="badge badge-outline badge-sm font-mono">reads: ctx</span>
) : null}
</div>
) : null}
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
<FieldTable title="Config" fields={meta.config} />
<FieldTable title="Input (data)" fields={meta.input} />
<FieldTable title="Output" fields={meta.output} />
<FieldTable title="Context" fields={meta.context} />
</div>
</div>
);
}