@oxygen-agent/cli 1.1011.493 → 1.1011.607
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 +1 -1
- package/dist/command-manifest.js +7 -0
- package/dist/crm-file-read-commands.d.ts +6 -0
- package/dist/crm-file-read-commands.js +16 -0
- package/dist/feed-read-flags.d.ts +3 -0
- package/dist/feed-read-flags.js +9 -0
- package/dist/functions-commands.js +2 -1
- package/dist/help.js +18 -5
- package/dist/index.js +168 -107
- package/dist/sender-limits-flags.js +6 -4
- package/dist/settings-commands.js +11 -11
- package/dist/whatsapp-account-flags.d.ts +4 -0
- package/dist/whatsapp-account-flags.js +18 -0
- package/node_modules/@oxygen/cli-ugc/dist/commands.js +2 -2
- package/node_modules/@oxygen/shared/dist/billing.d.ts +41 -0
- package/node_modules/@oxygen/shared/dist/billing.js +56 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +21 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +254 -21
- package/node_modules/@oxygen/shared/dist/contracts/billing-owner-read.d.ts +6 -0
- package/node_modules/@oxygen/shared/dist/contracts/billing-owner-read.js +7 -0
- package/node_modules/@oxygen/shared/dist/contracts/browser-operations.js +4 -2
- package/node_modules/@oxygen/shared/dist/contracts/copilot-sessions.d.ts +11 -0
- package/node_modules/@oxygen/shared/dist/contracts/copilot-sessions.js +7 -0
- package/node_modules/@oxygen/shared/dist/contracts/crm-file-bytes.d.ts +33 -0
- package/node_modules/@oxygen/shared/dist/contracts/crm-file-bytes.js +12 -0
- package/node_modules/@oxygen/shared/dist/contracts/customer-operations.js +6 -3
- package/node_modules/@oxygen/shared/dist/contracts/function-library-read.d.ts +14 -0
- package/node_modules/@oxygen/shared/dist/contracts/function-library-read.js +16 -0
- package/node_modules/@oxygen/shared/dist/contracts/inbox-drafts-read.d.ts +45 -0
- package/node_modules/@oxygen/shared/dist/contracts/inbox-drafts-read.js +21 -0
- package/node_modules/@oxygen/shared/dist/contracts/limits-read.d.ts +29 -0
- package/node_modules/@oxygen/shared/dist/contracts/limits-read.js +121 -0
- package/node_modules/@oxygen/shared/dist/contracts/linkedin-invites-list.js +1 -1
- package/node_modules/@oxygen/shared/dist/contracts/pipedrive-catalog.d.ts +18 -0
- package/node_modules/@oxygen/shared/dist/contracts/pipedrive-catalog.js +29 -0
- package/node_modules/@oxygen/shared/dist/contracts/publishing-reads.d.ts +181 -0
- package/node_modules/@oxygen/shared/dist/contracts/publishing-reads.js +62 -0
- package/node_modules/@oxygen/shared/dist/contracts/sender-limits.js +7 -5
- package/node_modules/@oxygen/shared/dist/contracts/sequence-list.d.ts +3 -0
- package/node_modules/@oxygen/shared/dist/contracts/sequence-list.js +8 -0
- package/node_modules/@oxygen/shared/dist/contracts/stored-read-window.d.ts +17 -0
- package/node_modules/@oxygen/shared/dist/contracts/stored-read-window.js +8 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-feed-read.d.ts +67 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-feed-read.js +19 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-row-read.d.ts +30 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-row-read.js +9 -0
- package/node_modules/@oxygen/shared/dist/contracts/whatsapp-reads.d.ts +111 -0
- package/node_modules/@oxygen/shared/dist/contracts/whatsapp-reads.js +33 -0
- package/node_modules/@oxygen/shared/dist/contracts/workspace-pages.d.ts +6 -5
- package/node_modules/@oxygen/shared/dist/contracts/workspace-pages.js +5 -5
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.d.ts +4 -1
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.generated.d.ts +17 -0
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.generated.js +26 -0
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.js +2 -32
- package/node_modules/@oxygen/shared/dist/feature-gates.d.ts +5 -0
- package/node_modules/@oxygen/shared/dist/feature-gates.js +6 -0
- package/node_modules/@oxygen/shared/dist/first-month-offer-window.d.ts +34 -0
- package/node_modules/@oxygen/shared/dist/first-month-offer-window.js +41 -0
- package/node_modules/@oxygen/shared/dist/first-month-offer.d.ts +42 -0
- package/node_modules/@oxygen/shared/dist/first-month-offer.js +56 -0
- package/node_modules/@oxygen/shared/dist/linkedin-sequences.d.ts +32 -1
- package/node_modules/@oxygen/shared/dist/linkedin-sequences.js +68 -4
- package/node_modules/@oxygen/shared/dist/otlp-log-sink.d.ts +6 -2
- package/node_modules/@oxygen/shared/dist/otlp-log-sink.js +6 -1
- package/node_modules/@oxygen/shared/dist/sql-error.js +13 -2
- package/node_modules/@oxygen/shared/dist/stripe-price-catalog.d.ts +3 -0
- package/node_modules/@oxygen/shared/dist/stripe-price-catalog.js +17 -1
- package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
- package/node_modules/@oxygen/shared/dist/workspace-file-storage.d.ts +11 -1
- package/node_modules/@oxygen/shared/dist/workspace-file-storage.js +29 -3
- package/package.json +1 -1
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
// MCP tool and the route use too. This overlay only keeps the flag names and
|
|
4
4
|
// help text the command shipped with before the contract existed.
|
|
5
5
|
import { OxygenError } from "@oxygen/shared/cli-result";
|
|
6
|
-
import { LINKEDIN_SENDER_LIMIT_DEFAULTS, LINKEDIN_SENDER_LIMIT_MAXIMUMS, } from "@oxygen/shared/linkedin-sequences";
|
|
6
|
+
import { LINKEDIN_SENDER_LIMIT_DEFAULTS, LINKEDIN_SENDER_LIMIT_MAXIMUMS, linkedInSenderLimitCautionLevel, } from "@oxygen/shared/linkedin-sequences";
|
|
7
7
|
import { SENDER_LIMITS_PATCH_CONTRACT } from "@oxygen/shared/contracts/sender-limits";
|
|
8
8
|
import { readContractFlags } from "./contract-flags.js";
|
|
9
9
|
/** "<text> (default N, max M)." for a LinkedIn sender limit flag, from the enforced constants. */
|
|
10
10
|
function linkedInLimitHelp(key, text) {
|
|
11
|
-
|
|
11
|
+
const caution = linkedInSenderLimitCautionLevel(key);
|
|
12
|
+
const risk = caution === undefined ? "" : ` Above ${caution} raises the risk of a LinkedIn restriction.`;
|
|
13
|
+
return `${text} (default ${LINKEDIN_SENDER_LIMIT_DEFAULTS[key]}, max ${LINKEDIN_SENDER_LIMIT_MAXIMUMS[key]}).${risk}`;
|
|
12
14
|
}
|
|
13
15
|
const LIMIT_FLAG_HELP = {
|
|
14
16
|
invites_per_day: "Daily LinkedIn connection invites cap",
|
|
@@ -31,8 +33,8 @@ const LIMIT_FLAG_HELP = {
|
|
|
31
33
|
sales_nav_search_results_per_day: "Daily cap on Sales Navigator search result rows fetched",
|
|
32
34
|
api_reads_per_day: "Daily cap on all other LinkedIn API reads",
|
|
33
35
|
total_reads_per_day: "Daily cap across all read units",
|
|
34
|
-
min_action_spacing_seconds: "Minimum seconds between actions",
|
|
35
|
-
action_spacing_jitter_seconds: "Random jitter seconds added to action spacing",
|
|
36
|
+
min_action_spacing_seconds: "Minimum seconds between automated actions. Campaigns also spread each day's limit across the working hours (20 invites in 07:00-22:00 go out 30-45 minutes apart), so this is a floor",
|
|
37
|
+
action_spacing_jitter_seconds: "Random jitter seconds added to action spacing; a spread campaign gap adds up to half of itself",
|
|
36
38
|
interactive_min_spacing_seconds: "Minimum seconds between human-sent Unibox actions",
|
|
37
39
|
interactive_spacing_jitter_seconds: "Random jitter seconds added to human-sent Unibox action spacing",
|
|
38
40
|
interactive_sends_per_hour: "Hourly cap on human-sent Unibox actions",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// `oxygen settings`:
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// `oxygen settings`: your own settings in a workspace. Its family today is
|
|
2
|
+
// `settings pages`, the web app's sidebar pages you hide for yourself there
|
|
3
|
+
// (Settings → Customise; per user since 2026-10-02). The set command's flags come from
|
|
4
4
|
// the shared contract that also generates `oxygen_settings_pages_update` and
|
|
5
5
|
// validates the route, so the CLI and MCP cannot disagree about what can be set.
|
|
6
6
|
import { Command } from "commander";
|
|
@@ -12,7 +12,7 @@ const list = WORKSPACE_PAGES_GET_OPERATION;
|
|
|
12
12
|
const update = WORKSPACE_PAGES_UPDATE_OPERATION;
|
|
13
13
|
export const WORKSPACE_PAGES_FLAG_OVERLAY = {
|
|
14
14
|
hide: {
|
|
15
|
-
help: "Pages to hide from
|
|
15
|
+
help: "Pages to hide from your own sidebar, comma-separated, each by its path (/unibox) or name (Unibox) from `settings pages list`. Hiding a section hides its sub-pages.",
|
|
16
16
|
valueName: "<pages>",
|
|
17
17
|
},
|
|
18
18
|
show: {
|
|
@@ -32,20 +32,20 @@ function names(value) {
|
|
|
32
32
|
export function buildWorkspacePagesBody(options) {
|
|
33
33
|
const body = readContractFlags(options, update.contract, WORKSPACE_PAGES_FLAG_OVERLAY);
|
|
34
34
|
if (!names(body.hide) && !names(body.show) && body.show_all !== true) {
|
|
35
|
-
throw new OxygenError("invalid_request", "Nothing to change: pass --hide <pages> to hide pages
|
|
35
|
+
throw new OxygenError("invalid_request", "Nothing to change: pass --hide <pages> to hide pages from your sidebar, --show <pages> to show hidden ones again, or --show-all. `settings pages list` names every page.", { exitCode: 1 });
|
|
36
36
|
}
|
|
37
37
|
return body;
|
|
38
38
|
}
|
|
39
39
|
export function registerSettingsCommands(program, handle) {
|
|
40
40
|
const settings = program
|
|
41
41
|
.command("settings")
|
|
42
|
-
.description("
|
|
43
|
-
+ "`settings pages` is Settings → Customise in the web app: hide or show pages in
|
|
44
|
-
+ "`settings pages list` shows each page and whether
|
|
45
|
-
+ "
|
|
42
|
+
.description("Settings in this workspace, each with its own scope. "
|
|
43
|
+
+ "`settings pages` is Settings → Customise in the web app and yours alone: hide or show pages in your own sidebar navigation (the left menu); teammates keep theirs. "
|
|
44
|
+
+ "`settings pages list` shows each page and whether you hid it; change it with `settings pages set --hide <pages>`, `--show <pages>` or `--show-all`. Nothing is deleted: a hidden page stays reachable by URL. "
|
|
45
|
+
+ "`settings beta-features` is workspace-wide: early-access features for everyone, changed by admins and owners. Free.");
|
|
46
46
|
const pages = new Command("pages")
|
|
47
|
-
.description("The web app's sidebar pages
|
|
48
|
-
+ "`list` shows every page with its section and whether it is hidden or visible; `set` hides or shows pages
|
|
47
|
+
.description("The web app's sidebar pages you hide for yourself in this workspace (Settings → Customise): page visibility in your navigation menu; teammates keep their own. "
|
|
48
|
+
+ "`list` shows every page with its section and whether it is hidden or visible; `set` hides or shows pages. "
|
|
49
49
|
+ "Hiding a section hides its sub-pages. Presentation only: nothing is deleted, and a hidden page stays reachable by URL and deep-link. Every response carries its `web_url`.");
|
|
50
50
|
pages.addCommand(new Command(list.cli.path.at(-1) ?? "list")
|
|
51
51
|
.description(list.cli.summary)
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ContractFlagOverlay } from "./contract-flags.js";
|
|
2
|
+
/** Preserve the shipped status/tag coercion and --no-usage spelling. */
|
|
3
|
+
export declare const WHATSAPP_ACCOUNT_FLAGS: ContractFlagOverlay;
|
|
4
|
+
export declare function whatsappAccountQuery(options: Record<string, unknown>): URLSearchParams;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { WHATSAPP_ACCOUNTS_READ_CONTRACT, whatsappReadQueryParams } from "@oxygen/shared/contracts/whatsapp-reads";
|
|
2
|
+
import { readContractFlags } from "./contract-flags.js";
|
|
3
|
+
/** Preserve the shipped status/tag coercion and --no-usage spelling. */
|
|
4
|
+
export const WHATSAPP_ACCOUNT_FLAGS = {
|
|
5
|
+
status: { valueName: "<status>", parse: raw => raw.trim() },
|
|
6
|
+
include_usage: { flag: "usage", negateHelp: "Skip today's per-account usage counts." },
|
|
7
|
+
tag: { valueName: "<tags>", parse: raw => raw.split(",").map(value => value.trim()).filter(Boolean).join(",") },
|
|
8
|
+
limit: { valueName: "<n>" }, offset: { valueName: "<n>" }, max_chars: { valueName: "<n>" },
|
|
9
|
+
};
|
|
10
|
+
export function whatsappAccountQuery(options) {
|
|
11
|
+
const input = readContractFlags(options, WHATSAPP_ACCOUNTS_READ_CONTRACT, WHATSAPP_ACCOUNT_FLAGS);
|
|
12
|
+
input.include_usage ??= true;
|
|
13
|
+
if (!input.status)
|
|
14
|
+
delete input.status;
|
|
15
|
+
if (!input.tag)
|
|
16
|
+
delete input.tag;
|
|
17
|
+
return whatsappReadQueryParams(input);
|
|
18
|
+
}
|
|
@@ -512,7 +512,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
|
|
|
512
512
|
{
|
|
513
513
|
name: "sponsor",
|
|
514
514
|
kind: "boolean",
|
|
515
|
-
description: "Sponsor each creator's LinkedIn account when they accept: your workspace pays its monthly credit reservation (shown in the preview), from when they connect LinkedIn. With --link-only,
|
|
515
|
+
description: "Sponsor each creator's LinkedIn account when they accept: your workspace pays its monthly credit reservation (shown in the preview), from when they connect LinkedIn; nothing is charged if they never accept or connect. With --link-only, the first call previews; repeat it with --approved --preview-token <that preview's token> to create the links.",
|
|
516
516
|
required: false,
|
|
517
517
|
},
|
|
518
518
|
{
|
|
@@ -1005,7 +1005,7 @@ export function registerUgcCommands(program, { request: requestOxygen, handle })
|
|
|
1005
1005
|
{
|
|
1006
1006
|
action: "sponsorship_preview",
|
|
1007
1007
|
command: "sponsorship preview",
|
|
1008
|
-
description: "Preview sponsoring creators as a signed-in master admin: funding is card (seat plus 10,000-credit grant) or credits (one LinkedIn reservation per creator). Org API keys cannot quote.",
|
|
1008
|
+
description: "Preview sponsoring creators who already joined, as a signed-in master admin: funding is card (seat plus 10,000-credit grant) or credits (one LinkedIn reservation per creator). Org API keys cannot quote. To sponsor creators who have not joined yet, invite them with creators invite --sponsor.",
|
|
1009
1009
|
fields: [
|
|
1010
1010
|
{
|
|
1011
1011
|
name: "program_id",
|
|
@@ -532,6 +532,47 @@ export declare const ANNUAL_BILLING_MONTHS_CHARGED = 10;
|
|
|
532
532
|
export declare function annualPlanPriceCents(monthlyPriceCents: number): number;
|
|
533
533
|
/** How often a plan Price bills. Credits are granted monthly on both. */
|
|
534
534
|
export type PlanBillingInterval = "month" | "year";
|
|
535
|
+
/** Commitment and payment frequency are separate: annual commitments bill monthly. */
|
|
536
|
+
export type PlanCommitmentTerm = "month" | "year";
|
|
537
|
+
export declare const ANNUAL_MONTHLY_TERMS_VERSION = "2026-10-02";
|
|
538
|
+
export declare function annualMonthlyPriceCents(monthlyPriceCents: number): number;
|
|
539
|
+
/** Read-only comparison; annual totals reflect twelve rounded monthly payments. */
|
|
540
|
+
export declare function purchasablePlanComparison(annualMonthlyAvailable: boolean): {
|
|
541
|
+
plan_key: "oxygen_199" | "oxygen_1999" | "oxygen_49" | "oxygen_499" | "oxygen_99" | "oxygen_999";
|
|
542
|
+
currency: string;
|
|
543
|
+
monthly_credits: number;
|
|
544
|
+
volume_bonus_percent: number;
|
|
545
|
+
monthly: {
|
|
546
|
+
payment_cents: number;
|
|
547
|
+
billing_interval: string;
|
|
548
|
+
commitment_months: number;
|
|
549
|
+
};
|
|
550
|
+
yearly: {
|
|
551
|
+
payment_cents: number;
|
|
552
|
+
billing_interval: string;
|
|
553
|
+
commitment_months: number;
|
|
554
|
+
total_payment_cents: number;
|
|
555
|
+
saving_cents: number;
|
|
556
|
+
prices_before_tax: boolean;
|
|
557
|
+
} | null;
|
|
558
|
+
}[];
|
|
559
|
+
export declare const ANNUAL_MONTHLY_PLAN_TERMS: {
|
|
560
|
+
readonly terms_version: "2026-10-02";
|
|
561
|
+
readonly commitment_months: 12;
|
|
562
|
+
readonly billing_interval: "month";
|
|
563
|
+
readonly credits_granted: "monthly_after_payment";
|
|
564
|
+
readonly renewal: "automatically_for_another_12_months";
|
|
565
|
+
readonly cancellation: "Stops annual renewal; monthly payments continue through the current term.";
|
|
566
|
+
readonly upgrades: "Immediate with proration; the current annual term end stays the same.";
|
|
567
|
+
readonly switch_from_monthly: "Starts at the next monthly billing boundary. The first discounted monthly payment starts the 12-month commitment; the current plan and credits stay until then.";
|
|
568
|
+
readonly downgrades_or_switch_to_monthly: "Take effect at the annual term end.";
|
|
569
|
+
};
|
|
570
|
+
export declare function readPlanCommitmentTerm(value: unknown): PlanCommitmentTerm | null;
|
|
571
|
+
/** Anchor arithmetic preserves Jan 31 and Feb 29 rather than drifting on clamps. */
|
|
572
|
+
export declare function annualCommitmentWindow(anchorSeconds: number, nowSeconds: number): {
|
|
573
|
+
start: number;
|
|
574
|
+
end: number;
|
|
575
|
+
};
|
|
535
576
|
export declare const PLAN_BILLING_INTERVALS: readonly PlanBillingInterval[];
|
|
536
577
|
/**
|
|
537
578
|
* A billing interval as a customer or an agent types it. `month`/`monthly` and
|
|
@@ -1059,6 +1059,62 @@ export const ANNUAL_BILLING_MONTHS_CHARGED = 10;
|
|
|
1059
1059
|
export function annualPlanPriceCents(monthlyPriceCents) {
|
|
1060
1060
|
return monthlyPriceCents * ANNUAL_BILLING_MONTHS_CHARGED;
|
|
1061
1061
|
}
|
|
1062
|
+
export const ANNUAL_MONTHLY_TERMS_VERSION = "2026-10-02";
|
|
1063
|
+
export function annualMonthlyPriceCents(monthlyPriceCents) {
|
|
1064
|
+
return Math.round(annualPlanPriceCents(monthlyPriceCents) / 12);
|
|
1065
|
+
}
|
|
1066
|
+
/** Read-only comparison; annual totals reflect twelve rounded monthly payments. */
|
|
1067
|
+
export function purchasablePlanComparison(annualMonthlyAvailable) {
|
|
1068
|
+
return PURCHASABLE_PLAN_KEYS.map((key) => {
|
|
1069
|
+
const plan = resolveBasePricingPlan(key);
|
|
1070
|
+
const monthly = plan.monthlyPriceCents;
|
|
1071
|
+
const annualPayment = annualMonthlyPriceCents(monthly);
|
|
1072
|
+
return {
|
|
1073
|
+
plan_key: key,
|
|
1074
|
+
currency: "usd",
|
|
1075
|
+
monthly_credits: plan.monthlyCredits,
|
|
1076
|
+
volume_bonus_percent: planVolumeBonusPercent(key),
|
|
1077
|
+
monthly: { payment_cents: monthly, billing_interval: "month", commitment_months: 1 },
|
|
1078
|
+
yearly: annualMonthlyAvailable ? {
|
|
1079
|
+
payment_cents: annualPayment,
|
|
1080
|
+
billing_interval: "month",
|
|
1081
|
+
commitment_months: 12,
|
|
1082
|
+
total_payment_cents: annualPayment * 12,
|
|
1083
|
+
saving_cents: monthly * 12 - annualPayment * 12,
|
|
1084
|
+
prices_before_tax: true,
|
|
1085
|
+
} : null,
|
|
1086
|
+
};
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
export const ANNUAL_MONTHLY_PLAN_TERMS = {
|
|
1090
|
+
terms_version: ANNUAL_MONTHLY_TERMS_VERSION,
|
|
1091
|
+
commitment_months: 12,
|
|
1092
|
+
billing_interval: "month",
|
|
1093
|
+
credits_granted: "monthly_after_payment",
|
|
1094
|
+
renewal: "automatically_for_another_12_months",
|
|
1095
|
+
cancellation: "Stops annual renewal; monthly payments continue through the current term.",
|
|
1096
|
+
upgrades: "Immediate with proration; the current annual term end stays the same.",
|
|
1097
|
+
switch_from_monthly: "Starts at the next monthly billing boundary. The first discounted monthly payment starts the 12-month commitment; the current plan and credits stay until then.",
|
|
1098
|
+
downgrades_or_switch_to_monthly: "Take effect at the annual term end.",
|
|
1099
|
+
};
|
|
1100
|
+
export function readPlanCommitmentTerm(value) {
|
|
1101
|
+
if (value === undefined || value === null || value === "")
|
|
1102
|
+
return null;
|
|
1103
|
+
return parsePlanBillingInterval(value);
|
|
1104
|
+
}
|
|
1105
|
+
/** Anchor arithmetic preserves Jan 31 and Feb 29 rather than drifting on clamps. */
|
|
1106
|
+
export function annualCommitmentWindow(anchorSeconds, nowSeconds) {
|
|
1107
|
+
const anchor = new Date(anchorSeconds * 1000);
|
|
1108
|
+
const boundary = (years) => {
|
|
1109
|
+
const year = anchor.getUTCFullYear() + years;
|
|
1110
|
+
const day = Math.min(anchor.getUTCDate(), new Date(Date.UTC(year, anchor.getUTCMonth() + 1, 0)).getUTCDate());
|
|
1111
|
+
return Date.UTC(year, anchor.getUTCMonth(), day, anchor.getUTCHours(), anchor.getUTCMinutes(), anchor.getUTCSeconds()) / 1000;
|
|
1112
|
+
};
|
|
1113
|
+
let years = Math.max(0, new Date(nowSeconds * 1000).getUTCFullYear() - anchor.getUTCFullYear());
|
|
1114
|
+
if (boundary(years) > nowSeconds)
|
|
1115
|
+
years = Math.max(0, years - 1);
|
|
1116
|
+
return { start: boundary(years), end: boundary(years + 1) };
|
|
1117
|
+
}
|
|
1062
1118
|
export const PLAN_BILLING_INTERVALS = ["month", "year"];
|
|
1063
1119
|
/**
|
|
1064
1120
|
* A billing interval as a customer or an agent types it. `month`/`monthly` and
|
|
@@ -216,6 +216,26 @@ export declare const CAPABILITY_ROUTE_MCP_CALLS: {
|
|
|
216
216
|
family: string;
|
|
217
217
|
};
|
|
218
218
|
};
|
|
219
|
+
rowFanOut: () => {
|
|
220
|
+
tool: string;
|
|
221
|
+
arguments: {
|
|
222
|
+
source: string;
|
|
223
|
+
target: string;
|
|
224
|
+
flatten: {
|
|
225
|
+
column: string;
|
|
226
|
+
path: string;
|
|
227
|
+
};
|
|
228
|
+
mapping: {
|
|
229
|
+
target: string;
|
|
230
|
+
source: {
|
|
231
|
+
type: string;
|
|
232
|
+
key: string;
|
|
233
|
+
};
|
|
234
|
+
path: string;
|
|
235
|
+
}[];
|
|
236
|
+
dry_run: boolean;
|
|
237
|
+
};
|
|
238
|
+
};
|
|
219
239
|
linkedinKeywordPosts: () => {
|
|
220
240
|
tool: string;
|
|
221
241
|
arguments: {
|
|
@@ -245,3 +265,4 @@ export declare const LOCAL_BUSINESS_SCRAPE_COMMAND = "oxygen companies search pr
|
|
|
245
265
|
* column through `columns add`, which the route recommends next.
|
|
246
266
|
*/
|
|
247
267
|
export declare const ROW_CLASSIFICATION_COMMAND = "oxygen columns catalog --family classification";
|
|
268
|
+
export declare const ROW_FAN_OUT_COMMAND = "oxygen tables send <source> <target> --flatten <column> --flatten-path <path> --mapping '[{\"target\":\"<column>\",\"source\":{\"type\":\"column\",\"key\":\"$element\"},\"path\":\"<field>\"}]' --dry-run";
|