@erdoai/cli 0.65.0 → 0.67.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/dist/index.js +100 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -396,6 +396,22 @@ var ErdoClient = class {
|
|
|
396
396
|
`/v1/received-emails${qs ? `?${qs}` : ""}`
|
|
397
397
|
);
|
|
398
398
|
}
|
|
399
|
+
// The audited outbound side of email. Listing omits bodies; get reads the
|
|
400
|
+
// exact stored message. The scalar filters use the GET mirror of the same
|
|
401
|
+
// service that backs MCP's erdo_list_emails.
|
|
402
|
+
listSentEmails(params) {
|
|
403
|
+
const q = new URLSearchParams();
|
|
404
|
+
if (params?.to) q.set("to", params.to);
|
|
405
|
+
if (params?.since) q.set("since", params.since);
|
|
406
|
+
if (params?.search) q.set("search", params.search);
|
|
407
|
+
if (params?.limit) q.set("limit", String(params.limit));
|
|
408
|
+
if (params?.offset) q.set("offset", String(params.offset));
|
|
409
|
+
const qs = q.toString();
|
|
410
|
+
return this.request("GET", `/v1/emails${qs ? `?${qs}` : ""}`);
|
|
411
|
+
}
|
|
412
|
+
getSentEmail(emailID) {
|
|
413
|
+
return this.request("GET", `/v1/emails/${encodeURIComponent(emailID)}`);
|
|
414
|
+
}
|
|
399
415
|
// Run a read-only HogQL query against the org's page-analytics events. Rows are
|
|
400
416
|
// positional per columns; enabled:false means page analytics is off for the org
|
|
401
417
|
// (not zero traffic). A rejected query surfaces PostHog's message as the error.
|
|
@@ -448,7 +464,7 @@ var ErdoClient = class {
|
|
|
448
464
|
`/v1/evals/suites/${encodeURIComponent(slug)}/cases/${encodeURIComponent(caseName)}`
|
|
449
465
|
);
|
|
450
466
|
}
|
|
451
|
-
runEvalSuite(slug, concurrency, commitSha, frontendCommitSha, backendCommitSha, source, modelOverride) {
|
|
467
|
+
runEvalSuite(slug, concurrency, commitSha, frontendCommitSha, backendCommitSha, source, modelOverride, rotateCases) {
|
|
452
468
|
return this.request(
|
|
453
469
|
"POST",
|
|
454
470
|
`/v1/evals/suites/${encodeURIComponent(slug)}/run`,
|
|
@@ -458,7 +474,8 @@ var ErdoClient = class {
|
|
|
458
474
|
frontend_commit_sha: frontendCommitSha,
|
|
459
475
|
backend_commit_sha: backendCommitSha,
|
|
460
476
|
source,
|
|
461
|
-
model_override: modelOverride
|
|
477
|
+
model_override: modelOverride,
|
|
478
|
+
rotate_cases: rotateCases
|
|
462
479
|
}
|
|
463
480
|
);
|
|
464
481
|
}
|
|
@@ -514,6 +531,14 @@ var ErdoClient = class {
|
|
|
514
531
|
`/v1/pages/restore/${encodeURIComponent(id)}`
|
|
515
532
|
);
|
|
516
533
|
}
|
|
534
|
+
// Copy a page: the deploy endpoint's clone mode. clone_from_page_id makes
|
|
535
|
+
// POST /v1/pages copy an existing page server-side instead of taking content.
|
|
536
|
+
clonePage(id, input) {
|
|
537
|
+
return this.request("POST", "/v1/pages", {
|
|
538
|
+
clone_from_page_id: id,
|
|
539
|
+
title: input?.title
|
|
540
|
+
});
|
|
541
|
+
}
|
|
517
542
|
// --- workstreams ---
|
|
518
543
|
listWorkstreams(status) {
|
|
519
544
|
const q = new URLSearchParams();
|
|
@@ -2527,7 +2552,13 @@ evalCmd.command("create <name>").description("Create a suite (in the active org)
|
|
|
2527
2552
|
}
|
|
2528
2553
|
}
|
|
2529
2554
|
);
|
|
2530
|
-
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)).option("--commit-sha <sha>", "full 40-character Git commit SHA to associate with the run").option("--frontend-commit-sha <sha>", "frontend revision in the evaluated production snapshot").option("--backend-commit-sha <sha>", "backend revision in the evaluated production snapshot").option("--source <source>", "staff-only run source: post_deploy, nightly, or rollback").option("--model <model>", "pin the suite's agent to a model for this run (e.g. glm-5.3) \u2014 for model comparisons").
|
|
2555
|
+
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)).option("--commit-sha <sha>", "full 40-character Git commit SHA to associate with the run").option("--frontend-commit-sha <sha>", "frontend revision in the evaluated production snapshot").option("--backend-commit-sha <sha>", "backend revision in the evaluated production snapshot").option("--source <source>", "staff-only run source: post_deploy, nightly, or rollback").option("--model <model>", "pin the suite's agent to a model for this run (e.g. glm-5.3) \u2014 for model comparisons").option("--rotate-cases <n>", "run a rotating subset of n cases (deterministic per suite + UTC day) instead of all cases", (v) => {
|
|
2556
|
+
const parsed = parseInt(v, 10);
|
|
2557
|
+
if (isNaN(parsed) || parsed < 0) {
|
|
2558
|
+
throw new Error(`--rotate-cases must be a non-negative integer, got "${v}"`);
|
|
2559
|
+
}
|
|
2560
|
+
return parsed;
|
|
2561
|
+
}).action(async (slug, opts) => {
|
|
2531
2562
|
try {
|
|
2532
2563
|
const api = new ErdoClient();
|
|
2533
2564
|
const { suite } = await api.getEvalSuite(slug);
|
|
@@ -2550,7 +2581,8 @@ evalCmd.command("run <slug>").description("Run a suite; --watch polls until it c
|
|
|
2550
2581
|
opts.frontendCommitSha,
|
|
2551
2582
|
opts.backendCommitSha,
|
|
2552
2583
|
opts.source,
|
|
2553
|
-
opts.model
|
|
2584
|
+
opts.model,
|
|
2585
|
+
opts.rotateCases
|
|
2554
2586
|
);
|
|
2555
2587
|
console.log(`run_id: ${run_id}`);
|
|
2556
2588
|
if (!opts.watch) return;
|
|
@@ -3807,6 +3839,24 @@ pagesCmd.command("restore <id>").description("Restore a previously deleted page
|
|
|
3807
3839
|
fail(e);
|
|
3808
3840
|
}
|
|
3809
3841
|
});
|
|
3842
|
+
pagesCmd.command("clone <id>").description(
|
|
3843
|
+
"Copy a page. The copy is byte-identical and starts private (publish state is never inherited); the source's lead-form pipelines are duplicated onto it and the ids in its content rewritten, so it captures its own leads"
|
|
3844
|
+
).option("--title <title>", 'title for the copy (default: "Copy of <source title>")').option("--json", "print the full JSON, including the cloned pipelines and id rewrites").action(async (id, opts) => {
|
|
3845
|
+
try {
|
|
3846
|
+
const res = await new ErdoClient().clonePage(id, { title: opts.title });
|
|
3847
|
+
if (opts.json) {
|
|
3848
|
+
print(res);
|
|
3849
|
+
return;
|
|
3850
|
+
}
|
|
3851
|
+
console.log(`${res.id} ${res.url}`);
|
|
3852
|
+
for (const p of res.cloned_pipelines || []) {
|
|
3853
|
+
console.error(`cloned pipeline: ${p.source_id} -> ${p.id}${p.slug ? ` (${p.slug})` : ""}`);
|
|
3854
|
+
}
|
|
3855
|
+
for (const note of res.notes || []) console.error(`note: ${note}`);
|
|
3856
|
+
} catch (e) {
|
|
3857
|
+
fail(e);
|
|
3858
|
+
}
|
|
3859
|
+
});
|
|
3810
3860
|
pagesCmd.command("get <id>").description("Show an artifact").action(async (id) => {
|
|
3811
3861
|
try {
|
|
3812
3862
|
print(await new ErdoClient().getArtifact(id));
|
|
@@ -4079,6 +4129,52 @@ emailCmd.command("received").description(
|
|
|
4079
4129
|
fail(e);
|
|
4080
4130
|
}
|
|
4081
4131
|
});
|
|
4132
|
+
var sentEmailsCmd = emailCmd.command("sent").description("Read the audited outbound email log and provider delivery evidence");
|
|
4133
|
+
sentEmailsCmd.command("list").description("List sent email, newest first, including immutable delivered_at evidence").option("--to <email>", "only mail sent to this address").option("--since <timestamp>", "only mail created at or after this RFC 3339 timestamp").option("--search <text>", "case-insensitive subject substring").option("--limit <n>", "page size (default 25, max 200)").option("--offset <n>", "rows to skip").option("--json", "print the raw JSON result instead of a table").action(
|
|
4134
|
+
async (opts) => {
|
|
4135
|
+
try {
|
|
4136
|
+
const res = await new ErdoClient().listSentEmails({
|
|
4137
|
+
to: opts.to,
|
|
4138
|
+
since: opts.since,
|
|
4139
|
+
search: opts.search,
|
|
4140
|
+
limit: opts.limit ? Number(opts.limit) : void 0,
|
|
4141
|
+
offset: opts.offset ? Number(opts.offset) : void 0
|
|
4142
|
+
});
|
|
4143
|
+
if (opts.json) {
|
|
4144
|
+
print(res);
|
|
4145
|
+
return;
|
|
4146
|
+
}
|
|
4147
|
+
const emails = res.emails ?? [];
|
|
4148
|
+
if (emails.length === 0) {
|
|
4149
|
+
console.log("No sent email matches those filters.");
|
|
4150
|
+
return;
|
|
4151
|
+
}
|
|
4152
|
+
printAlignedTable(
|
|
4153
|
+
["id", "to", "subject", "status", "delivered at", "latest event", "sent at"],
|
|
4154
|
+
emails.map((email) => [
|
|
4155
|
+
email.id,
|
|
4156
|
+
email.to,
|
|
4157
|
+
email.subject,
|
|
4158
|
+
email.status_reason ? `${email.status}: ${email.status_reason}` : email.status,
|
|
4159
|
+
email.delivered_at ?? "",
|
|
4160
|
+
email.last_delivery_event_at ?? "",
|
|
4161
|
+
email.sent_at ?? ""
|
|
4162
|
+
])
|
|
4163
|
+
);
|
|
4164
|
+
process.stderr.write(`showing ${emails.length} of ${res.total} matching message(s)
|
|
4165
|
+
`);
|
|
4166
|
+
} catch (e) {
|
|
4167
|
+
fail(e);
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
);
|
|
4171
|
+
sentEmailsCmd.command("get <emailID>").description("Read one sent email, including exact bodies and delivery evidence").action(async (emailID) => {
|
|
4172
|
+
try {
|
|
4173
|
+
print(await new ErdoClient().getSentEmail(emailID));
|
|
4174
|
+
} catch (e) {
|
|
4175
|
+
fail(e);
|
|
4176
|
+
}
|
|
4177
|
+
});
|
|
4082
4178
|
var datasetsCmd = program.command("datasets").description("Datasets");
|
|
4083
4179
|
datasetsCmd.command("list").description("List datasets").option(
|
|
4084
4180
|
"--class <class>",
|