@oxygen-agent/cli 1.1010.721 → 1.1010.905
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/auto-update.d.ts +129 -0
- package/dist/auto-update.js +392 -0
- package/dist/command-manifest.js +14 -0
- package/dist/credentials.d.ts +2 -0
- package/dist/credentials.js +6 -3
- package/dist/functions-commands.js +1 -1
- package/dist/http-client.js +28 -4
- package/dist/index.js +583 -145
- package/dist/run-wait.d.ts +3 -1
- package/dist/run-wait.js +19 -5
- package/dist/streamed-file-import.d.ts +58 -0
- package/dist/streamed-file-import.js +115 -0
- package/dist/update.d.ts +29 -0
- package/dist/update.js +62 -16
- package/dist/workflow-plan-limit-notices.d.ts +8 -0
- package/dist/workflow-plan-limit-notices.js +28 -0
- package/node_modules/@oxygen/cli-ugc/dist/commands.js +3 -3
- package/node_modules/@oxygen/shared/dist/billing-anchors.d.ts +17 -0
- package/node_modules/@oxygen/shared/dist/billing-anchors.js +27 -0
- package/node_modules/@oxygen/shared/dist/billing.d.ts +191 -35
- package/node_modules/@oxygen/shared/dist/billing.js +333 -42
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +55 -5
- package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +2 -2
- package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +2 -2
- package/node_modules/@oxygen/shared/dist/cost-estimate-view.d.ts +50 -0
- package/node_modules/@oxygen/shared/dist/cost-estimate-view.js +90 -0
- package/node_modules/@oxygen/shared/dist/cost-estimate.d.ts +167 -0
- package/node_modules/@oxygen/shared/dist/cost-estimate.js +361 -0
- package/node_modules/@oxygen/shared/dist/credit-gate.d.ts +26 -0
- package/node_modules/@oxygen/shared/dist/credit-gate.js +65 -0
- package/node_modules/@oxygen/shared/dist/email-deliverability-policy.d.ts +51 -0
- package/node_modules/@oxygen/shared/dist/email-deliverability-policy.js +101 -0
- package/node_modules/@oxygen/shared/dist/email-hard-bounce.d.ts +3 -1
- package/node_modules/@oxygen/shared/dist/email-hard-bounce.js +3 -3
- package/node_modules/@oxygen/shared/dist/error-redaction.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/error-redaction.js +1 -1
- 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 +13 -1
- package/node_modules/@oxygen/shared/dist/file-import.js +33 -6
- package/node_modules/@oxygen/shared/dist/hosted-ai.d.ts +73 -3
- package/node_modules/@oxygen/shared/dist/hosted-ai.js +246 -24
- package/node_modules/@oxygen/shared/dist/import-limits.d.ts +25 -1
- package/node_modules/@oxygen/shared/dist/import-limits.js +35 -2
- package/node_modules/@oxygen/shared/dist/index.d.ts +2 -22
- package/node_modules/@oxygen/shared/dist/index.js +2 -42
- package/node_modules/@oxygen/shared/dist/object-storage.d.ts +9 -0
- package/node_modules/@oxygen/shared/dist/object-storage.js +17 -0
- package/node_modules/@oxygen/shared/dist/operational-telemetry.d.ts +41 -0
- package/node_modules/@oxygen/shared/dist/operational-telemetry.js +55 -0
- package/node_modules/@oxygen/shared/dist/plan-band.d.ts +117 -1
- package/node_modules/@oxygen/shared/dist/plan-band.js +175 -10
- package/node_modules/@oxygen/shared/dist/plan-capabilities.d.ts +77 -7
- package/node_modules/@oxygen/shared/dist/plan-capabilities.js +87 -7
- package/node_modules/@oxygen/shared/dist/plan-limits-view.d.ts +219 -0
- package/node_modules/@oxygen/shared/dist/plan-limits-view.js +330 -0
- package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +204 -6
- package/node_modules/@oxygen/shared/dist/plan-limits.js +197 -15
- package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +80 -36
- package/node_modules/@oxygen/shared/dist/pricing-sheet.js +80 -31
- package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +38 -20
- package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +47 -34
- package/node_modules/@oxygen/shared/dist/provider-http-error.d.ts +10 -0
- package/node_modules/@oxygen/shared/dist/provider-http-error.js +27 -0
- package/node_modules/@oxygen/shared/dist/repricing.d.ts +127 -0
- package/node_modules/@oxygen/shared/dist/repricing.js +407 -6
- package/node_modules/@oxygen/shared/dist/semver.d.ts +21 -0
- package/node_modules/@oxygen/shared/dist/semver.js +41 -0
- package/node_modules/@oxygen/shared/dist/sending-limits.d.ts +5 -7
- package/node_modules/@oxygen/shared/dist/sending-limits.js +10 -16
- package/node_modules/@oxygen/shared/dist/sending-seats.d.ts +18 -15
- package/node_modules/@oxygen/shared/dist/sending-seats.js +22 -17
- package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +57 -8
- package/node_modules/@oxygen/shared/dist/spend-safety.js +64 -11
- package/node_modules/@oxygen/shared/dist/stripe-price-catalog.d.ts +15 -7
- package/node_modules/@oxygen/shared/dist/stripe-price-catalog.js +18 -5
- package/node_modules/@oxygen/shared/dist/table-capacity.d.ts +34 -5
- package/node_modules/@oxygen/shared/dist/table-capacity.js +25 -8
- package/node_modules/@oxygen/shared/dist/telemetry-export-observer.d.ts +6 -0
- package/node_modules/@oxygen/shared/dist/telemetry-export-observer.js +13 -5
- package/node_modules/@oxygen/shared/dist/telemetry-resource.d.ts +40 -0
- package/node_modules/@oxygen/shared/dist/telemetry-resource.js +35 -0
- package/node_modules/@oxygen/shared/dist/telemetry.js +5 -0
- package/node_modules/@oxygen/shared/dist/ugc.d.ts +15 -0
- package/node_modules/@oxygen/shared/dist/ugc.js +29 -0
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -3
- package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +14 -27
- package/node_modules/@oxygen/shared/dist/workspace-file-storage.d.ts +5 -0
- package/node_modules/@oxygen/shared/dist/workspace-file-storage.js +5 -0
- package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +3 -3
- package/node_modules/@oxygen/workflows/dist/graph/types.d.ts +15 -1
- package/node_modules/@oxygen/workflows/dist/graph/types.js +15 -1
- package/node_modules/@oxygen/workflows/dist/index.d.ts +45 -0
- package/node_modules/@oxygen/workflows/dist/index.js +152 -2
- package/node_modules/@oxygen/workflows/dist/usage-estimate.d.ts +10 -1
- package/node_modules/@oxygen/workflows/dist/usage-estimate.js +33 -29
- package/package.json +1 -1
|
@@ -10,12 +10,31 @@
|
|
|
10
10
|
* constants live here alone, and both of those modules re-export them, keeping
|
|
11
11
|
* one definition rather than a copy that drifts.
|
|
12
12
|
*/
|
|
13
|
+
const MIB = 1024 * 1024;
|
|
13
14
|
/**
|
|
14
15
|
* Formats that must be held in memory to parse at all — a JSON array has no
|
|
15
16
|
* record boundary to stream from, and XLSX is a zip container. CSV and JSONL
|
|
16
|
-
* stream, so only these two
|
|
17
|
+
* stream from object storage up to the plan's file limit, so only these two
|
|
18
|
+
* carry this lower ceiling (raised from 10 MiB by decision F.8, 2026-09-27).
|
|
19
|
+
*
|
|
20
|
+
* It also bounds every path that holds a whole file in one request: the inline
|
|
21
|
+
* multipart import used when object storage is not configured.
|
|
22
|
+
*/
|
|
23
|
+
export const MAX_BUFFERED_IMPORT_PARSE_BYTES = 100 * MIB;
|
|
24
|
+
/**
|
|
25
|
+
* A link import (`--url`, `oxygen_tables_import_url`, the wizard's link card)
|
|
26
|
+
* is downloaded and parsed inside the web request, so it keeps its own small
|
|
27
|
+
* ceiling. It is not a plan limit: a bigger file is downloaded and imported
|
|
28
|
+
* with `tables import --file`, which stages it in object storage.
|
|
29
|
+
*/
|
|
30
|
+
export const MAX_URL_IMPORT_BYTES = 10 * MIB;
|
|
31
|
+
/**
|
|
32
|
+
* The largest object one presigned PUT may carry on an S3-compatible store (S3
|
|
33
|
+
* and Ceph-based stores such as Hetzner Object Storage cap a single PUT at
|
|
34
|
+
* 5 GiB). A staged import is one PUT, so no plan's import file limit may
|
|
35
|
+
* exceed it.
|
|
17
36
|
*/
|
|
18
|
-
export const
|
|
37
|
+
export const IMPORT_OBJECT_SINGLE_PUT_MAX_BYTES = 5 * 1024 * MIB;
|
|
19
38
|
/**
|
|
20
39
|
* The platform's request-body ceiling — infrastructure, not a plan limit.
|
|
21
40
|
*
|
|
@@ -28,3 +47,17 @@ export const VERCEL_REQUEST_BODY_LIMIT_BYTES = 4 * 1024 * 1024;
|
|
|
28
47
|
export function isBufferedOnlyImportFormat(format) {
|
|
29
48
|
return format === "json" || format === "xlsx";
|
|
30
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* The refusal every surface gives a JSON or XLSX file over the buffered
|
|
52
|
+
* ceiling. It names the ceiling and the two formats that take a larger file,
|
|
53
|
+
* so the reader knows the fix is a format change, not a plan change.
|
|
54
|
+
*/
|
|
55
|
+
export function bufferedImportTooLargeMessage(format, fileBytes) {
|
|
56
|
+
const label = format.toUpperCase();
|
|
57
|
+
const size = typeof fileBytes === "number" ? ` This one is ${formatImportMib(fileBytes)}.` : "";
|
|
58
|
+
return `${label} files are read whole, so they are capped at ${formatImportMib(MAX_BUFFERED_IMPORT_PARSE_BYTES)}.${size} Save it as CSV or JSONL, which import up to your plan's file-size limit.`;
|
|
59
|
+
}
|
|
60
|
+
function formatImportMib(bytes) {
|
|
61
|
+
const mib = bytes / MIB;
|
|
62
|
+
return `${mib >= 10 ? Math.round(mib).toLocaleString("en-US") : mib.toFixed(1)} MiB`;
|
|
63
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { OXYGEN_MINIMUM_CLI_VERSION, OXYGEN_VERSION, } from "./version.js";
|
|
2
2
|
export { WORKFLOW_TRIGGER_AUTO_PAUSE_METADATA_KEYS, clearWorkflowTriggerAutoPauseMetadata, } from "./workflow-trigger-metadata.js";
|
|
3
3
|
export { WORKFLOW_STATUS_CHANGE_METADATA_KEY, type WorkflowStatusChange, type WorkflowStatusChangeActor, type WorkflowStatusChangeSource, describeWorkflowStatusChange, formatWorkflowStatusChangeTimestamp, parseWorkflowStatusChange, readWorkflowStatusChange, } from "./workflow-status-change.js";
|
|
4
4
|
export * from "./billing.js";
|
|
@@ -111,27 +111,7 @@ export * from "./workspace-event-catalog.js";
|
|
|
111
111
|
export * from "./notetaker-events.js";
|
|
112
112
|
export * from "./workspace-agents.js";
|
|
113
113
|
export declare const MAX_ROW_LOOP_WRITE_ROWS = 500;
|
|
114
|
-
export
|
|
115
|
-
major: number;
|
|
116
|
-
minor: number;
|
|
117
|
-
patch: number;
|
|
118
|
-
};
|
|
119
|
-
/**
|
|
120
|
-
* Parse a three-segment semantic version (e.g. `1.142.17`). Pre-release and
|
|
121
|
-
* build metadata suffixes (`-rc.1`, `+build`) are tolerated but ignored.
|
|
122
|
-
* Returns `null` when the input is not a parseable `major.minor.patch` string.
|
|
123
|
-
*/
|
|
124
|
-
export declare function parseSemver(version: string): SemanticVersion | null;
|
|
125
|
-
/**
|
|
126
|
-
* Compare two semantic versions. Returns -1 when `a < b`, 1 when `a > b`, and
|
|
127
|
-
* 0 when they are equal. Unparseable inputs compare as equal (0) so callers
|
|
128
|
-
* fail open rather than misordering garbage.
|
|
129
|
-
*/
|
|
130
|
-
export declare function compareSemver(a: string, b: string): -1 | 0 | 1;
|
|
131
|
-
/** True when `a` is a strictly greater semantic version than `b`. */
|
|
132
|
-
export declare function isVersionGreater(a: string, b: string): boolean;
|
|
133
|
-
/** True when `a` is a strictly lesser semantic version than `b`. */
|
|
134
|
-
export declare function isVersionLess(a: string, b: string): boolean;
|
|
114
|
+
export * from "./semver.js";
|
|
135
115
|
export * from "./ugc.js";
|
|
136
116
|
export * from "./ugc-amplification-identity.js";
|
|
137
117
|
export * from "./knowledge-repository.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { OXYGEN_MINIMUM_CLI_VERSION, OXYGEN_VERSION, } from "./version.js";
|
|
2
2
|
export { WORKFLOW_TRIGGER_AUTO_PAUSE_METADATA_KEYS, clearWorkflowTriggerAutoPauseMetadata, } from "./workflow-trigger-metadata.js";
|
|
3
3
|
export { WORKFLOW_STATUS_CHANGE_METADATA_KEY, describeWorkflowStatusChange, formatWorkflowStatusChangeTimestamp, parseWorkflowStatusChange, readWorkflowStatusChange, } from "./workflow-status-change.js";
|
|
4
4
|
export * from "./billing.js";
|
|
@@ -127,47 +127,7 @@ export * from "./workspace-agents.js";
|
|
|
127
127
|
// the COPY-based bulk engine. Tenant-db enforces this and the CLI/API row caps
|
|
128
128
|
// reference it so they never advertise a batch the row-loop will reject.
|
|
129
129
|
export const MAX_ROW_LOOP_WRITE_ROWS = 500;
|
|
130
|
-
|
|
131
|
-
* Parse a three-segment semantic version (e.g. `1.142.17`). Pre-release and
|
|
132
|
-
* build metadata suffixes (`-rc.1`, `+build`) are tolerated but ignored.
|
|
133
|
-
* Returns `null` when the input is not a parseable `major.minor.patch` string.
|
|
134
|
-
*/
|
|
135
|
-
export function parseSemver(version) {
|
|
136
|
-
const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(version);
|
|
137
|
-
if (!match)
|
|
138
|
-
return null;
|
|
139
|
-
return {
|
|
140
|
-
major: Number(match[1]),
|
|
141
|
-
minor: Number(match[2]),
|
|
142
|
-
patch: Number(match[3]),
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Compare two semantic versions. Returns -1 when `a < b`, 1 when `a > b`, and
|
|
147
|
-
* 0 when they are equal. Unparseable inputs compare as equal (0) so callers
|
|
148
|
-
* fail open rather than misordering garbage.
|
|
149
|
-
*/
|
|
150
|
-
export function compareSemver(a, b) {
|
|
151
|
-
const left = parseSemver(a);
|
|
152
|
-
const right = parseSemver(b);
|
|
153
|
-
if (!left || !right)
|
|
154
|
-
return 0;
|
|
155
|
-
for (const key of ["major", "minor", "patch"]) {
|
|
156
|
-
if (left[key] > right[key])
|
|
157
|
-
return 1;
|
|
158
|
-
if (left[key] < right[key])
|
|
159
|
-
return -1;
|
|
160
|
-
}
|
|
161
|
-
return 0;
|
|
162
|
-
}
|
|
163
|
-
/** True when `a` is a strictly greater semantic version than `b`. */
|
|
164
|
-
export function isVersionGreater(a, b) {
|
|
165
|
-
return compareSemver(a, b) > 0;
|
|
166
|
-
}
|
|
167
|
-
/** True when `a` is a strictly lesser semantic version than `b`. */
|
|
168
|
-
export function isVersionLess(a, b) {
|
|
169
|
-
return compareSemver(a, b) < 0;
|
|
170
|
-
}
|
|
130
|
+
export * from "./semver.js";
|
|
171
131
|
export * from "./ugc.js";
|
|
172
132
|
export * from "./ugc-amplification-identity.js";
|
|
173
133
|
export * from "./knowledge-repository.js";
|
|
@@ -62,6 +62,15 @@ export type PresignedImportUpload = {
|
|
|
62
62
|
expiresInSeconds: number;
|
|
63
63
|
};
|
|
64
64
|
export type PresignedPublishingMediaUpload = PresignedImportUpload;
|
|
65
|
+
/**
|
|
66
|
+
* Presign the one PUT that stages an import file under `imports/<org>/`.
|
|
67
|
+
*
|
|
68
|
+
* Import staging is deliberately NOT a workspace file (`workspace-file-storage`):
|
|
69
|
+
* it is transient input the worker streams once and deletes, so neither the
|
|
70
|
+
* 100 MiB per-file nor the 1 GiB retained-files ceiling of that store applies.
|
|
71
|
+
* Its ceiling is the caller's plan import limit, checked by the route before it
|
|
72
|
+
* asks, plus the single-PUT maximum below, which no plan exceeds.
|
|
73
|
+
*/
|
|
65
74
|
export declare function presignImportUpload(input: {
|
|
66
75
|
organizationId: string;
|
|
67
76
|
fileName?: string | null;
|
|
@@ -2,6 +2,7 @@ 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
4
|
import { OxygenError } from "./cli-result.js";
|
|
5
|
+
import { IMPORT_OBJECT_SINGLE_PUT_MAX_BYTES } from "./import-limits.js";
|
|
5
6
|
// S3-compatible object storage for large CSV/file imports. The CLI uploads the
|
|
6
7
|
// raw file straight to the bucket via a presigned PUT URL (bypassing Vercel's
|
|
7
8
|
// ~4.5MB request-body limit), then the Fly worker downloads it and COPY-loads
|
|
@@ -141,7 +142,23 @@ export function isCopilotAttachmentObjectKeyForOrganization(key, organizationId)
|
|
|
141
142
|
export function isPublishingMediaObjectKeyForOrganization(key, organizationId) {
|
|
142
143
|
return key.startsWith(`publishing-media/${organizationId}/`);
|
|
143
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Presign the one PUT that stages an import file under `imports/<org>/`.
|
|
147
|
+
*
|
|
148
|
+
* Import staging is deliberately NOT a workspace file (`workspace-file-storage`):
|
|
149
|
+
* it is transient input the worker streams once and deletes, so neither the
|
|
150
|
+
* 100 MiB per-file nor the 1 GiB retained-files ceiling of that store applies.
|
|
151
|
+
* Its ceiling is the caller's plan import limit, checked by the route before it
|
|
152
|
+
* asks, plus the single-PUT maximum below, which no plan exceeds.
|
|
153
|
+
*/
|
|
144
154
|
export async function presignImportUpload(input) {
|
|
155
|
+
if (!Number.isSafeInteger(input.contentLength) || input.contentLength < 1
|
|
156
|
+
|| input.contentLength > IMPORT_OBJECT_SINGLE_PUT_MAX_BYTES) {
|
|
157
|
+
throw new OxygenError("request_too_large", "Import file is too large to stage in one upload.", {
|
|
158
|
+
details: { file_bytes: input.contentLength, max_file_bytes: IMPORT_OBJECT_SINGLE_PUT_MAX_BYTES },
|
|
159
|
+
exitCode: 1,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
145
162
|
const { client, config } = resolveClient();
|
|
146
163
|
const storageKey = buildImportObjectKey({
|
|
147
164
|
organizationId: input.organizationId,
|
|
@@ -21,4 +21,45 @@ export declare function operationalSpanSnapshot<T extends {
|
|
|
21
21
|
instrumentationScope?: AttributeContainer;
|
|
22
22
|
spanContext(): unknown;
|
|
23
23
|
}>(span: T): T;
|
|
24
|
+
type ExportResource = {
|
|
25
|
+
attributes: Record<string, unknown>;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Maps the SDK resource onto the resource the collector destination exports,
|
|
29
|
+
* without touching the one every other destination reads. `rewrite` receives the
|
|
30
|
+
* SDK resource's attributes and returns the collector's; the result is
|
|
31
|
+
* sanitized once and memoized per source resource, so every span in a batch
|
|
32
|
+
* keeps sharing one resource object and the OTLP encoder still groups them into
|
|
33
|
+
* a single ResourceSpans entry.
|
|
34
|
+
*
|
|
35
|
+
* A resource whose async detectors are still pending (`asyncAttributesPending`)
|
|
36
|
+
* is mapped but not memoized, so attributes that settle later are picked up on
|
|
37
|
+
* a later export instead of an incomplete overlay being kept for the process.
|
|
38
|
+
*/
|
|
39
|
+
export declare function collectorResourceMapper(rewrite: (attributes: Record<string, unknown>) => Record<string, unknown>): (resource: MappableResource | undefined) => ExportResource;
|
|
40
|
+
type MappableResource = {
|
|
41
|
+
attributes?: Record<string, unknown>;
|
|
42
|
+
asyncAttributesPending?: boolean;
|
|
43
|
+
};
|
|
44
|
+
type SnapshotSpan = Parameters<typeof operationalSpanSnapshot>[0];
|
|
45
|
+
/**
|
|
46
|
+
* The collector's per-span export transform: the sanitized snapshot, with the
|
|
47
|
+
* resource swapped for the collector's when a mapper is given. Without one it
|
|
48
|
+
* is exactly `operationalSpanSnapshot`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function collectorSpanSnapshot(resourceFor?: (resource: MappableResource | undefined) => ExportResource): <T extends SnapshotSpan>(span: T) => T;
|
|
51
|
+
type MetricExporterLike = {
|
|
52
|
+
export(metrics: unknown, resultCallback: (result: {
|
|
53
|
+
code: number;
|
|
54
|
+
error?: Error | undefined;
|
|
55
|
+
}) => void): void;
|
|
56
|
+
shutdown(): Promise<void>;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Wraps a metric exporter so each ResourceMetrics batch carries the collector's
|
|
60
|
+
* resource. The reader-facing methods (temporality/aggregation selection,
|
|
61
|
+
* forceFlush) are forwarded only when the inner exporter has them, so the
|
|
62
|
+
* PeriodicExportingMetricReader sees exactly what it would have unwrapped.
|
|
63
|
+
*/
|
|
64
|
+
export declare function withCollectorMetricResource<E extends MetricExporterLike>(inner: E, resourceFor: (resource: MappableResource | undefined) => ExportResource): E;
|
|
24
65
|
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeTelemetryAttributes, redactSecretsInString } from "./redaction.js";
|
|
2
|
+
import { forwardExporterMethods } from "./telemetry-export-observer.js";
|
|
2
3
|
// Namespaced semantic-convention fields evade the generic exact-key log policy.
|
|
3
4
|
// Numeric usage remains operational data, subject to the shared secret policy.
|
|
4
5
|
const PAYLOAD_KEY = /(?:^|[._-])(?:prompts?|completions?|inputs?|outputs?|payloads?|rows?|messages?|content|body|customer_data)(?:$|[._-])|^(?:request|response)$/i;
|
|
@@ -71,3 +72,57 @@ function stripOperationalUrl(value) {
|
|
|
71
72
|
return value.split(/[?#]/, 1)[0] ?? "";
|
|
72
73
|
}
|
|
73
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Maps the SDK resource onto the resource the collector destination exports,
|
|
77
|
+
* without touching the one every other destination reads. `rewrite` receives the
|
|
78
|
+
* SDK resource's attributes and returns the collector's; the result is
|
|
79
|
+
* sanitized once and memoized per source resource, so every span in a batch
|
|
80
|
+
* keeps sharing one resource object and the OTLP encoder still groups them into
|
|
81
|
+
* a single ResourceSpans entry.
|
|
82
|
+
*
|
|
83
|
+
* A resource whose async detectors are still pending (`asyncAttributesPending`)
|
|
84
|
+
* is mapped but not memoized, so attributes that settle later are picked up on
|
|
85
|
+
* a later export instead of an incomplete overlay being kept for the process.
|
|
86
|
+
*/
|
|
87
|
+
export function collectorResourceMapper(rewrite) {
|
|
88
|
+
const cache = new WeakMap();
|
|
89
|
+
let withoutSource;
|
|
90
|
+
return (resource) => {
|
|
91
|
+
if (!resource)
|
|
92
|
+
return withoutSource ??= { attributes: operationalAttributes(rewrite({})) };
|
|
93
|
+
const cached = cache.get(resource);
|
|
94
|
+
if (cached)
|
|
95
|
+
return cached;
|
|
96
|
+
const mapped = { attributes: operationalAttributes(rewrite(resource.attributes ?? {})) };
|
|
97
|
+
if (!resource.asyncAttributesPending)
|
|
98
|
+
cache.set(resource, mapped);
|
|
99
|
+
return mapped;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The collector's per-span export transform: the sanitized snapshot, with the
|
|
104
|
+
* resource swapped for the collector's when a mapper is given. Without one it
|
|
105
|
+
* is exactly `operationalSpanSnapshot`.
|
|
106
|
+
*/
|
|
107
|
+
export function collectorSpanSnapshot(resourceFor) {
|
|
108
|
+
if (!resourceFor)
|
|
109
|
+
return (span) => operationalSpanSnapshot(span);
|
|
110
|
+
return (span) => ({ ...operationalSpanSnapshot(span), resource: resourceFor(span.resource) });
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Wraps a metric exporter so each ResourceMetrics batch carries the collector's
|
|
114
|
+
* resource. The reader-facing methods (temporality/aggregation selection,
|
|
115
|
+
* forceFlush) are forwarded only when the inner exporter has them, so the
|
|
116
|
+
* PeriodicExportingMetricReader sees exactly what it would have unwrapped.
|
|
117
|
+
*/
|
|
118
|
+
export function withCollectorMetricResource(inner, resourceFor) {
|
|
119
|
+
const wrapped = {
|
|
120
|
+
export(metrics, resultCallback) {
|
|
121
|
+
const batch = metrics;
|
|
122
|
+
inner.export({ ...batch, resource: resourceFor(batch.resource) }, resultCallback);
|
|
123
|
+
},
|
|
124
|
+
shutdown: () => inner.shutdown(),
|
|
125
|
+
};
|
|
126
|
+
forwardExporterMethods(inner, wrapped);
|
|
127
|
+
return wrapped;
|
|
128
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type LimitsTier } from "./plan-limits.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type RepricingOptions } from "./repricing.js";
|
|
3
|
+
import { type WorkspaceTableCapacityStatus } from "./table-capacity.js";
|
|
3
4
|
/**
|
|
4
5
|
* The seven plan bands of the 2026-09 repricing (spec § 4, slice S06): free
|
|
5
6
|
* plus one band per Oxygen plan size. They sit BESIDE the five-rung
|
|
@@ -15,6 +16,16 @@ export type PlanBand = "free" | "49" | "99" | "199" | "499" | "999" | "1999";
|
|
|
15
16
|
export declare const PLAN_BAND_ORDER: readonly PlanBand[];
|
|
16
17
|
/** The limits rung each band enforces at today. */
|
|
17
18
|
export declare const PLAN_BAND_LIMITS_TIER: Readonly<Record<PlanBand, LimitsTier>>;
|
|
19
|
+
/**
|
|
20
|
+
* L4.1 (repricing 2026-09, slice S55; decision record "Worker share"): a
|
|
21
|
+
* tenant's share of the legacy worker's tenant queue while other tenants wait.
|
|
22
|
+
* A weight-16 tenant gets sixteen quanta for every one a weight-1 tenant gets;
|
|
23
|
+
* with nobody else waiting every tenant is served at once, whatever its weight.
|
|
24
|
+
* It is a scheduling share, never a sold limit: capacity is sized so contention
|
|
25
|
+
* is rare (`.agents/skills/oxygen-worker-performance`, "Worker share target").
|
|
26
|
+
* An org whose band is not yet resolved schedules at the free weight.
|
|
27
|
+
*/
|
|
28
|
+
export declare const PLAN_BAND_WORKER_SHARE_WEIGHT: Readonly<Record<PlanBand, number>>;
|
|
18
29
|
/**
|
|
19
30
|
* PROPOSED (P-57, repricing spec § 4): a grandfathered or legacy plan takes the
|
|
20
31
|
* band of the limits rung it enforces at today, so no grandfathered customer
|
|
@@ -42,6 +53,58 @@ export declare function planBandForLimitsResolution(resolution: {
|
|
|
42
53
|
/** The band's monthly price, read from the Oxygen plan it names; null for free. */
|
|
43
54
|
export declare function planBandMonthlyPriceCents(band: PlanBand): number | null;
|
|
44
55
|
export declare function planBandLabel(band: PlanBand): string;
|
|
56
|
+
/**
|
|
57
|
+
* PROPOSED (P-54): the free plan keeps a 50-credit default. It has no monthly
|
|
58
|
+
* grant to take 10% of (10% of its one-time 1,000 would be 100).
|
|
59
|
+
*/
|
|
60
|
+
export declare const FREE_PLAN_DEFAULT_DELIVERY_CREDIT_CEILING = 50;
|
|
61
|
+
/**
|
|
62
|
+
* A plan size's target default delivery ceiling: 10% of its monthly credits,
|
|
63
|
+
* rounded half up (decision L5.1; the volume bonus counts, the partner bonus
|
|
64
|
+
* does not, P-54). This is the target, not always the value in force: see
|
|
65
|
+
* `resolveDefaultTriggerRunCreditCeilingForPlan`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function planBandDeliveryCreditCeilingTarget(band: PlanBand): number;
|
|
68
|
+
/** What an org's plan resolves to: the raw plan tier and its limits rung. */
|
|
69
|
+
export type PlanSpendResolution = {
|
|
70
|
+
planTier: string | null;
|
|
71
|
+
limitsTier: LimitsTier;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* The default credit ceiling of one LIVE workflow run fired by an unattended
|
|
75
|
+
* trigger (cron, webhook, event) that declares no `max_credits`, for a plan.
|
|
76
|
+
* `null` means no default applies (enterprise); an explicit cap always wins and
|
|
77
|
+
* is never clamped by this.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolveDefaultTriggerRunCreditCeilingForPlan(resolution: PlanSpendResolution, options?: RepricingOptions): number | null;
|
|
80
|
+
/** The same default for one standing or webhook table auto-run batch. */
|
|
81
|
+
export declare function resolveDefaultAutoRunBatchCreditCeilingForPlan(resolution: PlanSpendResolution, options?: RepricingOptions): number | null;
|
|
82
|
+
/**
|
|
83
|
+
* Public webhook ingress (repricing 2026-09, decision L4.4, ratified
|
|
84
|
+
* 2026-09-26): deliveries a minute that one webhook target (a Table endpoint,
|
|
85
|
+
* a workflow or Agent trigger, the workspace's RB2B receiver) accepts. It used
|
|
86
|
+
* to be a flat 600 per target, with 60 per sender IP on most targets. Every
|
|
87
|
+
* value rises, so this is live on release rather than held behind the
|
|
88
|
+
* repricing switch.
|
|
89
|
+
*/
|
|
90
|
+
export declare const PUBLIC_WEBHOOK_INGRESS_PER_TARGET_PER_MINUTE: Readonly<Record<PlanBand, number>>;
|
|
91
|
+
/**
|
|
92
|
+
* PROPOSED (P-50, repricing spec § 4.4): the decision raises the per-IP limit
|
|
93
|
+
* "to match", read as equal to the per-target limit (a share of 1). One sender
|
|
94
|
+
* (a form tool, a CRM) usually posts from one address, so any lower per-IP
|
|
95
|
+
* limit would cap a real integration below its plan's rate.
|
|
96
|
+
*/
|
|
97
|
+
export declare const PUBLIC_WEBHOOK_INGRESS_PER_IP_SHARE_OF_TARGET = 1;
|
|
98
|
+
export declare const PUBLIC_WEBHOOK_INGRESS_WINDOW_SECONDS = 60;
|
|
99
|
+
export type PublicWebhookIngressLimits = {
|
|
100
|
+
perTargetPerMinute: number;
|
|
101
|
+
perSenderIpPerMinute: number;
|
|
102
|
+
windowSeconds: number;
|
|
103
|
+
};
|
|
104
|
+
/** The webhook ingress limits a band enforces. */
|
|
105
|
+
export declare function resolvePublicWebhookIngressLimits(band: PlanBand): PublicWebhookIngressLimits;
|
|
106
|
+
/** The webhook ingress limits of one band, as the `/api/cli/limits` contract reports them. */
|
|
107
|
+
export declare function describeWebhookIngress(band: PlanBand): PlanBandLimitsReport["webhooks"];
|
|
45
108
|
/**
|
|
46
109
|
* Request rates, per minute unless named otherwise. The totals bound every
|
|
47
110
|
* `/api/cli/*` call; the operation buckets bind first for the calls a script
|
|
@@ -87,6 +150,15 @@ export type PlanBandLimitsReport = {
|
|
|
87
150
|
label: string;
|
|
88
151
|
monthly_price_usd: number | null;
|
|
89
152
|
monthly_credits: number | null;
|
|
153
|
+
/**
|
|
154
|
+
* Credits granted above face value ($1 = 100 credits), repricing 2026-09
|
|
155
|
+
* decision 1.3: 0 up to $199, then +5% / +10% / +15% on $499 / $999 / $1,999.
|
|
156
|
+
* Already included in `monthly_credits`. Null on free, which has no plan grant.
|
|
157
|
+
*/
|
|
158
|
+
volume_bonus_credits: number | null;
|
|
159
|
+
volume_bonus_percent: number | null;
|
|
160
|
+
/** What 100 plan credits cost on this size, the volume bonus included. */
|
|
161
|
+
usd_per_100_credits: number | null;
|
|
90
162
|
limits_tier: LimitsTier;
|
|
91
163
|
api: ApiRateLimitsReport;
|
|
92
164
|
storage: {
|
|
@@ -97,22 +169,66 @@ export type PlanBandLimitsReport = {
|
|
|
97
169
|
/** Equal to rows per Table (PROPOSED P-60): one file can fill an empty Table. */
|
|
98
170
|
import_max_rows_per_file: number;
|
|
99
171
|
import_max_file_bytes: number;
|
|
172
|
+
/**
|
|
173
|
+
* Where the values above stand against the ratified ladder (decision F.2):
|
|
174
|
+
* `in_force`, `scheduled` (they move to `target` at `effective_at`) or
|
|
175
|
+
* `awaiting_capacity_test` (`target` applies once the rows-per-Table
|
|
176
|
+
* capacity test at this size passes). A cut is announced only once the
|
|
177
|
+
* repricing date is set, so `target` is null while nothing is pending.
|
|
178
|
+
*/
|
|
179
|
+
status: WorkspaceTableCapacityStatus["status"];
|
|
180
|
+
effective_at: string | null;
|
|
181
|
+
target: PlanBandStorageTarget | null;
|
|
100
182
|
};
|
|
101
183
|
spend: {
|
|
102
184
|
trigger_run_credit_ceiling: number | null;
|
|
103
185
|
auto_run_batch_credit_ceiling: number | null;
|
|
104
186
|
agent_run_max_total_credits: number;
|
|
105
187
|
agent_run_max_inference_credits: number;
|
|
188
|
+
/** Paid work the attended Copilot may start without an approval card. */
|
|
189
|
+
copilot_approval_free_per_call_credits: number;
|
|
190
|
+
copilot_approval_free_per_session_credits: number;
|
|
191
|
+
/** The platform's runaway bound on one attended Copilot turn (every plan). */
|
|
192
|
+
copilot_attended_turn_backstop_credits: number;
|
|
106
193
|
org_daily_guard_warn_credits: number | null;
|
|
107
194
|
org_daily_guard_block_credits: number | null;
|
|
108
195
|
byok_column_run_max_rows: number | null;
|
|
109
196
|
byok_provider_daily_calls: number | null;
|
|
110
197
|
};
|
|
198
|
+
/**
|
|
199
|
+
* Table work limits (L6): rows one write request may carry, and columns one
|
|
200
|
+
* action run or standing auto-run may carry.
|
|
201
|
+
*/
|
|
202
|
+
tables: {
|
|
203
|
+
max_rows_per_write_request: number;
|
|
204
|
+
max_columns_per_run: number;
|
|
205
|
+
};
|
|
206
|
+
/** The raw signal-event feed: events per read and look-back days. */
|
|
111
207
|
signals: {
|
|
112
208
|
max_events: number;
|
|
113
209
|
max_window_days: number;
|
|
114
210
|
};
|
|
211
|
+
/** Public webhook ingress, per target and per sender IP (decision L4.4). */
|
|
212
|
+
webhooks: {
|
|
213
|
+
ingress_requests_per_target_per_minute: number;
|
|
214
|
+
ingress_requests_per_sender_ip_per_minute: number;
|
|
215
|
+
window_seconds: number;
|
|
216
|
+
};
|
|
217
|
+
workflows: {
|
|
218
|
+
/** Fastest cron schedule a workflow or Agent trigger may use, in force now. */
|
|
219
|
+
cron_min_interval_minutes: number;
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
/** The storage values a band moves to, in the `/api/cli/limits` field names. */
|
|
223
|
+
export type PlanBandStorageTarget = {
|
|
224
|
+
table_row_limit: number;
|
|
225
|
+
workspace_row_limit: number;
|
|
226
|
+
workspace_database_warning_bytes: number;
|
|
227
|
+
workspace_database_limit_bytes: number;
|
|
228
|
+
import_max_rows_per_file: number;
|
|
115
229
|
};
|
|
230
|
+
/** A band's storage status as `/api/cli/limits` reports it (`plan_bands[].storage` and `storage_capacity`). */
|
|
231
|
+
export declare function describePlanBandStorageStatus(band: PlanBand, options?: RepricingOptions): Pick<PlanBandLimitsReport["storage"], "status" | "effective_at" | "target">;
|
|
116
232
|
export declare function describePlanBandLimits(band: PlanBand, options?: RepricingOptions): PlanBandLimitsReport;
|
|
117
233
|
/** Every band's limits in force today, smallest first. */
|
|
118
234
|
export declare function describePlanBandLadder(options?: RepricingOptions): PlanBandLimitsReport[];
|