@oxygen-agent/cli 1.164.30 → 1.177.0

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.
Files changed (32) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +1195 -507
  3. package/dist/run-wait.d.ts +23 -0
  4. package/dist/run-wait.js +57 -0
  5. package/node_modules/@oxygen/shared/dist/cell-format.d.ts +2 -14
  6. package/node_modules/@oxygen/shared/dist/cell-format.js +3 -10
  7. package/node_modules/@oxygen/shared/dist/cli-envelope.d.ts +1 -1
  8. package/node_modules/@oxygen/shared/dist/cli-result.d.ts +39 -0
  9. package/node_modules/@oxygen/shared/dist/cli-result.js +52 -0
  10. package/node_modules/@oxygen/shared/dist/credit-guidance.d.ts +0 -1
  11. package/node_modules/@oxygen/shared/dist/credit-guidance.js +1 -1
  12. package/node_modules/@oxygen/shared/dist/file-import.js +1 -1
  13. package/node_modules/@oxygen/shared/dist/index.d.ts +2 -39
  14. package/node_modules/@oxygen/shared/dist/index.js +2 -44
  15. package/node_modules/@oxygen/shared/dist/log.d.ts +0 -1
  16. package/node_modules/@oxygen/shared/dist/log.js +8 -3
  17. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +0 -3
  18. package/node_modules/@oxygen/shared/dist/object-storage.js +1 -24
  19. package/node_modules/@oxygen/shared/dist/search-vocab.d.ts +18 -0
  20. package/node_modules/@oxygen/shared/dist/search-vocab.js +151 -0
  21. package/node_modules/@oxygen/shared/dist/select-options.d.ts +18 -0
  22. package/node_modules/@oxygen/shared/dist/select-options.js +121 -0
  23. package/node_modules/@oxygen/shared/dist/sequences.js +1 -1
  24. package/node_modules/@oxygen/shared/dist/sql-error.d.ts +0 -6
  25. package/node_modules/@oxygen/shared/dist/sql-error.js +67 -58
  26. package/node_modules/@oxygen/shared/dist/telemetry.d.ts +0 -1
  27. package/node_modules/@oxygen/shared/dist/telemetry.js +23 -18
  28. package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
  29. package/node_modules/@oxygen/shared/dist/version.js +1 -1
  30. package/node_modules/@oxygen/shared/dist/worker-failures-queue.d.ts +22 -0
  31. package/node_modules/@oxygen/shared/dist/worker-failures-queue.js +56 -0
  32. package/package.json +1 -1
@@ -0,0 +1,23 @@
1
+ export interface CliRunWaitConfig {
2
+ /** Run id echoed into the timeout error details. */
3
+ runId: string;
4
+ /** Raw --timeout-seconds flag; falls back to defaultTimeoutSeconds when unset. */
5
+ requestedTimeoutSeconds?: string | undefined;
6
+ /** Raw --interval-seconds flag; falls back to defaultIntervalSeconds when unset. */
7
+ requestedIntervalSeconds?: string | undefined;
8
+ defaultTimeoutSeconds: number;
9
+ defaultIntervalSeconds: number;
10
+ /** Fetches the latest run snapshot to inspect this poll. */
11
+ fetchRun: () => Promise<Record<string, unknown>>;
12
+ /** True when the run status is terminal for this resource. */
13
+ isTerminal: (status: string | null) => boolean;
14
+ /** Builds the response once a terminal status is observed. */
15
+ shapeTerminal: (run: Record<string, unknown>, status: string | null, polls: number, elapsedMs: number) => Record<string, unknown>;
16
+ /** OxygenError shape thrown when the deadline passes before a terminal status. */
17
+ timeoutCode: string;
18
+ timeoutMessage: string;
19
+ timeoutDetailIdKey: string;
20
+ /** Optional extra timeout details (e.g. workflow queued-no-worker guidance). */
21
+ timeoutExtraDetails?: (latestRun: Record<string, unknown> | null, status: string | null) => Record<string, unknown>;
22
+ }
23
+ export declare function waitForCliRun(config: CliRunWaitConfig): Promise<Record<string, unknown>>;
@@ -0,0 +1,57 @@
1
+ import { OxygenError } from "@oxygen/shared";
2
+ export async function waitForCliRun(config) {
3
+ const timeoutSeconds = readPositiveInt(config.requestedTimeoutSeconds)
4
+ ?? config.defaultTimeoutSeconds;
5
+ const intervalSeconds = readPositiveInt(config.requestedIntervalSeconds)
6
+ ?? config.defaultIntervalSeconds;
7
+ const startedAt = Date.now();
8
+ const deadline = startedAt + timeoutSeconds * 1000;
9
+ let polls = 0;
10
+ while (true) {
11
+ polls += 1;
12
+ const latestRun = await config.fetchRun();
13
+ const status = readRecordString(latestRun, "status");
14
+ if (config.isTerminal(status)) {
15
+ return config.shapeTerminal(latestRun, status, polls, Date.now() - startedAt);
16
+ }
17
+ const remainingMs = deadline - Date.now();
18
+ if (remainingMs <= 0) {
19
+ throw new OxygenError(config.timeoutCode, config.timeoutMessage, {
20
+ details: {
21
+ [config.timeoutDetailIdKey]: config.runId,
22
+ status: status ?? null,
23
+ timeout_seconds: timeoutSeconds,
24
+ polls,
25
+ ...(config.timeoutExtraDetails?.(latestRun, status) ?? {}),
26
+ },
27
+ exitCode: 1,
28
+ });
29
+ }
30
+ await sleep(Math.min(intervalSeconds * 1000, remainingMs));
31
+ }
32
+ }
33
+ // Local copies of index.ts's tiny readers keep this helper free of an
34
+ // index.ts <-> run-wait.ts import cycle (the MCP run-wait.ts module likewise
35
+ // defines its own sleep rather than importing from a tool file).
36
+ function readPositiveInt(value) {
37
+ const trimmed = value?.trim();
38
+ if (!trimmed)
39
+ return undefined;
40
+ const parsed = Number(trimmed);
41
+ if (!Number.isInteger(parsed) || parsed < 1) {
42
+ throw new OxygenError("invalid_number", "Expected a positive integer.", {
43
+ details: { value },
44
+ exitCode: 1,
45
+ });
46
+ }
47
+ return parsed;
48
+ }
49
+ function readRecordString(value, key) {
50
+ if (!value || typeof value !== "object" || Array.isArray(value))
51
+ return null;
52
+ const entry = value[key];
53
+ return typeof entry === "string" ? entry : null;
54
+ }
55
+ function sleep(ms) {
56
+ return new Promise((resolve) => setTimeout(resolve, ms));
57
+ }
@@ -11,7 +11,8 @@
11
11
  * and provider adapters, so a `text` column whose values parse cleanly as
12
12
  * numbers still gets thousands grouping at display time.
13
13
  * 3. Refuse to "rescue" things that aren't actually numbers (IP addresses,
14
- * version strings, phone numbers, URLs), via {@link looksLikeNumericText}.
14
+ * version strings, phone numbers, URLs): {@link rescueNumericText} returns
15
+ * null for those.
15
16
  */
16
17
  /** Surfaces have different escaping/length budgets, but the canonical string is shared. */
17
18
  export type CellFormatSurface = "cli" | "mcp" | "web";
@@ -38,19 +39,6 @@ export type CellFormatOptions = {
38
39
  * escaping, ellipsis budgets) belong outside this function.
39
40
  */
40
41
  export declare function formatCellForDisplay(value: unknown, column: CellColumnLike | null | undefined, options: CellFormatOptions): string;
41
- /**
42
- * Best-effort parse of a string that looks numeric (with or without thousands
43
- * grouping, with or without dotted IP-style separators) into a finite number.
44
- * Returns `null` when the string is clearly *not* a single number — IP
45
- * addresses, version strings, phone numbers, anything alphabetic.
46
- */
47
- export declare function rescueNumericText(raw: string): number | null;
48
- /**
49
- * True when a string is unambiguously numeric (integer, decimal, grouped, or
50
- * a mangled dotted form we can recover). Exported for callers that want to
51
- * highlight rescue cases without re-running the formatter.
52
- */
53
- export declare function looksLikeNumericText(value: string): boolean;
54
42
  /**
55
43
  * Decide whether the same value-level + column-level guards used inside
56
44
  * `formatCellForDisplay`'s text path should rescue this string. Exposed so
@@ -11,7 +11,8 @@
11
11
  * and provider adapters, so a `text` column whose values parse cleanly as
12
12
  * numbers still gets thousands grouping at display time.
13
13
  * 3. Refuse to "rescue" things that aren't actually numbers (IP addresses,
14
- * version strings, phone numbers, URLs), via {@link looksLikeNumericText}.
14
+ * version strings, phone numbers, URLs): {@link rescueNumericText} returns
15
+ * null for those.
15
16
  */
16
17
  const DEFAULT_LOCALE = "en-US";
17
18
  const INTEGER_RE = /^-?\d{1,15}$/;
@@ -99,7 +100,7 @@ export function formatCellForDisplay(value, column, options) {
99
100
  * Returns `null` when the string is clearly *not* a single number — IP
100
101
  * addresses, version strings, phone numbers, anything alphabetic.
101
102
  */
102
- export function rescueNumericText(raw) {
103
+ function rescueNumericText(raw) {
103
104
  const trimmed = raw.trim();
104
105
  if (!trimmed)
105
106
  return null;
@@ -168,14 +169,6 @@ function decodeDottedNumeric(raw) {
168
169
  const n = Number(normalized || "0");
169
170
  return Number.isFinite(n) ? sign * n : null;
170
171
  }
171
- /**
172
- * True when a string is unambiguously numeric (integer, decimal, grouped, or
173
- * a mangled dotted form we can recover). Exported for callers that want to
174
- * highlight rescue cases without re-running the formatter.
175
- */
176
- export function looksLikeNumericText(value) {
177
- return rescueNumericText(value) !== null;
178
- }
179
172
  function readDataType(column) {
180
173
  const raw = column?.dataType ?? column?.data_type ?? null;
181
174
  if (!raw)
@@ -1,4 +1,4 @@
1
- import type { CliResult } from "./index.js";
1
+ import type { CliResult } from "./cli-result.js";
2
2
  /** Server compatibility metadata extracted from a `CliResult.meta` envelope. */
3
3
  export type ServerCompatibility = {
4
4
  version?: string;
@@ -0,0 +1,39 @@
1
+ export type JsonValue = string | number | boolean | null | JsonValue[] | {
2
+ [key: string]: JsonValue;
3
+ };
4
+ export type CliMeta = {
5
+ command: string;
6
+ version: string;
7
+ minimum_cli_version?: string;
8
+ };
9
+ export type CliSuccess<T> = {
10
+ ok: true;
11
+ data: T;
12
+ meta: CliMeta;
13
+ };
14
+ export type CliFailure = {
15
+ ok: false;
16
+ error: {
17
+ code: string;
18
+ message: string;
19
+ details?: unknown;
20
+ };
21
+ meta: CliMeta;
22
+ };
23
+ export type CliResult<T> = CliSuccess<T> | CliFailure;
24
+ export declare class OxygenError extends Error {
25
+ readonly code: string;
26
+ readonly details?: unknown;
27
+ readonly exitCode: number;
28
+ constructor(code: string, message: string, options?: {
29
+ details?: unknown;
30
+ exitCode?: number;
31
+ });
32
+ }
33
+ export declare function success<T>(command: string, data: T, version?: string, minimumCliVersion?: string): CliSuccess<T>;
34
+ export declare function failure(command: string, error: {
35
+ code: string;
36
+ message: string;
37
+ details?: unknown;
38
+ }, version?: string, minimumCliVersion?: string): CliFailure;
39
+ export declare function toFailure(command: string, error: unknown, version?: string): CliFailure;
@@ -0,0 +1,52 @@
1
+ // Core CLI-result envelope + error primitives, owned by a dependency-free leaf
2
+ // module so the shared package's other leaf modules (sequences, file-import,
3
+ // object-storage, cli-envelope, ...) can depend on `OxygenError` / `CliResult`
4
+ // without importing the root barrel (`./index.js`). The barrel re-exports
5
+ // everything here, so public imports from `@oxygen/shared` are unchanged; this
6
+ // only removes an internal runtime cycle (barrel → leaf → barrel) and stops
7
+ // subpath modules pulling the whole barrel for one class. Depends only on
8
+ // `./version.js` (itself a leaf).
9
+ import { OXYGEN_MINIMUM_CLI_VERSION, OXYGEN_VERSION } from "./version.js";
10
+ export class OxygenError extends Error {
11
+ code;
12
+ details;
13
+ exitCode;
14
+ constructor(code, message, options = {}) {
15
+ super(message);
16
+ this.name = "OxygenError";
17
+ this.code = code;
18
+ this.details = options.details;
19
+ this.exitCode = options.exitCode ?? 1;
20
+ }
21
+ }
22
+ export function success(command, data, version = OXYGEN_VERSION, minimumCliVersion = OXYGEN_MINIMUM_CLI_VERSION) {
23
+ return {
24
+ ok: true,
25
+ data,
26
+ meta: {
27
+ command,
28
+ version,
29
+ minimum_cli_version: minimumCliVersion,
30
+ }
31
+ };
32
+ }
33
+ export function failure(command, error, version = OXYGEN_VERSION, minimumCliVersion = OXYGEN_MINIMUM_CLI_VERSION) {
34
+ return {
35
+ ok: false,
36
+ error,
37
+ meta: {
38
+ command,
39
+ version,
40
+ minimum_cli_version: minimumCliVersion,
41
+ }
42
+ };
43
+ }
44
+ export function toFailure(command, error, version = OXYGEN_VERSION) {
45
+ if (error instanceof OxygenError) {
46
+ return failure(command, { code: error.code, message: error.message, details: error.details }, version);
47
+ }
48
+ if (error instanceof Error) {
49
+ return failure(command, { code: "unexpected_error", message: error.message }, version);
50
+ }
51
+ return failure(command, { code: "unexpected_error", message: "An unexpected error occurred." }, version);
52
+ }
@@ -11,4 +11,3 @@ export declare function buildCreditGuidance(input: {
11
11
  availableCredits: number | null | undefined;
12
12
  headroomMultiplier?: number;
13
13
  }): CreditGuidance;
14
- export declare function recommendedCreditCeiling(estimatedCredits: number | null | undefined, headroomMultiplier?: number): number | null;
@@ -38,7 +38,7 @@ export function buildCreditGuidance(input) {
38
38
  credit_guidance: "Credits are tight for the recommended ceiling; ask before running, reduce scope, or top up credits.",
39
39
  };
40
40
  }
41
- export function recommendedCreditCeiling(estimatedCredits, headroomMultiplier = DEFAULT_HEADROOM_MULTIPLIER) {
41
+ function recommendedCreditCeiling(estimatedCredits, headroomMultiplier = DEFAULT_HEADROOM_MULTIPLIER) {
42
42
  const normalized = normalizeCreditValue(estimatedCredits);
43
43
  if (normalized === null)
44
44
  return null;
@@ -1,7 +1,7 @@
1
1
  import { extname } from "node:path";
2
2
  import readXlsxFile from "read-excel-file/node";
3
3
  import { inferImportColumnDataType, parseDateValueToIso, } from "./column-types.js";
4
- import { OxygenError } from "./index.js";
4
+ import { OxygenError } from "./cli-result.js";
5
5
  const MAX_IDENTIFIER_LENGTH = 63;
6
6
  export const MAX_BUFFERED_IMPORT_PARSE_BYTES = 10 * 1024 * 1024;
7
7
  export function inferRowsFileFormat(path) {
@@ -3,6 +3,7 @@ export { WORKFLOW_TRIGGER_AUTO_PAUSE_METADATA_KEYS, clearWorkflowTriggerAutoPaus
3
3
  export * from "./billing.js";
4
4
  export * from "./cell-format.js";
5
5
  export * from "./cli-envelope.js";
6
+ export * from "./cli-result.js";
6
7
  export * from "./column-types.js";
7
8
  export * from "./credit-guidance.js";
8
9
  export * from "./linkedin-sequences.js";
@@ -12,46 +13,8 @@ export * from "./provider-request-outcomes.js";
12
13
  export * from "./signup-lead-deliveries.js";
13
14
  export * from "./sql-error.js";
14
15
  export * from "./telemetry.js";
16
+ export * from "./worker-failures-queue.js";
15
17
  export declare const MAX_ROW_LOOP_WRITE_ROWS = 500;
16
- export type JsonValue = string | number | boolean | null | JsonValue[] | {
17
- [key: string]: JsonValue;
18
- };
19
- export type CliMeta = {
20
- command: string;
21
- version: string;
22
- minimum_cli_version?: string;
23
- };
24
- export type CliSuccess<T> = {
25
- ok: true;
26
- data: T;
27
- meta: CliMeta;
28
- };
29
- export type CliFailure = {
30
- ok: false;
31
- error: {
32
- code: string;
33
- message: string;
34
- details?: unknown;
35
- };
36
- meta: CliMeta;
37
- };
38
- export type CliResult<T> = CliSuccess<T> | CliFailure;
39
- export declare class OxygenError extends Error {
40
- readonly code: string;
41
- readonly details?: unknown;
42
- readonly exitCode: number;
43
- constructor(code: string, message: string, options?: {
44
- details?: unknown;
45
- exitCode?: number;
46
- });
47
- }
48
- export declare function success<T>(command: string, data: T, version?: string, minimumCliVersion?: string): CliSuccess<T>;
49
- export declare function failure(command: string, error: {
50
- code: string;
51
- message: string;
52
- details?: unknown;
53
- }, version?: string, minimumCliVersion?: string): CliFailure;
54
- export declare function toFailure(command: string, error: unknown, version?: string): CliFailure;
55
18
  export type SemanticVersion = {
56
19
  major: number;
57
20
  minor: number;
@@ -1,9 +1,9 @@
1
- import { OXYGEN_MINIMUM_CLI_VERSION, OXYGEN_VERSION } from "./version.js";
2
1
  export { OXYGEN_MINIMUM_CLI_VERSION, OXYGEN_VERSION } from "./version.js";
3
2
  export { WORKFLOW_TRIGGER_AUTO_PAUSE_METADATA_KEYS, clearWorkflowTriggerAutoPauseMetadata, } from "./workflow-trigger-metadata.js";
4
3
  export * from "./billing.js";
5
4
  export * from "./cell-format.js";
6
5
  export * from "./cli-envelope.js";
6
+ export * from "./cli-result.js";
7
7
  export * from "./column-types.js";
8
8
  export * from "./credit-guidance.js";
9
9
  export * from "./linkedin-sequences.js";
@@ -13,55 +13,13 @@ export * from "./provider-request-outcomes.js";
13
13
  export * from "./signup-lead-deliveries.js";
14
14
  export * from "./sql-error.js";
15
15
  export * from "./telemetry.js";
16
+ export * from "./worker-failures-queue.js";
16
17
  // Maximum rows a single row-loop write (insert/upsert/preview) may process. The
17
18
  // row-loop engine issues one DB round-trip per row, so a 500-row write already
18
19
  // approaches request timeouts (~50s observed in prod); larger batches must use
19
20
  // the COPY-based bulk engine. Tenant-db enforces this and the CLI/API row caps
20
21
  // reference it so they never advertise a batch the row-loop will reject.
21
22
  export const MAX_ROW_LOOP_WRITE_ROWS = 500;
22
- export class OxygenError extends Error {
23
- code;
24
- details;
25
- exitCode;
26
- constructor(code, message, options = {}) {
27
- super(message);
28
- this.name = "OxygenError";
29
- this.code = code;
30
- this.details = options.details;
31
- this.exitCode = options.exitCode ?? 1;
32
- }
33
- }
34
- export function success(command, data, version = OXYGEN_VERSION, minimumCliVersion = OXYGEN_MINIMUM_CLI_VERSION) {
35
- return {
36
- ok: true,
37
- data,
38
- meta: {
39
- command,
40
- version,
41
- minimum_cli_version: minimumCliVersion,
42
- }
43
- };
44
- }
45
- export function failure(command, error, version = OXYGEN_VERSION, minimumCliVersion = OXYGEN_MINIMUM_CLI_VERSION) {
46
- return {
47
- ok: false,
48
- error,
49
- meta: {
50
- command,
51
- version,
52
- minimum_cli_version: minimumCliVersion,
53
- }
54
- };
55
- }
56
- export function toFailure(command, error, version = OXYGEN_VERSION) {
57
- if (error instanceof OxygenError) {
58
- return failure(command, { code: error.code, message: error.message, details: error.details }, version);
59
- }
60
- if (error instanceof Error) {
61
- return failure(command, { code: "unexpected_error", message: error.message }, version);
62
- }
63
- return failure(command, { code: "unexpected_error", message: "An unexpected error occurred." }, version);
64
- }
65
23
  /**
66
24
  * Parse a three-segment semantic version (e.g. `1.142.17`). Pre-release and
67
25
  * build metadata suffixes (`-rc.1`, `+build`) are tolerated but ignored.
@@ -15,7 +15,6 @@ export type LogContext = {
15
15
  surface?: "mcp" | "cli" | "web" | "worker" | undefined;
16
16
  };
17
17
  export declare function withLogContext<T>(ctx: LogContext, fn: () => T): T;
18
- export declare function getLogContext(): LogContext;
19
18
  export declare function log(level: LogLevel, msg: string, fields?: Record<string, unknown>): void;
20
19
  export declare function errorId(err: unknown): string;
21
20
  export declare function errorFields(err: unknown): Record<string, unknown>;
@@ -7,7 +7,7 @@ export function withLogContext(ctx, fn) {
7
7
  const merged = { ...(store.getStore() ?? {}), ...ctx };
8
8
  return store.run(merged, fn);
9
9
  }
10
- export function getLogContext() {
10
+ function getLogContext() {
11
11
  return store.getStore() ?? {};
12
12
  }
13
13
  export function log(level, msg, fields) {
@@ -68,9 +68,14 @@ export function errorFields(err) {
68
68
  error_id: errorId(err),
69
69
  error_name: err.name,
70
70
  // Strip drizzle's `\nparams: <values>` tail so SQL parameter values never
71
- // reach logs (OXY-46); the SQL text and stack frames are preserved.
71
+ // reach logs (OXY-46).
72
72
  error_message: redactSqlParameters(err.message),
73
- error_stack: err.stack ? redactSqlParameters(err.stack) : err.stack,
73
+ // Deliberately NOT emitting `error_stack`: raw stack frames in
74
+ // Axiom-bound log fields leak absolute file paths and any credential
75
+ // dumped into a frame, and they tripped the prod/preview log-hygiene
76
+ // sweep (OXY-166). `error_id` already hashes name + message + first frame,
77
+ // so same-origin errors still group for triage without shipping the
78
+ // frames themselves; reproduce locally or follow trace_id for the stack.
74
79
  };
75
80
  }
76
81
  return { error_id: "non_error", error_message: redactSqlParameters(String(err)) };
@@ -18,9 +18,6 @@ export declare function presignImportUpload(input: {
18
18
  contentType?: string | null;
19
19
  contentLength: number;
20
20
  }): Promise<PresignedImportUpload>;
21
- export declare function downloadImportObject(input: {
22
- storageKey: string;
23
- }): Promise<Buffer>;
24
21
  export declare function getImportObjectMetadata(input: {
25
22
  storageKey: string;
26
23
  }): Promise<{
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, PutObjectCommand, S3Client, } from "@aws-sdk/client-s3";
3
3
  import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
4
- import { OxygenError } from "./index.js";
4
+ import { OxygenError } from "./cli-result.js";
5
5
  // S3-compatible object storage for large CSV/file imports. The CLI uploads the
6
6
  // raw file straight to the bucket via a presigned PUT URL (bypassing Vercel's
7
7
  // ~4.5MB request-body limit), then the Fly worker downloads it and COPY-loads
@@ -80,22 +80,6 @@ export async function presignImportUpload(input) {
80
80
  expiresInSeconds: PRESIGN_EXPIRY_SECONDS,
81
81
  };
82
82
  }
83
- export async function downloadImportObject(input) {
84
- const { client, config } = resolveClient();
85
- const result = await client.send(new GetObjectCommand({ Bucket: config.bucket, Key: input.storageKey }));
86
- const body = result.Body;
87
- if (!body) {
88
- throw new OxygenError("import_object_missing", "Import object had no body.", {
89
- details: { storage_key: input.storageKey },
90
- exitCode: 1,
91
- });
92
- }
93
- const transform = body.transformToByteArray;
94
- if (typeof transform === "function") {
95
- return Buffer.from(await transform.call(body));
96
- }
97
- return streamToBuffer(body);
98
- }
99
83
  export async function getImportObjectMetadata(input) {
100
84
  const { client, config } = resolveClient();
101
85
  const result = await client.send(new HeadObjectCommand({ Bucket: config.bucket, Key: input.storageKey }));
@@ -125,10 +109,3 @@ function sanitizeFileName(fileName) {
125
109
  const base = fileName.split(/[\\/]/).pop() ?? "";
126
110
  return base.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 120);
127
111
  }
128
- async function streamToBuffer(stream) {
129
- const chunks = [];
130
- for await (const chunk of stream) {
131
- chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk));
132
- }
133
- return Buffer.concat(chunks);
134
- }
@@ -0,0 +1,18 @@
1
+ export declare function normalizeText(value: string): string;
2
+ export declare function escapeRegExp(value: string): string;
3
+ export declare function extractUrls(value: string): string[];
4
+ export declare function extractDomains(value: string): string[];
5
+ export declare function parseMoney(amount: string, unit: string | undefined): number;
6
+ export declare function regionDisplayName(code: string): string | null;
7
+ export declare const COUNTRY_NAME_TO_ISO: Map<string, string>;
8
+ export declare const COUNTRY_ALIAS_TO_ISO: Record<string, string>;
9
+ export declare const CITY_TO_ISO: Record<string, string>;
10
+ export declare const KNOWN_TECHNOLOGIES: readonly ["salesforce", "hubspot", "shopify", "stripe", "aws", "azure", "gcp", "google cloud", "snowflake", "databricks", "postgres", "postgresql", "mysql", "mongodb", "redis", "kafka", "kubernetes", "docker", "react", "nextjs", "next.js", "vue", "angular", "node", "python", "ruby on rails", "django", "segment", "amplitude", "mixpanel", "intercom", "zendesk", "marketo", "pardot", "outreach", "salesloft", "gong", "clari", "netsuite", "workday", "sap", "oracle", "twilio", "klaviyo", "webflow", "wordpress", "magento", "bigcommerce", "woocommerce"];
11
+ export declare const INDUSTRY_TERMS: readonly ["saas", "b2b saas", "fintech", "healthtech", "healthcare", "edtech", "martech", "adtech", "proptech", "insurtech", "legaltech", "hrtech", "regtech", "biotech", "medtech", "cleantech", "climate tech", "cybersecurity", "security", "devtools", "developer tools", "e-commerce", "ecommerce", "logistics", "supply chain", "manufacturing", "construction", "real estate", "hospitality", "retail", "gaming", "media", "telecom", "automotive", "aerospace", "agritech", "foodtech", "ai", "artificial intelligence", "machine learning", "data analytics", "consulting", "staffing", "recruiting"];
12
+ export declare const EMPLOYEE_SEGMENTS: Record<string, {
13
+ min?: number;
14
+ max?: number;
15
+ }>;
16
+ export declare const KEYWORD_STOPWORDS: Set<string>;
17
+ export declare const DEPARTMENT_TERMS: Record<string, string>;
18
+ export declare const SENIORITY_TERMS: Record<string, string>;