@oxygen-agent/cli 1.128.5 → 1.134.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
@@ -34,4 +34,4 @@ oxygen update
34
34
 
35
35
  For product documentation and support, visit https://oxygen-agent.com.
36
36
 
37
- Version: 1.128.5
37
+ Version: 1.134.0
@@ -1,6 +1,6 @@
1
1
  import { type StoredCredentials } from "./credentials.js";
2
2
  type RequestOptions = {
3
- method?: "GET" | "POST" | "DELETE";
3
+ method?: "GET" | "POST" | "PATCH" | "DELETE";
4
4
  body?: Record<string, unknown>;
5
5
  formData?: FormData;
6
6
  credentials?: StoredCredentials;
package/dist/index.js CHANGED
@@ -808,32 +808,109 @@ export function createProgram() {
808
808
  }));
809
809
  tablesCommand.addCommand(new Command("webhook")
810
810
  .description("Create and manage direct table webhooks.")
811
+ .addCommand(new Command("list")
812
+ .description("List direct table webhooks.")
813
+ .argument("[table]", "Optional table id or slug.")
814
+ .option("--status <status>", "Filter by active or disabled.")
815
+ .option("--limit <n>", "Maximum webhooks to return. Defaults to 100.")
816
+ .option("--json", "Print a JSON envelope.")
817
+ .action((table, options) => handleAsyncAction("tables webhook list", options, () => requestOxygen(tableWebhookListPath({
818
+ table: table ?? options.table,
819
+ status: options.status,
820
+ limit: options.limit,
821
+ })))))
822
+ .addCommand(new Command("get")
823
+ .description("Get one direct table webhook by endpoint id.")
824
+ .argument("<endpoint_id>", "Webhook endpoint id, such as tw_...")
825
+ .option("--json", "Print a JSON envelope.")
826
+ .action((endpointId, options) => handleAsyncAction("tables webhook get", options, () => {
827
+ const params = new URLSearchParams({ endpoint_id: endpointId });
828
+ return requestOxygen(`/api/cli/tables/webhooks?${params.toString()}`);
829
+ })))
811
830
  .addCommand(new Command("create")
812
831
  .description("Create a direct webhook endpoint that writes inbound JSON into a table.")
813
832
  .argument("<table>", "Table id or slug.")
814
833
  .option("--name <name>", "Display name for the webhook.")
815
834
  .option("--mode <mode>", "insert or upsert. Defaults to upsert when --upsert-key is set, otherwise insert.")
835
+ .option("--auth-mode <mode>", "secret or none. Defaults to secret; use none only for public provider webhooks that cannot send auth headers.")
816
836
  .option("--upsert-key <key>", "Column key used to upsert rows. Required for upsert mode.")
817
837
  .option("--items-path <path>", "Dot path to an array of row objects in the webhook payload.")
818
838
  .option("--event-id-path <path>", "Dot path to the event id. Defaults to event_id, eventId, id, or payload hash.")
819
839
  .option("--event-type-path <path>", "Dot path to the event type. Defaults to type or event.")
820
840
  .option("--occurred-at-path <path>", "Dot path to the event timestamp.")
821
- .option("--json", "Print a JSON envelope.")
822
- .action(async (table, options) => {
823
- await handleAsyncAction("tables webhook create", options, async () => requestOxygen("/api/cli/tables/webhooks", {
841
+ .option("--auto-run-columns <csv>", "Comma-separated enrichment, tool, AI, or formula columns to queue for webhook-written rows.")
842
+ .option("--auto-run-max-credits <n>", "Approved credit safety ceiling for webhook-triggered paid auto-runs.")
843
+ .option("--auto-run-max-concurrency <n>", "Maximum concurrent row items for webhook-triggered auto-runs.")
844
+ .option("--auto-run-force", "Run auto-run columns even when the target cell already has a value.")
845
+ .option("--auto-run-connection-id <connection_id>", "Optional provider integration connection id for auto-runs.")
846
+ .option("--auto-run-approved", "Approve this webhook to queue the configured auto-run columns for rows it writes.")
847
+ .option("--json", "Print a JSON envelope.")
848
+ .action((table, options) => {
849
+ const autoRun = readTableWebhookAutoRunOptions(options);
850
+ return handleAsyncAction("tables webhook create", options, () => requestOxygen("/api/cli/tables/webhooks", {
824
851
  method: "POST",
825
852
  body: {
826
853
  table,
827
854
  ...(readOption(options.name) ? { name: readOption(options.name) } : {}),
828
855
  ...(readOption(options.mode) ? { mode: readOption(options.mode) } : {}),
856
+ ...(readOption(options.authMode) ? { auth_mode: readOption(options.authMode) } : {}),
829
857
  ...(readOption(options.upsertKey) ? { upsert_key: readOption(options.upsertKey) } : {}),
830
858
  ...(readOption(options.itemsPath) ? { items_path: readOption(options.itemsPath) } : {}),
831
859
  ...(readOption(options.eventIdPath) ? { event_id_path: readOption(options.eventIdPath) } : {}),
832
860
  ...(readOption(options.eventTypePath) ? { event_type_path: readOption(options.eventTypePath) } : {}),
833
861
  ...(readOption(options.occurredAtPath) ? { occurred_at_path: readOption(options.occurredAtPath) } : {}),
862
+ ...(autoRun ? { auto_run: autoRun } : {}),
834
863
  },
835
864
  }));
836
- })));
865
+ }))
866
+ .addCommand(new Command("update")
867
+ .description("Update a direct table webhook endpoint.")
868
+ .argument("<endpoint_id>", "Webhook endpoint id, such as tw_...")
869
+ .option("--name <name>", "Update the webhook display name.")
870
+ .option("--status <status>", "active or disabled.")
871
+ .option("--auth-mode <mode>", "secret or none. Setting secret rotates and returns a new webhook secret.")
872
+ .option("--auto-run-columns <csv>", "Comma-separated enrichment, tool, AI, or formula columns to queue for webhook-written rows.")
873
+ .option("--auto-run-max-credits <n>", "Approved credit safety ceiling for webhook-triggered paid auto-runs.")
874
+ .option("--auto-run-max-concurrency <n>", "Maximum concurrent row items for webhook-triggered auto-runs.")
875
+ .option("--auto-run-force", "Run auto-run columns even when the target cell already has a value.")
876
+ .option("--auto-run-connection-id <connection_id>", "Optional provider integration connection id for auto-runs.")
877
+ .option("--auto-run-approved", "Approve this webhook to queue the configured auto-run columns for rows it writes.")
878
+ .option("--clear-auto-run", "Remove the webhook auto-run configuration.")
879
+ .option("--json", "Print a JSON envelope.")
880
+ .action((endpointId, options) => {
881
+ const autoRun = readTableWebhookAutoRunOptions(options);
882
+ if (autoRun && options.clearAutoRun) {
883
+ throw new OxygenError("invalid_table_webhook", "Pass either auto-run options or --clear-auto-run, not both.", {
884
+ exitCode: 1,
885
+ });
886
+ }
887
+ return handleAsyncAction("tables webhook update", options, () => requestOxygen("/api/cli/tables/webhooks", {
888
+ method: "PATCH",
889
+ body: {
890
+ endpoint_id: endpointId,
891
+ ...(readOption(options.name) ? { name: readOption(options.name) } : {}),
892
+ ...(readOption(options.status) ? { status: readOption(options.status) } : {}),
893
+ ...(readOption(options.authMode) ? { auth_mode: readOption(options.authMode) } : {}),
894
+ ...(autoRun ? { auto_run: autoRun } : {}),
895
+ ...(options.clearAutoRun ? { clear_auto_run: true } : {}),
896
+ },
897
+ }));
898
+ }))
899
+ .addCommand(new Command("deliveries")
900
+ .description("List direct table webhook deliveries and auto-run enqueue status.")
901
+ .argument("[endpoint_id]", "Optional webhook endpoint id, such as tw_...")
902
+ .option("--table <table>", "Filter by table id or slug.")
903
+ .option("--status <status>", "Filter by received, completed, or failed.")
904
+ .option("--auto-run-status <status>", "Filter by not_configured, queued, skipped, or failed_to_enqueue.")
905
+ .option("--limit <n>", "Maximum deliveries to return. Defaults to 50.")
906
+ .option("--json", "Print a JSON envelope.")
907
+ .action((endpointId, options) => handleAsyncAction("tables webhook deliveries", options, () => requestOxygen(tableWebhookDeliveriesPath({
908
+ endpointId,
909
+ table: options.table,
910
+ status: options.status,
911
+ autoRunStatus: options.autoRunStatus,
912
+ limit: options.limit,
913
+ }))))));
837
914
  program
838
915
  .command("context")
839
916
  .description("Workspace-level GTM context commands.")
@@ -2071,12 +2148,12 @@ export function createProgram() {
2071
2148
  .option("--route-id <id>", "Route id from the plan to execute.")
2072
2149
  .option("--tool-id <tool>", "Tool id from the plan to execute.")
2073
2150
  .option("--table <table>", "Existing table id or slug to receive rows. If omitted for live, Oxygen creates a table.")
2151
+ .option("--upsert-key <column>", "Column key used for live upsert. Must match the plan upsert key, usually domain.")
2074
2152
  .option("--mode <mode>", "dry_run or live. Defaults to dry_run.")
2075
2153
  .option("--max-pages <n>", "Maximum provider pages to ingest. Defaults to the route estimate.")
2076
2154
  .option("--max-credits <n>", "Required credit ceiling for live runs.")
2077
2155
  .option("--target-count <n>", "Desired company count when planning from --prompt.")
2078
2156
  .option("--source-intent <intent>", "Override detected intent when planning from --prompt.")
2079
- .option("--preflight-complete", "Confirm required descriptor, count, enum, or provider-specific preflight checks before live mode.")
2080
2157
  .option("--approved", "Required for live runs after inspecting dry-run output.")
2081
2158
  .option("--json", "Print a JSON envelope.")
2082
2159
  .action(async (options) => {
@@ -2264,7 +2341,7 @@ export function createProgram() {
2264
2341
  .description("Inspect and retry durable signup lead webhook deliveries.")
2265
2342
  .addCommand(new Command("list")
2266
2343
  .description("List signup lead webhook deliveries for the current organization.")
2267
- .option("--status <status>", "Filter by pending, running, succeeded, retrying, failed, or dead.")
2344
+ .option("--status <status>", "Filter by pending, running, succeeded, skipped, retrying, failed, or dead.")
2268
2345
  .option("--limit <n>", "Maximum deliveries to return. Defaults to 50.")
2269
2346
  .option("--json", "Print a JSON envelope.")
2270
2347
  .action(async (options) => {
@@ -3600,6 +3677,66 @@ function normalizeWorkflowRunErrors(value) {
3600
3677
  function isTerminalWorkflowRunStatus(status) {
3601
3678
  return status === "completed" || status === "failed" || status === "canceled";
3602
3679
  }
3680
+ function tableWebhookListPath(options) {
3681
+ const params = new URLSearchParams();
3682
+ const table = readOption(options.table);
3683
+ const status = readOption(options.status);
3684
+ const limit = readPositiveInt(options.limit);
3685
+ if (table)
3686
+ params.set("table", table);
3687
+ if (status)
3688
+ params.set("status", status);
3689
+ if (limit)
3690
+ params.set("limit", String(limit));
3691
+ const query = params.toString();
3692
+ return `/api/cli/tables/webhooks${query ? `?${query}` : ""}`;
3693
+ }
3694
+ function tableWebhookDeliveriesPath(options) {
3695
+ const params = new URLSearchParams();
3696
+ const endpointId = readOption(options.endpointId);
3697
+ const table = readOption(options.table);
3698
+ const status = readOption(options.status);
3699
+ const autoRunStatus = readOption(options.autoRunStatus);
3700
+ const limit = readPositiveInt(options.limit);
3701
+ if (endpointId)
3702
+ params.set("endpoint_id", endpointId);
3703
+ if (table)
3704
+ params.set("table", table);
3705
+ if (status)
3706
+ params.set("status", status);
3707
+ if (autoRunStatus)
3708
+ params.set("auto_run_status", autoRunStatus);
3709
+ if (limit)
3710
+ params.set("limit", String(limit));
3711
+ const query = params.toString();
3712
+ return `/api/cli/tables/webhooks/deliveries${query ? `?${query}` : ""}`;
3713
+ }
3714
+ function readTableWebhookAutoRunOptions(options) {
3715
+ const columns = readCsvOption(options.autoRunColumns);
3716
+ const requested = columns.length > 0
3717
+ || options.autoRunMaxCredits !== undefined
3718
+ || options.autoRunMaxConcurrency !== undefined
3719
+ || Boolean(options.autoRunForce)
3720
+ || options.autoRunConnectionId !== undefined
3721
+ || Boolean(options.autoRunApproved);
3722
+ if (!requested)
3723
+ return null;
3724
+ if (columns.length === 0) {
3725
+ throw new OxygenError("invalid_table_webhook", "Pass --auto-run-columns when configuring webhook auto-runs.", {
3726
+ exitCode: 1,
3727
+ });
3728
+ }
3729
+ const maxCredits = readPositiveNumber(options.autoRunMaxCredits);
3730
+ const maxConcurrency = readPositiveInt(options.autoRunMaxConcurrency);
3731
+ return {
3732
+ columns,
3733
+ approved: Boolean(options.autoRunApproved),
3734
+ ...(maxCredits !== undefined ? { max_credits: maxCredits } : {}),
3735
+ ...(maxConcurrency ? { max_concurrency: maxConcurrency } : {}),
3736
+ ...(options.autoRunForce ? { force: true } : {}),
3737
+ ...(readOption(options.autoRunConnectionId) ? { connection_id: readOption(options.autoRunConnectionId) } : {}),
3738
+ };
3739
+ }
3603
3740
  function readTableRunActions(options) {
3604
3741
  if (options.actionsJson && readOption(options.column)) {
3605
3742
  throw new OxygenError("invalid_table_run", "Pass either --actions-json or --column, not both.", {
@@ -3728,13 +3865,13 @@ function readCompaniesSearchRunBody(options) {
3728
3865
  ...(options.routeId ? { route_id: options.routeId } : {}),
3729
3866
  ...(options.toolId ? { tool_id: options.toolId } : {}),
3730
3867
  ...(options.table ? { table: options.table } : {}),
3868
+ ...(options.upsertKey ? { upsert_key: options.upsertKey } : {}),
3731
3869
  ...(options.mode ? { mode: options.mode } : {}),
3732
3870
  ...(maxPages !== undefined ? { max_pages: maxPages } : {}),
3733
3871
  ...(maxCredits !== undefined ? { max_credits: maxCredits } : {}),
3734
3872
  ...(targetCount !== undefined ? { target_count: targetCount } : {}),
3735
3873
  ...(options.sourceIntent ? { source_intent: options.sourceIntent } : {}),
3736
3874
  ...(options.approved ? { approved: true } : {}),
3737
- ...(options.preflightComplete ? { preflight_complete: true } : {}),
3738
3875
  };
3739
3876
  }
3740
3877
  function readCompanySearchPlanJson(value) {
@@ -14,7 +14,7 @@ export function log(level, msg, fields) {
14
14
  ts: new Date().toISOString(),
15
15
  level,
16
16
  msg,
17
- service_name: process.env.OTEL_SERVICE_NAME ?? process.env.OXYGEN_SERVICE_NAME ?? null,
17
+ service_name: process.env.OXYGEN_SERVICE_NAME ?? process.env.OTEL_SERVICE_NAME ?? null,
18
18
  oxygen_version: OXYGEN_VERSION,
19
19
  sha: process.env.VERCEL_GIT_COMMIT_SHA ?? null,
20
20
  region: process.env.VERCEL_REGION ?? null,
@@ -24,9 +24,12 @@ export function log(level, msg, fields) {
24
24
  ...fields,
25
25
  }),
26
26
  });
27
- if (level === "error" || level === "warn") {
27
+ if (level === "error") {
28
28
  console.error(line);
29
29
  }
30
+ else if (level === "warn") {
31
+ console.warn(line);
32
+ }
30
33
  else {
31
34
  console.log(line);
32
35
  }
@@ -55,14 +55,27 @@ export function recordTelemetryHistogram(name, value, attributes) {
55
55
  histogram.record(value, normalizeTelemetryAttributes(commonTelemetryAttributes(attributes)));
56
56
  }
57
57
  export function commonTelemetryAttributes(attributes) {
58
+ const workerProcess = isWorkerProcess();
58
59
  return {
59
60
  "oxygen.version": OXYGEN_VERSION,
60
- "deployment.environment": process.env.VERCEL_ENV ?? process.env.NODE_ENV ?? null,
61
- "deployment.sha": process.env.VERCEL_GIT_COMMIT_SHA ?? process.env.FLY_IMAGE_REF ?? null,
62
- "cloud.region": process.env.VERCEL_REGION ?? process.env.FLY_REGION ?? null,
61
+ "deployment.environment": workerProcess
62
+ ? process.env.FLY_ENVIRONMENT ?? process.env.NODE_ENV ?? null
63
+ : process.env.VERCEL_ENV ?? process.env.NODE_ENV ?? null,
64
+ "deployment.sha": workerProcess
65
+ ? process.env.FLY_IMAGE_REF ?? process.env.VERCEL_GIT_COMMIT_SHA ?? null
66
+ : process.env.VERCEL_GIT_COMMIT_SHA ?? process.env.FLY_IMAGE_REF ?? null,
67
+ "cloud.region": workerProcess
68
+ ? process.env.FLY_REGION ?? process.env.VERCEL_REGION ?? null
69
+ : process.env.VERCEL_REGION ?? process.env.FLY_REGION ?? null,
63
70
  ...attributes,
64
71
  };
65
72
  }
73
+ function isWorkerProcess() {
74
+ if (process.env.OXYGEN_PROCESS_ROLE === "worker")
75
+ return true;
76
+ const flyApp = process.env.FLY_APP_NAME ?? process.env.FLY_APP ?? "";
77
+ return flyApp.includes("oxygen-table-worker");
78
+ }
66
79
  function getMeter() {
67
80
  return metrics.getMeter("oxygen", OXYGEN_VERSION);
68
81
  }
@@ -1,2 +1,2 @@
1
- export declare const OXYGEN_VERSION = "1.128.5";
1
+ export declare const OXYGEN_VERSION = "1.134.0";
2
2
  export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.0.0";
@@ -1,3 +1,3 @@
1
- export const OXYGEN_VERSION = "1.128.5";
1
+ export const OXYGEN_VERSION = "1.134.0";
2
2
  // Bump this only when deployed CLI/API contracts require a newer CLI.
3
3
  export const OXYGEN_MINIMUM_CLI_VERSION = "1.0.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxygen-agent/cli",
3
- "version": "1.128.5",
3
+ "version": "1.134.0",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",