@oxygen-agent/cli 1.256.13 → 1.263.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
CHANGED
package/dist/index.js
CHANGED
|
@@ -308,6 +308,7 @@ function normalizeDeleteRowIds(values) {
|
|
|
308
308
|
}
|
|
309
309
|
return rowIds;
|
|
310
310
|
}
|
|
311
|
+
const CUSTOM_HTTP_MANIFEST_DOCS_URL = "https://oxygen-agent.com/docs/providers/custom-http";
|
|
311
312
|
function readCustomIntegrationManifest(options) {
|
|
312
313
|
const manifestPath = readOption(options.manifest);
|
|
313
314
|
const manifestJson = readOption(options.manifestJson);
|
|
@@ -321,21 +322,38 @@ function readCustomIntegrationManifest(options) {
|
|
|
321
322
|
exitCode: 1,
|
|
322
323
|
});
|
|
323
324
|
}
|
|
324
|
-
|
|
325
|
+
if (manifestJson)
|
|
326
|
+
return parseJsonObject(manifestJson);
|
|
327
|
+
const filePath = resolve(manifestPath ?? "");
|
|
328
|
+
let content;
|
|
329
|
+
try {
|
|
330
|
+
content = readFileSync(filePath, "utf8");
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
const notFound = error?.code === "ENOENT";
|
|
334
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
335
|
+
throw new OxygenError("invalid_request", notFound
|
|
336
|
+
? `Manifest file not found: ${filePath}. Pass --manifest <path.json> or --manifest-json '<json>'. See ${CUSTOM_HTTP_MANIFEST_DOCS_URL}`
|
|
337
|
+
: `Could not read manifest file ${filePath}: ${reason}. See ${CUSTOM_HTTP_MANIFEST_DOCS_URL}`, { details: { path: filePath }, exitCode: 1 });
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
return parseJsonObject(content);
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
if (error instanceof OxygenError) {
|
|
344
|
+
throw new OxygenError(error.code, `Manifest file ${filePath} is invalid: ${error.message} See ${CUSTOM_HTTP_MANIFEST_DOCS_URL}`, {
|
|
345
|
+
details: { path: filePath, ...(isRecord(error.details) ? error.details : {}) },
|
|
346
|
+
exitCode: error.exitCode,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
throw error;
|
|
350
|
+
}
|
|
325
351
|
}
|
|
326
352
|
const CUSTOM_INTEGRATION_SECRET_KEYS = ["API_KEY", "TOKEN", "PASSWORD", "SECRET"];
|
|
327
353
|
function readCustomIntegrationSecret(options) {
|
|
328
|
-
const apiKey = readOption(options.apiKey);
|
|
329
354
|
const secretsFile = readOption(options.secretsFile);
|
|
330
|
-
if (apiKey && secretsFile) {
|
|
331
|
-
throw new OxygenError("invalid_request", "Pass either --api-key or --secrets-file, not both.", {
|
|
332
|
-
exitCode: 1,
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
if (apiKey)
|
|
336
|
-
return apiKey;
|
|
337
355
|
if (!secretsFile) {
|
|
338
|
-
throw new OxygenError("invalid_request", "Pass --
|
|
356
|
+
throw new OxygenError("invalid_request", "Pass --secrets-file.", {
|
|
339
357
|
exitCode: 1,
|
|
340
358
|
});
|
|
341
359
|
}
|
|
@@ -627,6 +645,7 @@ function buildCrmRelationshipUpsertBody(object, rowId, options) {
|
|
|
627
645
|
...(readOption(options.targetObject) ? { object: readOption(options.targetObject) } : {}),
|
|
628
646
|
row_id: options.targetRowId,
|
|
629
647
|
},
|
|
648
|
+
...(readOption(options.role) ? { role: readOption(options.role) } : {}),
|
|
630
649
|
mode: resolveCrmSetupMode(options),
|
|
631
650
|
};
|
|
632
651
|
}
|
|
@@ -1636,6 +1655,7 @@ export function createProgram() {
|
|
|
1636
1655
|
.requiredOption("--relationship <slug>", "Relationship slug from the source object, such as team or company.")
|
|
1637
1656
|
.option("--target-object <object>", "Target CRM object slug. Optional when the relationship has one target.")
|
|
1638
1657
|
.requiredOption("--target-row-id <row_id>", "Target CRM record row id.")
|
|
1658
|
+
.option("--role <role>", "Buying-committee role for a deals.stakeholders link: champion, economic_buyer, decision_maker, influencer, or end_user.")
|
|
1639
1659
|
.option("--dry-run", "Preview the relationship write without changing edges.")
|
|
1640
1660
|
.option("--live", "Apply the relationship write. Default is dry-run.")
|
|
1641
1661
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -3248,9 +3268,11 @@ export function createProgram() {
|
|
|
3248
3268
|
.requiredOption("--table <table>", "Table id or slug.")
|
|
3249
3269
|
.option("--status <status>", "Filter by active, queued, running, paused, completed, completed_with_errors, failed, canceling, or canceled. Defaults to active.")
|
|
3250
3270
|
.option("--limit <n>", "Maximum runs to return. Defaults to 20.")
|
|
3271
|
+
.option("--format <format>", "Format run history as json, jsonl, csv, or table (same serializer as `tables export`). Omit to keep the default envelope output.")
|
|
3272
|
+
.option("--output <path>", "Write the formatted run history to a file instead of embedding it in the response.")
|
|
3251
3273
|
.option("--json", "Print a JSON envelope.")
|
|
3252
3274
|
.action(async (options) => {
|
|
3253
|
-
await handleAsyncAction("table-runs list", options, () =>
|
|
3275
|
+
await handleAsyncAction("table-runs list", options, () => listTableRuns(options));
|
|
3254
3276
|
}))
|
|
3255
3277
|
.addCommand(new Command("get")
|
|
3256
3278
|
.description("Get one durable table action run.")
|
|
@@ -4459,7 +4481,6 @@ export function createProgram() {
|
|
|
4459
4481
|
.addCommand(new Command("connect")
|
|
4460
4482
|
.description("Attach the credential (bearer token, API key, or basic password) for an applied custom HTTP integration.")
|
|
4461
4483
|
.argument("<slug>", "Custom integration slug from the applied manifest.")
|
|
4462
|
-
.option("--api-key <value>", "Credential value. Prefer --secrets-file to keep it out of shell history.")
|
|
4463
4484
|
.option("--secrets-file <path>", "Path to a .env-style file holding the credential (a single entry, or one named API_KEY/TOKEN/PASSWORD/SECRET).")
|
|
4464
4485
|
.option("--json", "Print a JSON envelope.")
|
|
4465
4486
|
.action(async (slug, options) => {
|
|
@@ -7033,6 +7054,26 @@ export function createProgram() {
|
|
|
7033
7054
|
.option("--json", "Print a JSON envelope.")
|
|
7034
7055
|
.action(async (domain, options) => {
|
|
7035
7056
|
await handleAsyncAction("domains tracking status", options, () => requestOxygen(`/api/cli/domains/${encodeURIComponent(domain)}/tracking`));
|
|
7057
|
+
})))
|
|
7058
|
+
.addCommand(new Command("postmaster")
|
|
7059
|
+
.description("Google Postmaster Tools onboarding for a sending domain: register it with Postmaster, publish the DNS verification TXT via its Cloudflare zone, and check verification status. FREE — 0 Oxygen credits.")
|
|
7060
|
+
.addCommand(new Command("onboard")
|
|
7061
|
+
.description("Register the domain with Google Postmaster Tools and publish the DNS verification TXT automatically via the domain's Cloudflare zone (or return the record for manual DNS); verification then completes automatically in the background. Without --approve, returns a preview. FREE — 0 Oxygen credits.")
|
|
7062
|
+
.argument("<domain>", "Sending domain, such as acme.com.")
|
|
7063
|
+
.option("--approve", "Perform the onboarding. Without this flag, returns a preview only.")
|
|
7064
|
+
.option("--json", "Print a JSON envelope.")
|
|
7065
|
+
.action(async (domain, options) => {
|
|
7066
|
+
await handleAsyncAction("domains postmaster onboard", options, () => requestOxygen(`/api/cli/domains/${encodeURIComponent(domain)}/postmaster`, {
|
|
7067
|
+
method: "POST",
|
|
7068
|
+
body: { ...(options.approve ? { approved: true } : {}) },
|
|
7069
|
+
}));
|
|
7070
|
+
}))
|
|
7071
|
+
.addCommand(new Command("status")
|
|
7072
|
+
.description("Show the Google Postmaster Tools onboarding status for a domain: registration, DNS verification state, and whether reputation data is available. Read-only — 0 Oxygen credits.")
|
|
7073
|
+
.argument("<domain>", "Sending domain, such as acme.com.")
|
|
7074
|
+
.option("--json", "Print a JSON envelope.")
|
|
7075
|
+
.action(async (domain, options) => {
|
|
7076
|
+
await handleAsyncAction("domains postmaster status", options, () => requestOxygen(`/api/cli/domains/${encodeURIComponent(domain)}/postmaster`));
|
|
7036
7077
|
})))
|
|
7037
7078
|
.addCommand(new Command("add")
|
|
7038
7079
|
.description("Onboard a domain registered elsewhere by creating a Cloudflare zone for it, so its DNS can be managed here. Returns the nameservers to set at your registrar. Idempotent.")
|
|
@@ -9503,6 +9544,33 @@ async function exportRows(table, options) {
|
|
|
9503
9544
|
...(formatted.rescuedCount > 0 ? { rescuedNumericCells: formatted.rescuedCount } : {}),
|
|
9504
9545
|
};
|
|
9505
9546
|
}
|
|
9547
|
+
// `table-runs list --format` routes run history through the same serializer
|
|
9548
|
+
// `tables export` uses, so csv/jsonl/table run exports behave exactly like row
|
|
9549
|
+
// exports (header = union of run keys; nested objects like counts are
|
|
9550
|
+
// JSON-stringified by escapeCsvField). Without --format/--output the command
|
|
9551
|
+
// keeps its original envelope response untouched.
|
|
9552
|
+
async function listTableRuns(options) {
|
|
9553
|
+
const rawFormat = readOption(options.format);
|
|
9554
|
+
const outputPath = readOption(options.output);
|
|
9555
|
+
if (!rawFormat && !outputPath)
|
|
9556
|
+
return requestOxygen(tableRunsListPath(options));
|
|
9557
|
+
// Validate the format before spending the API call.
|
|
9558
|
+
const format = normalizeExportRowsFormat(rawFormat ?? undefined);
|
|
9559
|
+
const result = await requestOxygen(tableRunsListPath(options));
|
|
9560
|
+
const runs = Array.isArray(result.runs) ? result.runs.filter(isRecord) : [];
|
|
9561
|
+
const formatted = formatRows(runs, format);
|
|
9562
|
+
if (outputPath)
|
|
9563
|
+
writeFileSync(outputPath, formatted.content);
|
|
9564
|
+
return {
|
|
9565
|
+
table: result.table ?? null,
|
|
9566
|
+
status: result.status ?? null,
|
|
9567
|
+
format,
|
|
9568
|
+
runCount: runs.length,
|
|
9569
|
+
output: outputPath ?? null,
|
|
9570
|
+
...(outputPath ? {} : { content: formatted.content }),
|
|
9571
|
+
...(typeof result.web_url === "string" ? { web_url: result.web_url } : {}),
|
|
9572
|
+
};
|
|
9573
|
+
}
|
|
9506
9574
|
const TABLE_BUNDLE_SCHEMA_VERSION = 1;
|
|
9507
9575
|
const TABLE_BUNDLE_MAX_PAGE_SIZE = 1000;
|
|
9508
9576
|
const TABLE_BUNDLE_DEFAULT_PAGE_SIZE = 500;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const OXYGEN_VERSION = "1.
|
|
1
|
+
export declare const OXYGEN_VERSION = "1.263.0";
|
|
2
2
|
export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.181.0";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const OXYGEN_VERSION = "1.
|
|
1
|
+
export const OXYGEN_VERSION = "1.263.0";
|
|
2
2
|
// Bump this only when deployed CLI/API contracts require a newer CLI.
|
|
3
3
|
// 1.181.0: paid table action runs and background columns run require
|
|
4
4
|
// approved=true in addition to max_credits; older CLIs cannot send the flag.
|