@oxygen-agent/cli 1.1014.1343 → 1.1014.1451
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-families/program.js +2 -0
- package/dist/command-families/tables/register-reads.js +1 -1
- package/dist/command-manifest.js +1 -0
- package/dist/command-support.js +4 -2
- package/dist/commands/blueprints.js +10 -6
- package/dist/commands/clay-migration.d.ts +3 -0
- package/dist/commands/clay-migration.js +22 -0
- package/dist/commands/crm.js +5 -2
- package/dist/commands/dashboards.js +4 -2
- package/dist/commands/db.js +1 -1
- package/dist/commands/directory.js +7 -4
- package/dist/commands/domains.js +1 -1
- package/dist/commands/inbox.js +5 -2
- package/dist/commands/prompts.js +4 -2
- package/dist/commands/publishing.js +5 -2
- package/dist/commands/sequences.js +13 -4
- package/dist/commands/support.js +30 -19
- package/dist/customer-operation-commands.js +0 -42
- package/dist/http-client.js +4 -1
- package/dist/workspace-placement-commands.js +1 -1
- package/node_modules/@oxygen/shared/dist/capability-args.d.ts +19 -0
- package/node_modules/@oxygen/shared/dist/capability-args.js +73 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +15 -2
- package/node_modules/@oxygen/shared/dist/clay-migration-auth-state.d.ts +3 -0
- package/node_modules/@oxygen/shared/dist/clay-migration-auth-state.js +15 -0
- package/node_modules/@oxygen/shared/dist/contracts/browser-operations.js +2 -1
- package/node_modules/@oxygen/shared/dist/contracts/clay-migration.d.ts +71 -0
- package/node_modules/@oxygen/shared/dist/contracts/clay-migration.js +60 -0
- package/node_modules/@oxygen/shared/dist/contracts/operations.js +4 -6
- package/node_modules/@oxygen/shared/dist/contracts/table-query-raw.d.ts +5 -1
- package/node_modules/@oxygen/shared/dist/contracts/table-query-raw.js +25 -2
- package/node_modules/@oxygen/shared/dist/contracts/teammates.js +1 -1
- package/node_modules/@oxygen/shared/dist/dev-eval-context.js +1 -0
- package/node_modules/@oxygen/shared/dist/enrollment-origin.d.ts +3 -1
- package/node_modules/@oxygen/shared/dist/enrollment-origin.js +2 -0
- package/node_modules/@oxygen/shared/dist/guided-activation.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/guided-onboarding-company-context.d.ts +9 -2
- package/node_modules/@oxygen/shared/dist/guided-trial-billing.d.ts +10 -2
- package/node_modules/@oxygen/shared/dist/guided-trial-billing.js +2 -5
- package/node_modules/@oxygen/shared/dist/hosted-ai.js +8 -4
- package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +6 -0
- package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.js +1 -0
- package/node_modules/@oxygen/shared/dist/onboarding-plays.d.ts +68 -0
- package/node_modules/@oxygen/shared/dist/onboarding-plays.js +114 -0
- package/node_modules/@oxygen/shared/dist/onboarding-research.d.ts +42 -0
- package/node_modules/@oxygen/shared/dist/onboarding-research.js +62 -0
- package/node_modules/@oxygen/shared/dist/placement-copy.d.ts +8 -0
- package/node_modules/@oxygen/shared/dist/placement-copy.js +16 -0
- package/node_modules/@oxygen/shared/dist/product-analytics-events.d.ts +8 -0
- package/node_modules/@oxygen/shared/dist/product-analytics-events.js +8 -0
- package/node_modules/@oxygen/shared/dist/sequences.d.ts +30 -2
- package/node_modules/@oxygen/shared/dist/sequences.js +67 -7
- package/node_modules/@oxygen/shared/dist/teammates.d.ts +3 -1
- package/node_modules/@oxygen/shared/dist/teammates.js +4 -2
- package/node_modules/@oxygen/shared/dist/user-capability-routing.js +19 -40
- 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.js +4 -0
- package/package.json +1 -1
- package/node_modules/@oxygen/shared/dist/contracts/guided-company-files.d.ts +0 -30
- package/node_modules/@oxygen/shared/dist/contracts/guided-company-files.js +0 -53
- package/node_modules/@oxygen/shared/dist/contracts/guided-first-sourcing.d.ts +0 -120
- package/node_modules/@oxygen/shared/dist/contracts/guided-first-sourcing.js +0 -48
- package/node_modules/@oxygen/shared/dist/contracts/guided-onboarding-journey.d.ts +0 -267
- package/node_modules/@oxygen/shared/dist/contracts/guided-onboarding-journey.js +0 -63
- package/node_modules/@oxygen/shared/dist/guided-company-files.d.ts +0 -13
- package/node_modules/@oxygen/shared/dist/guided-company-files.js +0 -14
- package/node_modules/@oxygen/shared/dist/guided-first-sourcing.d.ts +0 -116
- package/node_modules/@oxygen/shared/dist/guided-first-sourcing.js +0 -11
- package/node_modules/@oxygen/shared/dist/guided-onboarding-answers.d.ts +0 -4
- package/node_modules/@oxygen/shared/dist/guided-onboarding-answers.js +0 -42
- package/node_modules/@oxygen/shared/dist/guided-onboarding-journey.d.ts +0 -147
- package/node_modules/@oxygen/shared/dist/guided-onboarding-journey.fixture.d.ts +0 -12
- package/node_modules/@oxygen/shared/dist/guided-onboarding-journey.fixture.js +0 -83
- package/node_modules/@oxygen/shared/dist/guided-onboarding-journey.js +0 -44
- package/node_modules/@oxygen/shared/dist/guided-onboarding-prospects.d.ts +0 -7
- package/node_modules/@oxygen/shared/dist/guided-onboarding-prospects.js +0 -13
- package/node_modules/@oxygen/shared/dist/guided-onboarding-recommendations.d.ts +0 -54
- package/node_modules/@oxygen/shared/dist/guided-onboarding-recommendations.js +0 -100
- package/node_modules/@oxygen/shared/dist/guided-onboarding-signals.d.ts +0 -4
- package/node_modules/@oxygen/shared/dist/guided-onboarding-signals.js +0 -34
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const MAX_ARG_ERRORS = 8;
|
|
2
|
+
function matchesJsonType(value, type) {
|
|
3
|
+
switch (type) {
|
|
4
|
+
case "string":
|
|
5
|
+
return typeof value === "string";
|
|
6
|
+
case "number":
|
|
7
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
8
|
+
case "integer":
|
|
9
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
10
|
+
case "boolean":
|
|
11
|
+
return typeof value === "boolean";
|
|
12
|
+
case "array":
|
|
13
|
+
return Array.isArray(value);
|
|
14
|
+
case "object":
|
|
15
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
16
|
+
case "null":
|
|
17
|
+
return value === null;
|
|
18
|
+
default:
|
|
19
|
+
// An unrecognised type keyword is not something this shallow check gets to
|
|
20
|
+
// fail a call over — silence beats a false positive that blocks a good call.
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Shallow top-level validation of proposed args against a capability's own
|
|
26
|
+
* inputSchema. Fail-open on anything it cannot read (no `properties`, exotic
|
|
27
|
+
* keywords, nested shapes): a wrongly-rejected call is a worse outcome than a
|
|
28
|
+
* call the route rejects a moment later, and the route still rejects it.
|
|
29
|
+
*/
|
|
30
|
+
export function validateCapabilityArgs(def, args) {
|
|
31
|
+
const schema = (def.inputSchema ?? {});
|
|
32
|
+
const properties = schema.properties;
|
|
33
|
+
if (!properties || typeof properties !== "object")
|
|
34
|
+
return { ok: true };
|
|
35
|
+
const errors = [];
|
|
36
|
+
const required = Array.isArray(schema.required)
|
|
37
|
+
? schema.required.filter((entry) => typeof entry === "string")
|
|
38
|
+
: [];
|
|
39
|
+
for (const name of required) {
|
|
40
|
+
if (!(name in args) || args[name] === undefined) {
|
|
41
|
+
errors.push(`missing required argument "${name}"`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (schema.additionalProperties === false) {
|
|
45
|
+
for (const key of Object.keys(args)) {
|
|
46
|
+
if (!(key in properties))
|
|
47
|
+
errors.push(`unknown argument "${key}"`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
for (const [key, value] of Object.entries(args)) {
|
|
51
|
+
const property = properties[key];
|
|
52
|
+
if (!property || value === undefined)
|
|
53
|
+
continue;
|
|
54
|
+
const declared = Array.isArray(property.type)
|
|
55
|
+
? property.type
|
|
56
|
+
: property.type !== undefined
|
|
57
|
+
? [property.type]
|
|
58
|
+
: [];
|
|
59
|
+
const types = declared.filter((entry) => typeof entry === "string");
|
|
60
|
+
if (types.length > 0 && !types.some((type) => matchesJsonType(value, type))) {
|
|
61
|
+
errors.push(`argument "${key}" must be ${types.join(" or ")}`);
|
|
62
|
+
}
|
|
63
|
+
const allowed = property.enum;
|
|
64
|
+
if (Array.isArray(allowed) &&
|
|
65
|
+
allowed.length > 0 &&
|
|
66
|
+
allowed.every((entry) => typeof entry === "string") &&
|
|
67
|
+
typeof value === "string" &&
|
|
68
|
+
!allowed.includes(value)) {
|
|
69
|
+
errors.push(`argument "${key}" must be one of: ${allowed.join(", ")}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return errors.length > 0 ? { ok: false, errors: errors.slice(0, MAX_ARG_ERRORS) } : { ok: true };
|
|
73
|
+
}
|
|
@@ -239,7 +239,7 @@ export const OXYGEN_CAPABILITY_ROUTES = [
|
|
|
239
239
|
gatewayTools: ["oxygen_tables_create", "oxygen_tools_search", "oxygen_columns_add", "oxygen_columns_catalog", "oxygen_enrich_column_preview", "oxygen_tables_link_bulk", "oxygen_callables_manage", "oxygen_tables_records_import"],
|
|
240
240
|
gatewayCommands: ["tables create", "tools search", "columns add", "columns catalog", "enrich-column preview", "tables link", "functions list", "functions draft", "tables records import"],
|
|
241
241
|
skills: ["oxygen-tables", "oxygen-enrichment", "oxygen-table-tidy", "oxygen-diagnostics", "oxygen-clay-migration", "oxygen-signals"],
|
|
242
|
-
endpointSections: ["action-columns", "callables", "functions", "columns", "company-enrichment", "enrich-column", "enrichment", "projects", "supabase", "table-action-items", "table-action-runs", "table-ingestion-runs", "tables"],
|
|
242
|
+
endpointSections: ["action-columns", "callables", "functions", "columns", "company-enrichment", "enrich-column", "enrichment", "migrations", "projects", "supabase", "table-action-items", "table-action-runs", "table-ingestion-runs", "tables"],
|
|
243
243
|
// "link"/"join"/"connect"/"relate" route here for `tables link`. Added after a
|
|
244
244
|
// blind user eval asked for exactly "link two tables" and was routed to
|
|
245
245
|
// `tables create` / `columns add` / `enrich-column preview` — none of which
|
|
@@ -1358,6 +1358,12 @@ function routeCardFor(card, query) {
|
|
|
1358
1358
|
notFor: "Provider credentials, enrichment, workspace billing, or staff-wide database operations.",
|
|
1359
1359
|
execution: database.execution,
|
|
1360
1360
|
};
|
|
1361
|
+
if (card.id === "tables" && isClayMigrationIntent(query))
|
|
1362
|
+
card = {
|
|
1363
|
+
...card,
|
|
1364
|
+
posture: "workspace_write",
|
|
1365
|
+
execution: "Start oxygen_clay_migration action=connect for browser sign-in; keep its migration_id for discovery, bounded source reads, table transfers, rebuild checkpoints and coverage reports. Read oxygen-clay-migration for the native reconstruction procedure. Create destination objects through their Oxygen tools, retain source outputs and report export limitations. Imported behavior stays inactive until separately approved. External MCP uses oxygen_capabilities_call.",
|
|
1366
|
+
};
|
|
1361
1367
|
const specializedSkill = preferredSkillForIntent(card, query);
|
|
1362
1368
|
return specializedSkill ? { ...card, skills: [specializedSkill, ...card.skills.filter((skill) => skill !== specializedSkill)] } : card;
|
|
1363
1369
|
}
|
|
@@ -1366,7 +1372,7 @@ function preferredSkillForIntent(card, query) {
|
|
|
1366
1372
|
if (card.id === "tables") {
|
|
1367
1373
|
if (linkedinUrlFindingRecommendation(query))
|
|
1368
1374
|
return "oxygen-enrichment";
|
|
1369
|
-
if (
|
|
1375
|
+
if (isClayMigrationIntent(query))
|
|
1370
1376
|
return "oxygen-clay-migration";
|
|
1371
1377
|
if (isTableMaintenanceIntent(query))
|
|
1372
1378
|
return "oxygen-table-tidy";
|
|
@@ -1387,6 +1393,9 @@ function preferredSkillForIntent(card, query) {
|
|
|
1387
1393
|
return "oxygen-signals";
|
|
1388
1394
|
return null;
|
|
1389
1395
|
}
|
|
1396
|
+
function isClayMigrationIntent(query) {
|
|
1397
|
+
return /\bclay\b/.test(query) && /\b(import|export|migrat\w*|mov\w*|transfer|bring|rebuild)\b/.test(query);
|
|
1398
|
+
}
|
|
1390
1399
|
function isTableMaintenanceIntent(query) {
|
|
1391
1400
|
return /\b(tables?|columns?|folders?)\b/.test(query)
|
|
1392
1401
|
&& !/\b(functions?|callables?|campaigns?|tags?|workflows?|agents?)\b/.test(query)
|
|
@@ -2169,6 +2178,8 @@ function isWorkspaceSkillIntent(query) {
|
|
|
2169
2178
|
return /\bskills?\b/.test(query) && /\b(create|author|write|upload|import|edit|update|archive|private|workspace|custom|own|reusable)\b/.test(query);
|
|
2170
2179
|
}
|
|
2171
2180
|
function explicitCapabilityIntent(query) {
|
|
2181
|
+
if (isClayMigrationIntent(query))
|
|
2182
|
+
return ROUTE_BY_ID.get("tables") ?? null;
|
|
2172
2183
|
if (isWorkspaceSkillIntent(query))
|
|
2173
2184
|
return ROUTE_BY_ID.get("knowledge-graph") ?? null;
|
|
2174
2185
|
const readOnly = readInspectionRecommendation(query);
|
|
@@ -2867,6 +2878,8 @@ function recommendationsFor(card, query) {
|
|
|
2867
2878
|
};
|
|
2868
2879
|
}
|
|
2869
2880
|
if (card.primitive === "tables") {
|
|
2881
|
+
if (isClayMigrationIntent(query))
|
|
2882
|
+
return { tools: ["oxygen_clay_migration"], commands: ["clay migration"], exactCommand: "oxygen clay migration --action connect --json", exactMcpCall: { tool: "oxygen_clay_migration", arguments: { action: "connect" } } };
|
|
2870
2883
|
const removal = tableRowRemovalRecommendation(query);
|
|
2871
2884
|
if (removal)
|
|
2872
2885
|
return removal;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Rotated credentials must survive a failed source read, without becoming part
|
|
2
|
+
// of a customer error, operator log or serialized tool result.
|
|
3
|
+
const failureStates = new WeakMap();
|
|
4
|
+
export function tagClayMigrationFailureState(error, encryptedState) {
|
|
5
|
+
if (error !== null && typeof error === "object")
|
|
6
|
+
failureStates.set(error, encryptedState);
|
|
7
|
+
}
|
|
8
|
+
/** Consume only state attached in this process by the migration adapter. */
|
|
9
|
+
export function readClayMigrationFailureState(error) {
|
|
10
|
+
if (error === null || typeof error !== "object")
|
|
11
|
+
return null;
|
|
12
|
+
const state = failureStates.get(error) ?? null;
|
|
13
|
+
failureStates.delete(error);
|
|
14
|
+
return state;
|
|
15
|
+
}
|
|
@@ -134,5 +134,6 @@ export const BROWSER_OPERATIONS = [
|
|
|
134
134
|
operation("notetaker.note.edit", "/api/cli/notetaker/sessions/{session}/note", "PATCH", "notetaker notes edit", "oxygen_notetaker_note_edit", "crm", "Save the markdown note for one meeting session and return the committed note.", { markdown: text() }, ["markdown"]),
|
|
135
135
|
operation("orgs.create", "/api/cli/orgs/create", "POST", "orgs create", "oxygen_workspace_create", "workspace", "Create a workspace for the authenticated person's account and begin native company setup. Workspace API keys cannot create personal workspaces.", { name: text(), company_domain: text("Company website or domain, or its LinkedIn company page URL when it has no website."), linkedin_profile_url: text("Creator's LinkedIn profile URL, separate from the company's page.") }, ["name", "company_domain"]),
|
|
136
136
|
operation("onboarding.complete", "/api/cli/onboarding/complete", "POST", "onboarding complete", "oxygen_onboarding_complete", "workspace", "Complete the active workspace's onboarding step and record its discovery-source choices. The other choice requires source_other.", { sources: arr(enumOf(["linkedin_content", "linkedin_dm", "linkedin_ads", "x", "youtube", "google", "ai_assistant", "email", "word_of_mouth", "referral", "event", "other"])), source_other: text(), redirect_url: text() }, ["sources"]),
|
|
137
|
-
operation("onboarding.
|
|
137
|
+
operation("onboarding.finish", "/api/cli/onboarding/finish", "POST", "onboarding finish", "oxygen_onboarding_finish", "workspace", "Finish agent-led onboarding once a play is chosen: the onboarding Oxygent chat opens as an ordinary chat, without the Knowledge pane. Changes nothing else and spends nothing."),
|
|
138
|
+
operation("onboarding.start", "/api/cli/onboarding/start", "POST", "onboarding start", "oxygen_onboarding_start", "workspace", "Answer onboarding's choice card. own_agent continues to connecting your own agent. copilot opens the Workspace Copilot with the onboarding conversation already started, billed in credits like any Copilot turn; choosing again reopens that conversation. restart (copilot) shows a finished onboarding again and asks the Oxygent to start over, as an ordinary send.", { path: enumOf(["own_agent", "copilot"]), play: text("A play slug carried to the install step."), restart: bool() }, ["path"], { spends: true }),
|
|
138
139
|
];
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { OperationSpec } from "./operation-request.js";
|
|
2
|
+
import { type ContractIssue, type Infer } from "./schema.js";
|
|
3
|
+
export declare const CLAY_MIGRATION_ACTIONS: readonly ["connect", "status", "discover", "read", "transfer", "checkpoint", "report", "disconnect"];
|
|
4
|
+
export declare const CLAY_RESOURCE_TYPES: readonly ["workspace", "folder", "workbook", "table", "audience", "workflow", "function", "claygent", "knowledge", "schedule", "campaign"];
|
|
5
|
+
export declare const CLAY_RESOURCE_DISPOSITIONS: readonly ["pending", "copied", "rebuilt", "needs_decision", "unsupported", "inaccessible", "excluded", "failed"];
|
|
6
|
+
export declare const CLAY_MIGRATION_CONTRACT: import("./schema.js").ContractObject<{
|
|
7
|
+
readonly action: {
|
|
8
|
+
type: "string";
|
|
9
|
+
enum: readonly ("checkpoint" | "connect" | "disconnect" | "discover" | "read" | "report" | "status" | "transfer")[];
|
|
10
|
+
description?: string;
|
|
11
|
+
};
|
|
12
|
+
readonly migration_id: import("./schema.js").StringProperty;
|
|
13
|
+
readonly source_workspace_id: import("./schema.js").StringProperty;
|
|
14
|
+
readonly resource_type: {
|
|
15
|
+
type: "string";
|
|
16
|
+
enum: readonly ("audience" | "campaign" | "claygent" | "folder" | "function" | "knowledge" | "schedule" | "table" | "workbook" | "workflow" | "workspace")[];
|
|
17
|
+
description?: string;
|
|
18
|
+
};
|
|
19
|
+
readonly resource_id: import("./schema.js").StringProperty;
|
|
20
|
+
readonly section: {
|
|
21
|
+
type: "string";
|
|
22
|
+
enum: readonly ("columns" | "fields" | "graph" | "metadata" | "record_ids" | "records" | "rows" | "sequence")[];
|
|
23
|
+
description?: string;
|
|
24
|
+
};
|
|
25
|
+
readonly path: import("./schema.js").StringProperty;
|
|
26
|
+
readonly text_offset: {
|
|
27
|
+
type: "integer";
|
|
28
|
+
description?: string;
|
|
29
|
+
minimum?: number;
|
|
30
|
+
maximum?: number;
|
|
31
|
+
"x-clamp"?: true;
|
|
32
|
+
};
|
|
33
|
+
readonly entity_type: {
|
|
34
|
+
type: "string";
|
|
35
|
+
enum: readonly ("companies" | "deals" | "people")[];
|
|
36
|
+
description?: string;
|
|
37
|
+
};
|
|
38
|
+
readonly record_ids: import("./schema.js").ArrayProperty<{
|
|
39
|
+
type: "integer";
|
|
40
|
+
description?: string;
|
|
41
|
+
minimum?: number;
|
|
42
|
+
maximum?: number;
|
|
43
|
+
"x-clamp"?: true;
|
|
44
|
+
}>;
|
|
45
|
+
readonly cursor: import("./schema.js").StringProperty;
|
|
46
|
+
readonly limit: {
|
|
47
|
+
type: "integer";
|
|
48
|
+
description?: string;
|
|
49
|
+
minimum?: number;
|
|
50
|
+
maximum?: number;
|
|
51
|
+
"x-clamp"?: true;
|
|
52
|
+
};
|
|
53
|
+
readonly target_table: import("./schema.js").StringProperty;
|
|
54
|
+
readonly source_cells_column: import("./schema.js").StringProperty;
|
|
55
|
+
readonly source_row_id_column: import("./schema.js").StringProperty;
|
|
56
|
+
readonly mapping: import("./schema.js").ArrayProperty<import("./schema.js").ContractObject<{
|
|
57
|
+
readonly source_column_id: import("./schema.js").StringProperty;
|
|
58
|
+
readonly target_column: import("./schema.js").StringProperty;
|
|
59
|
+
}, "source_column_id" | "target_column">>;
|
|
60
|
+
readonly disposition: {
|
|
61
|
+
type: "string";
|
|
62
|
+
enum: readonly ("copied" | "excluded" | "failed" | "inaccessible" | "needs_decision" | "pending" | "rebuilt" | "unsupported")[];
|
|
63
|
+
description?: string;
|
|
64
|
+
};
|
|
65
|
+
readonly target_kind: import("./schema.js").StringProperty;
|
|
66
|
+
readonly target_id: import("./schema.js").StringProperty;
|
|
67
|
+
readonly notes: import("./schema.js").StringProperty;
|
|
68
|
+
}, "action">;
|
|
69
|
+
export type ClayMigrationInput = Infer<typeof CLAY_MIGRATION_CONTRACT>;
|
|
70
|
+
export declare function clayMigrationInputIssues(args: Readonly<Record<string, unknown>>): ContractIssue[];
|
|
71
|
+
export declare const CLAY_MIGRATION_OPERATION: OperationSpec<typeof CLAY_MIGRATION_CONTRACT>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { arr, enumOf, int, obj, str } from "./schema.js";
|
|
2
|
+
export const CLAY_MIGRATION_ACTIONS = ["connect", "status", "discover", "read", "transfer", "checkpoint", "report", "disconnect"];
|
|
3
|
+
export const CLAY_RESOURCE_TYPES = ["workspace", "folder", "workbook", "table", "audience", "workflow", "function", "claygent", "knowledge", "schedule", "campaign"];
|
|
4
|
+
export const CLAY_RESOURCE_DISPOSITIONS = ["pending", "copied", "rebuilt", "needs_decision", "unsupported", "inaccessible", "excluded", "failed"];
|
|
5
|
+
export const CLAY_MIGRATION_CONTRACT = obj({
|
|
6
|
+
action: enumOf(CLAY_MIGRATION_ACTIONS),
|
|
7
|
+
migration_id: str({ minLength: 1, maxLength: 200 }),
|
|
8
|
+
source_workspace_id: str({ minLength: 1, maxLength: 200 }),
|
|
9
|
+
resource_type: enumOf(CLAY_RESOURCE_TYPES),
|
|
10
|
+
resource_id: str({ minLength: 1, maxLength: 200 }),
|
|
11
|
+
section: enumOf(["metadata", "columns", "rows", "graph", "fields", "record_ids", "records", "sequence"]),
|
|
12
|
+
path: str({ minLength: 1, maxLength: 1000, description: "Dotted path or JSON pointer into source configuration, e.g. data.0.settings." }),
|
|
13
|
+
text_offset: int({ minimum: 0, maximum: 8388608, description: "Continue a large scalar read at next_text_offset." }),
|
|
14
|
+
entity_type: enumOf(["people", "companies", "deals"]),
|
|
15
|
+
record_ids: arr(int({ minimum: 1 }), { minItems: 1, maxItems: 100 }),
|
|
16
|
+
cursor: str({ maxLength: 4000 }),
|
|
17
|
+
limit: int({ minimum: 1, maximum: 100 }),
|
|
18
|
+
target_table: str({ minLength: 1, maxLength: 200 }),
|
|
19
|
+
source_cells_column: str({ minLength: 1, maxLength: 200, description: "Existing JSON column preserving original Clay cells; default clay_source_cells." }),
|
|
20
|
+
source_row_id_column: str({ minLength: 1, maxLength: 200, description: "Existing text column for stable source row IDs; default clay_source_row_id." }),
|
|
21
|
+
mapping: arr(obj({ source_column_id: str({ minLength: 1, maxLength: 200 }), target_column: str({ minLength: 1, maxLength: 200 }) }, { required: ["source_column_id", "target_column"] }), { minItems: 1, maxItems: 500, description: "Source Clay column IDs or Audience field keys to existing Oxygen column keys." }),
|
|
22
|
+
disposition: enumOf(CLAY_RESOURCE_DISPOSITIONS),
|
|
23
|
+
target_kind: str({ minLength: 1, maxLength: 100 }),
|
|
24
|
+
target_id: str({ minLength: 1, maxLength: 200 }),
|
|
25
|
+
notes: str({ maxLength: 8000 }),
|
|
26
|
+
}, { required: ["action"] });
|
|
27
|
+
export function clayMigrationInputIssues(args) {
|
|
28
|
+
const issues = [];
|
|
29
|
+
const requireField = (key) => { if (args[key] === undefined)
|
|
30
|
+
issues.push({ path: key, message: `${key} is required for ${String(args.action)}.` }); };
|
|
31
|
+
if (args.action !== "connect")
|
|
32
|
+
requireField("migration_id");
|
|
33
|
+
if (["read", "transfer", "checkpoint"].includes(String(args.action)))
|
|
34
|
+
requireField("resource_type");
|
|
35
|
+
const workspaceRead = ["workspace", "knowledge"].includes(String(args.resource_type))
|
|
36
|
+
|| (args.resource_type === "audience" && ["fields", "record_ids", "records"].includes(String(args.section)));
|
|
37
|
+
if (["transfer", "checkpoint"].includes(String(args.action)) || (args.action === "read" && !workspaceRead))
|
|
38
|
+
requireField("resource_id");
|
|
39
|
+
if (args.action === "transfer") {
|
|
40
|
+
requireField("target_table");
|
|
41
|
+
requireField("mapping");
|
|
42
|
+
if (!["table", "audience"].includes(String(args.resource_type)))
|
|
43
|
+
issues.push({ path: "resource_type", message: "Bulk transfer requires a Clay table or Audience; rebuild other resources with native Oxygen tools." });
|
|
44
|
+
}
|
|
45
|
+
if (args.action === "checkpoint")
|
|
46
|
+
requireField("disposition");
|
|
47
|
+
if (args.section === "records") {
|
|
48
|
+
requireField("entity_type");
|
|
49
|
+
requireField("record_ids");
|
|
50
|
+
}
|
|
51
|
+
return issues;
|
|
52
|
+
}
|
|
53
|
+
export const CLAY_MIGRATION_OPERATION = {
|
|
54
|
+
id: "clay.migration", route: "/api/cli/migrations/clay", method: "POST",
|
|
55
|
+
contract: CLAY_MIGRATION_CONTRACT, inputCheck: clayMigrationInputIssues,
|
|
56
|
+
generated: { cli: false, mcp: false },
|
|
57
|
+
cli: { path: ["clay", "migration"], summary: "Migrate a Clay workspace into Oxygen: connect, discover source configuration, inspect bounded samples, transfer table and Audience rows, checkpoint native rebuilds and reconcile coverage. Creates no paid runs or active schedules." },
|
|
58
|
+
mcp: { name: "oxygen_clay_migration", title: "Oxygen: Migrate from Clay", description: "Connect to Clay with browser sign-in, discover resources, read source configuration and samples, transfer table and Audience rows to existing Oxygen tables, checkpoint rebuilds and report coverage. Use native Oxygen tools to create targets and rebuild behavior. Follow cursors; report unsupported or inaccessible resources. Never activates schedules or paid runs.", pack: "integrations", annotations: { openWorldHint: true, destructiveHint: false, idempotentHint: false } },
|
|
59
|
+
mutates: true, spends: false,
|
|
60
|
+
};
|
|
@@ -12,14 +12,12 @@ import { BROWSER_OPERATIONS } from "./browser-operations.js";
|
|
|
12
12
|
import { TABLE_FEED_UPDATE_OPERATION } from "./table-feed-update.js";
|
|
13
13
|
import { GEO_OPERATIONS } from "./geo.js";
|
|
14
14
|
import { CUSTOMER_OPERATIONS } from "./customer-operations.js";
|
|
15
|
-
import { GUIDED_ONBOARDING_JOURNEY_OPERATIONS } from "./guided-onboarding-journey.js";
|
|
16
|
-
import { GUIDED_FIRST_SOURCING_OPERATIONS } from "./guided-first-sourcing.js";
|
|
17
|
-
import { GUIDED_COMPANY_FILE_UPLOAD_OPERATION } from "./guided-company-files.js";
|
|
18
15
|
import { GUIDED_ACTIVATION_OPERATIONS } from "./guided-activation.js";
|
|
19
16
|
import { AGENT_SESSION_OPERATIONS } from "./agent-sessions.js";
|
|
20
17
|
import { REPLY_OXYGENT_OPERATIONS } from "./reply-oxygent.js";
|
|
21
18
|
import { TEAMMATE_OPERATIONS } from "./teammates.js";
|
|
22
19
|
import { WORKSPACE_SKILL_OPERATIONS } from "./workspace-skills.js";
|
|
20
|
+
import { CLAY_MIGRATION_OPERATION } from "./clay-migration.js";
|
|
23
21
|
export { operationPath, operationRequest } from "./operation-request.js";
|
|
24
22
|
/** The exact public grammar, including the operation's scoped route parameters. */
|
|
25
23
|
export function operationInputContract(spec) {
|
|
@@ -63,6 +61,6 @@ export function operationFormData(spec, body) {
|
|
|
63
61
|
}
|
|
64
62
|
return form;
|
|
65
63
|
}
|
|
66
|
-
export const OPERATION_SPECS = [SENDER_LIMITS_SET_OPERATION, CONNECTOR_UPDATE_OPERATION, CONNECTOR_EVENTS_REVOKE_OPERATION, WORKSPACE_PAGES_GET_OPERATION, WORKSPACE_PAGES_UPDATE_OPERATION, TABLE_FEED_UPDATE_OPERATION, ...CUSTOMER_OPERATIONS, ...GEO_OPERATIONS, ...BROWSER_OPERATIONS, ...AGENT_SESSION_OPERATIONS, ...GUIDED_ACTIVATION_OPERATIONS, ...
|
|
67
|
-
export const CLI_OPERATIONS = [...CUSTOMER_OPERATIONS, ...GEO_OPERATIONS, ...BROWSER_OPERATIONS, ...AGENT_SESSION_OPERATIONS, ...GUIDED_ACTIVATION_OPERATIONS, ...
|
|
68
|
-
export const MCP_OPERATIONS = [...CUSTOMER_OPERATIONS, ...GEO_OPERATIONS, ...BROWSER_OPERATIONS, ...AGENT_SESSION_OPERATIONS, ...GUIDED_ACTIVATION_OPERATIONS, ...
|
|
64
|
+
export const OPERATION_SPECS = [CLAY_MIGRATION_OPERATION, SENDER_LIMITS_SET_OPERATION, CONNECTOR_UPDATE_OPERATION, CONNECTOR_EVENTS_REVOKE_OPERATION, WORKSPACE_PAGES_GET_OPERATION, WORKSPACE_PAGES_UPDATE_OPERATION, TABLE_FEED_UPDATE_OPERATION, ...CUSTOMER_OPERATIONS, ...GEO_OPERATIONS, ...BROWSER_OPERATIONS, ...AGENT_SESSION_OPERATIONS, ...GUIDED_ACTIVATION_OPERATIONS, ...TEAMMATE_OPERATIONS, ...REPLY_OXYGENT_OPERATIONS, ...WORKSPACE_SKILL_OPERATIONS];
|
|
65
|
+
export const CLI_OPERATIONS = [...CUSTOMER_OPERATIONS, ...GEO_OPERATIONS, ...BROWSER_OPERATIONS, ...AGENT_SESSION_OPERATIONS, ...GUIDED_ACTIVATION_OPERATIONS, ...TEAMMATE_OPERATIONS, ...REPLY_OXYGENT_OPERATIONS, ...WORKSPACE_SKILL_OPERATIONS].filter((spec) => spec.generated?.cli !== false);
|
|
66
|
+
export const MCP_OPERATIONS = [...CUSTOMER_OPERATIONS, ...GEO_OPERATIONS, ...BROWSER_OPERATIONS, ...AGENT_SESSION_OPERATIONS, ...GUIDED_ACTIVATION_OPERATIONS, ...TEAMMATE_OPERATIONS, ...REPLY_OXYGENT_OPERATIONS, ...WORKSPACE_SKILL_OPERATIONS].filter((spec) => spec.generated?.mcp !== false);
|
|
@@ -13,4 +13,8 @@ export declare const TABLE_QUERY_CLI_DEFAULT_MAX_CHARS = 12000;
|
|
|
13
13
|
export declare function tableQueryRawResultFits(data: Record<string, unknown>, maxChars: number | undefined): boolean;
|
|
14
14
|
/** What a page shortened to fit its result window says to do next (CLI, MCP and API alike). */
|
|
15
15
|
export declare const TABLE_QUERY_RESULT_WINDOW_NEXT_STEP: string;
|
|
16
|
-
|
|
16
|
+
/** The field whose value is longest in a row (system fields excluded): the one to drop or inspect. */
|
|
17
|
+
export declare function tableRowWidestField(row: unknown): string | undefined;
|
|
18
|
+
/** Leads a refusal's next step with the exact field to drop or inspect, when the row is known. */
|
|
19
|
+
export declare function tableQueryWidestFieldStep(widestField: string | undefined): string;
|
|
20
|
+
export declare function tableQueryRawRecovery(table: string, row?: string, firstRow?: unknown): Record<string, unknown>;
|
|
@@ -12,10 +12,33 @@ export function tableQueryRawResultFits(data, maxChars) {
|
|
|
12
12
|
/** What a page shortened to fit its result window says to do next (CLI, MCP and API alike). */
|
|
13
13
|
export const TABLE_QUERY_RESULT_WINDOW_NEXT_STEP = "This page holds fewer rows than the limit so it fits the result window; every value is complete. "
|
|
14
14
|
+ "Continue with nextCursor (same table, filters, sorts and fields), or select fewer fields for more rows per page.";
|
|
15
|
-
|
|
15
|
+
/** The field whose value is longest in a row (system fields excluded): the one to drop or inspect. */
|
|
16
|
+
export function tableRowWidestField(row) {
|
|
17
|
+
if (!row || typeof row !== "object" || Array.isArray(row))
|
|
18
|
+
return undefined;
|
|
19
|
+
let widest;
|
|
20
|
+
let widestLength = 0;
|
|
21
|
+
for (const [key, value] of Object.entries(row)) {
|
|
22
|
+
if (key.startsWith("_") || value === undefined)
|
|
23
|
+
continue;
|
|
24
|
+
const length = JSON.stringify(value).length;
|
|
25
|
+
if (length > widestLength) {
|
|
26
|
+
widest = key;
|
|
27
|
+
widestLength = length;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return widest;
|
|
31
|
+
}
|
|
32
|
+
/** Leads a refusal's next step with the exact field to drop or inspect, when the row is known. */
|
|
33
|
+
export function tableQueryWidestFieldStep(widestField) {
|
|
34
|
+
return widestField ? `Field \`${widestField}\` is the largest value in that row: drop it from fields or inspect it. ` : "";
|
|
35
|
+
}
|
|
36
|
+
export function tableQueryRawRecovery(table, row, firstRow) {
|
|
37
|
+
const widestField = tableRowWidestField(firstRow);
|
|
16
38
|
return {
|
|
17
39
|
table,
|
|
18
40
|
...(row ? { row } : {}),
|
|
19
|
-
|
|
41
|
+
...(widestField ? { widest_field: widestField } : {}),
|
|
42
|
+
next_step: tableQueryWidestFieldStep(widestField) + "Reduce fields/limit. Inspect a large cell with `tables rows inspect --table <table> --row <row> --field <field> --projection value --path /row/<field>/<key>`; select a JSON Pointer and continue with value_cursor. MCP: hydrate oxygen_table_row_inspect with oxygen_capabilities_schema, then dispatch it through oxygen_capabilities_read. CLI: --full restores legacy reads; --output <path> keeps full JSON outside context.",
|
|
20
43
|
};
|
|
21
44
|
}
|
|
@@ -5,7 +5,7 @@ import { NEW_TEAMMATE_NAME, TEAMMATE_AVATAR_COLORS, TEAMMATE_AVATAR_KEYS, TEAMMA
|
|
|
5
5
|
import { arr, bool, enumOf, int, obj, str } from "./schema.js";
|
|
6
6
|
/**
|
|
7
7
|
* AI teammates (ADR 0032), branded Oxygents: Agents with one ongoing chat,
|
|
8
|
-
* shared by default or Personal, the workspace's first one ("
|
|
8
|
+
* shared by default or Personal, the workspace's first one ("Oxygent" until named) and
|
|
9
9
|
* any others added, none with a role (Tim, 2026-10-13). Every member but a client
|
|
10
10
|
* login has them where the workspace does (launched 2026-10-17).
|
|
11
11
|
* The people-facing names say Oxygent (`oxygen oxygents`, `oxygen_oxygents_*`,
|
|
@@ -28,6 +28,7 @@ export async function devEvalFetch(provider, operation, input, init, transport =
|
|
|
28
28
|
return context ? context.fetch(provider, operation, input, init, transport) : transport(input, init);
|
|
29
29
|
}
|
|
30
30
|
export const DEV_EVAL_SAFE_CAPABILITIES = new Set([
|
|
31
|
+
"oxygen_knowledge_index", "oxygen_knowledge_search", "oxygen_knowledge_page_get",
|
|
31
32
|
"oxygen_tables_list", "oxygen_tables_sources", "oxygen_tables_describe", "oxygen_tables_preview", "oxygen_tables_query", "oxygen_tables_create", "oxygen_tables_update", "oxygen_tables_rows_add", "oxygen_tables_rows_update",
|
|
32
33
|
"oxygen_columns_catalog", "oxygen_columns_deps", "oxygen_columns_add", "oxygen_columns_update", "oxygen_columns_run", "oxygen_columns_materialize",
|
|
33
34
|
"oxygen_enrichment_catalog", "oxygen_tools_search", "oxygen_tools_describe", "oxygen_tools_check_access", "oxygen_tools_plan_table_batch", "oxygen_tools_run_dry", "oxygen_tools_run_live",
|
|
@@ -16,7 +16,9 @@ export type EnrollmentOriginKind = typeof ENROLLMENT_ORIGIN_KINDS[number];
|
|
|
16
16
|
export declare const ENROLLMENT_ACTOR_TYPES: readonly ["user", "agent", "workflow", "api_key", "system"];
|
|
17
17
|
export type EnrollmentActorType = typeof ENROLLMENT_ACTOR_TYPES[number];
|
|
18
18
|
/** The surface the enroll call came through. */
|
|
19
|
-
export declare const ENROLLMENT_GATEWAYS: readonly ["cli", "mcp", "web", "copilot", "agent", "workflow", "engagement_watch"
|
|
19
|
+
export declare const ENROLLMENT_GATEWAYS: readonly ["cli", "mcp", "web", "copilot", "agent", "workflow", "engagement_watch",
|
|
20
|
+
/** The scheduled sync that enrolls new rows of a live campaign's bound table. */
|
|
21
|
+
"table_sync"];
|
|
20
22
|
export type EnrollmentGateway = typeof ENROLLMENT_GATEWAYS[number];
|
|
21
23
|
export declare const ENROLLMENT_REF_TYPES: readonly ["workflow_run", "agent_run", "copilot_session", "engagement_watch", "guided_activation"];
|
|
22
24
|
export type EnrollmentRefType = typeof ENROLLMENT_REF_TYPES[number];
|
|
@@ -47,11 +47,13 @@ export type GuidedActivation = {
|
|
|
47
47
|
resources: GuidedActivationResources;
|
|
48
48
|
outcomes: Partial<Record<"first_leads" | "sequence" | "launch" | GuidedActivationPurpose, "proposed" | "armed" | "launched" | "confirmed_sent" | "paused">>;
|
|
49
49
|
reviews: Partial<Record<GuidedActivationReview["purpose"], GuidedActivationReview>>;
|
|
50
|
+
/** `finished_at`: the person chose a play (or closed onboarding), so the chat is an ordinary Oxygent chat again. */
|
|
50
51
|
onboarding_start: {
|
|
51
52
|
state: "claimed" | "posted";
|
|
52
53
|
chat_id: string;
|
|
53
54
|
turn_id?: string;
|
|
54
55
|
event_seq?: number;
|
|
56
|
+
finished_at?: string;
|
|
55
57
|
} | null;
|
|
56
58
|
last_fault: {
|
|
57
59
|
code: string;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { GuidedOnboardingAnswers } from "./guided-onboarding-journey.js";
|
|
2
1
|
/** One native-supported input budget for web/CLI/MCP and D research preparation. */
|
|
3
2
|
export declare const GUIDED_ONBOARDING_COMPANY_CONTEXT_LIMITS: {
|
|
4
3
|
readonly descriptionChars: 6000;
|
|
@@ -7,6 +6,14 @@ export declare const GUIDED_ONBOARDING_COMPANY_CONTEXT_LIMITS: {
|
|
|
7
6
|
readonly nameChars: 160;
|
|
8
7
|
readonly urlChars: 2000;
|
|
9
8
|
};
|
|
9
|
+
/** Company context saved on a guided activation; the knowledge bootstrap still reads it. */
|
|
10
|
+
export type GuidedOnboardingCompanyContext = {
|
|
11
|
+
website: string | null;
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
context_links: string[];
|
|
15
|
+
file_ids: string[];
|
|
16
|
+
};
|
|
10
17
|
export declare const GUIDED_ONBOARDING_COMPANY_CONTEXT_CONTRACT: import("./contracts/schema.js").ContractObject<{
|
|
11
18
|
readonly website: {
|
|
12
19
|
oneOf: [import("./contracts/schema.js").StringProperty, import("./contracts/schema.js").NullProperty];
|
|
@@ -19,4 +26,4 @@ export declare const GUIDED_ONBOARDING_COMPANY_CONTEXT_CONTRACT: import("./contr
|
|
|
19
26
|
}, "context_links" | "description" | "file_ids" | "name" | "website">;
|
|
20
27
|
/** Input-only rule; existing evidence links retain their independent navigation policy. */
|
|
21
28
|
export declare function normalizeGuidedOnboardingContextLink(value: string): string;
|
|
22
|
-
export declare function normalizeGuidedOnboardingCompanyContext(input: unknown):
|
|
29
|
+
export declare function normalizeGuidedOnboardingCompanyContext(input: unknown): GuidedOnboardingCompanyContext;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/** DEV onboarding offer.
|
|
1
|
+
/** Retired DEV onboarding trial offer. New checkouts no longer create it; the
|
|
2
|
+
* marker still identifies subscriptions that were started under it. */
|
|
2
3
|
export declare const GUIDED_TRIAL_OFFER: {
|
|
3
4
|
readonly key: "guided_onboarding_v2";
|
|
4
5
|
readonly plan: "oxygen_49";
|
|
@@ -10,7 +11,6 @@ export declare const GUIDED_TRIAL_OFFER: {
|
|
|
10
11
|
readonly card_required: true;
|
|
11
12
|
readonly early_charge_allowed: false;
|
|
12
13
|
};
|
|
13
|
-
export declare function guidedTrialAcquisitionEnabled(env?: Record<string, string | undefined>): boolean;
|
|
14
14
|
export declare function isGuidedTrialSubscription(metadata: Record<string, unknown> | null | undefined): boolean;
|
|
15
15
|
export type GuidedTrialBilling = {
|
|
16
16
|
offer: typeof GUIDED_TRIAL_OFFER;
|
|
@@ -24,3 +24,11 @@ export type GuidedTrialBilling = {
|
|
|
24
24
|
spendable_credits: number;
|
|
25
25
|
funded_work_paused: boolean;
|
|
26
26
|
};
|
|
27
|
+
/** Read projection from native billing: a paid plan or a retained guided trial. */
|
|
28
|
+
export type GuidedOnboardingEligibility = {
|
|
29
|
+
state: "unverified" | "checkout_required" | "checkout_pending" | "eligible" | "unavailable";
|
|
30
|
+
basis: "paid" | "trial" | null;
|
|
31
|
+
subscription_id: string | null;
|
|
32
|
+
observed_at: string | null;
|
|
33
|
+
trial_ends_at: string | null;
|
|
34
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/** Retired DEV onboarding trial offer. New checkouts no longer create it; the
|
|
2
|
+
* marker still identifies subscriptions that were started under it. */
|
|
3
3
|
export const GUIDED_TRIAL_OFFER = {
|
|
4
4
|
key: "guided_onboarding_v2",
|
|
5
5
|
plan: "oxygen_49",
|
|
@@ -11,9 +11,6 @@ export const GUIDED_TRIAL_OFFER = {
|
|
|
11
11
|
card_required: true,
|
|
12
12
|
early_charge_allowed: false,
|
|
13
13
|
};
|
|
14
|
-
export function guidedTrialAcquisitionEnabled(env = process.env) {
|
|
15
|
-
return guidedActivationEnabled(env);
|
|
16
|
-
}
|
|
17
14
|
export function isGuidedTrialSubscription(metadata) {
|
|
18
15
|
return metadata?.oxygen_trial_offer === GUIDED_TRIAL_OFFER.key;
|
|
19
16
|
}
|
|
@@ -195,7 +195,10 @@ export const HOSTED_AI_MODEL_REGISTRY = {
|
|
|
195
195
|
reasoningEffort: "medium",
|
|
196
196
|
estPromptUsdPerM: 0.1,
|
|
197
197
|
estCompletionUsdPerM: 0.5,
|
|
198
|
-
|
|
198
|
+
// Reasoning tokens count against max_tokens: at 4,096 Haiku spent 3.5-4k
|
|
199
|
+
// thinking and returned no answer. Copilot's cap for the same model and
|
|
200
|
+
// effort. Spend admission uses AI_COLUMN_TIER_COGS_USD, not this ceiling.
|
|
201
|
+
maxOutputTokens: 16_384,
|
|
199
202
|
},
|
|
200
203
|
high: {
|
|
201
204
|
model: "openai/gpt-6.1-sol",
|
|
@@ -204,7 +207,8 @@ export const HOSTED_AI_MODEL_REGISTRY = {
|
|
|
204
207
|
reasoningEffort: "medium",
|
|
205
208
|
estPromptUsdPerM: 2,
|
|
206
209
|
estCompletionUsdPerM: 10,
|
|
207
|
-
|
|
210
|
+
// Reasoning counts against max_tokens, so Balanced's cap (see Balanced).
|
|
211
|
+
maxOutputTokens: 16_384,
|
|
208
212
|
},
|
|
209
213
|
},
|
|
210
214
|
copilot: COPILOT_MODEL_SPECS,
|
|
@@ -279,8 +283,8 @@ export const KNOWLEDGE_BOOTSTRAP_SYNTHESIS_MODEL = {
|
|
|
279
283
|
fallbackModels: ["openai/gpt-6-luna"],
|
|
280
284
|
disableReasoning: true,
|
|
281
285
|
// The profile plus the cited note of a well-documented company runs past the
|
|
282
|
-
// Balanced tier's 4,096: on dev (2026-10-18) attio.com and lemlist.com stopped
|
|
283
|
-
// exactly 4,096 tokens (`finish_reason: length`), mid-note, as invalid JSON, so the
|
|
286
|
+
// Balanced tier's then 4,096: on dev (2026-10-18) attio.com and lemlist.com stopped
|
|
287
|
+
// at exactly 4,096 tokens (`finish_reason: length`), mid-note, as invalid JSON, so the
|
|
284
288
|
// run ended `partial` with no research page. A shorter answer is unaffected.
|
|
285
289
|
maxOutputTokens: 8192,
|
|
286
290
|
// The same model ran 3x apart by provider on dev (2026-10-18): DigitalOcean and
|
|
@@ -256,6 +256,12 @@ export type KnowledgeBootstrapConsent = {
|
|
|
256
256
|
source: string | null;
|
|
257
257
|
/** Clerk user who accepted, when the surface knows. Informational. */
|
|
258
258
|
granted_by_clerk_user_id: string | null;
|
|
259
|
+
/**
|
|
260
|
+
* `agent`: agent-led onboarding (Philipp, 2026-10-19). The Oxygent researches the
|
|
261
|
+
* company in the chat with its sub-agents, so the automatic background pass and
|
|
262
|
+
* the brain draft do not run; a manual request still does.
|
|
263
|
+
*/
|
|
264
|
+
research?: "agent";
|
|
259
265
|
};
|
|
260
266
|
/**
|
|
261
267
|
* Read consent out of an organization's control-DB metadata blob, FAIL-CLOSED.
|
|
@@ -243,6 +243,7 @@ function readGrant(raw) {
|
|
|
243
243
|
...(creatorLinkedinUrl ? { creator_linkedin_url: creatorLinkedinUrl } : {}),
|
|
244
244
|
source: typeof record.source === "string" && record.source.length > 0 ? record.source : null,
|
|
245
245
|
granted_by_clerk_user_id: grantedBy,
|
|
246
|
+
...(record.research === "agent" ? { research: "agent" } : {}),
|
|
246
247
|
},
|
|
247
248
|
};
|
|
248
249
|
}
|