@erdoai/cli 0.117.1 → 0.118.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 +78 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1149,6 +1149,13 @@ var ErdoClient = class {
1149
1149
  const qs = q.toString();
1150
1150
  return this.request("GET", `/v1/datasets-purposes${qs ? `?${qs}` : ""}`);
1151
1151
  }
1152
+ // Reads the declared write contract through the slug-addressed fetch route's
1153
+ // declared_schema view. That route is the one a dataset-scoped API key can
1154
+ // reach (and is confined to its own datasets there); the dataset-details
1155
+ // route is not, because its response also names other datasets.
1156
+ getDatasetDeclaredSchema(slug) {
1157
+ return this.request("POST", `/v1/datasets/${encodeURIComponent(slug)}/fetch`, { view: "declared_schema" });
1158
+ }
1152
1159
  // Create an empty dataset with its declared columns. The server refuses a
1153
1160
  // create without a schema unless the purpose's columns are platform-defined.
1154
1161
  createDataset(input) {
@@ -1583,6 +1590,15 @@ var ErdoClient = class {
1583
1590
  );
1584
1591
  }
1585
1592
  // --- knowledge ---
1593
+ getKnowledge(id) {
1594
+ return this.request("GET", `/v1/knowledge/${encodeURIComponent(id)}`);
1595
+ }
1596
+ updateKnowledge(id, input) {
1597
+ return this.request("POST", `/v1/knowledge/${encodeURIComponent(id)}/actions`, {
1598
+ action: "update",
1599
+ ...input
1600
+ });
1601
+ }
1586
1602
  listKnowledge(visibility, options) {
1587
1603
  const params = new URLSearchParams();
1588
1604
  if (visibility) params.set("visibility", visibility);
@@ -1719,6 +1735,7 @@ var ErdoClient = class {
1719
1735
  // what the evidence said afterwards. Referenced by slug, never UUID.
1720
1736
  listDecisions(opts) {
1721
1737
  const params = new URLSearchParams();
1738
+ if (opts.organization_slug) params.set("organization_slug", opts.organization_slug);
1722
1739
  if (opts.workstream_slug) params.set("workstream_slug", opts.workstream_slug);
1723
1740
  if (opts.source) params.set("source", opts.source);
1724
1741
  if (opts.decision_class) params.set("decision_class", opts.decision_class);
@@ -4254,7 +4271,7 @@ function renderReportEffect(e) {
4254
4271
  console.log(` outcome: ${e.outcome_label}`);
4255
4272
  }
4256
4273
  }
4257
- decisionsCmd.command("list").description("List decisions, newest first").option("--workstream <slug>", "only decisions filed under this workstream/Strategy").option(
4274
+ decisionsCmd.command("list").description("List decisions, newest first").option("--organization <slug>", "read an authorized client organization (default: active organization)").option("--workstream <slug>", "only decisions filed under this workstream/Strategy").option(
4258
4275
  "--source <source>",
4259
4276
  "producer family: approval | escalation | engine_gate | allocator | experiment | workstream_commitment"
4260
4277
  ).option("--class <class>", "decision class, e.g. paid_media.ad_group.pause").option("--subject-kind <kind>", "only decisions about this kind of subject").option("--subject-ref <id>", "only decisions about this exact subject").option(
@@ -4267,6 +4284,7 @@ decisionsCmd.command("list").description("List decisions, newest first").option(
4267
4284
  async (opts) => {
4268
4285
  try {
4269
4286
  const res = await new ErdoClient().listDecisions({
4287
+ organization_slug: opts.organization,
4270
4288
  workstream_slug: opts.workstream,
4271
4289
  source: opts.source,
4272
4290
  decision_class: opts.class,
@@ -6747,10 +6765,36 @@ Read one with: erdo datasets fetch ${res.dataset_slug} --revision <id> --sql "SE
6747
6765
  }
6748
6766
  });
6749
6767
  datasetsCmd.command("schema <slug>").alias("describe").description(
6750
- "Show a dataset's physical columns \u2014 the names and types you can reference in `datasets fetch --sql`, read from the stored `data` table itself (DuckDB DESCRIBE) so they are what is actually there, not what was declared. For a database or warehouse dataset, DESCRIBE its real table names instead: `datasets fetch <slug> --sql 'DESCRIBE <table>'`."
6751
- ).option("--json", "print the raw JSON result instead of a table").action(async (slug, opts) => {
6768
+ "Show physical columns by default, or the declared write contract with --declared. Physical columns are the names and types you can reference in `datasets fetch --sql`, read from the stored `data` table itself (DuckDB DESCRIBE) so they are what is actually there, not what was declared. For a database or warehouse dataset, DESCRIBE its real table names instead: `datasets fetch <slug> --sql 'DESCRIBE <table>'`."
6769
+ ).option("--json", "print the raw JSON result instead of a table").option("--declared", "read the declared write contract (column names, type hints, required flags, semantic roles) instead of the physical columns").action(async (slug, opts) => {
6752
6770
  try {
6753
- const res = await new ErdoClient().fetchDatasetContents(slug, { sql_query: "DESCRIBE data" });
6771
+ const client = new ErdoClient();
6772
+ if (opts.declared) {
6773
+ const res2 = await client.getDatasetDeclaredSchema(slug);
6774
+ if (!res2 || typeof res2 !== "object" || res2.view !== "declared_schema")
6775
+ throw new Error("Invalid dataset schema response: the server did not answer the declared_schema view");
6776
+ const schema = res2.declared_schema;
6777
+ if (schema != null && (!Array.isArray(schema.columns) || schema.columns.some((column) => !column || typeof column.name !== "string" || !column.name.trim())))
6778
+ throw new Error("Invalid dataset schema response: declared columns are malformed");
6779
+ if (opts.json) {
6780
+ print(res2);
6781
+ return;
6782
+ }
6783
+ if (schema == null) {
6784
+ console.log(`${slug} has no declared column contract. Use datasets schema ${slug} to inspect physical columns.`);
6785
+ return;
6786
+ }
6787
+ if (!schema.columns.length) {
6788
+ console.log(`${slug}'s declared column contract contains no columns.`);
6789
+ return;
6790
+ }
6791
+ printAlignedTable(
6792
+ ["column", "type", "required", "semantic role", "description"],
6793
+ schema.columns.map((column) => [column.name, column.type || "", column.required ? "yes" : "no", column.semantic_role || "", column.description || ""])
6794
+ );
6795
+ return;
6796
+ }
6797
+ const res = await client.fetchDatasetContents(slug, { sql_query: "DESCRIBE data" });
6754
6798
  if (opts.json) {
6755
6799
  print(res);
6756
6800
  return;
@@ -8142,6 +8186,36 @@ pipelinesCmd.command("executions <slug>").description("Show an event pipeline's
8142
8186
  }
8143
8187
  });
8144
8188
  var knowledgeCmd = program.command("knowledge").description("Knowledge objects");
8189
+ knowledgeCmd.command("get <id>").description("Get one full typed Knowledge object, including links and related objects").action(async (id) => {
8190
+ try {
8191
+ print(await new ErdoClient().getKnowledge(id));
8192
+ } catch (e) {
8193
+ fail(e);
8194
+ }
8195
+ });
8196
+ knowledgeCmd.command("update <id>").description("Update a Knowledge object while preserving fields omitted from the command").option("--body <value>", "new body text, or @file; pass an empty value to clear the body").option("--config <file>", "JSON object file containing the complete replacement config, or @file").option("--title <title>", "new title").action(async (id, opts) => {
8197
+ try {
8198
+ if (opts.title === void 0 && opts.body === void 0 && opts.config === void 0) {
8199
+ throw new Error("provide at least one of --title, --body, or --config");
8200
+ }
8201
+ if (opts.title !== void 0 && !opts.title.trim()) {
8202
+ throw new Error("title must not be empty");
8203
+ }
8204
+ const replacementConfig = opts.config === void 0 ? void 0 : readJSONObject(opts.config.startsWith("@") ? opts.config.slice(1) : opts.config, "--config");
8205
+ const replacementBody = opts.body === void 0 ? void 0 : readMaybeFile(opts.body) ?? "";
8206
+ const client = new ErdoClient();
8207
+ const current = await client.getKnowledge(id);
8208
+ const object = current.object;
8209
+ print(await client.updateKnowledge(id, {
8210
+ title: opts.title ?? object.title,
8211
+ body_markdown: replacementBody ?? object.body_markdown,
8212
+ config_json: replacementConfig ?? object.config_json,
8213
+ expected_updated_at: object.updated_at
8214
+ }));
8215
+ } catch (e) {
8216
+ fail(e);
8217
+ }
8218
+ });
8145
8219
  knowledgeCmd.command("list").description("List knowledge objects").option(
8146
8220
  "--public",
8147
8221
  "only entries opted into anonymous external surfaces (website widgets)"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erdoai/cli",
3
- "version": "0.117.1",
3
+ "version": "0.118.0",
4
4
  "description": "Erdo CLI — drive datasets, pages, and evals from the terminal or CI",
5
5
  "type": "module",
6
6
  "bin": {