@erdoai/cli 0.31.0 → 0.33.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 +93 -4
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -180,10 +180,13 @@ function looksLikeHTML(text) {
180
180
  function fetchMe(token, orgId) {
181
181
  return rawRequest(resolveApiUrl(), token, orgId, "GET", "/v1/me");
182
182
  }
183
+ var announcedOrg = false;
183
184
  var ErdoClient = class {
184
185
  baseURL;
185
186
  token;
186
187
  orgId;
188
+ orgPinned;
189
+ orgName;
187
190
  constructor(orgOverride) {
188
191
  this.baseURL = resolveApiUrl();
189
192
  const acct = activeAccount();
@@ -193,8 +196,27 @@ var ErdoClient = class {
193
196
  }
194
197
  this.token = token;
195
198
  this.orgId = resolveOrgId(acct, orgOverride);
199
+ this.orgPinned = Boolean(orgOverride || process.env.ERDO_ORG);
200
+ this.orgName = acct?.organizationName;
201
+ }
202
+ announceOrgOnce(method) {
203
+ if (announcedOrg) return;
204
+ if (method.toUpperCase() === "GET") return;
205
+ announcedOrg = true;
206
+ if (this.orgPinned && this.orgId) {
207
+ process.stderr.write(`org: ${this.orgId} (pinned)
208
+ `);
209
+ } else if (this.orgId) {
210
+ process.stderr.write(
211
+ `org: ${this.orgName ?? this.orgId} (active org \u2014 pass --org to pin)
212
+ `
213
+ );
214
+ } else {
215
+ process.stderr.write("org: token default (no org resolved \u2014 pass --org to pin)\n");
216
+ }
196
217
  }
197
218
  request(method, path, body) {
219
+ this.announceOrgOnce(method);
198
220
  return rawRequest(this.baseURL, this.token, this.orgId, method, path, body);
199
221
  }
200
222
  me() {
@@ -288,6 +310,29 @@ var ErdoClient = class {
288
310
  createProject(input) {
289
311
  return this.request("POST", "/v1/projects", input);
290
312
  }
313
+ // --- pages ---
314
+ listPages(params) {
315
+ const q = new URLSearchParams();
316
+ if (params?.query) q.set("query", params.query);
317
+ if (params?.createdAfter) q.set("created_after", params.createdAfter);
318
+ if (params?.createdBefore) q.set("created_before", params.createdBefore);
319
+ if (params?.limit) q.set("limit", String(params.limit));
320
+ if (params?.offset) q.set("offset", String(params.offset));
321
+ const qs = q.toString();
322
+ return this.request("GET", `/v1/pages${qs ? `?${qs}` : ""}`);
323
+ }
324
+ deletePage(id) {
325
+ return this.request(
326
+ "DELETE",
327
+ `/v1/pages/${encodeURIComponent(id)}`
328
+ );
329
+ }
330
+ restorePage(id) {
331
+ return this.request(
332
+ "POST",
333
+ `/v1/pages/restore/${encodeURIComponent(id)}`
334
+ );
335
+ }
291
336
  // --- workstreams ---
292
337
  listWorkstreams(status) {
293
338
  const q = new URLSearchParams();
@@ -1825,6 +1870,19 @@ evalCmd.command("create <name>").description("Create a suite (in the active org)
1825
1870
  evalCmd.command("run <slug>").description("Run a suite; --watch polls until it completes").option("-w, --watch", "poll until the run finishes and print results").option("-c, --concurrency <n>", "parallel cases", (v) => parseInt(v, 10)).action(async (slug, opts) => {
1826
1871
  try {
1827
1872
  const api = new ErdoClient();
1873
+ const { suite } = await api.getEvalSuite(slug);
1874
+ if (suite.evaluate_artifact && !process.env.ERDO_ORG) {
1875
+ const resolved = resolveOrgId(activeAccount()) ?? "<org>";
1876
+ console.error(
1877
+ [
1878
+ `Refusing to run "${slug}": it builds real artifacts in the resolved org.`,
1879
+ "The active org is machine-global \u2014 a concurrent session can switch it, so this",
1880
+ "run could land in the wrong org. Re-run with the org pinned:",
1881
+ ` erdo --org ${resolved} eval run ${slug}`
1882
+ ].join("\n")
1883
+ );
1884
+ process.exit(1);
1885
+ }
1828
1886
  const { run_id } = await api.runEvalSuite(slug, opts.concurrency);
1829
1887
  console.log(`run_id: ${run_id}`);
1830
1888
  if (!opts.watch) return;
@@ -2066,8 +2124,9 @@ approvalsCmd.command("list").description("List approval requests, optionally fil
2066
2124
  return;
2067
2125
  }
2068
2126
  for (const r of res.requests) {
2127
+ const occ = r.occurrence_count && r.occurrence_count > 1 ? ` \xD7${r.occurrence_count}` : "";
2069
2128
  console.log(
2070
- `${r.id} ${r.status} ${r.action_key} ${r.action_display} ${r.created_at}`
2129
+ `${r.id} ${r.status} ${r.action_key} ${r.action_display} ${r.created_at}${occ}`
2071
2130
  );
2072
2131
  }
2073
2132
  } catch (e) {
@@ -2293,10 +2352,40 @@ pagesCmd.command("validate").description("Validate page content without deployin
2293
2352
  fail(e);
2294
2353
  }
2295
2354
  });
2296
- pagesCmd.command("list").description("List artifacts (pages, charts, ...)").option("-t, --type <type>", "filter by type (e.g. html_page)").option("-l, --limit <n>", "max results", (v) => parseInt(v, 10)).action(async (opts) => {
2355
+ pagesCmd.command("list").description("List pages (newest first). With --type, lists any artifact type instead.").option("-t, --type <type>", "list all artifacts of this type (e.g. html) rather than just pages").option("--query <substr>", "case-insensitive title substring filter (pages only)").option("--created-after <iso>", "only pages created at/after this RFC3339 timestamp (pages only)").option("--created-before <iso>", "only pages created at/before this RFC3339 timestamp (pages only)").option("-l, --limit <n>", "max results", (v) => parseInt(v, 10)).option("--offset <n>", "pagination offset", (v) => parseInt(v, 10)).action(
2356
+ async (opts) => {
2357
+ try {
2358
+ if (opts.type) {
2359
+ const { artifacts } = await new ErdoClient().listArtifacts(opts.type, opts.limit);
2360
+ for (const a of artifacts) console.log(`${a.id} ${a.type} ${a.title}`);
2361
+ return;
2362
+ }
2363
+ const { pages } = await new ErdoClient().listPages({
2364
+ query: opts.query,
2365
+ createdAfter: opts.createdAfter,
2366
+ createdBefore: opts.createdBefore,
2367
+ limit: opts.limit,
2368
+ offset: opts.offset
2369
+ });
2370
+ for (const p of pages) {
2371
+ const vis = p.public ? p.public_url || "public" : "private";
2372
+ console.log(`${p.id} ${p.created_at} ${vis} ${p.title}`);
2373
+ }
2374
+ } catch (e) {
2375
+ fail(e);
2376
+ }
2377
+ }
2378
+ );
2379
+ pagesCmd.command("delete <id>").description("Delete a page (soft delete \u2014 unpublishes it and hides it from listings; restorable)").action(async (id) => {
2380
+ try {
2381
+ print(await new ErdoClient().deletePage(id));
2382
+ } catch (e) {
2383
+ fail(e);
2384
+ }
2385
+ });
2386
+ pagesCmd.command("restore <id>").description("Restore a previously deleted page (comes back private)").action(async (id) => {
2297
2387
  try {
2298
- const { artifacts } = await new ErdoClient().listArtifacts(opts.type, opts.limit);
2299
- for (const a of artifacts) console.log(`${a.id} ${a.type} ${a.title}`);
2388
+ print(await new ErdoClient().restorePage(id));
2300
2389
  } catch (e) {
2301
2390
  fail(e);
2302
2391
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erdoai/cli",
3
- "version": "0.31.0",
4
- "description": "Erdo CLI \u2014 drive datasets, pages, and evals from the terminal or CI",
3
+ "version": "0.33.0",
4
+ "description": "Erdo CLI drive datasets, pages, and evals from the terminal or CI",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "erdo": "dist/index.js"