@oxygen-agent/cli 1.1014.985 → 1.1014.1087
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.d.ts +2 -0
- package/dist/command-families/program.js +241 -0
- package/dist/command-families/tables/automation.d.ts +22 -0
- package/dist/command-families/tables/automation.js +250 -0
- package/dist/command-families/tables/bundle-export.d.ts +7 -0
- package/dist/command-families/tables/bundle-export.js +198 -0
- package/dist/command-families/tables/bundle-format.d.ts +66 -0
- package/dist/command-families/tables/bundle-format.js +274 -0
- package/dist/command-families/tables/bundle-import.d.ts +20 -0
- package/dist/command-families/tables/bundle-import.js +260 -0
- package/dist/command-families/tables/display.d.ts +107 -0
- package/dist/command-families/tables/display.js +229 -0
- package/dist/command-families/tables/import-batches.d.ts +26 -0
- package/dist/command-families/tables/import-batches.js +94 -0
- package/dist/command-families/tables/import-columns.d.ts +24 -0
- package/dist/command-families/tables/import-columns.js +131 -0
- package/dist/command-families/tables/import-upload.d.ts +30 -0
- package/dist/command-families/tables/import-upload.js +203 -0
- package/dist/command-families/tables/import-values.d.ts +10 -0
- package/dist/command-families/tables/import-values.js +60 -0
- package/dist/command-families/tables/imports.d.ts +19 -0
- package/dist/command-families/tables/imports.js +200 -0
- package/dist/command-families/tables/options.d.ts +314 -0
- package/dist/command-families/tables/options.js +1 -0
- package/dist/command-families/tables/register-automation.d.ts +2 -0
- package/dist/command-families/tables/register-automation.js +127 -0
- package/dist/command-families/tables/register-external-imports.d.ts +2 -0
- package/dist/command-families/tables/register-external-imports.js +293 -0
- package/dist/command-families/tables/register-files.d.ts +2 -0
- package/dist/command-families/tables/register-files.js +72 -0
- package/dist/command-families/tables/register-followers.d.ts +2 -0
- package/dist/command-families/tables/register-followers.js +73 -0
- package/dist/command-families/tables/register-lifecycle.d.ts +2 -0
- package/dist/command-families/tables/register-lifecycle.js +114 -0
- package/dist/command-families/tables/register-reads.d.ts +2 -0
- package/dist/command-families/tables/register-reads.js +187 -0
- package/dist/command-families/tables/register-relations.d.ts +2 -0
- package/dist/command-families/tables/register-relations.js +244 -0
- package/dist/command-families/tables/register-row-actions.d.ts +2 -0
- package/dist/command-families/tables/register-row-actions.js +53 -0
- package/dist/command-families/tables/register-row-writes.d.ts +2 -0
- package/dist/command-families/tables/register-row-writes.js +140 -0
- package/dist/command-families/tables/register-views.d.ts +2 -0
- package/dist/command-families/tables/register-views.js +83 -0
- package/dist/command-families/tables/register-watchers.d.ts +2 -0
- package/dist/command-families/tables/register-watchers.js +65 -0
- package/dist/command-families/tables/register-webhooks.d.ts +2 -0
- package/dist/command-families/tables/register-webhooks.js +126 -0
- package/dist/command-families/tables/registration-context.d.ts +8 -0
- package/dist/command-families/tables/registration-context.js +1 -0
- package/dist/command-families/tables/registration.d.ts +3 -0
- package/dist/command-families/tables/registration.js +30 -0
- package/dist/command-families/tables/row-selection.d.ts +5 -0
- package/dist/command-families/tables/row-selection.js +82 -0
- package/dist/command-families/tables/send.d.ts +6 -0
- package/dist/command-families/tables/send.js +111 -0
- package/dist/command-manifest.js +1 -0
- package/dist/commands/copilot.js +8 -0
- package/dist/commands/deliverability.js +4 -2
- package/dist/commands/sequences.js +30 -2
- package/dist/commands/tables.d.ts +1 -3
- package/dist/commands/tables.js +1 -3505
- 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 +1 -99
- package/dist/index.js +5 -337
- package/dist/knowledge-mirror.js +1 -1
- package/dist/skills.js +4 -2
- package/dist/update.js +2 -1
- package/dist/workspace-placement-commands.d.ts +3 -0
- package/dist/workspace-placement-commands.js +32 -0
- package/node_modules/@oxygen/shared/dist/agent-sessions.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/agent-sessions.js +11 -3
- package/node_modules/@oxygen/shared/dist/agents-enabled.d.ts +29 -0
- package/node_modules/@oxygen/shared/dist/agents-enabled.js +51 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +39 -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 +17 -15
- 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 +4 -0
- package/node_modules/@oxygen/shared/dist/feature-gates.js +5 -0
- 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/index.d.ts +0 -1
- package/node_modules/@oxygen/shared/dist/index.js +0 -6
- package/node_modules/@oxygen/shared/dist/table-limits.d.ts +1 -0
- package/node_modules/@oxygen/shared/dist/table-limits.js +6 -0
- package/node_modules/@oxygen/shared/dist/teammates.d.ts +13 -8
- package/node_modules/@oxygen/shared/dist/teammates.js +20 -11
- package/node_modules/@oxygen/shared/dist/user-capability-routing.js +78 -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 +149 -0
- package/node_modules/@oxygen/shared/dist/workspace-placement-view.js +101 -0
- package/node_modules/@oxygen/shared/dist/workspace-placement.d.ts +77 -0
- package/node_modules/@oxygen/shared/dist/workspace-placement.js +94 -0
- package/package.json +1 -1
|
@@ -236,6 +236,144 @@ export function dropBlankImportCells(row, keepKey) {
|
|
|
236
236
|
export function normalizeImportColumnKey(value) {
|
|
237
237
|
return toSnakeIdentifier(value, "column");
|
|
238
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Read `ignore_source_keys`: the headers a mapping step set to "Don't import".
|
|
241
|
+
* A JSON array (staged body) or its JSON text (multipart form field); headers
|
|
242
|
+
* are matched verbatim, so they are not trimmed. Anything malformed reads as
|
|
243
|
+
* no choice at all, never as a reason to fail the import.
|
|
244
|
+
*/
|
|
245
|
+
export function readImportHeaderList(value) {
|
|
246
|
+
let parsed = value;
|
|
247
|
+
if (typeof value === "string") {
|
|
248
|
+
try {
|
|
249
|
+
parsed = JSON.parse(value);
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (!Array.isArray(parsed))
|
|
256
|
+
return [];
|
|
257
|
+
return parsed.filter((entry) => typeof entry === "string" && entry.length > 0).slice(0, 1_000);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Decide, once per file header, which column of an EXISTING table it lands in.
|
|
261
|
+
*
|
|
262
|
+
* File imports used to hand every header to the row writer verbatim, and the
|
|
263
|
+
* writer refuses an unknown key for the whole chunk. A standard export carries
|
|
264
|
+
* columns the table does not have — Baserow puts an `id` first — so on
|
|
265
|
+
* 2026-10-12 and 2026-10-15 three workspaces' CRM imports wrote nothing at all
|
|
266
|
+
* and showed only `invalid_row_values`. Headers now resolve in a fixed order:
|
|
267
|
+
* an explicit choice (`explicitMap`, `ignore`) first, then the column key, then
|
|
268
|
+
* the column's label or the normalized key. A header that resolves to no
|
|
269
|
+
* column, or to a column another header already fills, is left out and
|
|
270
|
+
* reported, never guessed: two headers writing one column would overwrite each
|
|
271
|
+
* other. Rows keep their cells; only the keys are renamed or dropped.
|
|
272
|
+
*/
|
|
273
|
+
export function createImportHeaderProjector(input) {
|
|
274
|
+
const exact = new Map();
|
|
275
|
+
const aliases = new Map();
|
|
276
|
+
for (const column of input.columns) {
|
|
277
|
+
if (!column.key || column.key.startsWith("_"))
|
|
278
|
+
continue;
|
|
279
|
+
exact.set(column.key, column.key);
|
|
280
|
+
for (const alias of [
|
|
281
|
+
column.label?.trim(),
|
|
282
|
+
normalizeImportColumnKey(column.key),
|
|
283
|
+
column.label ? normalizeImportColumnKey(column.label) : undefined,
|
|
284
|
+
]) {
|
|
285
|
+
if (!alias)
|
|
286
|
+
continue;
|
|
287
|
+
const existing = aliases.get(alias);
|
|
288
|
+
if (existing === undefined)
|
|
289
|
+
aliases.set(alias, column.key);
|
|
290
|
+
else if (existing !== column.key)
|
|
291
|
+
aliases.set(alias, null);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const explicitMap = input.explicitMap ?? {};
|
|
295
|
+
const ignore = new Set(input.ignore ?? []);
|
|
296
|
+
const keyByHeader = new Map();
|
|
297
|
+
const ignored = new Map();
|
|
298
|
+
const claimed = new Set();
|
|
299
|
+
const decide = (headers) => {
|
|
300
|
+
const pending = headers.filter((header) => !keyByHeader.has(header) && !ignored.has(header));
|
|
301
|
+
const aliasCandidates = new Map();
|
|
302
|
+
const skip = (header, reason, column) => ignored.set(header, { header, reason, ...(column ? { column } : {}) });
|
|
303
|
+
const claim = (header, key) => {
|
|
304
|
+
keyByHeader.set(header, key);
|
|
305
|
+
claimed.add(key);
|
|
306
|
+
};
|
|
307
|
+
// Explicit choices and exact keys claim their columns before any alias can.
|
|
308
|
+
for (const header of pending) {
|
|
309
|
+
if (ignore.has(header)) {
|
|
310
|
+
skip(header, "not_selected");
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const explicit = explicitMap[header];
|
|
314
|
+
if (explicit) {
|
|
315
|
+
claim(header, explicit);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const key = exact.get(header) ?? exact.get(header.trim());
|
|
319
|
+
if (key && !claimed.has(key))
|
|
320
|
+
claim(header, key);
|
|
321
|
+
}
|
|
322
|
+
for (const header of pending) {
|
|
323
|
+
if (keyByHeader.has(header) || ignored.has(header))
|
|
324
|
+
continue;
|
|
325
|
+
const exactKey = exact.get(header) ?? exact.get(header.trim());
|
|
326
|
+
if (exactKey) {
|
|
327
|
+
skip(header, "duplicate_target", exactKey);
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
// `_created_at` must not alias `created_at`: system keys are never written.
|
|
331
|
+
if (header.startsWith("_")) {
|
|
332
|
+
skip(header, "system_column");
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
const alias = aliases.get(header.trim()) ?? aliases.get(normalizeImportColumnKey(header)) ?? null;
|
|
336
|
+
if (!alias) {
|
|
337
|
+
skip(header, "no_matching_column");
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
aliasCandidates.set(alias, [...(aliasCandidates.get(alias) ?? []), header]);
|
|
341
|
+
}
|
|
342
|
+
for (const [key, candidates] of aliasCandidates) {
|
|
343
|
+
if (candidates.length === 1 && !claimed.has(key)) {
|
|
344
|
+
claim(candidates[0], key);
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
for (const header of candidates)
|
|
348
|
+
skip(header, "duplicate_target", key);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
return {
|
|
352
|
+
/** Resolve any headers first seen in these rows; earlier decisions stand. */
|
|
353
|
+
observe(rows) {
|
|
354
|
+
decide(inferImportColumnLabels(rows));
|
|
355
|
+
},
|
|
356
|
+
/** The row with every key renamed to its column, unwritten headers dropped. */
|
|
357
|
+
project(row) {
|
|
358
|
+
const projected = {};
|
|
359
|
+
for (const [header, value] of Object.entries(row)) {
|
|
360
|
+
if (!keyByHeader.has(header) && !ignored.has(header))
|
|
361
|
+
decide([header]);
|
|
362
|
+
const key = keyByHeader.get(header);
|
|
363
|
+
if (key !== undefined)
|
|
364
|
+
projected[key] = value;
|
|
365
|
+
}
|
|
366
|
+
return projected;
|
|
367
|
+
},
|
|
368
|
+
/** header → column for every header that writes; for a preview or a receipt. */
|
|
369
|
+
mapping() {
|
|
370
|
+
return Object.fromEntries(keyByHeader);
|
|
371
|
+
},
|
|
372
|
+
ignored() {
|
|
373
|
+
return [...ignored.values()];
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
}
|
|
239
377
|
async function parseXlsxRows(buffer, options) {
|
|
240
378
|
const rows = await parseXlsxWorkbookBuffer(buffer, options);
|
|
241
379
|
const [header, ...body] = rows;
|
|
@@ -8,6 +8,14 @@ export type GuidedActivationRoutine = {
|
|
|
8
8
|
export declare const GUIDED_ACTIVATION_POINTERS: readonly ["knowledge", "first_leads_table", "sequence", "sender", "oxygent", "direct_chat", "scan_routine", "briefing_routine"];
|
|
9
9
|
export type GuidedActivationPointer = typeof GUIDED_ACTIVATION_POINTERS[number];
|
|
10
10
|
export type GuidedActivationResources = Partial<Record<GuidedActivationPointer, string>>;
|
|
11
|
+
/** Read projection only. Historical resource/Start identities stay unchanged. */
|
|
12
|
+
export type GuidedActivationConversation = {
|
|
13
|
+
source_chat_id: string;
|
|
14
|
+
canonical_chat_id: string;
|
|
15
|
+
oxygent_id: string;
|
|
16
|
+
visibility: "workspace" | "personal";
|
|
17
|
+
history_migration_pending: boolean;
|
|
18
|
+
};
|
|
11
19
|
export declare const GUIDED_ACTIVATION_REVISIONS: readonly ["configuration", "sequence", "audience", "recipients", "sender", "copy", "knowledge", "schedule", "authority"];
|
|
12
20
|
export type GuidedActivationRevisions = Record<typeof GUIDED_ACTIVATION_REVISIONS[number], string>;
|
|
13
21
|
export type GuidedActivationBounds = {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Browser-safe budgets for the native guided company-file owner and all transports. */
|
|
2
|
+
export declare const GUIDED_COMPANY_FILE_LIMITS: {
|
|
3
|
+
readonly textBytes: 1500000;
|
|
4
|
+
readonly pdfBytes: 5242880;
|
|
5
|
+
readonly retainedWorkspaceBytes: 1073741824;
|
|
6
|
+
readonly bodyTimeoutMs: 15000;
|
|
7
|
+
readonly storageTimeoutMs: 15000;
|
|
8
|
+
readonly bodyLimitBytes: 5308416;
|
|
9
|
+
readonly nameBytes: 255;
|
|
10
|
+
};
|
|
11
|
+
export declare const GUIDED_COMPANY_FILE_CONTENT_TYPES: readonly ["text/plain", "text/markdown", "application/pdf"];
|
|
12
|
+
export type GuidedCompanyFileContentType = typeof GUIDED_COMPANY_FILE_CONTENT_TYPES[number];
|
|
13
|
+
export declare function guidedCompanyFileByteLimit(contentType: GuidedCompanyFileContentType): number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Browser-safe budgets for the native guided company-file owner and all transports. */
|
|
2
|
+
export const GUIDED_COMPANY_FILE_LIMITS = {
|
|
3
|
+
textBytes: 1_500_000,
|
|
4
|
+
pdfBytes: 5_242_880,
|
|
5
|
+
retainedWorkspaceBytes: 1_073_741_824,
|
|
6
|
+
bodyTimeoutMs: 15_000,
|
|
7
|
+
storageTimeoutMs: 15_000,
|
|
8
|
+
bodyLimitBytes: 5_308_416,
|
|
9
|
+
nameBytes: 255,
|
|
10
|
+
};
|
|
11
|
+
export const GUIDED_COMPANY_FILE_CONTENT_TYPES = ["text/plain", "text/markdown", "application/pdf"];
|
|
12
|
+
export function guidedCompanyFileByteLimit(contentType) {
|
|
13
|
+
return contentType === "application/pdf" ? GUIDED_COMPANY_FILE_LIMITS.pdfBytes : GUIDED_COMPANY_FILE_LIMITS.textBytes;
|
|
14
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { GuidedOnboardingAnswers, GuidedOnboardingProspectLimitation } from "./guided-onboarding-journey.js";
|
|
2
|
+
export type GuidedFirstSourcingOwner = {
|
|
3
|
+
organizationId: string;
|
|
4
|
+
actorId: string;
|
|
5
|
+
activationId: string;
|
|
6
|
+
};
|
|
7
|
+
export type GuidedFirstSourcingBounds = {
|
|
8
|
+
targetCount: number;
|
|
9
|
+
maxPages: number;
|
|
10
|
+
maxCredits: number;
|
|
11
|
+
};
|
|
12
|
+
export type GuidedFirstSourcingCriteria = {
|
|
13
|
+
sourceKey: string;
|
|
14
|
+
digest: string;
|
|
15
|
+
company: NonNullable<GuidedOnboardingAnswers["company_review"]>;
|
|
16
|
+
targeting: {
|
|
17
|
+
filters: Record<string, unknown>;
|
|
18
|
+
signals: GuidedOnboardingAnswers["signals"];
|
|
19
|
+
limitations: GuidedOnboardingProspectLimitation[];
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export type GuidedFirstSourcingQuote = {
|
|
23
|
+
toolId: "blitzapi.people_search";
|
|
24
|
+
perPageCredits: number;
|
|
25
|
+
revision: string;
|
|
26
|
+
canRun: boolean;
|
|
27
|
+
};
|
|
28
|
+
export type GuidedFirstSourcingPreview = {
|
|
29
|
+
id: string;
|
|
30
|
+
activationId: string;
|
|
31
|
+
actorId: string;
|
|
32
|
+
activationRevision: number;
|
|
33
|
+
tableId: string;
|
|
34
|
+
criteria: GuidedFirstSourcingCriteria;
|
|
35
|
+
bounds: GuidedFirstSourcingBounds;
|
|
36
|
+
quote: GuidedFirstSourcingQuote & {
|
|
37
|
+
pages: number;
|
|
38
|
+
estimatedCredits: number;
|
|
39
|
+
};
|
|
40
|
+
expiresAt: string;
|
|
41
|
+
digest: string;
|
|
42
|
+
};
|
|
43
|
+
/** Current authority witness, distinct from the provider query's stable identity.
|
|
44
|
+
* Confirmation revisions, journey generation, navigation and preview/cap expiry
|
|
45
|
+
* cannot turn the same approved native source into another first pull. */
|
|
46
|
+
export declare function guidedFirstSourcingAudienceWitness(answers: GuidedOnboardingAnswers): {
|
|
47
|
+
company: string | null;
|
|
48
|
+
company_size: import("./guided-onboarding-journey.js").GuidedOnboardingChoice | null;
|
|
49
|
+
markets: import("./guided-onboarding-journey.js").GuidedOnboardingChoice | null;
|
|
50
|
+
industries: import("./guided-onboarding-journey.js").GuidedOnboardingChoice | null;
|
|
51
|
+
personas: import("./guided-onboarding-journey.js").GuidedOnboardingChoice | null;
|
|
52
|
+
signals: {
|
|
53
|
+
hiring: import("./guided-onboarding-journey.js").GuidedOnboardingSignal;
|
|
54
|
+
technology: import("./guided-onboarding-journey.js").GuidedOnboardingTechnologySignal;
|
|
55
|
+
} | null;
|
|
56
|
+
};
|
|
57
|
+
/** Optional GET scope for a current native NIGHTLY quote. The timezone is a
|
|
58
|
+
* customer/browser IANA suggestion; it never confirms or saves a schedule. */
|
|
59
|
+
export type GuidedFirstSourcingDefaultsRequest = {
|
|
60
|
+
revision: number;
|
|
61
|
+
generation: number;
|
|
62
|
+
timezoneHint: string;
|
|
63
|
+
};
|
|
64
|
+
/** Structural projection of E's actual readonly producer; no native import in shared. */
|
|
65
|
+
export type GuidedFirstSourcingRoutineDefaults = {
|
|
66
|
+
initial: {
|
|
67
|
+
sourceIds: string[];
|
|
68
|
+
limits: {
|
|
69
|
+
max_examined: number;
|
|
70
|
+
max_new_leads: number;
|
|
71
|
+
max_provider_pages: number;
|
|
72
|
+
max_provider_credits: number;
|
|
73
|
+
};
|
|
74
|
+
scanBudget: {
|
|
75
|
+
per_run_credits: number;
|
|
76
|
+
daily_credits: number;
|
|
77
|
+
};
|
|
78
|
+
briefingBudget: {
|
|
79
|
+
per_run_credits: number;
|
|
80
|
+
daily_credits: number;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
sourceNames: Record<string, string>;
|
|
84
|
+
quote: {
|
|
85
|
+
provider_credits_per_run: number;
|
|
86
|
+
inference_credits_per_run: 0;
|
|
87
|
+
source_quotes: Array<{
|
|
88
|
+
source_id: string;
|
|
89
|
+
provider_credits_per_page: number;
|
|
90
|
+
incremental_mode: "cursor" | "watermark";
|
|
91
|
+
}>;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
export type GuidedFirstSourcingRoutineDefaultsScope = GuidedFirstSourcingOwner & GuidedFirstSourcingDefaultsRequest & {
|
|
95
|
+
sourceKey: string;
|
|
96
|
+
};
|
|
97
|
+
/** Observation metadata stays outside form defaults. Quoted time alone must
|
|
98
|
+
* never reset edits; consumers reject responses outside their current scope. */
|
|
99
|
+
export type GuidedFirstSourcingRoutineDefaultsReadback = {
|
|
100
|
+
routineDefaults: null;
|
|
101
|
+
routineDefaultsScope: null;
|
|
102
|
+
} | {
|
|
103
|
+
routineDefaults: null;
|
|
104
|
+
routineDefaultsScope: GuidedFirstSourcingRoutineDefaultsScope & {
|
|
105
|
+
state: "not_ready";
|
|
106
|
+
};
|
|
107
|
+
} | {
|
|
108
|
+
routineDefaults: GuidedFirstSourcingRoutineDefaults;
|
|
109
|
+
routineDefaultsScope: GuidedFirstSourcingRoutineDefaultsScope & {
|
|
110
|
+
state: "ready";
|
|
111
|
+
quoteDigest: string;
|
|
112
|
+
quotedAt: string;
|
|
113
|
+
defaultMaxCredits: number;
|
|
114
|
+
defaultsDigest: string;
|
|
115
|
+
};
|
|
116
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Current authority witness, distinct from the provider query's stable identity.
|
|
2
|
+
* Confirmation revisions, journey generation, navigation and preview/cap expiry
|
|
3
|
+
* cannot turn the same approved native source into another first pull. */
|
|
4
|
+
export function guidedFirstSourcingAudienceWitness(answers) {
|
|
5
|
+
return {
|
|
6
|
+
company: answers.company_review?.statement ?? null,
|
|
7
|
+
company_size: answers.audience_company_size ?? null, markets: answers.audience_markets ?? null,
|
|
8
|
+
industries: answers.audience_industries ?? null, personas: answers.audience_personas ?? null,
|
|
9
|
+
signals: answers.signals ?? null,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GuidedOnboardingAnswers, GuidedOnboardingStep } from "./guided-onboarding-journey.js";
|
|
2
|
+
/** Only the current step can be edited, never native billing/resources/research.
|
|
3
|
+
* Validation does not claim a file is owned, a connection exists or results ran. */
|
|
4
|
+
export declare function normalizeGuidedOnboardingAnswers(step: GuidedOnboardingStep, input: unknown): GuidedOnboardingAnswers;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { OxygenError } from "./cli-result.js";
|
|
2
|
+
import { validateContract } from "./contracts/schema.js";
|
|
3
|
+
import { GUIDED_ONBOARDING_ANSWERS_CONTRACT } from "./contracts/guided-onboarding-journey.js";
|
|
4
|
+
import { normalizeGuidedOnboardingCompanyContext } from "./guided-onboarding-company-context.js";
|
|
5
|
+
import { normalizeGuidedOnboardingSignals } from "./guided-onboarding-signals.js";
|
|
6
|
+
const fail = (message) => { throw new OxygenError("invalid_onboarding_answer", message, { exitCode: 2 }); };
|
|
7
|
+
const clean = (value) => value.normalize("NFKC").trim().replace(/\s+/gu, " ");
|
|
8
|
+
const choices = (values) => {
|
|
9
|
+
const names = values.map(clean);
|
|
10
|
+
if (names.some(value => !value))
|
|
11
|
+
return fail("Choose a nonempty audience value.");
|
|
12
|
+
return [...new Map(names.map(value => [value.toLowerCase(), value])).values()];
|
|
13
|
+
};
|
|
14
|
+
/** Only the current step can be edited, never native billing/resources/research.
|
|
15
|
+
* Validation does not claim a file is owned, a connection exists or results ran. */
|
|
16
|
+
export function normalizeGuidedOnboardingAnswers(step, input) {
|
|
17
|
+
const checked = validateContract(GUIDED_ONBOARDING_ANSWERS_CONTRACT, input, { unknown: "reject", overMax: "reject" });
|
|
18
|
+
if (!checked.ok)
|
|
19
|
+
return fail("Use the reviewed answer fields for this onboarding step.");
|
|
20
|
+
const answers = checked.value;
|
|
21
|
+
if (Object.keys(answers).some(key => key !== step))
|
|
22
|
+
return fail("Save only the current step's answers.");
|
|
23
|
+
if (answers.company_context)
|
|
24
|
+
answers.company_context = normalizeGuidedOnboardingCompanyContext(answers.company_context);
|
|
25
|
+
if (answers.company_review) {
|
|
26
|
+
const statement = answers.company_review.statement.trim();
|
|
27
|
+
if (!statement || !/^(?:0|[1-9]\d*)$/.test(answers.company_review.profile_revision))
|
|
28
|
+
return fail("Review a company statement at the current native profile revision.");
|
|
29
|
+
answers.company_review = { ...answers.company_review, statement };
|
|
30
|
+
}
|
|
31
|
+
for (const key of ["audience_company_size", "audience_markets", "audience_industries", "audience_personas"]) {
|
|
32
|
+
if (answers[key])
|
|
33
|
+
answers[key] = { values: choices(answers[key].values) };
|
|
34
|
+
}
|
|
35
|
+
if (answers.signals)
|
|
36
|
+
answers.signals = normalizeGuidedOnboardingSignals(answers.signals);
|
|
37
|
+
if (answers.prospects)
|
|
38
|
+
answers.prospects = { ...answers.prospects, feedback: answers.prospects.feedback.trim() };
|
|
39
|
+
if (answers.tour)
|
|
40
|
+
answers.tour = { visited: [...new Set(answers.tour.visited)] };
|
|
41
|
+
return answers;
|
|
42
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GuidedOnboardingAnswers } from "./guided-onboarding-journey.js";
|
|
2
|
+
/** One native-supported input budget for web/CLI/MCP and D research preparation. */
|
|
3
|
+
export declare const GUIDED_ONBOARDING_COMPANY_CONTEXT_LIMITS: {
|
|
4
|
+
readonly descriptionChars: 6000;
|
|
5
|
+
readonly contextLinks: 5;
|
|
6
|
+
readonly fileIds: 5;
|
|
7
|
+
readonly nameChars: 160;
|
|
8
|
+
readonly urlChars: 2000;
|
|
9
|
+
};
|
|
10
|
+
export declare const GUIDED_ONBOARDING_COMPANY_CONTEXT_CONTRACT: import("./contracts/schema.js").ContractObject<{
|
|
11
|
+
readonly website: {
|
|
12
|
+
oneOf: [import("./contracts/schema.js").StringProperty, import("./contracts/schema.js").NullProperty];
|
|
13
|
+
description?: string;
|
|
14
|
+
};
|
|
15
|
+
readonly name: import("./contracts/schema.js").StringProperty;
|
|
16
|
+
readonly description: import("./contracts/schema.js").StringProperty;
|
|
17
|
+
readonly context_links: import("./contracts/schema.js").ArrayProperty<import("./contracts/schema.js").StringProperty>;
|
|
18
|
+
readonly file_ids: import("./contracts/schema.js").ArrayProperty<import("./contracts/schema.js").StringProperty>;
|
|
19
|
+
}, "context_links" | "description" | "file_ids" | "name" | "website">;
|
|
20
|
+
/** Input-only rule; existing evidence links retain their independent navigation policy. */
|
|
21
|
+
export declare function normalizeGuidedOnboardingContextLink(value: string): string;
|
|
22
|
+
export declare function normalizeGuidedOnboardingCompanyContext(input: unknown): NonNullable<GuidedOnboardingAnswers["company_context"]>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { OxygenError } from "./cli-result.js";
|
|
2
|
+
import { arr, nullable, obj, str, validateContract } from "./contracts/schema.js";
|
|
3
|
+
/** One native-supported input budget for web/CLI/MCP and D research preparation. */
|
|
4
|
+
export const GUIDED_ONBOARDING_COMPANY_CONTEXT_LIMITS = {
|
|
5
|
+
descriptionChars: 6000, contextLinks: 5, fileIds: 5, nameChars: 160, urlChars: 2000,
|
|
6
|
+
};
|
|
7
|
+
const limits = GUIDED_ONBOARDING_COMPANY_CONTEXT_LIMITS;
|
|
8
|
+
export const GUIDED_ONBOARDING_COMPANY_CONTEXT_CONTRACT = obj({
|
|
9
|
+
website: nullable(str({ maxLength: limits.urlChars })), name: str({ maxLength: limits.nameChars }),
|
|
10
|
+
description: str({ maxLength: limits.descriptionChars }),
|
|
11
|
+
context_links: arr(str({ minLength: 1, maxLength: limits.urlChars }), { maxItems: limits.contextLinks }),
|
|
12
|
+
file_ids: arr(str({ minLength: 1, maxLength: 160 }), { maxItems: limits.fileIds }),
|
|
13
|
+
}, { required: ["website", "name", "description", "context_links", "file_ids"] });
|
|
14
|
+
const fail = (message) => { throw new OxygenError("invalid_onboarding_answer", message, { exitCode: 2 }); };
|
|
15
|
+
/** Input-only rule; existing evidence links retain their independent navigation policy. */
|
|
16
|
+
export function normalizeGuidedOnboardingContextLink(value) {
|
|
17
|
+
try {
|
|
18
|
+
const url = new URL(value.includes("://") ? value : `https://${value}`);
|
|
19
|
+
if (url.protocol !== "https:" || url.username || url.password || !url.hostname.includes("."))
|
|
20
|
+
return fail("Use an HTTPS website or context link without credentials.");
|
|
21
|
+
return url.href;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return fail("Use a valid HTTPS website or context link.");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function normalizeGuidedOnboardingCompanyContext(input) {
|
|
28
|
+
const checked = validateContract(GUIDED_ONBOARDING_COMPANY_CONTEXT_CONTRACT, input, { unknown: "reject", overMax: "reject" });
|
|
29
|
+
if (!checked.ok)
|
|
30
|
+
return fail("Use up to 6000 description characters, five context links and five Knowledge files.");
|
|
31
|
+
const value = checked.value;
|
|
32
|
+
const website = value.website?.trim() ? normalizeGuidedOnboardingContextLink(value.website.trim()) : null;
|
|
33
|
+
const description = value.description.trim();
|
|
34
|
+
if (!website && !description)
|
|
35
|
+
return fail("Provide a website or describe your company.");
|
|
36
|
+
return { website, name: value.name.normalize("NFKC").trim().replace(/\s+/gu, " "), description,
|
|
37
|
+
context_links: [...new Set(value.context_links.map(link => normalizeGuidedOnboardingContextLink(link.trim())))], file_ids: [...new Set(value.file_ids)] };
|
|
38
|
+
}
|
|
@@ -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;
|