skill(iter-1): fix CLI getRecords flag + docs from eval feedback

Ran 4 end-to-end evals (skill-creator flow): all 23 assertions passed (100%).
The evals exposed 3 issues, now fixed:

1. CLI bug: getRecords/createRecord/updateRecord --target-table flag was
   read as opts['target-table'] but commander stores it camelCase
   (opts.targetTable). Added a pick() helper accepting both forms.
2. trigger-types.md: buttonClick output said record.fields.* implying all
   fields; actually record.fields only contains the button field's count.
   Documented the back-channel API fetch pattern for other fields.
3. automation-guide.md: documented that 'workflow test' uses mock input
   with empty fields, so upstream outputs are absent in test mode — use
   real fire for data-dependent validation.

Also: corrected button field options (workflow.id object, not workflowId).
This commit is contained in:
yeuimu
2026-08-05 10:48:33 +08:00
parent d3790ab856
commit 3e06a10fe0
6 changed files with 92 additions and 16 deletions
+15 -4
View File
@@ -501,10 +501,14 @@ function readFile(p: string): string {
/** Build action config from granular flags. */
export function buildActionConfig(opts: Record<string, string>): Record<string, unknown> {
const type = opts.type;
// Helper: commander stores --kebab-case flags as camelCase in opts (e.g.
// --target-table -> opts.targetTable). Accept both forms for safety.
const pick = (k: string): string | undefined => (opts[k] ?? opts[toCamel(k)]) as string | undefined;
const config: Record<string, unknown> = {};
switch (type) {
case 'script': {
if (opts['code-file']) config.code = readFile(opts['code-file']);
const codeFile = pick('code-file');
if (codeFile) config.code = readFile(codeFile);
else if (opts.code) config.code = opts.code;
if (opts.timeout) config.timeout = Number(opts.timeout);
break;
@@ -519,17 +523,20 @@ export function buildActionConfig(opts: Record<string, string>): Record<string,
if (opts.url) config.url = opts.url;
if (opts.method) config.method = opts.method;
if (opts.headers) config.headers = JSON.parse(opts.headers);
if (opts['req-body']) config.body = JSON.parse(opts['req-body']);
const reqBody = pick('req-body');
if (reqBody) config.body = JSON.parse(reqBody);
break;
}
case 'createRecord':
case 'updateRecord': {
if (opts['target-table']) config.tableId = opts['target-table'];
const tt = pick('target-table');
if (tt) config.tableId = tt;
if (opts.records) config.records = JSON.parse(opts.records);
break;
}
case 'getRecords': {
if (opts['target-table']) config.tableId = opts['target-table'];
const tt = pick('target-table');
if (tt) config.tableId = tt;
if (opts.query) config.query = JSON.parse(opts.query);
break;
}
@@ -538,3 +545,7 @@ export function buildActionConfig(opts: Record<string, string>): Record<string,
}
return config;
}
function toCamel(s: string): string {
return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
}