@oxygen-agent/cli 1.1011.626 → 1.1011.650
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/help.js +1 -1
- package/dist/index.js +4 -4
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.d.ts +8 -4
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.generated.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.generated.js +5 -1
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.js +6 -4
- package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +6 -0
- package/node_modules/@oxygen/shared/dist/provider-balance-signal.d.ts +8 -1
- package/node_modules/@oxygen/shared/dist/provider-balance-signal.js +34 -3
- package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/help.js
CHANGED
|
@@ -149,7 +149,7 @@ export function applyOxygenHelp(program, binaryName) {
|
|
|
149
149
|
` 3. ${binaryName} context resolve --json load workspace context before operating primitives`,
|
|
150
150
|
// Populated workspaces need the same first-win guidance as empty ones.
|
|
151
151
|
` Getting started or choosing what to do next? ${binaryName} skills get oxygen-onboarding --json`,
|
|
152
|
-
" It
|
|
152
|
+
" It sharpens your offer and ICP, then ranks the warmest leads you can reach now.",
|
|
153
153
|
` 4. ${binaryName} capabilities search "<goal>" --json route the goal, then hydrate one exact command`,
|
|
154
154
|
` ${binaryName} commands search "<term>" --json find a command by name or purpose instead of dumping the manifest`,
|
|
155
155
|
` 5. ${binaryName} recipes list "<goal>" --view summary --json choose a play from the Recipe catalog for your goal`,
|
package/dist/index.js
CHANGED
|
@@ -7108,7 +7108,7 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
7108
7108
|
.description("List workspace tables in the current tenant database.")
|
|
7109
7109
|
.option("--project <project>", "Project id or slug to filter by.")
|
|
7110
7110
|
.option("--tag <tag>", "Only tables carrying this workspace tag (see `oxygen tags list`).")
|
|
7111
|
-
.option("--include-archived", "Also list archived
|
|
7111
|
+
.option("--include-archived", "Also list archived, delete-scheduled and purging tables (the trash; each carries a lifecycle with purge_scheduled_at, and one with purgeStartedAt is being purged and can no longer be restored).")
|
|
7112
7112
|
.option("--limit <n>", "Maximum tables to list. Defaults to 200; hard cap is 1000.")
|
|
7113
7113
|
.option("--all", "List every table instead of the newest window.")
|
|
7114
7114
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -7324,7 +7324,7 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
7324
7324
|
});
|
|
7325
7325
|
}))
|
|
7326
7326
|
.addCommand(new Command("restore")
|
|
7327
|
-
.description("Restore an archived or delete-scheduled table: cancels the purge timer and reclaims its slug.")
|
|
7327
|
+
.description("Restore an archived or delete-scheduled table: cancels the purge timer and reclaims its slug. A table whose purge has begun (lifecycle.purgeStartedAt) can no longer be restored.")
|
|
7328
7328
|
.argument("[table]", "Table id or slug (the pre-delete slug works).")
|
|
7329
7329
|
.option("--tables <refs>", "Restore a comma-separated batch; alternative to the table argument.")
|
|
7330
7330
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -11209,8 +11209,8 @@ Examples:
|
|
|
11209
11209
|
}));
|
|
11210
11210
|
program
|
|
11211
11211
|
.command("limits")
|
|
11212
|
-
.description("Plan-tier limits, spend-safety defaults, per-channel sending limits, and storage capacity posture.")
|
|
11213
|
-
.addHelpText("after", "\nRun `oxygen limits show --json` to see your current plan's API and webhook rates, Table and workspace storage headroom, and the next scheduled change
|
|
11212
|
+
.description("Plan-tier limits, spend-safety defaults, per-channel sending limits, and storage capacity posture. `limits show --section capacity` returns storage alone, including which Table is full.")
|
|
11213
|
+
.addHelpText("after", "\nRun `oxygen limits show --json` to see your current plan's API and webhook rates, Table and workspace storage headroom, and the next scheduled change. The $999 and $1,999 rows-per-Table increases remain held until capacity testing passes.\n")
|
|
11214
11214
|
.addCommand(addContractFlags(new Command("show")
|
|
11215
11215
|
.description("Compare every plan size: price, monthly credits, volume bonus and price per 100 credits (`plan_bands`). Show your plan band and its limits beside every plan size's (API rate, webhook ingress, storage, import file size, columns per auto-run, signals feed, spend defaults incl. Agent and Copilot caps, fastest workflow schedule), the per-channel sending limits every plan shares (emails per mailbox, WhatsApp, LinkedIn, calls) and its workflow Code-step and run-attempt limits, plus Tables capacity usage naming the largest Table. Each plan size's storage says whether it is in force, scheduled to change on a date, or awaiting its rows-per-Table capacity test, with the values it moves to. `spend_safety_defaults.enterprise_agent_run_default` gives Enterprise the $1,999 band’s in-force Agent default with no contract override; `agent_run_approved_max_credits` is the maximum for an explicitly approved higher run. `spend_safety_defaults.applies_to` says what each spend default bounds: an unattended trigger delivery, a table auto-run batch, one Agent run, or the attended Copilot. `web_url` opens the same view in the web app (Settings → Plan limits), including any scheduled change. Read-only; spends no credits. Recovery: https://oxygen-agent.com/docs/safety/billing."), LIMITS_READ_QUERY_CONTRACT)
|
|
11216
11216
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -10,12 +10,16 @@ export type CopilotPlaybook = {
|
|
|
10
10
|
title: string;
|
|
11
11
|
/** The featured catalog recipe that carries this play: its kit, prerequisites and approval gates. */
|
|
12
12
|
recipeSlug: string;
|
|
13
|
+
/** The play's request in the person's own words, the same text its card copies (2026-10-03). */
|
|
14
|
+
prompt: string;
|
|
13
15
|
};
|
|
14
16
|
export declare const COPILOT_PLAYBOOKS: readonly CopilotPlaybook[];
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
18
|
+
* What a chip writes into the composer: the play's own request, the same words
|
|
19
|
+
* its prompt card copies for the person's agent (plays as prompts, current
|
|
20
|
+
* chat, 2026-10-03), then the skill named the way a person says it. The
|
|
21
|
+
* Copilot's prompt maps that title back to the slug, so the user reads and
|
|
22
|
+
* sends exactly what the chip promised.
|
|
19
23
|
*/
|
|
20
|
-
export declare function copilotPlaybookPrompt(playbook: Pick<CopilotPlaybook, "title">): string;
|
|
24
|
+
export declare function copilotPlaybookPrompt(playbook: Pick<CopilotPlaybook, "title" | "prompt">): string;
|
|
21
25
|
export declare function getCopilotPlaybook(slug: string): CopilotPlaybook | null;
|
|
@@ -2,16 +2,20 @@ export declare const COPILOT_PLAYBOOKS_GENERATED: readonly [{
|
|
|
2
2
|
readonly slug: "tam-sourcing";
|
|
3
3
|
readonly title: "TAM sourcing";
|
|
4
4
|
readonly recipeSlug: "icp-to-account-map";
|
|
5
|
+
readonly prompt: "Turn our ICP into a scored list of target accounts, with the evidence behind each score, so I can see which segments fit best.";
|
|
5
6
|
}, {
|
|
6
7
|
readonly slug: "linkedin-content-strategy";
|
|
7
8
|
readonly title: "LinkedIn content strategy";
|
|
8
9
|
readonly recipeSlug: "founder-posting-system";
|
|
10
|
+
readonly prompt: "Help me post on LinkedIn consistently in my own voice: draft posts from our positioning and ICP, let me approve each one, and track how they perform.";
|
|
9
11
|
}, {
|
|
10
12
|
readonly slug: "inbound-led-outbound";
|
|
11
13
|
readonly title: "Inbound-led outbound";
|
|
12
14
|
readonly recipeSlug: "inbound-led-outbound";
|
|
15
|
+
readonly prompt: "Turn the people who react to and comment on LinkedIn posts I pick into pipeline: score them against our ICP and message only the good fits from a capped sequence.";
|
|
13
16
|
}, {
|
|
14
17
|
readonly slug: "signal-based-outbound";
|
|
15
18
|
readonly title: "Signal-based outbound";
|
|
16
19
|
readonly recipeSlug: "daily-warm-lead-queue";
|
|
20
|
+
readonly prompt: "Give me one ranked list every morning of the warmest people to contact, from website visitors, profile viewers, post engagers and new followers.";
|
|
17
21
|
}];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// GENERATED by apps/web/scripts/generate-copilot-playbooks.ts from the recipe
|
|
2
|
-
// catalog (featured recipes: `featured_order`, `label`, `playbook` in
|
|
2
|
+
// catalog (featured recipes: `featured_order`, `label`, `playbook`, `prompt` in
|
|
3
3
|
// apps/web/src/agent-skills/oxygen-recipes/recipes).
|
|
4
4
|
// Do not edit by hand — run `npm run skills:metadata -w @oxygen/web`.
|
|
5
5
|
export const COPILOT_PLAYBOOKS_GENERATED = [
|
|
@@ -7,20 +7,24 @@ export const COPILOT_PLAYBOOKS_GENERATED = [
|
|
|
7
7
|
slug: "tam-sourcing",
|
|
8
8
|
title: "TAM sourcing",
|
|
9
9
|
recipeSlug: "icp-to-account-map",
|
|
10
|
+
prompt: "Turn our ICP into a scored list of target accounts, with the evidence behind each score, so I can see which segments fit best.",
|
|
10
11
|
},
|
|
11
12
|
{
|
|
12
13
|
slug: "linkedin-content-strategy",
|
|
13
14
|
title: "LinkedIn content strategy",
|
|
14
15
|
recipeSlug: "founder-posting-system",
|
|
16
|
+
prompt: "Help me post on LinkedIn consistently in my own voice: draft posts from our positioning and ICP, let me approve each one, and track how they perform.",
|
|
15
17
|
},
|
|
16
18
|
{
|
|
17
19
|
slug: "inbound-led-outbound",
|
|
18
20
|
title: "Inbound-led outbound",
|
|
19
21
|
recipeSlug: "inbound-led-outbound",
|
|
22
|
+
prompt: "Turn the people who react to and comment on LinkedIn posts I pick into pipeline: score them against our ICP and message only the good fits from a capped sequence.",
|
|
20
23
|
},
|
|
21
24
|
{
|
|
22
25
|
slug: "signal-based-outbound",
|
|
23
26
|
title: "Signal-based outbound",
|
|
24
27
|
recipeSlug: "daily-warm-lead-queue",
|
|
28
|
+
prompt: "Give me one ranked list every morning of the warmest people to contact, from website visitors, profile viewers, post engagers and new followers.",
|
|
25
29
|
},
|
|
26
30
|
];
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { COPILOT_PLAYBOOKS_GENERATED } from "./copilot-playbooks.generated.js";
|
|
2
2
|
export const COPILOT_PLAYBOOKS = COPILOT_PLAYBOOKS_GENERATED;
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* What a chip writes into the composer: the play's own request, the same words
|
|
5
|
+
* its prompt card copies for the person's agent (plays as prompts, current
|
|
6
|
+
* chat, 2026-10-03), then the skill named the way a person says it. The
|
|
7
|
+
* Copilot's prompt maps that title back to the slug, so the user reads and
|
|
8
|
+
* sends exactly what the chip promised.
|
|
7
9
|
*/
|
|
8
10
|
export function copilotPlaybookPrompt(playbook) {
|
|
9
|
-
return
|
|
11
|
+
return `${playbook.prompt} Use the ${playbook.title} skill.`;
|
|
10
12
|
}
|
|
11
13
|
export function getCopilotPlaybook(slug) {
|
|
12
14
|
return COPILOT_PLAYBOOKS.find((playbook) => playbook.slug === slug) ?? null;
|
|
@@ -153,6 +153,12 @@ export type KnowledgeBootstrapMarker = {
|
|
|
153
153
|
run_id: string | null;
|
|
154
154
|
/** Managed credits actually spent, across every phase. Never exceeds the cap. */
|
|
155
155
|
credits_used: number;
|
|
156
|
+
/**
|
|
157
|
+
* `unknown` when the pass stopped with no record of which provider calls it made: a
|
|
158
|
+
* legacy attempt closed as `interrupted_without_checkpoint`. `credits_used` is then
|
|
159
|
+
* not a measurement, and nothing about what was read or spent may be claimed.
|
|
160
|
+
*/
|
|
161
|
+
effect_outcome?: "unknown";
|
|
156
162
|
/**
|
|
157
163
|
* The workspace domain researched (from organizations.iconDomain). Null (stored
|
|
158
164
|
* as "", the key the execution and onboarding checks compare on) for a company
|
|
@@ -83,13 +83,18 @@ export declare function managedBalanceFloorEnvVar(provider: string): string;
|
|
|
83
83
|
/**
|
|
84
84
|
* The floor in force for one provider. `null` means "do not judge this balance".
|
|
85
85
|
*
|
|
86
|
+
* A wallet reported in a currency with no floor of its own gets `0`, not the credit
|
|
87
|
+
* default: an empty account is still `exhausted`, and how soon it empties is the
|
|
88
|
+
* runway monitor's question (`provider_balance.runway`, 14 days at measured burn).
|
|
89
|
+
* Give it a measured entry in MANAGED_BALANCE_FLOORS to warn earlier.
|
|
90
|
+
*
|
|
86
91
|
* The env override is the operator's escape hatch between deploys: a top-up that
|
|
87
92
|
* changes the plan size, or a provider that turns out to be noisy at the default,
|
|
88
93
|
* is one Doppler value away from being right. `off`/`none`/`disabled` switches the
|
|
89
94
|
* provider off the monitor entirely; an unparseable or negative value is IGNORED
|
|
90
95
|
* rather than obeyed, because a typo must not silently disarm an alert.
|
|
91
96
|
*/
|
|
92
|
-
export declare function managedBalanceFloor(provider: string, env?: Record<string, string | undefined
|
|
97
|
+
export declare function managedBalanceFloor(provider: string, env?: Record<string, string | undefined>, balanceUnit?: string | null): number | null;
|
|
93
98
|
export type ProviderBalanceVerdict = {
|
|
94
99
|
status: ProviderBalanceStatus;
|
|
95
100
|
/** The single boolean the monitor's description tells a responder to read. */
|
|
@@ -109,5 +114,7 @@ export declare function classifyManagedBalance(input: {
|
|
|
109
114
|
/** The balance fetcher's own status. Anything but "ok" means we are blind. */
|
|
110
115
|
fetchStatus: "ok" | "auth_error" | "rate_limited" | "error";
|
|
111
116
|
balanceRemaining: number | null;
|
|
117
|
+
/** The unit the fetcher reported. Decides whether the credit default may apply. */
|
|
118
|
+
balanceUnit?: string | null;
|
|
112
119
|
env?: Record<string, string | undefined>;
|
|
113
120
|
}): ProviderBalanceVerdict;
|
|
@@ -71,6 +71,20 @@ export const DEFAULT_MANAGED_BALANCE_FLOOR = 1_000;
|
|
|
71
71
|
* inherits DEFAULT_MANAGED_BALANCE_FLOOR.
|
|
72
72
|
*/
|
|
73
73
|
export const MANAGED_BALANCE_FLOORS = {
|
|
74
|
+
// R21, 2026-10-02. The two USD wallets below used to inherit the 1,000-CREDIT default
|
|
75
|
+
// (see CURRENCY_BALANCE_UNITS). Each floor applies that default's own intent — roughly
|
|
76
|
+
// three to eight days of measured burn, in the wallet's unit — to the largest 24-hour
|
|
77
|
+
// burn in prod `provider_balance.snapshot` from 2026-09-10 to 2026-10-02.
|
|
78
|
+
//
|
|
79
|
+
// Bright Data: largest 24h burn $0.17 (total $0.30 in 21.8 days), so the band is
|
|
80
|
+
// $0.51-$1.36. $1 is ~6 peak days.
|
|
81
|
+
brightdata: 1,
|
|
82
|
+
// InboxKit: one reseller wallet behind every tenant's managed mailbox orders, so it moves
|
|
83
|
+
// in purchase-sized steps; the largest 24h burn was one $28.75 step on 2026-09-28, and an
|
|
84
|
+
// order on 2026-08-17 was $22.25. Only 5.6 days of snapshots exist, so treat the maximum
|
|
85
|
+
// as thin. $90 is ~3 peak days; the runway P1 (<14 days at measured burn) is the earlier
|
|
86
|
+
// warning, and its line read 8.6 days (warn) for this wallet at 02:45 on 2026-10-02.
|
|
87
|
+
inboxkit: 90,
|
|
74
88
|
// A 1,000-credit/month plan. The default floor would mark it low on the first day
|
|
75
89
|
// of every billing period, forever — the classic alert nobody reads. Measured
|
|
76
90
|
// 2026-09-07: it has ranged 1,002 -> 670 over 30 days, so 150 is ~15% of the plan
|
|
@@ -96,16 +110,31 @@ export const MANAGED_BALANCE_FLOORS = {
|
|
|
96
110
|
export function managedBalanceFloorEnvVar(provider) {
|
|
97
111
|
return `OXYGEN_MANAGED_BALANCE_FLOOR_${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}`;
|
|
98
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Units that are money rather than provider credits. DEFAULT_MANAGED_BALANCE_FLOOR is a
|
|
115
|
+
* credit count, so it must never judge one of these: on 2026-10-02 it held Bright Data
|
|
116
|
+
* ($8.68 against a largest 24h burn of $0.17) and InboxKit ($144.07) "low" against a
|
|
117
|
+
* floor of 1,000, a number in a different unit from the wallet it judged.
|
|
118
|
+
*/
|
|
119
|
+
const CURRENCY_BALANCE_UNITS = new Set(["usd", "eur", "gbp"]);
|
|
120
|
+
function isCurrencyBalanceUnit(unit) {
|
|
121
|
+
return typeof unit === "string" && CURRENCY_BALANCE_UNITS.has(unit.trim().toLowerCase());
|
|
122
|
+
}
|
|
99
123
|
/**
|
|
100
124
|
* The floor in force for one provider. `null` means "do not judge this balance".
|
|
101
125
|
*
|
|
126
|
+
* A wallet reported in a currency with no floor of its own gets `0`, not the credit
|
|
127
|
+
* default: an empty account is still `exhausted`, and how soon it empties is the
|
|
128
|
+
* runway monitor's question (`provider_balance.runway`, 14 days at measured burn).
|
|
129
|
+
* Give it a measured entry in MANAGED_BALANCE_FLOORS to warn earlier.
|
|
130
|
+
*
|
|
102
131
|
* The env override is the operator's escape hatch between deploys: a top-up that
|
|
103
132
|
* changes the plan size, or a provider that turns out to be noisy at the default,
|
|
104
133
|
* is one Doppler value away from being right. `off`/`none`/`disabled` switches the
|
|
105
134
|
* provider off the monitor entirely; an unparseable or negative value is IGNORED
|
|
106
135
|
* rather than obeyed, because a typo must not silently disarm an alert.
|
|
107
136
|
*/
|
|
108
|
-
export function managedBalanceFloor(provider, env = process.env) {
|
|
137
|
+
export function managedBalanceFloor(provider, env = process.env, balanceUnit) {
|
|
109
138
|
const raw = env[managedBalanceFloorEnvVar(provider)]?.trim();
|
|
110
139
|
if (raw) {
|
|
111
140
|
const lowered = raw.toLowerCase();
|
|
@@ -118,7 +147,9 @@ export function managedBalanceFloor(provider, env = process.env) {
|
|
|
118
147
|
const configured = MANAGED_BALANCE_FLOORS[provider];
|
|
119
148
|
if (configured === null)
|
|
120
149
|
return null;
|
|
121
|
-
|
|
150
|
+
if (configured !== undefined)
|
|
151
|
+
return configured;
|
|
152
|
+
return isCurrencyBalanceUnit(balanceUnit) ? 0 : DEFAULT_MANAGED_BALANCE_FLOOR;
|
|
122
153
|
}
|
|
123
154
|
/**
|
|
124
155
|
* Turn one balance reading into the verdict both producers log.
|
|
@@ -127,7 +158,7 @@ export function managedBalanceFloor(provider, env = process.env) {
|
|
|
127
158
|
* without a provider, a cron, or a network.
|
|
128
159
|
*/
|
|
129
160
|
export function classifyManagedBalance(input) {
|
|
130
|
-
const floor = managedBalanceFloor(input.provider, input.env ?? process.env);
|
|
161
|
+
const floor = managedBalanceFloor(input.provider, input.env ?? process.env, input.balanceUnit);
|
|
131
162
|
if (input.fetchStatus !== "ok") {
|
|
132
163
|
// We could not read the balance. That is a monitoring outage, not a funding
|
|
133
164
|
// outage, so it must NOT enter the balance monitor: a rotated key would
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const OXYGEN_BUILD_VERSION = "1.1011.
|
|
1
|
+
export declare const OXYGEN_BUILD_VERSION = "1.1011.650";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// GENERATED by scripts/ci/version-stamp.mjs from VERSION + git history. Do not edit; do not commit.
|
|
2
|
-
export const OXYGEN_BUILD_VERSION = "1.1011.
|
|
2
|
+
export const OXYGEN_BUILD_VERSION = "1.1011.650";
|