@pixelml/agenticflow-cli 1.5.2 → 1.5.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,SAAS,EAAE,cAAc,EAsIrC,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,cAAc,CAEnD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAInE"}
1
+ {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,SAAS,EAAE,cAAc,EAoJrC,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,cAAc,CAEnD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAInE"}
@@ -5,6 +5,20 @@
5
5
  * and displayed after upgrade.
6
6
  */
7
7
  export const CHANGELOG = [
8
+ {
9
+ version: "1.5.3",
10
+ date: "2026-04-14",
11
+ highlights: [
12
+ "Model preflight on `af agent create/update` — invalid model strings (typos, missing slash) fail fast BEFORE the agent gets created with a broken config. Unknown-but-plausible models warn but proceed (so new models work between CLI releases)",
13
+ "Structured error hints on 401/403/404/409/422/429 — every common HTTP failure now carries an actionable `hint` in --json output pointing at the right recovery command (`af whoami`, `af agent list`, fetch-and-reconcile, etc.)",
14
+ "`af agent update` emits a stderr `[info]` line naming which null-valued fields got auto-stripped. Closes the footgun where bots thought they'd cleared a field but the server never saw null. Silenced with --json (keeps stdout clean for piping)",
15
+ ],
16
+ for_ai: [
17
+ "If you're iterating on an agent's system prompt with `--patch`, don't also clear optional fields by sending null — the CLI strips them and the stderr info line tells you which ones were dropped",
18
+ "When a command fails, check the `hint` field in the error envelope before retrying — 404s point you at the matching `list` command, 422s point you at `details.payload` for field-level errors",
19
+ "Pass only models from `af bootstrap --json > models[]` — typos fail at validation time, not at next `agent run`. If you're trying a brand-new model and hit a warning, you can proceed (CLI is conservative — warns but doesn't block)",
20
+ ],
21
+ },
8
22
  {
9
23
  version: "1.5.2",
10
24
  date: "2026-04-14",
@@ -1 +1 @@
1
- {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAy4BpC,wBAAgB,aAAa,IAAI,OAAO,CA81KvC;AAED,wBAAsB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB3D"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAi8BpC,wBAAgB,aAAa,IAAI,OAAO,CAs2KvC;AAED,wBAAsB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB3D"}
package/dist/cli/main.js CHANGED
@@ -17,9 +17,10 @@ import { LinearConnector } from "./gateway/connectors/linear.js";
17
17
  import { WebhookConnector } from "./gateway/connectors/webhook.js";
18
18
  import { listBlueprints, getBlueprint } from "./company-blueprints.js";
19
19
  import { CHANGELOG, getLatestChangelog } from "./changelog.js";
20
- import { stripNullFields } from "./utils/patch.js";
20
+ import { stripNullFields, AGENT_UPDATE_STRIP_NULL_FIELDS } from "./utils/patch.js";
21
21
  import { inspectMcpToolsPattern } from "./utils/mcp-inspect.js";
22
22
  import { emitDeprecation } from "./utils/deprecation.js";
23
+ import { validateModel } from "./utils/models.js";
23
24
  import { OperationRegistry, defaultSpecPath, loadOpenapiSpec, isPublic, } from "./spec.js";
24
25
  import { listPlaybooks, getPlaybook } from "./playbooks.js";
25
26
  import { loadPolicy, writeDefaultPolicy, policyFilePath, } from "./policy.js";
@@ -438,6 +439,19 @@ function buildClient(parentOpts) {
438
439
  projectId: resolveProjectId(parentOpts.projectId),
439
440
  });
440
441
  }
442
+ /**
443
+ * Map of HTTP status codes to actionable hints AI operators can follow without
444
+ * additional context. Keeps error responses useful when the server's error
445
+ * message is terse (e.g. "Agent not found" with no follow-up).
446
+ */
447
+ const STATUS_HINT_MAP = {
448
+ 401: "Authentication failed. Run `af whoami` to check current auth, or `af login --api-key <key>` to refresh.",
449
+ 403: "You don't have permission for this operation. Check the resource's workspace/project or your API key's scopes.",
450
+ 404: "Resource not found. Run the matching `list` command (e.g. `af agent list --json`) to see available IDs, or double-check the ID you passed.",
451
+ 409: "Conflict — the resource state disagrees with your request. Fetch the current state with `get` and reconcile before retrying.",
452
+ 422: "Validation failed. Check `details.payload` for the specific field errors — pydantic returns a list with field name + expected type per issue.",
453
+ 429: "Rate limited. Back off and retry with exponential delay.",
454
+ };
441
455
  /** Wrap an async SDK call with error handling. */
442
456
  async function run(fn) {
443
457
  try {
@@ -458,11 +472,47 @@ async function run(fn) {
458
472
  details["request_id"] = err.requestId;
459
473
  if (err.payload !== null && err.payload !== undefined)
460
474
  details["payload"] = err.payload;
461
- fail("request_failed", message, undefined, details);
475
+ const hint = STATUS_HINT_MAP[err.statusCode];
476
+ fail("request_failed", message, hint, details);
462
477
  }
463
478
  fail("request_failed", message);
464
479
  }
465
480
  }
481
+ /**
482
+ * Validate the `model` field on an agent create/update payload, if present.
483
+ * Fail-fast on implausible strings; warn (stderr) on plausible-but-unknown
484
+ * strings so new models work without CLI updates.
485
+ */
486
+ function preflightModel(payload, context) {
487
+ if (!("model" in payload))
488
+ return;
489
+ const res = validateModel(payload["model"]);
490
+ if (!res.valid) {
491
+ fail("invalid_option_value", `Invalid model in ${context}: ${String(payload["model"])}.`, res.suggestion);
492
+ }
493
+ if (!res.known && res.suggestion && !isJsonFlagEnabled()) {
494
+ console.error(`[warn] ${res.suggestion}`);
495
+ }
496
+ }
497
+ /**
498
+ * Report which keys got stripped by stripNullFields() so callers don't think
499
+ * they successfully cleared a field when the CLI silently dropped it.
500
+ * Emitted to stderr only (keeps stdout JSON clean for piping).
501
+ */
502
+ function warnOnStrippedNulls(original, stripped) {
503
+ if (isJsonFlagEnabled())
504
+ return; // don't pollute stderr on bot-driven runs
505
+ const dropped = [];
506
+ for (const key of AGENT_UPDATE_STRIP_NULL_FIELDS) {
507
+ if (key in original && original[key] === null && !(key in stripped)) {
508
+ dropped.push(key);
509
+ }
510
+ }
511
+ if (dropped.length > 0) {
512
+ console.error(`[info] Stripped ${dropped.length} null-valued field(s) the server rejects on update: ${dropped.join(", ")}. ` +
513
+ "This is expected — server-required shape. See `af schema agent --field update --json` for the full list.");
514
+ }
515
+ }
466
516
  // ═══════════════════════════════════════════════════════════════════
467
517
  // Spec-based helpers (for generic commands: call, ops, catalog, doctor)
468
518
  // ═══════════════════════════════════════════════════════════════════
@@ -3487,6 +3537,7 @@ export function createProgram() {
3487
3537
  const body = loadJsonPayload(opts.body);
3488
3538
  hardenInput(JSON.stringify(body), "agent create body");
3489
3539
  ensureLocalValidation("agent.create", validateAgentCreatePayload(body));
3540
+ preflightModel(body, "agent create");
3490
3541
  if (opts.dryRun) {
3491
3542
  printResult({ schema: "agenticflow.dry_run.v1", valid: true, target: "agent.create", payload: body });
3492
3543
  return;
@@ -3504,15 +3555,22 @@ export function createProgram() {
3504
3555
  const client = buildClient(program.opts());
3505
3556
  const body = loadJsonPayload(opts.body);
3506
3557
  ensureLocalValidation("agent.update", validateAgentUpdatePayload(body));
3558
+ preflightModel(body, "agent update");
3507
3559
  if (opts.patch) {
3508
3560
  await run(() => client.agents.patch(opts.agentId, body, {
3509
- prepare: (merged) => stripNullFields(merged),
3561
+ prepare: (merged) => {
3562
+ const stripped = stripNullFields(merged);
3563
+ warnOnStrippedNulls(merged, stripped);
3564
+ return stripped;
3565
+ },
3510
3566
  }));
3511
3567
  }
3512
3568
  else {
3513
3569
  // Full replace, but strip server-rejected nulls so a round-tripped
3514
3570
  // `af agent get | af agent update --body @-` workflow doesn't 422.
3515
- const prepared = stripNullFields(body);
3571
+ const original = body;
3572
+ const prepared = stripNullFields(original);
3573
+ warnOnStrippedNulls(original, prepared);
3516
3574
  await run(() => client.agents.update(opts.agentId, prepared));
3517
3575
  }
3518
3576
  });