@erdoai/cli 0.54.0 → 0.55.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.
- package/README.md +15 -0
- package/dist/index.js +73 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -87,6 +87,21 @@ erdo --org 2200-brickell datasets query 2200-brickell.page-events \
|
|
|
87
87
|
"which pages get the most views, and how many convert?"
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
**A file dataset keeps the versions it overwrote.** Its contents are stored, and
|
|
91
|
+
each write that replaces them keeps the version it replaced, so an import that
|
|
92
|
+
landed bad rows over good ones has not destroyed them. List the versions, then
|
|
93
|
+
read one back with `fetch` — the same SQL you would run against the live table.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
erdo datasets revisions acme.leads # live version first, then superseded
|
|
97
|
+
erdo datasets fetch acme.leads --revision <id> \
|
|
98
|
+
--sql "SELECT * FROM data" # query those older contents
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The history is read-only: nothing here rolls a dataset back. Restoring means
|
|
102
|
+
fetching the rows out of the old revision and writing them in again through the
|
|
103
|
+
normal write path.
|
|
104
|
+
|
|
90
105
|
```bash
|
|
91
106
|
erdo datasets list # slug, type, status, class, name
|
|
92
107
|
erdo datasets upload ./leads.csv # create a dataset from a file
|
package/dist/index.js
CHANGED
|
@@ -713,6 +713,9 @@ var ErdoClient = class {
|
|
|
713
713
|
// named saved filters. filter_names are additive on top of the dataset's default
|
|
714
714
|
// filters — they narrow the result, never bypass a default. An unknown name is
|
|
715
715
|
// rejected server-side with the available names.
|
|
716
|
+
//
|
|
717
|
+
// revision_id runs the same read against a superseded storage revision instead
|
|
718
|
+
// of the dataset's live contents — the ids come from listDatasetRevisions.
|
|
716
719
|
fetchDatasetContents(slug, opts) {
|
|
717
720
|
return this.request(
|
|
718
721
|
"POST",
|
|
@@ -720,10 +723,21 @@ var ErdoClient = class {
|
|
|
720
723
|
{
|
|
721
724
|
sql_query: opts.sql_query,
|
|
722
725
|
limit: opts.limit,
|
|
723
|
-
filter_names: opts.filter_names
|
|
726
|
+
filter_names: opts.filter_names,
|
|
727
|
+
revision_id: opts.revision_id
|
|
724
728
|
}
|
|
725
729
|
);
|
|
726
730
|
}
|
|
731
|
+
// A file dataset's storage is versioned: every write that replaces its contents
|
|
732
|
+
// keeps the version it replaced, and this lists them — the live (primary) one
|
|
733
|
+
// first, then superseded ones newest first. superseded_at is the moment a newer
|
|
734
|
+
// version took over, and is null both on the live revision and on a stored file
|
|
735
|
+
// that was never live (an upload merged into an existing table); file_type may be
|
|
736
|
+
// absent when the stored file's type was never recorded. Read one back by passing
|
|
737
|
+
// its id as revision_id to fetchDatasetContents.
|
|
738
|
+
listDatasetRevisions(slug) {
|
|
739
|
+
return this.request("GET", `/v1/datasets/${encodeURIComponent(slug)}/revisions`);
|
|
740
|
+
}
|
|
727
741
|
uploadDatasetFile(body) {
|
|
728
742
|
return this.request("POST", "/v1/datasets-upload", body);
|
|
729
743
|
}
|
|
@@ -2471,6 +2485,12 @@ agentCmd.command("threads").description("List your threads").action(async () =>
|
|
|
2471
2485
|
fail(e);
|
|
2472
2486
|
}
|
|
2473
2487
|
});
|
|
2488
|
+
function contentBlockLabel(c) {
|
|
2489
|
+
const type = c.ui_content_type || c.content_type;
|
|
2490
|
+
const payload = c.content;
|
|
2491
|
+
const toolName = payload && typeof payload === "object" && !Array.isArray(payload) && typeof payload.name === "string" ? payload.name : void 0;
|
|
2492
|
+
return toolName ? `${type}: ${toolName}` : type;
|
|
2493
|
+
}
|
|
2474
2494
|
agentCmd.command("messages <threadId>").description("Show a thread's messages (role + text)").option("-v, --verbose", "print full content for non-text entries (tool calls, results, etc.) instead of a placeholder").action(async (threadId, opts) => {
|
|
2475
2495
|
try {
|
|
2476
2496
|
const { messages } = await new ErdoClient().getThreadMessages(threadId);
|
|
@@ -2485,10 +2505,10 @@ agentCmd.command("messages <threadId>").description("Show a thread's messages (r
|
|
|
2485
2505
|
if (c.content_type === "text") {
|
|
2486
2506
|
console.log(c.content);
|
|
2487
2507
|
} else if (opts.verbose) {
|
|
2488
|
-
console.log(`\x1B[2m[${c
|
|
2508
|
+
console.log(`\x1B[2m[${contentBlockLabel(c)}]\x1B[0m`);
|
|
2489
2509
|
console.log(typeof c.content === "string" ? c.content : JSON.stringify(c.content, null, 2));
|
|
2490
2510
|
} else {
|
|
2491
|
-
console.log(`\x1B[2m[${c
|
|
2511
|
+
console.log(`\x1B[2m[${contentBlockLabel(c)}]\x1B[0m`);
|
|
2492
2512
|
}
|
|
2493
2513
|
}
|
|
2494
2514
|
}
|
|
@@ -3458,14 +3478,57 @@ datasetsCmd.command("fetch <slug>").description(
|
|
|
3458
3478
|
"opt into a saved filter by name (repeatable); additive on top of the dataset's default filters (see: erdo datasets filter list <slug>)",
|
|
3459
3479
|
(v, acc) => acc.concat(v),
|
|
3460
3480
|
[]
|
|
3461
|
-
).
|
|
3481
|
+
).option(
|
|
3482
|
+
"--revision <id>",
|
|
3483
|
+
"read a superseded storage revision instead of the live table \u2014 the same SQL runs against the contents this id names, so a version that was overwritten is still queryable (see: erdo datasets revisions <slug> for the ids)"
|
|
3484
|
+
).action(
|
|
3485
|
+
async (slug, opts) => {
|
|
3486
|
+
try {
|
|
3487
|
+
print(
|
|
3488
|
+
await new ErdoClient().fetchDatasetContents(slug, {
|
|
3489
|
+
sql_query: opts.sql,
|
|
3490
|
+
limit: opts.limit,
|
|
3491
|
+
filter_names: opts.filter.length ? opts.filter : void 0,
|
|
3492
|
+
revision_id: opts.revision
|
|
3493
|
+
})
|
|
3494
|
+
);
|
|
3495
|
+
} catch (e) {
|
|
3496
|
+
fail(e);
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
);
|
|
3500
|
+
datasetsCmd.command("revisions <slug>").description(
|
|
3501
|
+
"List the stored versions of a file dataset's contents. Every write that replaces a file dataset keeps the version it replaced, so an import that overwrote good rows with bad ones has not lost them: this lists the live version first and the superseded ones newest first, and each row's id is what `datasets fetch <slug> --revision <id>` reads \u2014 the same SQL, run against those older contents. History is read-only and nothing here rolls a dataset back; restoring means fetching the rows out of the old revision and writing them in again through the normal write path."
|
|
3502
|
+
).option("--json", "print the raw JSON result instead of a table").action(async (slug, opts) => {
|
|
3462
3503
|
try {
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3504
|
+
const res = await new ErdoClient().listDatasetRevisions(slug);
|
|
3505
|
+
if (opts.json) {
|
|
3506
|
+
print(res);
|
|
3507
|
+
return;
|
|
3508
|
+
}
|
|
3509
|
+
const revisions = res.revisions ?? [];
|
|
3510
|
+
if (revisions.length === 0) {
|
|
3511
|
+
console.log(
|
|
3512
|
+
`${res.dataset_slug} has no stored revisions \u2014 versions are kept for file datasets, whose contents Erdo stores and replaces on each write. A database or warehouse dataset is queried live at its source and keeps no history here.`
|
|
3513
|
+
);
|
|
3514
|
+
return;
|
|
3515
|
+
}
|
|
3516
|
+
printAlignedTable(
|
|
3517
|
+
["id", "created", "superseded", "live", "name", "type"],
|
|
3518
|
+
revisions.map((r) => [
|
|
3519
|
+
r.id,
|
|
3520
|
+
r.created_at,
|
|
3521
|
+
r.superseded_at ?? "",
|
|
3522
|
+
r.is_primary ? "yes" : "",
|
|
3523
|
+
r.display_name,
|
|
3524
|
+
// file_type is the specific answer (csv, xlsx) and item_type the general
|
|
3525
|
+
// one; the more specific wins when it was recorded.
|
|
3526
|
+
r.file_type || r.item_type
|
|
3527
|
+
])
|
|
3528
|
+
);
|
|
3529
|
+
console.log(
|
|
3530
|
+
`
|
|
3531
|
+
Read one with: erdo datasets fetch ${res.dataset_slug} --revision <id> --sql "SELECT * FROM data"`
|
|
3469
3532
|
);
|
|
3470
3533
|
} catch (e) {
|
|
3471
3534
|
fail(e);
|