@erdoai/cli 0.57.0 → 0.59.0

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.
Files changed (2) hide show
  1. package/dist/index.js +86 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -579,6 +579,14 @@ var ErdoClient = class {
579
579
  input
580
580
  );
581
581
  }
582
+ // --- page feedback ---
583
+ // Structured client page-feedback intake. Each item names its page by
584
+ // experiment_slug + variant_key and mints a 'defect' observation (judge_slug
585
+ // human:<you>) on the ledger with the feedback text stored verbatim as the
586
+ // reason — the same channel respondAttentionItem's defects flag writes to.
587
+ recordPageFeedback(items) {
588
+ return this.request("POST", "/v1/page-feedback", { items });
589
+ }
582
590
  // --- activity feed ---
583
591
  // The unified, ranked, read-only feed. It defaults to attention items,
584
592
  // approvals, and workstream events; catalog and execution history are opt-in.
@@ -1385,6 +1393,18 @@ function timedOutMessage(threadID) {
1385
1393
  function print(value) {
1386
1394
  console.log(JSON.stringify(value, null, 2));
1387
1395
  }
1396
+ function printPageReview(review) {
1397
+ if (!review) return;
1398
+ if (!review.reviewed) {
1399
+ console.error(`review: not run${review.reason ? ` (${review.reason})` : ""}`);
1400
+ return;
1401
+ }
1402
+ console.error(`review: ${review.summary || `${review.issues?.length ?? 0} issue(s)`}`);
1403
+ for (const issue of review.issues || []) {
1404
+ console.error(` [${issue.severity}/${issue.category}] ${issue.description}`);
1405
+ if (issue.suggestion) console.error(` fix: ${issue.suggestion}`);
1406
+ }
1407
+ }
1388
1408
  function printAlignedTable(columns, rows) {
1389
1409
  const cell = (v) => v === null || v === void 0 ? "" : typeof v === "object" ? JSON.stringify(v) : String(v);
1390
1410
  const widths = columns.map((c, i) => Math.max(c.length, ...rows.map((r) => cell(r[i]).length), 0));
@@ -2065,7 +2085,7 @@ expCmd.command("create").description("Create an experiment with its variants, ev
2065
2085
  }
2066
2086
  }
2067
2087
  );
2068
- expCmd.command("observations <slug>").description("Read an experiment's observation log (metric reads / decisions / actions / judge forecasts)").option("--variant <key>", "filter to one variant").option("--type <type>", "metric_read, decision_check, action, prediction, comparison").option("--judge <slug>", "filter to one judge's forecasts within this experiment").option("-n, --limit <n>", "max rows", (v) => parseInt(v, 10)).action(
2088
+ expCmd.command("observations <slug>").description("Read an experiment's observation log (metrics / decisions / actions / judge forecasts / defects)").option("--variant <key>", "filter to one variant").option("--type <type>", "metric_read, decision_check, action_taken, prediction, comparison, defect").option("--judge <slug>", "filter to one judge's forecasts within this experiment").option("-n, --limit <n>", "max rows", (v) => parseInt(v, 10)).action(
2069
2089
  async (slug, opts) => {
2070
2090
  try {
2071
2091
  print(
@@ -3093,6 +3113,64 @@ attnCmd.command("respond <id>").description(
3093
3113
  }
3094
3114
  }
3095
3115
  );
3116
+ var pageFeedbackCmd = program.command("page-feedback").description(
3117
+ "Structured client page-feedback intake \u2014 mints defect observations bound to a page's experiment variant"
3118
+ );
3119
+ pageFeedbackCmd.command("record").description(
3120
+ "Record one or more page-feedback items. Each item's feedback text is stored VERBATIM as the resulting defect observation's reason \u2014 no summarizing or rewriting happens here. Use --experiment/--variant/--feedback for a single item, or --items for a whole round."
3121
+ ).option("--experiment <slug>", "experiment slug or uuid the page belongs to (single-item form)").option("--variant <key>", "the page variant this feedback is about (single-item form)").option(
3122
+ "--feedback <text>",
3123
+ "the client's own words, stored byte-for-byte as supplied (single-item form)"
3124
+ ).option(
3125
+ "--image-key <key>",
3126
+ "optional bucket_key from a prior image upload, anchoring this item to an image (single-item form)"
3127
+ ).option(
3128
+ "--items <json>",
3129
+ `a whole feedback round as JSON, or @path to a JSON file: '[{"experiment_slug":"...","variant_key":"...","feedback":"..."}]'`
3130
+ ).action(
3131
+ async (opts) => {
3132
+ try {
3133
+ const singleGiven = opts.experiment !== void 0 || opts.variant !== void 0 || opts.feedback !== void 0 || opts.imageKey !== void 0;
3134
+ if (opts.items !== void 0 && singleGiven) {
3135
+ fail(
3136
+ new Error(
3137
+ "provide either --items or the single-item flags (--experiment/--variant/--feedback/--image-key), not both"
3138
+ )
3139
+ );
3140
+ }
3141
+ let items;
3142
+ if (opts.items !== void 0) {
3143
+ let parsed;
3144
+ try {
3145
+ parsed = JSON.parse(readMaybeFile(opts.items));
3146
+ } catch {
3147
+ throw new Error(
3148
+ `--items must be valid JSON (or @path to a JSON file), e.g. '[{"experiment_slug":"...","variant_key":"...","feedback":"..."}]'`
3149
+ );
3150
+ }
3151
+ if (!Array.isArray(parsed)) {
3152
+ throw new Error("--items must be a JSON array of {experiment_slug, variant_key, feedback} objects");
3153
+ }
3154
+ items = parsed;
3155
+ } else {
3156
+ if (!opts.experiment || !opts.variant || !opts.feedback) {
3157
+ throw new Error("provide --items, or all of --experiment, --variant, --feedback");
3158
+ }
3159
+ items = [
3160
+ {
3161
+ experiment_slug: opts.experiment,
3162
+ variant_key: opts.variant,
3163
+ feedback: opts.feedback,
3164
+ image_bucket_key: opts.imageKey
3165
+ }
3166
+ ];
3167
+ }
3168
+ print(await new ErdoClient().recordPageFeedback(items));
3169
+ } catch (e) {
3170
+ fail(e);
3171
+ }
3172
+ }
3173
+ );
3096
3174
  function activityLine(it) {
3097
3175
  const handle = it.slug || it.id;
3098
3176
  const parts = [it.title || it.type];
@@ -3397,7 +3475,10 @@ pagesCmd.command("update <id>").description(
3397
3475
  ).option("--title <title>", "new title").option("--html <htmlOr@file>", "HTML (or @path to a file)").option("--js <jsOr@file>", "JS/JSX (or @path)").option("--css <cssOr@file>", "CSS (or @path)").option(
3398
3476
  "--meta-title <title>",
3399
3477
  'new public SEO title (omit to keep current; pass "" to clear back to the default)'
3400
- ).option("--meta-description <description>", 'new public SEO description (omit to keep current; pass "" to clear)').option("--datasets <csv>", 'replacement read-dataset slugs ("[]" clears)').option("--writable-datasets <csv>", 'replacement writable-dataset slugs ("[]" clears)').option("--kv <csv>", 'replacement read KV-store slugs ("[]" clears)').option("--writable-kv <csv>", 'replacement writable KV-store slugs ("[]" clears)').option("--public", "make the page publicly viewable").option("--private", "make the page private").action(
3478
+ ).option("--meta-description <description>", 'new public SEO description (omit to keep current; pass "" to clear)').option("--datasets <csv>", 'replacement read-dataset slugs ("[]" clears)').option("--writable-datasets <csv>", 'replacement writable-dataset slugs ("[]" clears)').option("--kv <csv>", 'replacement read KV-store slugs ("[]" clears)').option("--writable-kv <csv>", 'replacement writable KV-store slugs ("[]" clears)').option("--public", "make the page publicly viewable").option("--private", "make the page private").option(
3479
+ "--request-review",
3480
+ "ask the judge lenses to review the page after this update and report findings -- for material edits to a LIVE page (layout, forms/CTA, legal/compliance copy, restructured sections), not cosmetic tweaks. First builds and full rewrites are already reviewed automatically"
3481
+ ).action(
3401
3482
  async (id, opts) => {
3402
3483
  try {
3403
3484
  const res = await new ErdoClient().updatePage(id, {
@@ -3411,10 +3492,12 @@ pagesCmd.command("update <id>").description(
3411
3492
  writable_dataset_slugs: grantList(opts.writableDatasets),
3412
3493
  kv_slugs: grantList(opts.kv),
3413
3494
  writable_kv_slugs: grantList(opts.writableKv),
3414
- public: opts.public ? true : opts.private ? false : void 0
3495
+ public: opts.public ? true : opts.private ? false : void 0,
3496
+ request_review: !!opts.requestReview
3415
3497
  });
3416
3498
  console.log(`${res.id} ${res.public_url || res.url}`);
3417
3499
  if (res.warning) console.error(`warning: ${res.warning}`);
3500
+ printPageReview(res.review);
3418
3501
  } catch (e) {
3419
3502
  fail(e);
3420
3503
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erdoai/cli",
3
- "version": "0.57.0",
3
+ "version": "0.59.0",
4
4
  "description": "Erdo CLI — drive datasets, pages, and evals from the terminal or CI",
5
5
  "type": "module",
6
6
  "bin": {