@oxygen-agent/cli 1.1014.1035 → 1.1014.1132
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 +1 -0
- package/dist/commands/columns.js +1 -1
- package/dist/commands/deliverability.js +2 -0
- package/dist/commands/sequences.js +30 -2
- package/dist/commands/viewers.js +1 -2
- package/dist/credentials.js +1 -1
- package/dist/customer-operation-commands.js +62 -3
- package/dist/help.js +1 -1
- package/dist/index.d.ts +0 -97
- package/dist/index.js +0 -98
- package/dist/workspace-placement-commands.d.ts +3 -0
- package/dist/workspace-placement-commands.js +42 -0
- package/node_modules/@oxygen/shared/dist/agent-sessions.d.ts +6 -1
- package/node_modules/@oxygen/shared/dist/agent-sessions.js +18 -6
- package/node_modules/@oxygen/shared/dist/agents-enabled.d.ts +8 -9
- package/node_modules/@oxygen/shared/dist/agents-enabled.js +12 -8
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +24 -6
- package/node_modules/@oxygen/shared/dist/column-autofill.js +2 -2
- package/node_modules/@oxygen/shared/dist/contracts/agent-sessions.js +1 -1
- package/node_modules/@oxygen/shared/dist/contracts/customer-operations.js +1 -1
- package/node_modules/@oxygen/shared/dist/contracts/guided-activation.js +5 -5
- package/node_modules/@oxygen/shared/dist/contracts/guided-company-files.d.ts +30 -0
- package/node_modules/@oxygen/shared/dist/contracts/guided-company-files.js +53 -0
- package/node_modules/@oxygen/shared/dist/contracts/guided-first-sourcing.d.ts +120 -0
- package/node_modules/@oxygen/shared/dist/contracts/guided-first-sourcing.js +48 -0
- package/node_modules/@oxygen/shared/dist/contracts/guided-onboarding-journey.d.ts +267 -0
- package/node_modules/@oxygen/shared/dist/contracts/guided-onboarding-journey.js +63 -0
- package/node_modules/@oxygen/shared/dist/contracts/operations.d.ts +6 -0
- package/node_modules/@oxygen/shared/dist/contracts/operations.js +9 -4
- package/node_modules/@oxygen/shared/dist/contracts/table-query-raw.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/contracts/table-query-raw.js +3 -0
- package/node_modules/@oxygen/shared/dist/contracts/teammates.js +9 -8
- package/node_modules/@oxygen/shared/dist/data-suppliers.d.ts +32 -2
- package/node_modules/@oxygen/shared/dist/data-suppliers.js +44 -4
- package/node_modules/@oxygen/shared/dist/email-tracking-token.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/email-tracking-token.js +1 -0
- package/node_modules/@oxygen/shared/dist/feature-gates.d.ts +3 -4
- package/node_modules/@oxygen/shared/dist/feature-gates.js +3 -4
- package/node_modules/@oxygen/shared/dist/file-import.d.ts +46 -0
- package/node_modules/@oxygen/shared/dist/file-import.js +138 -0
- package/node_modules/@oxygen/shared/dist/guided-activation.d.ts +8 -0
- package/node_modules/@oxygen/shared/dist/guided-company-files.d.ts +13 -0
- package/node_modules/@oxygen/shared/dist/guided-company-files.js +14 -0
- package/node_modules/@oxygen/shared/dist/guided-first-sourcing.d.ts +116 -0
- package/node_modules/@oxygen/shared/dist/guided-first-sourcing.js +11 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-answers.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-answers.js +42 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-company-context.d.ts +22 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-company-context.js +38 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-journey.d.ts +147 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-journey.fixture.d.ts +12 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-journey.fixture.js +83 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-journey.js +44 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-prospects.d.ts +7 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-prospects.js +13 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-signals.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-signals.js +34 -0
- package/node_modules/@oxygen/shared/dist/guided-trial-billing.d.ts +26 -0
- package/node_modules/@oxygen/shared/dist/guided-trial-billing.js +19 -0
- package/node_modules/@oxygen/shared/dist/hosted-ai.js +108 -118
- package/node_modules/@oxygen/shared/dist/knowledge-links.d.ts +29 -0
- package/node_modules/@oxygen/shared/dist/knowledge-links.js +84 -1
- package/node_modules/@oxygen/shared/dist/linkedin-sequences.d.ts +5 -14
- package/node_modules/@oxygen/shared/dist/linkedin-sequences.js +22 -5
- package/node_modules/@oxygen/shared/dist/managed-scraper-backend.d.ts +18 -0
- package/node_modules/@oxygen/shared/dist/managed-scraper-backend.js +17 -0
- package/node_modules/@oxygen/shared/dist/teammates.d.ts +7 -5
- package/node_modules/@oxygen/shared/dist/teammates.js +11 -20
- package/node_modules/@oxygen/shared/dist/user-capability-routing.js +88 -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/dist/workspace-placement-view.d.ts +150 -0
- package/node_modules/@oxygen/shared/dist/workspace-placement-view.js +102 -0
- package/node_modules/@oxygen/shared/dist/workspace-placement.d.ts +84 -0
- package/node_modules/@oxygen/shared/dist/workspace-placement.js +107 -0
- package/package.json +1 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/** Full DEV onboarding, approved by Philipp on 2026-10-16.
|
|
2
|
+
* Browser-safe vocabulary. Native owners, never navigation or caller assertions,
|
|
3
|
+
* establish research results, billing eligibility and resource authority. */
|
|
4
|
+
export declare const GUIDED_ONBOARDING_JOURNEY_VERSION: 1;
|
|
5
|
+
export declare const GUIDED_ONBOARDING_PART1_STEPS: readonly ["company_context", "company_research", "company_review", "audience_company_size", "audience_markets", "audience_industries", "audience_personas", "signals", "prospects", "trial"];
|
|
6
|
+
export declare const GUIDED_ONBOARDING_PART2_STEPS: readonly ["welcome", "daily_rhythm", "linkedin", "campaign", "sequence", "routines", "tour"];
|
|
7
|
+
export declare const GUIDED_ONBOARDING_STEPS: readonly ["company_context", "company_research", "company_review", "audience_company_size", "audience_markets", "audience_industries", "audience_personas", "signals", "prospects", "trial", "welcome", "daily_rhythm", "linkedin", "campaign", "sequence", "routines", "tour", "complete"];
|
|
8
|
+
export type GuidedOnboardingStep = typeof GUIDED_ONBOARDING_STEPS[number];
|
|
9
|
+
export type GuidedOnboardingPart = "part1" | "part2" | "complete";
|
|
10
|
+
export declare function guidedOnboardingPart(step: GuidedOnboardingStep): GuidedOnboardingPart;
|
|
11
|
+
export type GuidedOnboardingChoice = {
|
|
12
|
+
values: string[];
|
|
13
|
+
};
|
|
14
|
+
export type GuidedOnboardingSignal = {
|
|
15
|
+
mode: "none" | "selected";
|
|
16
|
+
values: string[];
|
|
17
|
+
};
|
|
18
|
+
export declare const GUIDED_ONBOARDING_TECHNOLOGY_RELATIONSHIPS: readonly ["uses", "replaces", "integrates_with"];
|
|
19
|
+
export type GuidedOnboardingTechnologyRelationship = typeof GUIDED_ONBOARDING_TECHNOLOGY_RELATIONSHIPS[number];
|
|
20
|
+
export type GuidedOnboardingTechnology = {
|
|
21
|
+
name: string;
|
|
22
|
+
relationship: GuidedOnboardingTechnologyRelationship;
|
|
23
|
+
};
|
|
24
|
+
export type GuidedOnboardingTechnologySignal = {
|
|
25
|
+
mode: "none" | "selected";
|
|
26
|
+
values: GuidedOnboardingTechnology[];
|
|
27
|
+
};
|
|
28
|
+
export type GuidedOnboardingAnswers = {
|
|
29
|
+
company_context?: {
|
|
30
|
+
website: string | null;
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
context_links: string[];
|
|
34
|
+
file_ids: string[];
|
|
35
|
+
};
|
|
36
|
+
/** Saving a statement alone is not its native confirmation receipt. */
|
|
37
|
+
company_review?: {
|
|
38
|
+
statement: string;
|
|
39
|
+
profile_revision: string;
|
|
40
|
+
};
|
|
41
|
+
audience_company_size?: GuidedOnboardingChoice;
|
|
42
|
+
audience_markets?: GuidedOnboardingChoice;
|
|
43
|
+
audience_industries?: GuidedOnboardingChoice;
|
|
44
|
+
audience_personas?: GuidedOnboardingChoice;
|
|
45
|
+
signals?: {
|
|
46
|
+
hiring: GuidedOnboardingSignal;
|
|
47
|
+
technology: GuidedOnboardingTechnologySignal;
|
|
48
|
+
};
|
|
49
|
+
prospects?: {
|
|
50
|
+
decision: "continue" | "refine";
|
|
51
|
+
feedback: string;
|
|
52
|
+
};
|
|
53
|
+
/** Connect is an intent. Only the native sender owner can prove a connection. */
|
|
54
|
+
linkedin?: {
|
|
55
|
+
choice: "connect" | "skip";
|
|
56
|
+
};
|
|
57
|
+
/** A draft remains a valid outcome on the optional LinkedIn branch. */
|
|
58
|
+
sequence?: {
|
|
59
|
+
decision: "review" | "keep_draft";
|
|
60
|
+
};
|
|
61
|
+
tour?: {
|
|
62
|
+
visited: Array<"overview" | "leads" | "sourcing" | "sequence">;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export type GuidedOnboardingResearchStatus = "not_started" | "running" | "completed" | "partial" | "unavailable" | "failed" | "credits_exhausted";
|
|
66
|
+
export type GuidedOnboardingResearch = {
|
|
67
|
+
status: GuidedOnboardingResearchStatus;
|
|
68
|
+
run_id: string | null;
|
|
69
|
+
knowledge_page_ids: string[];
|
|
70
|
+
/** Fixed customer-safe code only. Provider diagnostics remain in their owner. */
|
|
71
|
+
fault: {
|
|
72
|
+
code: string;
|
|
73
|
+
retryable: boolean;
|
|
74
|
+
} | null;
|
|
75
|
+
};
|
|
76
|
+
export type GuidedOnboardingProspect = {
|
|
77
|
+
row_id: string;
|
|
78
|
+
person_key: string;
|
|
79
|
+
name: string;
|
|
80
|
+
title: string;
|
|
81
|
+
company: string;
|
|
82
|
+
linkedin_url: string | null;
|
|
83
|
+
sources: Array<{
|
|
84
|
+
url: string;
|
|
85
|
+
title: string;
|
|
86
|
+
}>;
|
|
87
|
+
fit: {
|
|
88
|
+
rationale: string;
|
|
89
|
+
criteria: string[];
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
export type GuidedOnboardingProspectLimitation = {
|
|
93
|
+
field: string;
|
|
94
|
+
code: "unsupported_filter";
|
|
95
|
+
blocking: boolean;
|
|
96
|
+
message: string;
|
|
97
|
+
values: string[];
|
|
98
|
+
suggestions: string[];
|
|
99
|
+
};
|
|
100
|
+
export type GuidedOnboardingProspects = {
|
|
101
|
+
status: "not_started" | "running" | "ready" | "partial" | "empty" | "unavailable" | "failed" | "credits_exhausted";
|
|
102
|
+
table_id: string | null;
|
|
103
|
+
ingestion_run_ids: string[];
|
|
104
|
+
/** Up to five native source-backed people; an empty array is never success. */
|
|
105
|
+
people: GuidedOnboardingProspect[];
|
|
106
|
+
/** Absent in legacy receipts means unknown, never proof of supported filters.
|
|
107
|
+
* Current D projections supply actual structured diagnostics, including []. */
|
|
108
|
+
limitations?: GuidedOnboardingProspectLimitation[];
|
|
109
|
+
fault: {
|
|
110
|
+
code: string;
|
|
111
|
+
retryable: boolean;
|
|
112
|
+
} | null;
|
|
113
|
+
};
|
|
114
|
+
/** Read projection from native billing, not an accepted browser mutation field.
|
|
115
|
+
* I owns the actual test Checkout/subscription/grant producer and its signatures. */
|
|
116
|
+
export type GuidedOnboardingEligibility = {
|
|
117
|
+
state: "unverified" | "checkout_required" | "checkout_pending" | "eligible" | "unavailable";
|
|
118
|
+
basis: "paid" | "trial" | null;
|
|
119
|
+
subscription_id: string | null;
|
|
120
|
+
observed_at: string | null;
|
|
121
|
+
trial_ends_at: string | null;
|
|
122
|
+
};
|
|
123
|
+
export type GuidedOnboardingJourney = {
|
|
124
|
+
version: typeof GUIDED_ONBOARDING_JOURNEY_VERSION;
|
|
125
|
+
/** Increments on non-destructive restart; activation revision guards writes. */
|
|
126
|
+
generation: number;
|
|
127
|
+
step: GuidedOnboardingStep;
|
|
128
|
+
completed_steps: GuidedOnboardingStep[];
|
|
129
|
+
/** Presentation state is authoritative and independent of deduplicated history. */
|
|
130
|
+
navigation: {
|
|
131
|
+
paused: boolean;
|
|
132
|
+
tour_active_stop: "overview" | "leads" | "sourcing" | "sequence" | null;
|
|
133
|
+
};
|
|
134
|
+
answers: GuidedOnboardingAnswers;
|
|
135
|
+
/** Native confirmation binds the actual typed company profile revision. */
|
|
136
|
+
company_confirmation: {
|
|
137
|
+
profile_revision: string;
|
|
138
|
+
statement_digest: string;
|
|
139
|
+
confirmed_at: string;
|
|
140
|
+
} | null;
|
|
141
|
+
research: GuidedOnboardingResearch;
|
|
142
|
+
prospects: GuidedOnboardingProspects;
|
|
143
|
+
};
|
|
144
|
+
/** Free initialization; creates no research, chat turn, subscription or resource. */
|
|
145
|
+
export declare function createGuidedOnboardingJourney(): GuidedOnboardingJourney;
|
|
146
|
+
/** Old saved v1 records have no current-stop evidence. Never guess from visited[]. */
|
|
147
|
+
export declare function normalizeSavedGuidedOnboardingJourney(journey: GuidedOnboardingJourney): GuidedOnboardingJourney;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type GuidedOnboardingJourney, type GuidedOnboardingEligibility } from "./guided-onboarding-journey.js";
|
|
2
|
+
/** Synthetic component/test data only. Never substitute this for hosted receipts. */
|
|
3
|
+
export declare const GUIDED_ONBOARDING_FIXTURE_NAMES: readonly ["part1_initial", "research_running", "company_review", "audience_question", "technology_relationships", "prospects_ready", "prospects_partial", "prospects_empty", "prospects_unavailable", "prospects_failed", "research_failed", "credits_exhausted", "checkout_pending", "billing_unavailable", "part2_trial", "part2_paid", "linkedin_skipped", "tour_paused_back", "complete"];
|
|
4
|
+
export type GuidedOnboardingFixtureName = typeof GUIDED_ONBOARDING_FIXTURE_NAMES[number];
|
|
5
|
+
export type GuidedOnboardingFixture = {
|
|
6
|
+
fixture_only: true;
|
|
7
|
+
label: string;
|
|
8
|
+
activation_revision: number;
|
|
9
|
+
journey: GuidedOnboardingJourney;
|
|
10
|
+
eligibility: GuidedOnboardingEligibility;
|
|
11
|
+
};
|
|
12
|
+
export declare function createGuidedOnboardingFixture(name: GuidedOnboardingFixtureName): GuidedOnboardingFixture;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createGuidedOnboardingJourney, GUIDED_ONBOARDING_STEPS, } from "./guided-onboarding-journey.js";
|
|
2
|
+
/** Synthetic component/test data only. Never substitute this for hosted receipts. */
|
|
3
|
+
export const GUIDED_ONBOARDING_FIXTURE_NAMES = [
|
|
4
|
+
"part1_initial", "research_running", "company_review", "audience_question", "technology_relationships",
|
|
5
|
+
"prospects_ready", "prospects_partial", "prospects_empty", "prospects_unavailable", "prospects_failed", "research_failed",
|
|
6
|
+
"credits_exhausted", "checkout_pending", "billing_unavailable", "part2_trial", "part2_paid", "linkedin_skipped", "tour_paused_back", "complete",
|
|
7
|
+
];
|
|
8
|
+
export function createGuidedOnboardingFixture(name) {
|
|
9
|
+
const fixture = {
|
|
10
|
+
fixture_only: true, label: `Synthetic onboarding fixture: ${name}`, activation_revision: 7,
|
|
11
|
+
journey: createGuidedOnboardingJourney(),
|
|
12
|
+
eligibility: { state: "checkout_required", basis: null, subscription_id: null, observed_at: "2026-10-16T12:00:00.000Z", trial_ends_at: null },
|
|
13
|
+
};
|
|
14
|
+
const { journey, eligibility } = fixture;
|
|
15
|
+
if (name === "research_running") {
|
|
16
|
+
journey.step = "company_research";
|
|
17
|
+
journey.research = { status: "running", run_id: "fixture-research-run", knowledge_page_ids: [], fault: null };
|
|
18
|
+
}
|
|
19
|
+
else if (name === "company_review") {
|
|
20
|
+
journey.step = "company_review";
|
|
21
|
+
journey.answers.company_review = { statement: "Synthetic company statement for panel tests.", profile_revision: "3" };
|
|
22
|
+
journey.research = { status: "completed", run_id: "fixture-research-run", knowledge_page_ids: ["fixture-company-page"], fault: null };
|
|
23
|
+
}
|
|
24
|
+
else if (name === "audience_question") {
|
|
25
|
+
journey.step = "audience_markets";
|
|
26
|
+
journey.answers.audience_company_size = { values: ["11–50"] };
|
|
27
|
+
journey.answers.audience_markets = { values: ["Germany", "Custom test market"] };
|
|
28
|
+
}
|
|
29
|
+
else if (name === "technology_relationships") {
|
|
30
|
+
journey.step = "signals";
|
|
31
|
+
journey.answers.signals = {
|
|
32
|
+
hiring: { mode: "selected", values: ["Revenue Operations Manager"] },
|
|
33
|
+
technology: { mode: "selected", values: [
|
|
34
|
+
{ name: "Apollo", relationship: "replaces" },
|
|
35
|
+
{ name: "Apollo", relationship: "integrates_with" },
|
|
36
|
+
] },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
else if (name.startsWith("prospects_")) {
|
|
40
|
+
journey.step = "prospects";
|
|
41
|
+
journey.prospects.status = name === "prospects_ready" ? "ready" : name === "prospects_partial" ? "partial"
|
|
42
|
+
: name === "prospects_unavailable" ? "unavailable" : name === "prospects_failed" ? "failed" : "empty";
|
|
43
|
+
journey.prospects.table_id = "fixture-prospects-table";
|
|
44
|
+
if (name === "prospects_ready" || name === "prospects_partial") {
|
|
45
|
+
journey.prospects.ingestion_run_ids = ["fixture-prospects-ingestion"];
|
|
46
|
+
journey.prospects.people = Array.from({ length: name === "prospects_ready" ? 5 : 2 }, (_, index) => ({
|
|
47
|
+
row_id: `fixture-person-${index + 1}`, person_key: `fixture-key-${index + 1}`,
|
|
48
|
+
name: `Example Buyer ${index + 1}`, title: "Example sales leader", company: "Example Company",
|
|
49
|
+
linkedin_url: null, sources: [{ url: "https://example.test/source", title: "Synthetic source — not provider evidence" }],
|
|
50
|
+
fit: { rationale: "Synthetic fit explanation for layout tests.", criteria: ["example persona"] },
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (name === "research_failed" || name === "credits_exhausted") {
|
|
55
|
+
journey.step = "company_research";
|
|
56
|
+
journey.research.status = name === "research_failed" ? "failed" : "credits_exhausted";
|
|
57
|
+
journey.research.fault = { code: name === "research_failed" ? "research_unavailable" : "insufficient_credits", retryable: name === "research_failed" };
|
|
58
|
+
}
|
|
59
|
+
else if (name === "checkout_pending" || name === "billing_unavailable") {
|
|
60
|
+
journey.step = "trial";
|
|
61
|
+
eligibility.state = name === "checkout_pending" ? "checkout_pending" : "unavailable";
|
|
62
|
+
}
|
|
63
|
+
else if (["part2_trial", "part2_paid", "linkedin_skipped", "tour_paused_back", "complete"].includes(name)) {
|
|
64
|
+
journey.step = name === "complete" ? "complete" : name === "linkedin_skipped" ? "campaign" : name === "tour_paused_back" ? "tour" : "welcome";
|
|
65
|
+
eligibility.state = "eligible";
|
|
66
|
+
eligibility.basis = name === "part2_paid" ? "paid" : "trial";
|
|
67
|
+
eligibility.subscription_id = "fixture-subscription";
|
|
68
|
+
eligibility.trial_ends_at = eligibility.basis === "trial" ? "2026-10-23T12:00:00.000Z" : null;
|
|
69
|
+
if (name === "linkedin_skipped")
|
|
70
|
+
journey.answers.linkedin = { choice: "skip" };
|
|
71
|
+
}
|
|
72
|
+
const index = GUIDED_ONBOARDING_STEPS.indexOf(journey.step);
|
|
73
|
+
journey.completed_steps = GUIDED_ONBOARDING_STEPS.slice(0, index);
|
|
74
|
+
if (index > GUIDED_ONBOARDING_STEPS.indexOf("company_review")) {
|
|
75
|
+
journey.answers.company_review = { statement: "Synthetic reviewed company statement.", profile_revision: "3" };
|
|
76
|
+
journey.company_confirmation = { profile_revision: "3", statement_digest: "a".repeat(64), confirmed_at: "2026-10-16T12:00:00.000Z" };
|
|
77
|
+
}
|
|
78
|
+
if (name === "tour_paused_back") {
|
|
79
|
+
journey.answers.tour = { visited: ["overview", "leads", "sourcing"] };
|
|
80
|
+
journey.navigation = { paused: true, tour_active_stop: "leads" };
|
|
81
|
+
}
|
|
82
|
+
return fixture;
|
|
83
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Full DEV onboarding, approved by Philipp on 2026-10-16.
|
|
2
|
+
* Browser-safe vocabulary. Native owners, never navigation or caller assertions,
|
|
3
|
+
* establish research results, billing eligibility and resource authority. */
|
|
4
|
+
export const GUIDED_ONBOARDING_JOURNEY_VERSION = 1;
|
|
5
|
+
export const GUIDED_ONBOARDING_PART1_STEPS = [
|
|
6
|
+
"company_context", "company_research", "company_review",
|
|
7
|
+
"audience_company_size", "audience_markets", "audience_industries", "audience_personas",
|
|
8
|
+
"signals", "prospects", "trial",
|
|
9
|
+
];
|
|
10
|
+
export const GUIDED_ONBOARDING_PART2_STEPS = [
|
|
11
|
+
"welcome", "daily_rhythm", "linkedin", "campaign", "sequence", "routines", "tour",
|
|
12
|
+
];
|
|
13
|
+
export const GUIDED_ONBOARDING_STEPS = [
|
|
14
|
+
...GUIDED_ONBOARDING_PART1_STEPS, ...GUIDED_ONBOARDING_PART2_STEPS, "complete",
|
|
15
|
+
];
|
|
16
|
+
export function guidedOnboardingPart(step) {
|
|
17
|
+
if (step === "complete")
|
|
18
|
+
return "complete";
|
|
19
|
+
if (GUIDED_ONBOARDING_PART1_STEPS.includes(step))
|
|
20
|
+
return "part1";
|
|
21
|
+
if (GUIDED_ONBOARDING_PART2_STEPS.includes(step))
|
|
22
|
+
return "part2";
|
|
23
|
+
throw new TypeError("Unknown onboarding step.");
|
|
24
|
+
}
|
|
25
|
+
export const GUIDED_ONBOARDING_TECHNOLOGY_RELATIONSHIPS = ["uses", "replaces", "integrates_with"];
|
|
26
|
+
/** Free initialization; creates no research, chat turn, subscription or resource. */
|
|
27
|
+
export function createGuidedOnboardingJourney() {
|
|
28
|
+
return {
|
|
29
|
+
version: GUIDED_ONBOARDING_JOURNEY_VERSION, generation: 1, step: "company_context",
|
|
30
|
+
completed_steps: [], navigation: { paused: false, tour_active_stop: null }, answers: {}, company_confirmation: null,
|
|
31
|
+
research: { status: "not_started", run_id: null, knowledge_page_ids: [], fault: null },
|
|
32
|
+
prospects: { status: "not_started", table_id: null, ingestion_run_ids: [], people: [], fault: null },
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Old saved v1 records have no current-stop evidence. Never guess from visited[]. */
|
|
36
|
+
export function normalizeSavedGuidedOnboardingJourney(journey) {
|
|
37
|
+
if (journey.navigation === undefined)
|
|
38
|
+
return { ...journey, navigation: { paused: false, tour_active_stop: null } };
|
|
39
|
+
const navigation = journey.navigation;
|
|
40
|
+
if (!navigation || typeof navigation.paused !== "boolean" || (navigation.tour_active_stop !== null
|
|
41
|
+
&& !["overview", "leads", "sourcing", "sequence"].includes(navigation.tour_active_stop)))
|
|
42
|
+
throw new TypeError("Invalid saved onboarding navigation.");
|
|
43
|
+
return journey;
|
|
44
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GuidedOnboardingProspectLimitation, GuidedOnboardingProspects } from "./guided-onboarding-journey.js";
|
|
2
|
+
/** Bind actual D result.targeting.limitations, never infer support from success,
|
|
3
|
+
* an empty people list, a legacy absence, or a general fault. Preserve native
|
|
4
|
+
* result status/fit/source/ingestion truth and the compatible fault unchanged. */
|
|
5
|
+
export declare function projectGuidedOnboardingProspects(prospects: GuidedOnboardingProspects, limitations: unknown): GuidedOnboardingProspects & {
|
|
6
|
+
limitations: GuidedOnboardingProspectLimitation[];
|
|
7
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { OxygenError } from "./cli-result.js";
|
|
2
|
+
import { arr, bool, enumOf, obj, str, validateContract } from "./contracts/schema.js";
|
|
3
|
+
const limitationsContract = obj({ limitations: arr(obj({ field: str({ minLength: 1 }), code: enumOf(["unsupported_filter"]),
|
|
4
|
+
blocking: bool(), message: str({ minLength: 1 }), values: arr(str()), suggestions: arr(str()) }, { required: ["field", "code", "blocking", "message", "values", "suggestions"] })) }, { required: ["limitations"] });
|
|
5
|
+
/** Bind actual D result.targeting.limitations, never infer support from success,
|
|
6
|
+
* an empty people list, a legacy absence, or a general fault. Preserve native
|
|
7
|
+
* result status/fit/source/ingestion truth and the compatible fault unchanged. */
|
|
8
|
+
export function projectGuidedOnboardingProspects(prospects, limitations) {
|
|
9
|
+
const checked = validateContract(limitationsContract, { limitations }, { unknown: "reject", overMax: "reject" });
|
|
10
|
+
if (!checked.ok)
|
|
11
|
+
throw new OxygenError("onboarding_preview_diagnostics_invalid", "The preview could not describe its supported targeting. Review your saved criteria before retrying.");
|
|
12
|
+
return { ...prospects, limitations: checked.value.limitations.map(item => ({ ...item, values: [...item.values], suggestions: [...item.suggestions] })) };
|
|
13
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GuidedOnboardingAnswers } from "./guided-onboarding-journey.js";
|
|
2
|
+
/** Same product with distinct relationships is intentional, not a duplicate.
|
|
3
|
+
* This normalizes saved intent, never claims that a provider supports a filter. */
|
|
4
|
+
export declare function normalizeGuidedOnboardingSignals(value: unknown): NonNullable<GuidedOnboardingAnswers["signals"]>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { OxygenError } from "./cli-result.js";
|
|
2
|
+
import { validateContract } from "./contracts/schema.js";
|
|
3
|
+
import { GUIDED_ONBOARDING_SIGNALS_CONTRACT } from "./contracts/guided-onboarding-journey.js";
|
|
4
|
+
const fail = () => {
|
|
5
|
+
throw new OxygenError("invalid_onboarding_answer", "Choose hiring roles and technologies with uses, replaces or integrates_with, or explicitly choose none.", { exitCode: 2 });
|
|
6
|
+
};
|
|
7
|
+
const displayName = (name) => name.normalize("NFKC").trim().replace(/\s+/gu, " ");
|
|
8
|
+
/** Same product with distinct relationships is intentional, not a duplicate.
|
|
9
|
+
* This normalizes saved intent, never claims that a provider supports a filter. */
|
|
10
|
+
export function normalizeGuidedOnboardingSignals(value) {
|
|
11
|
+
const parsed = validateContract(GUIDED_ONBOARDING_SIGNALS_CONTRACT, value, { unknown: "reject", overMax: "reject" });
|
|
12
|
+
if (!parsed.ok)
|
|
13
|
+
return fail();
|
|
14
|
+
const { hiring, technology } = parsed.value;
|
|
15
|
+
if ((hiring.mode === "none") !== (hiring.values.length === 0)
|
|
16
|
+
|| (technology.mode === "none") !== (technology.values.length === 0))
|
|
17
|
+
return fail();
|
|
18
|
+
const roles = hiring.values.map(displayName);
|
|
19
|
+
if (roles.some(role => !role))
|
|
20
|
+
return fail();
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
const technologies = [];
|
|
23
|
+
for (const item of technology.values) {
|
|
24
|
+
const name = displayName(item.name);
|
|
25
|
+
if (!name)
|
|
26
|
+
return fail();
|
|
27
|
+
const key = JSON.stringify([name.toLowerCase(), item.relationship]);
|
|
28
|
+
if (seen.has(key))
|
|
29
|
+
continue;
|
|
30
|
+
seen.add(key);
|
|
31
|
+
technologies.push({ name, relationship: item.relationship });
|
|
32
|
+
}
|
|
33
|
+
return { hiring: { mode: hiring.mode, values: roles }, technology: { mode: technology.mode, values: technologies } };
|
|
34
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** DEV onboarding offer. Existing subscription terms and production acquisition stay intact. */
|
|
2
|
+
export declare const GUIDED_TRIAL_OFFER: {
|
|
3
|
+
readonly key: "guided_onboarding_v2";
|
|
4
|
+
readonly plan: "oxygen_49";
|
|
5
|
+
readonly currency: "usd";
|
|
6
|
+
readonly trial_days: 7;
|
|
7
|
+
readonly trial_credits: 2000;
|
|
8
|
+
readonly amount_due_now_cents: 0;
|
|
9
|
+
readonly monthly_price_cents: 4900;
|
|
10
|
+
readonly card_required: true;
|
|
11
|
+
readonly early_charge_allowed: false;
|
|
12
|
+
};
|
|
13
|
+
export declare function guidedTrialAcquisitionEnabled(env?: Record<string, string | undefined>): boolean;
|
|
14
|
+
export declare function isGuidedTrialSubscription(metadata: Record<string, unknown> | null | undefined): boolean;
|
|
15
|
+
export type GuidedTrialBilling = {
|
|
16
|
+
offer: typeof GUIDED_TRIAL_OFFER;
|
|
17
|
+
eligible: boolean;
|
|
18
|
+
checkout_allowed: boolean;
|
|
19
|
+
state: "trial" | "paid" | "checkout_required" | "trial_unavailable" | "subscription_pending";
|
|
20
|
+
billing_owner_organization_id: string;
|
|
21
|
+
subscription_id: string | null;
|
|
22
|
+
trial_ends_at: string | null;
|
|
23
|
+
cancellation_scheduled: boolean;
|
|
24
|
+
spendable_credits: number;
|
|
25
|
+
funded_work_paused: boolean;
|
|
26
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { guidedActivationEnabled } from "./guided-activation.js";
|
|
2
|
+
/** DEV onboarding offer. Existing subscription terms and production acquisition stay intact. */
|
|
3
|
+
export const GUIDED_TRIAL_OFFER = {
|
|
4
|
+
key: "guided_onboarding_v2",
|
|
5
|
+
plan: "oxygen_49",
|
|
6
|
+
currency: "usd",
|
|
7
|
+
trial_days: 7,
|
|
8
|
+
trial_credits: 2_000,
|
|
9
|
+
amount_due_now_cents: 0,
|
|
10
|
+
monthly_price_cents: 4_900,
|
|
11
|
+
card_required: true,
|
|
12
|
+
early_charge_allowed: false,
|
|
13
|
+
};
|
|
14
|
+
export function guidedTrialAcquisitionEnabled(env = process.env) {
|
|
15
|
+
return guidedActivationEnabled(env);
|
|
16
|
+
}
|
|
17
|
+
export function isGuidedTrialSubscription(metadata) {
|
|
18
|
+
return metadata?.oxygen_trial_offer === GUIDED_TRIAL_OFFER.key;
|
|
19
|
+
}
|
|
@@ -22,6 +22,101 @@
|
|
|
22
22
|
* can re-source the catalog without dragging the barrel in.
|
|
23
23
|
*/
|
|
24
24
|
import { copilotAudience, isCopilotFlagOn } from "./copilot-access.js";
|
|
25
|
+
/**
|
|
26
|
+
* The Copilot's tiers, which an Oxygent's own chat runs at. Hoisted out of the
|
|
27
|
+
* registry so the Agent use case can share the same spec objects.
|
|
28
|
+
*/
|
|
29
|
+
const COPILOT_MODEL_SPECS = {
|
|
30
|
+
/**
|
|
31
|
+
* "Oxygen Auto" -- the earlier default, retained as an explicit choice.
|
|
32
|
+
* Its conversation thread stays fixed for its whole life. It is NOT a router: the
|
|
33
|
+
* model never changes mid-session, because an OpenRouter prompt cache is
|
|
34
|
+
* model-scoped and a mid-turn switch would turn a ~66% cache HIT rate into a
|
|
35
|
+
* cache WRITE on a fresh model, ten times a turn. Models only change below
|
|
36
|
+
* this thread, where the context is fresh -- see COPILOT_ERRAND_LEVEL.
|
|
37
|
+
*
|
|
38
|
+
* Before the 2026-10-10 Sol refresh, Auto ran Kimi K3. Its
|
|
39
|
+
* `reasoningEffort: "medium"` made that tier worth shipping.
|
|
40
|
+
* Until 2026-09-21 Kimi was sent with NO `reasoning` field at
|
|
41
|
+
* all, on a registry comment asserting K3 was max-reasoning-only. Measured
|
|
42
|
+
* against the live API on the same prompt and tool schema, that claim was
|
|
43
|
+
* false and the omission was the expensive case:
|
|
44
|
+
*
|
|
45
|
+
* omitted -> 412 reasoning tokens, $0.00779, 10.0s
|
|
46
|
+
* low -> 206, $0.00566, 9.2s
|
|
47
|
+
* medium -> 124, $0.00342, 4.8s <- 56% cheaper, 2.1x faster
|
|
48
|
+
* high -> 528, $0.01075, 14.8s
|
|
49
|
+
*
|
|
50
|
+
* All four returned the same answer. Reasoning was 38% of output tokens on a
|
|
51
|
+
* surface where output is ~61% of the bill.
|
|
52
|
+
*/
|
|
53
|
+
auto: {
|
|
54
|
+
model: "openai/gpt-6.1-sol",
|
|
55
|
+
displayName: "Oxygen Auto",
|
|
56
|
+
// Approved 2026-10-10 for NEW sessions. Existing sessions retain their
|
|
57
|
+
// persisted resolved_model; Kimi's priced spec survives in the legacy map.
|
|
58
|
+
fallbackModels: ["anthropic/claude-sonnet-5.5"],
|
|
59
|
+
reasoningEffort: "medium",
|
|
60
|
+
estPromptUsdPerM: 2,
|
|
61
|
+
estCompletionUsdPerM: 10,
|
|
62
|
+
// Reasoning tokens count against this cap, so 8,192 left a long tool call
|
|
63
|
+
// (a full sequence draft, a wide table write) to be cut off mid-argument,
|
|
64
|
+
// which fails the turn on the second time. Credit holds are sized from the
|
|
65
|
+
// expected output (billing.ts), so this moves only the conservative clamp.
|
|
66
|
+
maxOutputTokens: 16_384,
|
|
67
|
+
},
|
|
68
|
+
low: {
|
|
69
|
+
// The errand model: sub-agents, compaction summaries and auto-titles. A
|
|
70
|
+
// child builds its own Agent with its own messages, so it starts cold on
|
|
71
|
+
// any model -- which is why a switch is free HERE and nowhere above it.
|
|
72
|
+
//
|
|
73
|
+
// This was deepseek/deepseek-v4.1-flash for about an hour, chosen for
|
|
74
|
+
// being newer and measured correct on a one-tool arithmetic probe. Probed
|
|
75
|
+
// again against the REAL runtime tool schemas from tools.ts
|
|
76
|
+
// (capability_search + capability_run, nested `args`, optional approval
|
|
77
|
+
// fields) under the same provider.require_parameters=true the transport
|
|
78
|
+
// always sends, it returned `finish_reason: "error"` with zero tool calls
|
|
79
|
+
// on 1 of 5 attempts, every one served by the Relace endpoint. v4-flash
|
|
80
|
+
// went 5/5 clean on StreamLake, is CHEAPER on both axes, and is already
|
|
81
|
+
// what auto-titles run on -- so the newer model was worse on reliability
|
|
82
|
+
// and on price, and the only thing recommending it was its version number.
|
|
83
|
+
//
|
|
84
|
+
// A child that emits no tool call returns nothing for what it spent, and
|
|
85
|
+
// the transport does not retry `finish_reason: "error"` on the primary
|
|
86
|
+
// (classifyModelError sends it straight to the next model), so a 20%
|
|
87
|
+
// error rate here is a 20% double round trip on every delegation.
|
|
88
|
+
model: "deepseek/deepseek-v4-flash",
|
|
89
|
+
displayName: "Oxygen Fast",
|
|
90
|
+
// v4.1-flash earns its place HERE: it works 4 times in 5 and it is a
|
|
91
|
+
// genuinely different endpoint on a different provider, which is the one
|
|
92
|
+
// thing a fallback has to be.
|
|
93
|
+
fallbackModels: ["deepseek/deepseek-v4.1-flash"],
|
|
94
|
+
reasoningEffort: "low",
|
|
95
|
+
estPromptUsdPerM: 0.09,
|
|
96
|
+
estCompletionUsdPerM: 0.18,
|
|
97
|
+
maxOutputTokens: 8192,
|
|
98
|
+
},
|
|
99
|
+
medium: {
|
|
100
|
+
model: "anthropic/claude-haiku-5.5",
|
|
101
|
+
displayName: "Oxygen Balanced",
|
|
102
|
+
fallbackModels: ["deepseek/deepseek-v4.1-flash"],
|
|
103
|
+
reasoningEffort: "medium",
|
|
104
|
+
estPromptUsdPerM: 0.1,
|
|
105
|
+
estCompletionUsdPerM: 0.5,
|
|
106
|
+
// A conversation tier (the default since #5225), so Auto's cap (see Auto).
|
|
107
|
+
maxOutputTokens: 16_384,
|
|
108
|
+
},
|
|
109
|
+
high: {
|
|
110
|
+
model: "openai/gpt-6.1-sol",
|
|
111
|
+
displayName: "Oxygen Max",
|
|
112
|
+
fallbackModels: ["anthropic/claude-sonnet-5.5"],
|
|
113
|
+
reasoningEffort: "medium",
|
|
114
|
+
estPromptUsdPerM: 2,
|
|
115
|
+
estCompletionUsdPerM: 10,
|
|
116
|
+
// A conversation tier, so Auto's cap (see Auto).
|
|
117
|
+
maxOutputTokens: 16_384,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
25
120
|
export const HOSTED_AI_MODEL_REGISTRY = {
|
|
26
121
|
/**
|
|
27
122
|
* Historical calibration of the September AI-column tiers, re-picked
|
|
@@ -112,124 +207,20 @@ export const HOSTED_AI_MODEL_REGISTRY = {
|
|
|
112
207
|
maxOutputTokens: 4096,
|
|
113
208
|
},
|
|
114
209
|
},
|
|
115
|
-
copilot:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* `reasoningEffort: "medium"` made that tier worth shipping.
|
|
126
|
-
* Until 2026-09-21 Kimi was sent with NO `reasoning` field at
|
|
127
|
-
* all, on a registry comment asserting K3 was max-reasoning-only. Measured
|
|
128
|
-
* against the live API on the same prompt and tool schema, that claim was
|
|
129
|
-
* false and the omission was the expensive case:
|
|
130
|
-
*
|
|
131
|
-
* omitted -> 412 reasoning tokens, $0.00779, 10.0s
|
|
132
|
-
* low -> 206, $0.00566, 9.2s
|
|
133
|
-
* medium -> 124, $0.00342, 4.8s <- 56% cheaper, 2.1x faster
|
|
134
|
-
* high -> 528, $0.01075, 14.8s
|
|
135
|
-
*
|
|
136
|
-
* All four returned the same answer. Reasoning was 38% of output tokens on a
|
|
137
|
-
* surface where output is ~61% of the bill.
|
|
138
|
-
*/
|
|
139
|
-
auto: {
|
|
140
|
-
model: "openai/gpt-6.1-sol",
|
|
141
|
-
displayName: "Oxygen Auto",
|
|
142
|
-
// Approved 2026-10-10 for NEW sessions. Existing sessions retain their
|
|
143
|
-
// persisted resolved_model; Kimi's priced spec survives in the legacy map.
|
|
144
|
-
fallbackModels: ["anthropic/claude-sonnet-5.5"],
|
|
145
|
-
reasoningEffort: "medium",
|
|
146
|
-
estPromptUsdPerM: 2,
|
|
147
|
-
estCompletionUsdPerM: 10,
|
|
148
|
-
// Reasoning tokens count against this cap, so 8,192 left a long tool call
|
|
149
|
-
// (a full sequence draft, a wide table write) to be cut off mid-argument,
|
|
150
|
-
// which fails the turn on the second time. Credit holds are sized from the
|
|
151
|
-
// expected output (billing.ts), so this moves only the conservative clamp.
|
|
152
|
-
maxOutputTokens: 16_384,
|
|
153
|
-
},
|
|
154
|
-
low: {
|
|
155
|
-
// The errand model: sub-agents, compaction summaries and auto-titles. A
|
|
156
|
-
// child builds its own Agent with its own messages, so it starts cold on
|
|
157
|
-
// any model -- which is why a switch is free HERE and nowhere above it.
|
|
158
|
-
//
|
|
159
|
-
// This was deepseek/deepseek-v4.1-flash for about an hour, chosen for
|
|
160
|
-
// being newer and measured correct on a one-tool arithmetic probe. Probed
|
|
161
|
-
// again against the REAL runtime tool schemas from tools.ts
|
|
162
|
-
// (capability_search + capability_run, nested `args`, optional approval
|
|
163
|
-
// fields) under the same provider.require_parameters=true the transport
|
|
164
|
-
// always sends, it returned `finish_reason: "error"` with zero tool calls
|
|
165
|
-
// on 1 of 5 attempts, every one served by the Relace endpoint. v4-flash
|
|
166
|
-
// went 5/5 clean on StreamLake, is CHEAPER on both axes, and is already
|
|
167
|
-
// what auto-titles run on -- so the newer model was worse on reliability
|
|
168
|
-
// and on price, and the only thing recommending it was its version number.
|
|
169
|
-
//
|
|
170
|
-
// A child that emits no tool call returns nothing for what it spent, and
|
|
171
|
-
// the transport does not retry `finish_reason: "error"` on the primary
|
|
172
|
-
// (classifyModelError sends it straight to the next model), so a 20%
|
|
173
|
-
// error rate here is a 20% double round trip on every delegation.
|
|
174
|
-
model: "deepseek/deepseek-v4-flash",
|
|
175
|
-
displayName: "Oxygen Fast",
|
|
176
|
-
// v4.1-flash earns its place HERE: it works 4 times in 5 and it is a
|
|
177
|
-
// genuinely different endpoint on a different provider, which is the one
|
|
178
|
-
// thing a fallback has to be.
|
|
179
|
-
fallbackModels: ["deepseek/deepseek-v4.1-flash"],
|
|
180
|
-
reasoningEffort: "low",
|
|
181
|
-
estPromptUsdPerM: 0.09,
|
|
182
|
-
estCompletionUsdPerM: 0.18,
|
|
183
|
-
maxOutputTokens: 8192,
|
|
184
|
-
},
|
|
185
|
-
medium: {
|
|
186
|
-
model: "anthropic/claude-haiku-5.5",
|
|
187
|
-
displayName: "Oxygen Balanced",
|
|
188
|
-
fallbackModels: ["deepseek/deepseek-v4.1-flash"],
|
|
189
|
-
reasoningEffort: "medium",
|
|
190
|
-
estPromptUsdPerM: 0.1,
|
|
191
|
-
estCompletionUsdPerM: 0.5,
|
|
192
|
-
// A conversation tier (the default since #5225), so Auto's cap (see Auto).
|
|
193
|
-
maxOutputTokens: 16_384,
|
|
194
|
-
},
|
|
195
|
-
high: {
|
|
196
|
-
model: "openai/gpt-6.1-sol",
|
|
197
|
-
displayName: "Oxygen Max",
|
|
198
|
-
fallbackModels: ["anthropic/claude-sonnet-5.5"],
|
|
199
|
-
reasoningEffort: "medium",
|
|
200
|
-
estPromptUsdPerM: 2,
|
|
201
|
-
estCompletionUsdPerM: 10,
|
|
202
|
-
// A conversation tier, so Auto's cap (see Auto).
|
|
203
|
-
maxOutputTokens: 16_384,
|
|
204
|
-
},
|
|
205
|
-
},
|
|
210
|
+
copilot: COPILOT_MODEL_SPECS,
|
|
211
|
+
/**
|
|
212
|
+
* An Oxygent's background tasks and routines run on the very models its chat
|
|
213
|
+
* does, so one tier means one model wherever the Oxygent works (Philipp,
|
|
214
|
+
* 2026-10-17). Until then Agents kept their September tiers (DeepSeek V4
|
|
215
|
+
* Flash / V4 Pro / Kimi K2.6), which the 2026-10-10 refresh left out of scope.
|
|
216
|
+
* Shared by reference, so a Copilot tier refresh moves Agents with it;
|
|
217
|
+
* `OXYGEN_AGENT_MODEL_*` still overrides Agents alone. Retired ids keep
|
|
218
|
+
* their tier label through LEGACY_MANAGED_AI_COLUMN_MODELS.
|
|
219
|
+
*/
|
|
206
220
|
agent: {
|
|
207
|
-
low:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
fallbackModels: [],
|
|
211
|
-
reasoningEffort: "medium",
|
|
212
|
-
estPromptUsdPerM: 0.09,
|
|
213
|
-
estCompletionUsdPerM: 0.18,
|
|
214
|
-
maxOutputTokens: 8192,
|
|
215
|
-
},
|
|
216
|
-
medium: {
|
|
217
|
-
model: "deepseek/deepseek-v4-pro",
|
|
218
|
-
displayName: "Oxygen Balanced",
|
|
219
|
-
fallbackModels: ["deepseek/deepseek-v4-flash"],
|
|
220
|
-
reasoningEffort: "high",
|
|
221
|
-
estPromptUsdPerM: 0.435,
|
|
222
|
-
estCompletionUsdPerM: 0.87,
|
|
223
|
-
maxOutputTokens: 8192,
|
|
224
|
-
},
|
|
225
|
-
high: {
|
|
226
|
-
model: "moonshotai/kimi-k2.6",
|
|
227
|
-
displayName: "Oxygen Max",
|
|
228
|
-
fallbackModels: ["deepseek/deepseek-v4-pro"],
|
|
229
|
-
estPromptUsdPerM: 0.66,
|
|
230
|
-
estCompletionUsdPerM: 3.41,
|
|
231
|
-
maxOutputTokens: 8192,
|
|
232
|
-
},
|
|
221
|
+
low: COPILOT_MODEL_SPECS.low,
|
|
222
|
+
medium: COPILOT_MODEL_SPECS.medium,
|
|
223
|
+
high: COPILOT_MODEL_SPECS.high,
|
|
233
224
|
},
|
|
234
225
|
};
|
|
235
226
|
/** Persisted conversations keep their original pricing, effort and fallbacks. */
|
|
@@ -449,7 +440,6 @@ export const IMAGE_INPUT_MODELS = new Set([
|
|
|
449
440
|
"anthropic/claude-sonnet-5.5",
|
|
450
441
|
"anthropic/claude-haiku-5.5",
|
|
451
442
|
"moonshotai/kimi-k3",
|
|
452
|
-
"moonshotai/kimi-k2.6",
|
|
453
443
|
"deepseek/deepseek-v4.1-flash",
|
|
454
444
|
"google/gemini-3.8-flash",
|
|
455
445
|
]);
|