@oxygen-agent/cli 1.1011.326 → 1.1011.440
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 +15 -4
- package/dist/connectors-commands.d.ts +4 -1
- package/dist/connectors-commands.js +84 -10
- package/dist/contract-flags.d.ts +2 -0
- package/dist/contract-flags.js +26 -11
- package/dist/crm-support-flags.d.ts +11 -0
- package/dist/crm-support-flags.js +60 -0
- package/dist/customer-operation-commands.d.ts +5 -0
- package/dist/customer-operation-commands.js +101 -0
- package/dist/database-query-flags.d.ts +2 -0
- package/dist/database-query-flags.js +6 -0
- package/dist/help.d.ts +3 -1
- package/dist/help.js +43 -0
- package/dist/http-client.d.ts +2 -0
- package/dist/http-client.js +41 -1
- package/dist/index.js +640 -234
- package/dist/knowledge-repository-commands.js +12 -14
- package/dist/mailbox-ramp-notice.d.ts +11 -0
- package/dist/mailbox-ramp-notice.js +53 -0
- package/dist/settings-commands.d.ts +11 -0
- package/dist/settings-commands.js +73 -0
- package/dist/skills.d.ts +5 -4
- package/dist/skills.js +106 -79
- package/dist/tool-catalog-detail-command.d.ts +7 -0
- package/dist/tool-catalog-detail-command.js +19 -0
- package/dist/tool-catalog-search-window.d.ts +6 -0
- package/dist/tool-catalog-search-window.js +12 -0
- package/dist/transcript.js +1 -0
- package/node_modules/@oxygen/shared/dist/bounded-read-result.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/bounded-read-result.js +25 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +47 -1
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +625 -39
- package/node_modules/@oxygen/shared/dist/connection-approval.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/connection-approval.js +2 -0
- package/node_modules/@oxygen/shared/dist/contracts/browser-operations.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/contracts/browser-operations.js +110 -0
- package/node_modules/@oxygen/shared/dist/contracts/connectors.d.ts +32 -6
- package/node_modules/@oxygen/shared/dist/contracts/connectors.js +56 -4
- package/node_modules/@oxygen/shared/dist/contracts/crm-attributes.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/contracts/crm-attributes.js +39 -0
- package/node_modules/@oxygen/shared/dist/contracts/crm-enrichment-read.d.ts +21 -0
- package/node_modules/@oxygen/shared/dist/contracts/crm-enrichment-read.js +15 -0
- package/node_modules/@oxygen/shared/dist/contracts/crm-support.d.ts +117 -0
- package/node_modules/@oxygen/shared/dist/contracts/crm-support.js +43 -0
- package/node_modules/@oxygen/shared/dist/contracts/customer-operations.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/contracts/customer-operations.js +131 -0
- package/node_modules/@oxygen/shared/dist/contracts/dashboard-tabs.d.ts +3 -0
- package/node_modules/@oxygen/shared/dist/contracts/dashboard-tabs.js +2 -0
- package/node_modules/@oxygen/shared/dist/contracts/database.d.ts +30 -0
- package/node_modules/@oxygen/shared/dist/contracts/database.js +29 -0
- package/node_modules/@oxygen/shared/dist/contracts/integration-connect.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/contracts/integration-connect.js +7 -0
- package/node_modules/@oxygen/shared/dist/contracts/knowledge-content-reads.d.ts +43 -0
- package/node_modules/@oxygen/shared/dist/contracts/knowledge-content-reads.js +20 -0
- package/node_modules/@oxygen/shared/dist/contracts/linkedin-invites-list.d.ts +12 -0
- package/node_modules/@oxygen/shared/dist/contracts/linkedin-invites-list.js +8 -0
- package/node_modules/@oxygen/shared/dist/contracts/operations.d.ts +48 -2
- package/node_modules/@oxygen/shared/dist/contracts/operations.js +68 -2
- package/node_modules/@oxygen/shared/dist/contracts/table-grid-query.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-grid-query.js +6 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-query-grid.d.ts +21 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-query-grid.js +27 -0
- package/node_modules/@oxygen/shared/dist/contracts/tool-catalog-detail.d.ts +19 -0
- package/node_modules/@oxygen/shared/dist/contracts/tool-catalog-detail.js +10 -0
- package/node_modules/@oxygen/shared/dist/contracts/tool-catalog-search-window.d.ts +12 -0
- package/node_modules/@oxygen/shared/dist/contracts/tool-catalog-search-window.js +7 -0
- package/node_modules/@oxygen/shared/dist/contracts/workspace-pages.d.ts +17 -0
- package/node_modules/@oxygen/shared/dist/contracts/workspace-pages.js +49 -0
- package/node_modules/@oxygen/shared/dist/decision-ledger-parser.d.ts +32 -0
- package/node_modules/@oxygen/shared/dist/decision-ledger-parser.js +303 -0
- package/node_modules/@oxygen/shared/dist/decision-ledger.d.ts +10 -0
- package/node_modules/@oxygen/shared/dist/decision-ledger.generated.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/decision-ledger.generated.js +717 -0
- package/node_modules/@oxygen/shared/dist/decision-ledger.js +20 -0
- package/node_modules/@oxygen/shared/dist/email-campaign-ramp.d.ts +104 -0
- package/node_modules/@oxygen/shared/dist/email-campaign-ramp.js +250 -0
- package/node_modules/@oxygen/shared/dist/mcp-event-contract.d.ts +10 -7
- package/node_modules/@oxygen/shared/dist/mcp-event-contract.js +11 -7
- package/node_modules/@oxygen/shared/dist/mcp-table-widget.d.ts +50 -0
- package/node_modules/@oxygen/shared/dist/mcp-table-widget.js +24 -0
- package/node_modules/@oxygen/shared/dist/plan-band.d.ts +8 -0
- package/node_modules/@oxygen/shared/dist/plan-band.js +12 -0
- package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +20 -0
- package/node_modules/@oxygen/shared/dist/plan-limits.js +41 -0
- package/node_modules/@oxygen/shared/dist/provider-input-value.d.ts +5 -0
- package/node_modules/@oxygen/shared/dist/provider-input-value.js +10 -0
- package/node_modules/@oxygen/shared/dist/sequences.d.ts +33 -4
- package/node_modules/@oxygen/shared/dist/sequences.js +48 -13
- package/node_modules/@oxygen/shared/dist/user-capability-routing.js +17 -0
- 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/package.json +8 -6
- package/package.json +1 -1
- package/node_modules/@oxygen/shared/dist/copilot-skills.d.ts +0 -15
- package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +0 -31
- package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +0 -41
- package/node_modules/@oxygen/shared/dist/copilot-skills.js +0 -6
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DECISION_LEDGER_ENTRIES } from "./decision-ledger.generated.js";
|
|
2
|
+
export { parseDecisionLedger } from "./decision-ledger-parser.js";
|
|
3
|
+
const DECISIONS_BY_ID = new Map(DECISION_LEDGER_ENTRIES.map((entry) => [entry.id, entry]));
|
|
4
|
+
/**
|
|
5
|
+
* The ledger entry for a decision id. An exact id wins ("D34a" is its own
|
|
6
|
+
* decision); otherwise an answer-option suffix resolves to its base decision
|
|
7
|
+
* ("D19a" and "D19(a)" are D19's option (a)).
|
|
8
|
+
*/
|
|
9
|
+
export function getDecision(id) {
|
|
10
|
+
const key = id.trim();
|
|
11
|
+
const exact = DECISIONS_BY_ID.get(key);
|
|
12
|
+
if (exact)
|
|
13
|
+
return exact;
|
|
14
|
+
const base = /^(D\d+)(?:[a-z]|\([a-z]\))$/.exec(key)?.[1];
|
|
15
|
+
return base ? DECISIONS_BY_ID.get(base) ?? null : null;
|
|
16
|
+
}
|
|
17
|
+
/** Every ledger entry, sorted by decision id. */
|
|
18
|
+
export function listDecisions() {
|
|
19
|
+
return DECISION_LEDGER_ENTRIES;
|
|
20
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The standard ramp, by completed sending days: 5 a day through 2, 10 through 5,
|
|
3
|
+
* 20 through 8, then the configured cap. `maxAgeDays` keeps its historical name;
|
|
4
|
+
* its input is completed sending days, not mailbox age.
|
|
5
|
+
*/
|
|
6
|
+
export declare const WARMUP_RAMP_DAILY_CAPS: readonly [{
|
|
7
|
+
readonly maxAgeDays: 2;
|
|
8
|
+
readonly cap: 5;
|
|
9
|
+
}, {
|
|
10
|
+
readonly maxAgeDays: 5;
|
|
11
|
+
readonly cap: 10;
|
|
12
|
+
}, {
|
|
13
|
+
readonly maxAgeDays: 8;
|
|
14
|
+
readonly cap: 20;
|
|
15
|
+
}];
|
|
16
|
+
/**
|
|
17
|
+
* A custom ramp. `cap`, when present, is a permanent ceiling for this inbox (it
|
|
18
|
+
* never climbs past it, even when the daily cap is higher); absent, the ramp
|
|
19
|
+
* climbs until it reaches the inbox's configured daily cap.
|
|
20
|
+
*/
|
|
21
|
+
export type MailboxCustomRampConfig = {
|
|
22
|
+
start_per_day: number;
|
|
23
|
+
increase_every_days: number;
|
|
24
|
+
step: number;
|
|
25
|
+
cap?: number;
|
|
26
|
+
};
|
|
27
|
+
/** The ramp switched off: the configured daily cap applies from the first sending day. */
|
|
28
|
+
export type MailboxRampOffConfig = {
|
|
29
|
+
enabled: false;
|
|
30
|
+
};
|
|
31
|
+
export type MailboxRampConfig = MailboxCustomRampConfig | MailboxRampOffConfig;
|
|
32
|
+
export declare const MAILBOX_RAMP_MODES: readonly ["standard", "custom", "off"];
|
|
33
|
+
export type MailboxRampMode = (typeof MAILBOX_RAMP_MODES)[number];
|
|
34
|
+
export declare function isMailboxRampOff(config: MailboxRampConfig | null | undefined): config is MailboxRampOffConfig;
|
|
35
|
+
export declare function mailboxRampMode(config: MailboxRampConfig | null | undefined): MailboxRampMode;
|
|
36
|
+
/** The custom knobs, or null for the standard ramp and for a ramp switched off. */
|
|
37
|
+
export declare function customMailboxRamp(config: MailboxRampConfig | null | undefined): MailboxCustomRampConfig | null;
|
|
38
|
+
export type MailboxRampConfigParse = {
|
|
39
|
+
ok: true;
|
|
40
|
+
config: MailboxRampConfig | null;
|
|
41
|
+
} | {
|
|
42
|
+
ok: false;
|
|
43
|
+
field: string | null;
|
|
44
|
+
message: string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The one validator for a ramp_config write, shared by the API route (400) and
|
|
48
|
+
* the tenant write (OxygenError). null/undefined selects the standard ramp.
|
|
49
|
+
* `{enabled: false}` turns the ramp off and takes no other field. Otherwise
|
|
50
|
+
* start_per_day, increase_every_days (>= 1) and step are required non-negative
|
|
51
|
+
* integers, and cap is an optional non-negative integer.
|
|
52
|
+
*/
|
|
53
|
+
export declare function parseMailboxRampConfig(value: unknown): MailboxRampConfigParse;
|
|
54
|
+
/**
|
|
55
|
+
* Encode a validated public config for rolling web/worker deployments. The
|
|
56
|
+
* snapshot is the configured cap in force, taken under the mailbox's row lock.
|
|
57
|
+
* New readers discard it; it is never a permanent custom ceiling. Cap edits
|
|
58
|
+
* must refresh it, including Off's fixed start, so old warm-up targets cannot
|
|
59
|
+
* retain a higher value after the mailbox's daily cap is lowered.
|
|
60
|
+
*/
|
|
61
|
+
export declare function serializeMailboxRampConfig(config: MailboxRampConfig | null, configuredDailyCap: number): Record<string, unknown> | null;
|
|
62
|
+
/** Non-throwing read of stored ramp_config; private compatibility fields never reach public readbacks. */
|
|
63
|
+
export declare function readMailboxRampConfig(value: unknown): MailboxRampConfig | null;
|
|
64
|
+
/** Refresh only a synthetic compatibility ceiling; explicit caps and malformed legacy rows stay intact. */
|
|
65
|
+
export declare function refreshMailboxRampConfigDailyCap(value: unknown, configuredDailyCap: number): unknown;
|
|
66
|
+
/** The standard ramp's ceiling after `sendingDays` completed sending days; null once past its tiers. */
|
|
67
|
+
export declare function warmupRampDailyCap(sendingDays: number): number | null;
|
|
68
|
+
/**
|
|
69
|
+
* A custom ramp's ceiling after `sendingDays` completed sending days: start_per_day
|
|
70
|
+
* plus one `step` per completed `increase_every_days` window, held to `cap` when
|
|
71
|
+
* one is set. A (defensively) zero interval never climbs instead of dividing by zero.
|
|
72
|
+
*/
|
|
73
|
+
export declare function rampConfigDailyCap(config: MailboxCustomRampConfig, sendingDays: number): number;
|
|
74
|
+
/** The campaign ramp's ceiling in any mode; null when the ramp does not hold the inbox back. */
|
|
75
|
+
export declare function campaignRampDailyCap(config: MailboxRampConfig | null | undefined, sendingDays: number): number | null;
|
|
76
|
+
/** One level of the schedule: from this 1-based sending day the inbox may send `perDay`. */
|
|
77
|
+
export type CampaignRampStep = {
|
|
78
|
+
fromSendingDay: number;
|
|
79
|
+
perDay: number;
|
|
80
|
+
};
|
|
81
|
+
export type CampaignRampSchedule = {
|
|
82
|
+
mode: MailboxRampMode;
|
|
83
|
+
/** Every level the inbox passes through, ending at the most it will ever send a day. */
|
|
84
|
+
steps: CampaignRampStep[];
|
|
85
|
+
/** The 1-based sending day on which the inbox first sends its full daily cap; null if it never does. */
|
|
86
|
+
fullCapOnSendingDay: number | null;
|
|
87
|
+
/** True when `steps` stopped early at `maxSteps`. */
|
|
88
|
+
truncated: boolean;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* The 1-based sending day on which the ramp first lets the inbox send its full
|
|
92
|
+
* daily cap: 1 when the ramp is off or already at the cap, null when it never
|
|
93
|
+
* gets there (a custom cap below the daily cap, or no increase).
|
|
94
|
+
*/
|
|
95
|
+
export declare function campaignRampFullCapSendingDay(config: MailboxRampConfig | null | undefined, dailyCap: number): number | null;
|
|
96
|
+
/**
|
|
97
|
+
* The day-by-day plan a ramp produces against a daily cap, as distinct levels.
|
|
98
|
+
* Standard against 25: 5 (day 1), 10 (day 4), 20 (day 7), 25 (day 10). A custom
|
|
99
|
+
* ramp whose own cap sits below the daily cap ends at that cap and never reports
|
|
100
|
+
* a full-cap day. `maxSteps` bounds a very gentle custom ramp (1 a day, +1 a day).
|
|
101
|
+
*/
|
|
102
|
+
export declare function campaignRampSchedule(config: MailboxRampConfig | null | undefined, dailyCap: number, options?: {
|
|
103
|
+
maxSteps?: number;
|
|
104
|
+
}): CampaignRampSchedule;
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
// Per-mailbox campaign ramp-up: how much campaign email an inbox may send on each
|
|
2
|
+
// of its first sending days before its configured daily cap applies. A sending
|
|
3
|
+
// day is a completed UTC day on which the mailbox had an accepted campaign send
|
|
4
|
+
// (`campaignSendingDays`), so idle days and import age never advance it.
|
|
5
|
+
//
|
|
6
|
+
// Three modes, one stored column (`email_mailboxes.ramp_config`):
|
|
7
|
+
// - standard (null) 5 / 10 / 20 a day over the first nine sending days,
|
|
8
|
+
// then the configured cap.
|
|
9
|
+
// - custom start_per_day, plus `step` every `increase_every_days`
|
|
10
|
+
// sending days, until the configured cap. An optional
|
|
11
|
+
// `cap` is a permanent ceiling below the daily cap.
|
|
12
|
+
// - off ({enabled:false}) the configured cap from the first sending day, for
|
|
13
|
+
// an inbox that already has sending history elsewhere.
|
|
14
|
+
//
|
|
15
|
+
// Pure and browser-safe: the send claim, every API readback and the web preview
|
|
16
|
+
// compute the same numbers from these functions.
|
|
17
|
+
/**
|
|
18
|
+
* The standard ramp, by completed sending days: 5 a day through 2, 10 through 5,
|
|
19
|
+
* 20 through 8, then the configured cap. `maxAgeDays` keeps its historical name;
|
|
20
|
+
* its input is completed sending days, not mailbox age.
|
|
21
|
+
*/
|
|
22
|
+
export const WARMUP_RAMP_DAILY_CAPS = [
|
|
23
|
+
{ maxAgeDays: 2, cap: 5 },
|
|
24
|
+
{ maxAgeDays: 5, cap: 10 },
|
|
25
|
+
{ maxAgeDays: 8, cap: 20 },
|
|
26
|
+
];
|
|
27
|
+
export const MAILBOX_RAMP_MODES = ["standard", "custom", "off"];
|
|
28
|
+
export function isMailboxRampOff(config) {
|
|
29
|
+
return Boolean(config) && config.enabled === false;
|
|
30
|
+
}
|
|
31
|
+
export function mailboxRampMode(config) {
|
|
32
|
+
if (!config)
|
|
33
|
+
return "standard";
|
|
34
|
+
return isMailboxRampOff(config) ? "off" : "custom";
|
|
35
|
+
}
|
|
36
|
+
/** The custom knobs, or null for the standard ramp and for a ramp switched off. */
|
|
37
|
+
export function customMailboxRamp(config) {
|
|
38
|
+
return config && !isMailboxRampOff(config) ? config : null;
|
|
39
|
+
}
|
|
40
|
+
const CUSTOM_REQUIRED_FIELDS = ["start_per_day", "increase_every_days", "step"];
|
|
41
|
+
function isNonNegativeInteger(value) {
|
|
42
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The one validator for a ramp_config write, shared by the API route (400) and
|
|
46
|
+
* the tenant write (OxygenError). null/undefined selects the standard ramp.
|
|
47
|
+
* `{enabled: false}` turns the ramp off and takes no other field. Otherwise
|
|
48
|
+
* start_per_day, increase_every_days (>= 1) and step are required non-negative
|
|
49
|
+
* integers, and cap is an optional non-negative integer.
|
|
50
|
+
*/
|
|
51
|
+
export function parseMailboxRampConfig(value) {
|
|
52
|
+
if (value === undefined || value === null)
|
|
53
|
+
return { ok: true, config: null };
|
|
54
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
55
|
+
return { ok: false, field: null, message: "ramp_config must be an object, or null for the standard ramp." };
|
|
56
|
+
}
|
|
57
|
+
const record = value;
|
|
58
|
+
if (record.enabled !== undefined && typeof record.enabled !== "boolean") {
|
|
59
|
+
return { ok: false, field: "enabled", message: "ramp_config.enabled must be true or false." };
|
|
60
|
+
}
|
|
61
|
+
if (record.enabled === false) {
|
|
62
|
+
const extra = Object.keys(record).filter((key) => key !== "enabled" && record[key] !== undefined);
|
|
63
|
+
if (extra.length > 0) {
|
|
64
|
+
return {
|
|
65
|
+
ok: false,
|
|
66
|
+
field: extra[0] ?? null,
|
|
67
|
+
message: "ramp_config {enabled: false} turns the ramp off; send it without other fields.",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return { ok: true, config: { enabled: false } };
|
|
71
|
+
}
|
|
72
|
+
const config = {};
|
|
73
|
+
for (const field of CUSTOM_REQUIRED_FIELDS) {
|
|
74
|
+
const raw = record[field];
|
|
75
|
+
if (!isNonNegativeInteger(raw)) {
|
|
76
|
+
return { ok: false, field, message: `ramp_config.${field} must be a non-negative integer.` };
|
|
77
|
+
}
|
|
78
|
+
config[field] = raw;
|
|
79
|
+
}
|
|
80
|
+
if (config.increase_every_days < 1) {
|
|
81
|
+
return { ok: false, field: "increase_every_days", message: "ramp_config.increase_every_days must be at least 1." };
|
|
82
|
+
}
|
|
83
|
+
if (record.cap !== undefined && record.cap !== null) {
|
|
84
|
+
if (!isNonNegativeInteger(record.cap)) {
|
|
85
|
+
return { ok: false, field: "cap", message: "ramp_config.cap must be a non-negative integer, or omitted to climb to the daily cap." };
|
|
86
|
+
}
|
|
87
|
+
config.cap = record.cap;
|
|
88
|
+
}
|
|
89
|
+
return { ok: true, config };
|
|
90
|
+
}
|
|
91
|
+
// Private persistence only. Previous workers require all four custom knobs and
|
|
92
|
+
// otherwise read a row as the standard ramp (which can exceed a new 0/1-day
|
|
93
|
+
// custom start). Keep them a bounded, valid ramp until they have rolled too.
|
|
94
|
+
const STORAGE_MARKER = "__oxygen_ramp_compat";
|
|
95
|
+
const STORED_FIELDS = new Set([...CUSTOM_REQUIRED_FIELDS, "cap", STORAGE_MARKER]);
|
|
96
|
+
/**
|
|
97
|
+
* Encode a validated public config for rolling web/worker deployments. The
|
|
98
|
+
* snapshot is the configured cap in force, taken under the mailbox's row lock.
|
|
99
|
+
* New readers discard it; it is never a permanent custom ceiling. Cap edits
|
|
100
|
+
* must refresh it, including Off's fixed start, so old warm-up targets cannot
|
|
101
|
+
* retain a higher value after the mailbox's daily cap is lowered.
|
|
102
|
+
*/
|
|
103
|
+
export function serializeMailboxRampConfig(config, configuredDailyCap) {
|
|
104
|
+
if (!config)
|
|
105
|
+
return null;
|
|
106
|
+
const cap = wholeDailyCap(configuredDailyCap);
|
|
107
|
+
if (isMailboxRampOff(config)) {
|
|
108
|
+
return { start_per_day: cap, increase_every_days: 1, step: 0, cap, [STORAGE_MARKER]: "off-v1" };
|
|
109
|
+
}
|
|
110
|
+
if (config.cap !== undefined)
|
|
111
|
+
return { ...config };
|
|
112
|
+
return { ...config, cap, [STORAGE_MARKER]: "uncapped-v1" };
|
|
113
|
+
}
|
|
114
|
+
/** Non-throwing read of stored ramp_config; private compatibility fields never reach public readbacks. */
|
|
115
|
+
export function readMailboxRampConfig(value) {
|
|
116
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
117
|
+
const record = value;
|
|
118
|
+
if (Object.hasOwn(record, STORAGE_MARKER)) {
|
|
119
|
+
if (Object.keys(record).some((key) => !STORED_FIELDS.has(key)))
|
|
120
|
+
return null;
|
|
121
|
+
const legacy = parseMailboxRampConfig(record);
|
|
122
|
+
if (!legacy.ok || !legacy.config || isMailboxRampOff(legacy.config)
|
|
123
|
+
|| !isNonNegativeInteger(record.cap))
|
|
124
|
+
return null;
|
|
125
|
+
if (record[STORAGE_MARKER] === "off-v1") {
|
|
126
|
+
return legacy.config.start_per_day === record.cap && legacy.config.step === 0
|
|
127
|
+
&& legacy.config.increase_every_days === 1 ? { enabled: false } : null;
|
|
128
|
+
}
|
|
129
|
+
if (record[STORAGE_MARKER] !== "uncapped-v1")
|
|
130
|
+
return null;
|
|
131
|
+
const { cap: _snapshot, ...custom } = legacy.config;
|
|
132
|
+
return custom;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const parsed = parseMailboxRampConfig(value);
|
|
136
|
+
return parsed.ok ? parsed.config : null;
|
|
137
|
+
}
|
|
138
|
+
/** Refresh only a synthetic compatibility ceiling; explicit caps and malformed legacy rows stay intact. */
|
|
139
|
+
export function refreshMailboxRampConfigDailyCap(value, configuredDailyCap) {
|
|
140
|
+
const config = readMailboxRampConfig(value);
|
|
141
|
+
return config && (isMailboxRampOff(config) || config.cap === undefined)
|
|
142
|
+
? serializeMailboxRampConfig(config, configuredDailyCap) : value;
|
|
143
|
+
}
|
|
144
|
+
function wholeSendingDays(sendingDays) {
|
|
145
|
+
return Number.isFinite(sendingDays) && sendingDays > 0 ? Math.floor(sendingDays) : 0;
|
|
146
|
+
}
|
|
147
|
+
/** The standard ramp's ceiling after `sendingDays` completed sending days; null once past its tiers. */
|
|
148
|
+
export function warmupRampDailyCap(sendingDays) {
|
|
149
|
+
const days = wholeSendingDays(sendingDays);
|
|
150
|
+
for (const tier of WARMUP_RAMP_DAILY_CAPS) {
|
|
151
|
+
if (days <= tier.maxAgeDays)
|
|
152
|
+
return tier.cap;
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* A custom ramp's ceiling after `sendingDays` completed sending days: start_per_day
|
|
158
|
+
* plus one `step` per completed `increase_every_days` window, held to `cap` when
|
|
159
|
+
* one is set. A (defensively) zero interval never climbs instead of dividing by zero.
|
|
160
|
+
*/
|
|
161
|
+
export function rampConfigDailyCap(config, sendingDays) {
|
|
162
|
+
const days = wholeSendingDays(sendingDays);
|
|
163
|
+
const periods = config.increase_every_days >= 1 ? Math.floor(days / config.increase_every_days) : 0;
|
|
164
|
+
const value = config.start_per_day + config.step * periods;
|
|
165
|
+
const ceiling = typeof config.cap === "number" ? Math.min(value, config.cap) : value;
|
|
166
|
+
return Math.max(0, ceiling);
|
|
167
|
+
}
|
|
168
|
+
/** The campaign ramp's ceiling in any mode; null when the ramp does not hold the inbox back. */
|
|
169
|
+
export function campaignRampDailyCap(config, sendingDays) {
|
|
170
|
+
if (isMailboxRampOff(config))
|
|
171
|
+
return null;
|
|
172
|
+
const custom = customMailboxRamp(config);
|
|
173
|
+
return custom ? rampConfigDailyCap(custom, sendingDays) : warmupRampDailyCap(sendingDays);
|
|
174
|
+
}
|
|
175
|
+
/** Completed sending days at which the standard ramp changes level. */
|
|
176
|
+
const STANDARD_RAMP_BOUNDARIES = [0, ...WARMUP_RAMP_DAILY_CAPS.map((tier) => tier.maxAgeDays + 1)];
|
|
177
|
+
function wholeDailyCap(dailyCap) {
|
|
178
|
+
return Number.isFinite(dailyCap) && dailyCap > 0 ? Math.floor(dailyCap) : 0;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The 1-based sending day on which the ramp first lets the inbox send its full
|
|
182
|
+
* daily cap: 1 when the ramp is off or already at the cap, null when it never
|
|
183
|
+
* gets there (a custom cap below the daily cap, or no increase).
|
|
184
|
+
*/
|
|
185
|
+
export function campaignRampFullCapSendingDay(config, dailyCap) {
|
|
186
|
+
const cap = wholeDailyCap(dailyCap);
|
|
187
|
+
if (cap === 0 || isMailboxRampOff(config))
|
|
188
|
+
return 1;
|
|
189
|
+
const custom = customMailboxRamp(config);
|
|
190
|
+
if (!custom) {
|
|
191
|
+
for (const sendingDays of STANDARD_RAMP_BOUNDARIES) {
|
|
192
|
+
const ramp = warmupRampDailyCap(sendingDays);
|
|
193
|
+
if (ramp === null || ramp >= cap)
|
|
194
|
+
return sendingDays + 1;
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
if (typeof custom.cap === "number" && custom.cap < cap)
|
|
199
|
+
return null;
|
|
200
|
+
if (custom.start_per_day >= cap)
|
|
201
|
+
return 1;
|
|
202
|
+
if (custom.step <= 0)
|
|
203
|
+
return null;
|
|
204
|
+
const periods = Math.ceil((cap - custom.start_per_day) / custom.step);
|
|
205
|
+
return periods * Math.max(1, custom.increase_every_days) + 1;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* The day-by-day plan a ramp produces against a daily cap, as distinct levels.
|
|
209
|
+
* Standard against 25: 5 (day 1), 10 (day 4), 20 (day 7), 25 (day 10). A custom
|
|
210
|
+
* ramp whose own cap sits below the daily cap ends at that cap and never reports
|
|
211
|
+
* a full-cap day. `maxSteps` bounds a very gentle custom ramp (1 a day, +1 a day).
|
|
212
|
+
*/
|
|
213
|
+
export function campaignRampSchedule(config, dailyCap, options = {}) {
|
|
214
|
+
const mode = mailboxRampMode(config);
|
|
215
|
+
const cap = wholeDailyCap(dailyCap);
|
|
216
|
+
const maxSteps = Math.max(2, Math.floor(options.maxSteps ?? 60));
|
|
217
|
+
const steps = [];
|
|
218
|
+
// Levels change only at a tier boundary (standard) or a period boundary
|
|
219
|
+
// (custom), so visiting those boundaries visits every distinct level.
|
|
220
|
+
const visit = (sendingDays) => {
|
|
221
|
+
const ramp = campaignRampDailyCap(config, sendingDays);
|
|
222
|
+
const perDay = ramp === null ? cap : Math.min(cap, ramp);
|
|
223
|
+
if (steps[steps.length - 1]?.perDay === perDay)
|
|
224
|
+
return;
|
|
225
|
+
steps.push({ fromSendingDay: sendingDays + 1, perDay });
|
|
226
|
+
};
|
|
227
|
+
const custom = customMailboxRamp(config);
|
|
228
|
+
let truncated = false;
|
|
229
|
+
if (mode === "off") {
|
|
230
|
+
visit(0);
|
|
231
|
+
}
|
|
232
|
+
else if (!custom) {
|
|
233
|
+
for (const sendingDays of STANDARD_RAMP_BOUNDARIES)
|
|
234
|
+
visit(sendingDays);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
const ceiling = typeof custom.cap === "number" ? Math.min(cap, custom.cap) : cap;
|
|
238
|
+
const every = Math.max(1, custom.increase_every_days);
|
|
239
|
+
for (let period = 0;; period += 1) {
|
|
240
|
+
visit(period * every);
|
|
241
|
+
if ((steps[steps.length - 1]?.perDay ?? 0) >= ceiling || custom.step <= 0)
|
|
242
|
+
break;
|
|
243
|
+
if (steps.length >= maxSteps) {
|
|
244
|
+
truncated = true;
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return { mode, steps, fullCapOnSendingDay: campaignRampFullCapSendingDay(config, cap), truncated };
|
|
250
|
+
}
|
|
@@ -16,12 +16,18 @@ export type McpReplyClassification = (typeof MCP_REPLY_CLASSIFICATIONS)[number];
|
|
|
16
16
|
export declare const MCP_REPLY_CHANNELS: readonly ["email", "linkedin", "whatsapp"];
|
|
17
17
|
/** How an enrollment ended: the Sequencer's own terminal statuses. */
|
|
18
18
|
export declare const MCP_ENROLLMENT_OUTCOMES: readonly ["completed", "replied", "stopped", "failed", "excluded"];
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The durable-run ledgers `run_outcome_analytics` reads (`SettledRunKind` in
|
|
21
|
+
* @oxygen/tenant-db), without Workspace Copilot turns: a turn is attended and
|
|
22
|
+
* private to its member, the own-action guard already drops a subscriber's own
|
|
23
|
+
* turns, and delivering other members' turns would expose private activity
|
|
24
|
+
* with deep links the subscriber may not be able to open.
|
|
25
|
+
*/
|
|
26
|
+
export declare const MCP_RUN_KINDS: readonly ["workflow", "table_action", "table_ingestion", "agent"];
|
|
21
27
|
export type McpRunKind = (typeof MCP_RUN_KINDS)[number];
|
|
22
28
|
/**
|
|
23
29
|
* Every terminal status those ledgers write, with one spelling of cancel:
|
|
24
|
-
* Workflow and Table runs write `canceled`, Agent runs
|
|
30
|
+
* Workflow and Table runs write `canceled`, Agent runs `cancelled`.
|
|
25
31
|
*/
|
|
26
32
|
export declare const MCP_RUN_STATUSES: readonly ["completed", "completed_with_errors", "failed", "canceled", "budget_exhausted", "effect_unknown"];
|
|
27
33
|
export type McpRunStatus = (typeof MCP_RUN_STATUSES)[number];
|
|
@@ -285,7 +291,7 @@ declare const RECORD_STAGE_CHANGED_PAYLOAD: ContractObject<{
|
|
|
285
291
|
declare const RUN_SETTLED_PAYLOAD: ContractObject<{
|
|
286
292
|
readonly kind: {
|
|
287
293
|
type: "string";
|
|
288
|
-
enum: readonly ("agent" | "
|
|
294
|
+
enum: readonly ("agent" | "table_action" | "table_ingestion" | "workflow")[];
|
|
289
295
|
description?: string;
|
|
290
296
|
};
|
|
291
297
|
readonly status: {
|
|
@@ -574,9 +580,6 @@ export type McpRunSettledSource = McpRunSettledCommon & ({
|
|
|
574
580
|
} | {
|
|
575
581
|
kind: "agent";
|
|
576
582
|
agentSlug: string;
|
|
577
|
-
} | {
|
|
578
|
-
kind: "copilot_turn";
|
|
579
|
-
copilotSessionId: string;
|
|
580
583
|
});
|
|
581
584
|
/** A settled run as `run.settled`. Its producer is OXP-11.5.21. */
|
|
582
585
|
export declare function projectRunSettledEvent(source: McpRunSettledSource, context?: McpEventLinkOptions): McpRunSettledPayload;
|
|
@@ -59,11 +59,17 @@ const REPLY_LABELS_DELIVERED_AS_IS = new Set([
|
|
|
59
59
|
export const MCP_REPLY_CHANNELS = ["email", "linkedin", "whatsapp"];
|
|
60
60
|
/** How an enrollment ended: the Sequencer's own terminal statuses. */
|
|
61
61
|
export const MCP_ENROLLMENT_OUTCOMES = SEQUENCE_TERMINAL_STATUSES;
|
|
62
|
-
/**
|
|
63
|
-
|
|
62
|
+
/**
|
|
63
|
+
* The durable-run ledgers `run_outcome_analytics` reads (`SettledRunKind` in
|
|
64
|
+
* @oxygen/tenant-db), without Workspace Copilot turns: a turn is attended and
|
|
65
|
+
* private to its member, the own-action guard already drops a subscriber's own
|
|
66
|
+
* turns, and delivering other members' turns would expose private activity
|
|
67
|
+
* with deep links the subscriber may not be able to open.
|
|
68
|
+
*/
|
|
69
|
+
export const MCP_RUN_KINDS = ["workflow", "table_action", "table_ingestion", "agent"];
|
|
64
70
|
/**
|
|
65
71
|
* Every terminal status those ledgers write, with one spelling of cancel:
|
|
66
|
-
* Workflow and Table runs write `canceled`, Agent runs
|
|
72
|
+
* Workflow and Table runs write `canceled`, Agent runs `cancelled`.
|
|
67
73
|
*/
|
|
68
74
|
export const MCP_RUN_STATUSES = [
|
|
69
75
|
"completed",
|
|
@@ -160,7 +166,7 @@ const RUN_SETTLED_INPUT = obj({
|
|
|
160
166
|
});
|
|
161
167
|
const RUN_SETTLED_PAYLOAD = payloadObject({
|
|
162
168
|
kind: enumOf(MCP_RUN_KINDS, {
|
|
163
|
-
description: "What ran: a Workflow run, a Table action run, a Table import (`table_ingestion`)
|
|
169
|
+
description: "What ran: a Workflow run, a Table action run, a Table import (`table_ingestion`) or an Agent run.",
|
|
164
170
|
}),
|
|
165
171
|
status: enumOf(MCP_RUN_STATUSES, {
|
|
166
172
|
description: "How it ended. An Agent run can also end `budget_exhausted` or `effect_unknown`.",
|
|
@@ -189,7 +195,7 @@ export const MCP_EVENT_DEFINITIONS = [
|
|
|
189
195
|
eventDefinition("enrollment.ended", "A lead's enrollment in an OXYGEN Sequence ended: the lead replied, every step was sent, the enrollment was stopped or excluded, or sending failed.", ENROLLMENT_ENDED_INPUT, ENROLLMENT_ENDED_PAYLOAD),
|
|
190
196
|
eventDefinition("meeting.completed", "OXYGEN's Meeting Notetaker finished processing a recorded meeting; its transcript and meeting note are ready in OXYGEN.", MEETING_COMPLETED_INPUT, MEETING_COMPLETED_PAYLOAD),
|
|
191
197
|
eventDefinition("record.stage_changed", "A CRM record's stage changed in OXYGEN, such as a person's lead stage, a company's account stage or a deal's pipeline stage.", RECORD_STAGE_CHANGED_INPUT, RECORD_STAGE_CHANGED_PAYLOAD),
|
|
192
|
-
eventDefinition("run.settled", "A run in OXYGEN reached its final status: a Workflow run, a Table action run or import, an Agent run
|
|
198
|
+
eventDefinition("run.settled", "A run in OXYGEN reached its final status: a Workflow run, a Table action run or import, or an Agent run.", RUN_SETTLED_INPUT, RUN_SETTLED_PAYLOAD),
|
|
193
199
|
eventDefinition("approval.requested", "A Workflow run or an Agent run in OXYGEN paused and is waiting for a person to approve its next step.", APPROVAL_REQUESTED_INPUT, APPROVAL_REQUESTED_PAYLOAD),
|
|
194
200
|
];
|
|
195
201
|
const DEFINITIONS_BY_NAME = new Map(MCP_EVENT_DEFINITIONS.map((entry) => [entry.name, entry]));
|
|
@@ -574,8 +580,6 @@ function runPath(source) {
|
|
|
574
580
|
return `/tables/${encodeURIComponent(source.tableId)}/ingestions/${encodeURIComponent(source.runId)}`;
|
|
575
581
|
case "agent":
|
|
576
582
|
return agentRunPath(source.agentSlug, source.runId);
|
|
577
|
-
case "copilot_turn":
|
|
578
|
-
return `/copilot/${encodeURIComponent(source.copilotSessionId)}`;
|
|
579
583
|
}
|
|
580
584
|
}
|
|
581
585
|
// Every catalogue projection first proves the row is that event, so a reader
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export declare const TABLE_WIDGET_NAME = "oxygen.table";
|
|
2
|
+
/** A run filling the Table, shown as progress until it reaches a terminal state. */
|
|
3
|
+
export type TableWidgetRun = {
|
|
4
|
+
kind: "ingestion" | "column_run";
|
|
5
|
+
id: string;
|
|
6
|
+
status: string;
|
|
7
|
+
terminal: boolean;
|
|
8
|
+
/** Settled / total work items in this run (chunks for an ingestion), not Table rows. */
|
|
9
|
+
rowsDone?: number | null;
|
|
10
|
+
rowsTarget?: number | null;
|
|
11
|
+
creditsUsed?: number | null;
|
|
12
|
+
creditsCap?: number | null;
|
|
13
|
+
};
|
|
14
|
+
export type TableWidgetGridPage = {
|
|
15
|
+
/** SerializedWorkspaceColumn[] from the web grid serializer. */
|
|
16
|
+
columns: unknown[];
|
|
17
|
+
/** SerializedWorkspaceTableRow[] from the web grid serializer. */
|
|
18
|
+
rows: unknown[];
|
|
19
|
+
cellStates?: Record<string, Record<string, unknown>> | null;
|
|
20
|
+
rowCount?: number | null;
|
|
21
|
+
hasMore?: boolean;
|
|
22
|
+
nextCursor?: string | null;
|
|
23
|
+
/**
|
|
24
|
+
* SerializedWorkspaceColumnStats[], the grid's column stats: what it
|
|
25
|
+
* collapses as empty, its header fill lines and run bars. Only a first page
|
|
26
|
+
* carries them, and only when they answered in time.
|
|
27
|
+
*/
|
|
28
|
+
columnStats?: unknown[] | null;
|
|
29
|
+
/**
|
|
30
|
+
* An empty first page's fill state, the body of GET
|
|
31
|
+
* /api/tables/<id>/fill-progress: rows still being written, a failed fill,
|
|
32
|
+
* or neither.
|
|
33
|
+
*/
|
|
34
|
+
fillProgress?: Record<string, unknown> | null;
|
|
35
|
+
};
|
|
36
|
+
export type TableWidgetPayload = {
|
|
37
|
+
version: 1;
|
|
38
|
+
/** "table": rows of a saved Table. "preview": sample rows of a search that saved nothing yet. */
|
|
39
|
+
source: "table" | "preview";
|
|
40
|
+
title: string;
|
|
41
|
+
/** The counts line under the title, e.g. "1,840 matches · 0 credits". */
|
|
42
|
+
summary?: string | null;
|
|
43
|
+
/** The Table these rows belong to; absent for a preview. Paging and live progress read it. */
|
|
44
|
+
tableId?: string | null;
|
|
45
|
+
webUrl?: string | null;
|
|
46
|
+
grid: TableWidgetGridPage;
|
|
47
|
+
run?: TableWidgetRun | null;
|
|
48
|
+
};
|
|
49
|
+
/** The payload inside a tool result, or null when the result carries none (a refusal, a filter list). */
|
|
50
|
+
export declare function readTableWidgetPayload(result: unknown): TableWidgetPayload | null;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// What an MCP tool hands the OXYGEN Table widget. The tool puts it in its
|
|
2
|
+
// result's `_meta["oxygen/widget"].data`; MCP Apps hosts pass result `_meta` to
|
|
3
|
+
// the widget and not to the model, so the grid page the widget draws costs the
|
|
4
|
+
// model no context. The widget renders the page with the web grid's own
|
|
5
|
+
// components, so `grid` carries the web grid's serialization unchanged
|
|
6
|
+
// (columns, rows, cell states as GET /api/tables/<id>/rows returns them).
|
|
7
|
+
export const TABLE_WIDGET_NAME = "oxygen.table";
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
/** The payload inside a tool result, or null when the result carries none (a refusal, a filter list). */
|
|
12
|
+
export function readTableWidgetPayload(result) {
|
|
13
|
+
if (!isRecord(result) || !isRecord(result._meta))
|
|
14
|
+
return null;
|
|
15
|
+
const widget = result._meta["oxygen/widget"];
|
|
16
|
+
if (!isRecord(widget) || widget.name !== TABLE_WIDGET_NAME || !isRecord(widget.data))
|
|
17
|
+
return null;
|
|
18
|
+
const data = widget.data;
|
|
19
|
+
if (data.version !== 1 || typeof data.title !== "string" || !isRecord(data.grid))
|
|
20
|
+
return null;
|
|
21
|
+
if (!Array.isArray(data.grid.columns) || !Array.isArray(data.grid.rows))
|
|
22
|
+
return null;
|
|
23
|
+
return data;
|
|
24
|
+
}
|
|
@@ -84,6 +84,14 @@ export type PlanSpendResolution = {
|
|
|
84
84
|
* is never clamped by this.
|
|
85
85
|
*/
|
|
86
86
|
export declare function resolveDefaultTriggerRunCreditCeilingForPlan(resolution: PlanSpendResolution, options?: RepricingOptions): number | null;
|
|
87
|
+
/**
|
|
88
|
+
* The default rolling 24-hour credit ceiling of one connected app (an MCP OAuth
|
|
89
|
+
* connection such as ChatGPT) while it holds MCP event subscriptions (ADR 0030
|
|
90
|
+
* §11, decision D3): the trigger default above, so the two cannot drift.
|
|
91
|
+
* Enterprise has no trigger default and uses the largest rung's, the way Agent
|
|
92
|
+
* run defaults do; a connection is never uncapped by default.
|
|
93
|
+
*/
|
|
94
|
+
export declare function resolveDefaultConnectionCreditCeilingForPlan(resolution: PlanSpendResolution, options?: RepricingOptions): number;
|
|
87
95
|
/** The same default for one standing or webhook table auto-run batch. */
|
|
88
96
|
export declare function resolveDefaultAutoRunBatchCreditCeilingForPlan(resolution: PlanSpendResolution, options?: RepricingOptions): number | null;
|
|
89
97
|
/**
|
|
@@ -183,6 +183,18 @@ function resolveDeliveryCreditCeiling(resolution, preRepricingTable, options) {
|
|
|
183
183
|
export function resolveDefaultTriggerRunCreditCeilingForPlan(resolution, options = {}) {
|
|
184
184
|
return resolveDeliveryCreditCeiling(resolution, DEFAULT_TRIGGER_RUN_CREDIT_CEILING, options);
|
|
185
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* The default rolling 24-hour credit ceiling of one connected app (an MCP OAuth
|
|
188
|
+
* connection such as ChatGPT) while it holds MCP event subscriptions (ADR 0030
|
|
189
|
+
* §11, decision D3): the trigger default above, so the two cannot drift.
|
|
190
|
+
* Enterprise has no trigger default and uses the largest rung's, the way Agent
|
|
191
|
+
* run defaults do; a connection is never uncapped by default.
|
|
192
|
+
*/
|
|
193
|
+
export function resolveDefaultConnectionCreditCeilingForPlan(resolution, options = {}) {
|
|
194
|
+
return resolveDefaultTriggerRunCreditCeilingForPlan(resolution, options)
|
|
195
|
+
?? resolveDefaultTriggerRunCreditCeilingForPlan(bandSpendResolution("1999"), options)
|
|
196
|
+
?? 0;
|
|
197
|
+
}
|
|
186
198
|
/** The same default for one standing or webhook table auto-run batch. */
|
|
187
199
|
export function resolveDefaultAutoRunBatchCreditCeilingForPlan(resolution, options = {}) {
|
|
188
200
|
return resolveDeliveryCreditCeiling(resolution, DEFAULT_AUTO_RUN_BATCH_CREDIT_CEILING, options);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type RepricingOptions } from "./repricing.js";
|
|
2
|
+
export { CONNECTION_CEILING_ABOVE_DEFAULT_APPROVAL_KIND } from "./connection-approval.js";
|
|
2
3
|
/**
|
|
3
4
|
* The five enforcement rungs of the per-plan limits ladder. Every PlanTier maps
|
|
4
5
|
* onto exactly one rung: "free" doubles as the unentitled fallback (no live
|
|
@@ -844,6 +845,25 @@ export declare function assertAgentRunCeilingApproval(input: {
|
|
|
844
845
|
}): {
|
|
845
846
|
aboveDefault: boolean;
|
|
846
847
|
};
|
|
848
|
+
/**
|
|
849
|
+
* The same approval posture for a connected app's rolling 24-hour credit
|
|
850
|
+
* ceiling (ADR 0030 §11): at or under the default (the plan-sized trigger
|
|
851
|
+
* default) nothing more to approve; above it only with the explicit
|
|
852
|
+
* above-default approval, whose flag and refusal shape match the Agent run and
|
|
853
|
+
* trigger ceilings; above the platform maximum never. `defaultCredits` is the
|
|
854
|
+
* lowest default among the workspaces the app can spend in, so the approval
|
|
855
|
+
* covers every one of them.
|
|
856
|
+
*/
|
|
857
|
+
export declare function assertConnectionCreditCeilingApproval(input: {
|
|
858
|
+
creditCeiling: number;
|
|
859
|
+
defaultCredits: number;
|
|
860
|
+
approveAboveDefault: boolean;
|
|
861
|
+
appName: string;
|
|
862
|
+
/** The workspace whose default is the one compared, named in the refusal. */
|
|
863
|
+
workspaceName?: string;
|
|
864
|
+
}): {
|
|
865
|
+
aboveDefault: boolean;
|
|
866
|
+
};
|
|
847
867
|
/**
|
|
848
868
|
* The ceilings one run is held to, for the worker and every budget check that
|
|
849
869
|
* reads a run's authority. A run with a recorded above-default approval is
|