@usenaive-sdk/cli 0.12.5 → 0.13.1
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 +69 -6
- package/dist/client.d.ts +48 -0
- package/dist/client.js +199 -27
- package/dist/client.js.map +1 -1
- package/dist/commands/aeo.js +58 -23
- package/dist/commands/aeo.js.map +1 -1
- package/dist/commands/app-data.js +29 -11
- package/dist/commands/app-data.js.map +1 -1
- package/dist/commands/approvals.js +142 -9
- package/dist/commands/approvals.js.map +1 -1
- package/dist/commands/apps.d.ts +7 -0
- package/dist/commands/apps.js +255 -18
- package/dist/commands/apps.js.map +1 -1
- package/dist/commands/audio.d.ts +9 -0
- package/dist/commands/audio.js +391 -0
- package/dist/commands/audio.js.map +1 -0
- package/dist/commands/auth.d.ts +1 -0
- package/dist/commands/auth.js +47 -19
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/billing.js +9 -9
- package/dist/commands/billing.js.map +1 -1
- package/dist/commands/brain.js +813 -54
- package/dist/commands/brain.js.map +1 -1
- package/dist/commands/browser.js +8 -8
- package/dist/commands/browser.js.map +1 -1
- package/dist/commands/business.js +117 -16
- package/dist/commands/business.js.map +1 -1
- package/dist/commands/clone.js +8 -4
- package/dist/commands/clone.js.map +1 -1
- package/dist/commands/companies.d.ts +8 -0
- package/dist/commands/companies.js +137 -47
- package/dist/commands/companies.js.map +1 -1
- package/dist/commands/company-data.d.ts +2 -0
- package/dist/commands/company-data.js +168 -0
- package/dist/commands/company-data.js.map +1 -0
- package/dist/commands/compute.js +295 -18
- package/dist/commands/compute.js.map +1 -1
- package/dist/commands/connections.d.ts +6 -0
- package/dist/commands/connections.js +42 -2
- package/dist/commands/connections.js.map +1 -1
- package/dist/commands/domains.js +63 -19
- package/dist/commands/domains.js.map +1 -1
- package/dist/commands/ecommerce.js +19 -9
- package/dist/commands/ecommerce.js.map +1 -1
- package/dist/commands/email.js +56 -9
- package/dist/commands/email.js.map +1 -1
- package/dist/commands/formation.js +5 -5
- package/dist/commands/formation.js.map +1 -1
- package/dist/commands/identity.js +4 -3
- package/dist/commands/identity.js.map +1 -1
- package/dist/commands/images.js +86 -12
- package/dist/commands/images.js.map +1 -1
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +44 -36
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/jobs.js +1 -0
- package/dist/commands/jobs.js.map +1 -1
- package/dist/commands/legacy-auth.d.ts +27 -0
- package/dist/commands/legacy-auth.js +64 -0
- package/dist/commands/legacy-auth.js.map +1 -0
- package/dist/commands/llm.js +14 -1
- package/dist/commands/llm.js.map +1 -1
- package/dist/commands/login.js +2 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +7 -0
- package/dist/commands/logout.js +55 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/media.js +3 -3
- package/dist/commands/media.js.map +1 -1
- package/dist/commands/mobile.d.ts +2 -0
- package/dist/commands/mobile.js +42 -1
- package/dist/commands/mobile.js.map +1 -1
- package/dist/commands/payments.js +1 -1
- package/dist/commands/people.d.ts +2 -0
- package/dist/commands/people.js +197 -0
- package/dist/commands/people.js.map +1 -0
- package/dist/commands/phone.js +40 -83
- package/dist/commands/phone.js.map +1 -1
- package/dist/commands/projects.d.ts +13 -0
- package/dist/commands/projects.js +220 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/register.js +13 -5
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/sandbox.d.ts +2 -0
- package/dist/commands/sandbox.js +558 -0
- package/dist/commands/sandbox.js.map +1 -0
- package/dist/commands/search.js +27 -13
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/seo.js +16 -8
- package/dist/commands/seo.js.map +1 -1
- package/dist/commands/sessions.d.ts +6 -0
- package/dist/commands/sessions.js +109 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/social-data.d.ts +2 -0
- package/dist/commands/social-data.js +245 -0
- package/dist/commands/social-data.js.map +1 -0
- package/dist/commands/social.js +9 -7
- package/dist/commands/social.js.map +1 -1
- package/dist/commands/tasks.js +9 -0
- package/dist/commands/tasks.js.map +1 -1
- package/dist/commands/teams.d.ts +69 -0
- package/dist/commands/teams.js +503 -0
- package/dist/commands/teams.js.map +1 -0
- package/dist/commands/up.d.ts +150 -0
- package/dist/commands/up.js +465 -15
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/usage.js +15 -4
- package/dist/commands/usage.js.map +1 -1
- package/dist/commands/use.d.ts +9 -0
- package/dist/commands/use.js +76 -11
- package/dist/commands/use.js.map +1 -1
- package/dist/commands/users.d.ts +8 -0
- package/dist/commands/users.js +28 -9
- package/dist/commands/users.js.map +1 -1
- package/dist/commands/vault.js +31 -1
- package/dist/commands/vault.js.map +1 -1
- package/dist/commands/verification.js +1 -1
- package/dist/commands/verification.js.map +1 -1
- package/dist/commands/video.js +118 -19
- package/dist/commands/video.js.map +1 -1
- package/dist/commands/wallet.js +3 -3
- package/dist/commands/wallet.js.map +1 -1
- package/dist/commands/whoami.js +17 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config.d.ts +16 -1
- package/dist/config.js +15 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +250 -24
- package/dist/index.js.map +1 -1
- package/dist/lib/brain-select.d.ts +193 -0
- package/dist/lib/brain-select.js +403 -0
- package/dist/lib/brain-select.js.map +1 -0
- package/dist/lib/cli-validation.d.ts +12 -0
- package/dist/lib/cli-validation.js +46 -0
- package/dist/lib/cli-validation.js.map +1 -0
- package/dist/lib/deprecation.d.ts +158 -0
- package/dist/lib/deprecation.js +140 -0
- package/dist/lib/deprecation.js.map +1 -0
- package/dist/lib/duration.d.ts +8 -0
- package/dist/lib/duration.js +11 -0
- package/dist/lib/duration.js.map +1 -0
- package/dist/lib/http-response.d.ts +11 -0
- package/dist/lib/http-response.js +96 -0
- package/dist/lib/http-response.js.map +1 -0
- package/dist/lib/pricing.d.ts +132 -0
- package/dist/lib/pricing.js +148 -0
- package/dist/lib/pricing.js.map +1 -0
- package/dist/lib/stream-frames.d.ts +114 -0
- package/dist/lib/stream-frames.js +169 -0
- package/dist/lib/stream-frames.js.map +1 -0
- package/dist/lib/teams-catalog.d.ts +141 -0
- package/dist/lib/teams-catalog.js +765 -0
- package/dist/lib/teams-catalog.js.map +1 -0
- package/dist/lib/unknown-command.d.ts +55 -1
- package/dist/lib/unknown-command.js +113 -0
- package/dist/lib/unknown-command.js.map +1 -1
- package/dist/output.d.ts +127 -5
- package/dist/output.js +189 -12
- package/dist/output.js.map +1 -1
- package/package.json +3 -3
- package/dist/commands/link.d.ts +0 -3
- package/dist/commands/link.js +0 -91
- package/dist/commands/link.js.map +0 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { agentError, setPendingDeprecation } from "../output.js";
|
|
2
|
+
/**
|
|
3
|
+
* The eight names the legacy orchestration runtime answers to in this tree.
|
|
4
|
+
* Exported so a staleness check can hold it against the source rather than
|
|
5
|
+
* against memory — a list like this becomes folklore the moment nothing reads it.
|
|
6
|
+
*/
|
|
7
|
+
export const LEGACY_RUNTIME_ALIASES = [
|
|
8
|
+
"orchestration",
|
|
9
|
+
"warm pool",
|
|
10
|
+
"instance pool",
|
|
11
|
+
"Hermes",
|
|
12
|
+
"sidecar",
|
|
13
|
+
"container runtime",
|
|
14
|
+
"hosted runtime",
|
|
15
|
+
"runtime.pool",
|
|
16
|
+
];
|
|
17
|
+
const MIGRATION_GUIDE = "https://usenaive.ai/docs/migration-guides/legacy-orchestration-to-durable-teams";
|
|
18
|
+
/** Build the full record from the commander command plus its spec. */
|
|
19
|
+
export function deprecationRecord(cmd, spec) {
|
|
20
|
+
return { ...spec, subject: `naive ${cmd.name()}` };
|
|
21
|
+
}
|
|
22
|
+
/** The machine half — what rides the stdout envelope. */
|
|
23
|
+
export function deprecationNotice(rec, status) {
|
|
24
|
+
return {
|
|
25
|
+
id: rec.id,
|
|
26
|
+
subject: rec.subject,
|
|
27
|
+
status,
|
|
28
|
+
replacement: rec.replacement,
|
|
29
|
+
since: rec.since,
|
|
30
|
+
sunset: rec.sunset.kind === "frozen" ? "frozen" : { on: rec.sunset.date },
|
|
31
|
+
guide: rec.guide,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function sunsetLine(rec) {
|
|
35
|
+
return rec.sunset.kind === "frozen"
|
|
36
|
+
? "frozen, no sunset date"
|
|
37
|
+
: `sunset ${rec.sunset.date}`;
|
|
38
|
+
}
|
|
39
|
+
function replacementLines(rec) {
|
|
40
|
+
if (rec.replacement.kind === "use") {
|
|
41
|
+
return [` Use instead: ${rec.replacement.what}`];
|
|
42
|
+
}
|
|
43
|
+
// The honest row. There is no replacement, and the reason is mandatory.
|
|
44
|
+
return [
|
|
45
|
+
" Use instead: nothing — this capability has no replacement.",
|
|
46
|
+
` Because: ${rec.replacement.because}`,
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The banner, as a string. Pure, so the wording is a test rather than a habit.
|
|
51
|
+
* The first line carries the two facts an operator needs before anything else:
|
|
52
|
+
* it is deprecated, and it KEEPS WORKING.
|
|
53
|
+
*/
|
|
54
|
+
export function renderDeprecationBanner(rec) {
|
|
55
|
+
const lines = [];
|
|
56
|
+
lines.push(`⚠ \`${rec.subject}\` is DEPRECATED and will keep working. [${rec.id}]`);
|
|
57
|
+
lines.push(` It drives ${rec.drives}`);
|
|
58
|
+
if (rec.alsoCalled.length > 0) {
|
|
59
|
+
lines.push(` (also called: ${rec.alsoCalled.join(", ")})`);
|
|
60
|
+
}
|
|
61
|
+
lines.push(...replacementLines(rec));
|
|
62
|
+
lines.push(` Why: ${rec.why}`);
|
|
63
|
+
for (const gap of rec.gaps ?? []) {
|
|
64
|
+
lines.push(` No replacement for \`${rec.subject} ${gap.sub}\`: ${gap.because}`);
|
|
65
|
+
}
|
|
66
|
+
lines.push(` Since ${rec.since} · ${sunsetLine(rec)} · migration guide:`);
|
|
67
|
+
lines.push(` ${rec.guide}`);
|
|
68
|
+
return lines.join("\n") + "\n";
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Emitted ids, so the banner appears ONCE per process even when a group's hook
|
|
72
|
+
* and a future subcommand's hook both fire. Exported for tests only.
|
|
73
|
+
*/
|
|
74
|
+
const _emitted = new Set();
|
|
75
|
+
export function _resetDeprecationBannersForTest() {
|
|
76
|
+
_emitted.clear();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Mark a command group deprecated. The group keeps working; every invocation
|
|
80
|
+
* writes the banner to stderr (once per process) and attaches the machine notice
|
|
81
|
+
* to the next stdout envelope.
|
|
82
|
+
*
|
|
83
|
+
* Returns the record so the caller can assert on it — the registry in index.ts is
|
|
84
|
+
* built from the return values, which is what makes the set of deprecations a
|
|
85
|
+
* value a test can read instead of a side effect it has to observe.
|
|
86
|
+
*/
|
|
87
|
+
export function markDeprecated(cmd, spec) {
|
|
88
|
+
const rec = deprecationRecord(cmd, spec);
|
|
89
|
+
cmd.hook("preAction", () => {
|
|
90
|
+
setPendingDeprecation(deprecationNotice(rec, "deprecated"));
|
|
91
|
+
if (!_emitted.has(rec.id)) {
|
|
92
|
+
_emitted.add(rec.id);
|
|
93
|
+
process.stderr.write(renderDeprecationBanner(rec));
|
|
94
|
+
}
|
|
95
|
+
// and then nothing. The action runs.
|
|
96
|
+
});
|
|
97
|
+
return rec;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* A RETIRED command: it no longer does anything, and saying so is the whole
|
|
101
|
+
* behaviour. Distinct from `markDeprecated`, which never refuses.
|
|
102
|
+
*
|
|
103
|
+
* ── WHY THE CODE IS `deprecated_command` AND WHY IT IS NOT IN THE SERVER UNION ──
|
|
104
|
+
*
|
|
105
|
+
* `platform/kernel/src/errors.ts` holds a 25-member `ErrorCode` union typed as
|
|
106
|
+
* `Record<ErrorCode, number>` in `STATUS_MAP` — it is the set of codes an HTTP
|
|
107
|
+
* RESPONSE can carry, and every member owes a status. `deprecated_command` is
|
|
108
|
+
* minted here, by the CLI, for a command that makes no request at all: there is
|
|
109
|
+
* no response and therefore no status to map. Adding it to that union would put
|
|
110
|
+
* a code the server can never emit into the type that says what the server emits.
|
|
111
|
+
*
|
|
112
|
+
* It is instead the fourth member of the CLI-LOCAL code namespace that already
|
|
113
|
+
* exists in this package and is already relied on by callers:
|
|
114
|
+
* `cli_outdated` and `unknown_subcommand` (lib/unknown-command.ts:8) and
|
|
115
|
+
* `upstream_error` (client.ts:97). All three are minted client-side and none is
|
|
116
|
+
* in the server union. `CLI_LOCAL_ERROR_CODES` below names the set so it stays a
|
|
117
|
+
* declared four rather than a habit.
|
|
118
|
+
*/
|
|
119
|
+
export const CLI_LOCAL_ERROR_CODES = [
|
|
120
|
+
"cli_outdated",
|
|
121
|
+
"unknown_subcommand",
|
|
122
|
+
"upstream_error",
|
|
123
|
+
"deprecated_command",
|
|
124
|
+
];
|
|
125
|
+
export function retiredCommand(opts) {
|
|
126
|
+
if (opts.notice)
|
|
127
|
+
setPendingDeprecation(opts.notice);
|
|
128
|
+
// A retired command's notice cannot ride a success envelope — there isn't one —
|
|
129
|
+
// so in machine mode the id travels on the error object instead.
|
|
130
|
+
agentError({
|
|
131
|
+
action: opts.action,
|
|
132
|
+
error: {
|
|
133
|
+
code: "deprecated_command",
|
|
134
|
+
message: opts.message,
|
|
135
|
+
...(opts.notice && { deprecation: opts.notice }),
|
|
136
|
+
},
|
|
137
|
+
recovery_steps: opts.recovery_steps,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=deprecation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deprecation.js","sourceRoot":"","sources":["../../src/lib/deprecation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function parseDurationArg(raw) {
|
|
2
|
+
const n = Number(raw);
|
|
3
|
+
if (raw.trim() === "" || !Number.isFinite(n) || n <= 0) {
|
|
4
|
+
return {
|
|
5
|
+
ok: false,
|
|
6
|
+
message: `--duration must be a positive number of seconds (e.g. 5 or 10); got "${raw}"`,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
return { ok: true, value: n };
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=duration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration.js","sourceRoot":"","sources":["../../src/lib/duration.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,wEAAwE,GAAG,GAAG;SACxF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ParsedHttpResponse {
|
|
2
|
+
status: number;
|
|
3
|
+
data: unknown;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Parse an API response without assuming every proxy/error page is JSON.
|
|
7
|
+
* Empty successful responses remain valid; every other non-JSON response is
|
|
8
|
+
* converted to the same structured error shape the CLI already understands.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseHttpResponse(response: Response): Promise<ParsedHttpResponse>;
|
|
11
|
+
export declare function networkErrorResponse(error: unknown): ParsedHttpResponse;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
const MAX_RESPONSE_PREVIEW = 240;
|
|
2
|
+
function redactSecrets(value) {
|
|
3
|
+
return value
|
|
4
|
+
.replace(/\b((?:nv|dr)_sk_)[A-Za-z0-9._-]+/gi, "$1[redacted]")
|
|
5
|
+
.replace(/\b(Bearer\s+)[A-Za-z0-9._~-]+/gi, "$1[redacted]");
|
|
6
|
+
}
|
|
7
|
+
function safePreview(value) {
|
|
8
|
+
const preview = redactSecrets(value)
|
|
9
|
+
.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, " ")
|
|
10
|
+
.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, " ")
|
|
11
|
+
.replace(/<[^>]+>/g, " ")
|
|
12
|
+
.replace(/[\u0000-\u001f\u007f]+/g, " ")
|
|
13
|
+
.replace(/\s+/g, " ")
|
|
14
|
+
.trim()
|
|
15
|
+
.slice(0, MAX_RESPONSE_PREVIEW);
|
|
16
|
+
return preview || undefined;
|
|
17
|
+
}
|
|
18
|
+
function codeForStatus(status) {
|
|
19
|
+
if (status === 401)
|
|
20
|
+
return "unauthorized";
|
|
21
|
+
if (status === 403)
|
|
22
|
+
return "forbidden";
|
|
23
|
+
if (status === 404)
|
|
24
|
+
return "resource_not_found";
|
|
25
|
+
if (status === 429)
|
|
26
|
+
return "rate_limited";
|
|
27
|
+
if (status >= 500)
|
|
28
|
+
return "internal_error";
|
|
29
|
+
return "invalid_input";
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse an API response without assuming every proxy/error page is JSON.
|
|
33
|
+
* Empty successful responses remain valid; every other non-JSON response is
|
|
34
|
+
* converted to the same structured error shape the CLI already understands.
|
|
35
|
+
*/
|
|
36
|
+
export async function parseHttpResponse(response) {
|
|
37
|
+
const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim() || undefined;
|
|
38
|
+
const text = await response.text();
|
|
39
|
+
const jsonText = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
|
|
40
|
+
if (!text.trim()) {
|
|
41
|
+
if (response.ok || response.status === 204)
|
|
42
|
+
return { status: response.status, data: {} };
|
|
43
|
+
return {
|
|
44
|
+
status: response.status,
|
|
45
|
+
data: {
|
|
46
|
+
error: {
|
|
47
|
+
code: codeForStatus(response.status),
|
|
48
|
+
message: `Naive API returned an empty error response (HTTP ${response.status}).`,
|
|
49
|
+
hint: "Retry once; if this persists, the API route or upstream proxy may be unavailable.",
|
|
50
|
+
upstream_status: response.status,
|
|
51
|
+
...(contentType && { content_type: contentType }),
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const looksJson = /(?:^|[+/])json$/i.test(contentType ?? "") || /^[\[{]/.test(jsonText.trim());
|
|
57
|
+
if (looksJson) {
|
|
58
|
+
try {
|
|
59
|
+
return { status: response.status, data: JSON.parse(jsonText) };
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Fall through to the structured invalid-response envelope below.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const normalizedStatus = response.ok ? 502 : response.status;
|
|
66
|
+
const preview = safePreview(text);
|
|
67
|
+
return {
|
|
68
|
+
status: normalizedStatus,
|
|
69
|
+
data: {
|
|
70
|
+
error: {
|
|
71
|
+
code: codeForStatus(normalizedStatus),
|
|
72
|
+
message: `Naive API returned ${contentType ?? "a non-JSON response"} instead of JSON (HTTP ${response.status}).`,
|
|
73
|
+
hint: response.status === 404
|
|
74
|
+
? "The requested API route may not be deployed yet. Check the target environment and retry."
|
|
75
|
+
: "Retry once; if this persists, check API or upstream-provider health.",
|
|
76
|
+
upstream_status: response.status,
|
|
77
|
+
...(contentType && { content_type: contentType }),
|
|
78
|
+
...(preview && { response_preview: preview }),
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function networkErrorResponse(error) {
|
|
84
|
+
return {
|
|
85
|
+
status: 503,
|
|
86
|
+
data: {
|
|
87
|
+
error: {
|
|
88
|
+
code: "network_error",
|
|
89
|
+
message: "Could not reach the Naive API.",
|
|
90
|
+
hint: "Check your connection and NAIVE_BASE_URL, then retry.",
|
|
91
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=http-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-response.js","sourceRoot":"","sources":["../../src/lib/http-response.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed public prices mirrored from the API meters, so CLI copy cannot silently
|
|
3
|
+
* drift from billing. Keep dynamic model costs out of this table.
|
|
4
|
+
*
|
|
5
|
+
* The source of truth is `FIXED_CREDIT_COSTS` in platform/billing/src/pricing.ts
|
|
6
|
+
* and `pricing-parity.test.ts` holds the two equal. This header used to name
|
|
7
|
+
* packages/api/src/lib/pricing.ts — a path the #497 restructure deleted — and
|
|
8
|
+
* to promise a "dogfood contract test" that no file in the repo implemented.
|
|
9
|
+
*/
|
|
10
|
+
export declare const FIXED_CREDIT_COSTS: {
|
|
11
|
+
readonly emailSend: 0.016;
|
|
12
|
+
readonly webSearch: 0.2;
|
|
13
|
+
readonly urlRead: 0.05;
|
|
14
|
+
readonly researchQuick: 0.5;
|
|
15
|
+
readonly researchThorough: 1;
|
|
16
|
+
readonly researchExhaustive: 1.6;
|
|
17
|
+
readonly brainQuery: 0.08;
|
|
18
|
+
readonly brainIngestBase: 0.1;
|
|
19
|
+
readonly brainIngestPerKb: 0.0002;
|
|
20
|
+
readonly brainIngestMaxCredits: 10;
|
|
21
|
+
readonly socialPost: 2.5;
|
|
22
|
+
readonly socialXPost: 0.5;
|
|
23
|
+
readonly socialXPostWithLink: 5;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The DataForSEO-backed data primitives (seo / aeo / app-data / business /
|
|
27
|
+
* ecommerce), mirrored from `DATA_API_CREDIT_COSTS` in
|
|
28
|
+
* platform/billing/src/pricing.ts, which is where the reasoning, the vendor list
|
|
29
|
+
* price behind each number and the market anchor live. Held equal to it by
|
|
30
|
+
* packages/api/src/__tests__/credit-price-parity.test.ts.
|
|
31
|
+
*
|
|
32
|
+
* These are LIST prices. A charge is additionally floored at 1.2× what the call
|
|
33
|
+
* cost us upstream, so a row-heavy response can settle above the figure quoted
|
|
34
|
+
* here — which is why every CLI hint renders the response's own `credits_used`
|
|
35
|
+
* and only the `--help` epilogues quote this table.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DATA_API_CREDIT_COSTS: {
|
|
38
|
+
readonly seoKeywordsAdsLive: 2;
|
|
39
|
+
readonly seoKeywordsAdsStandard: 1.5;
|
|
40
|
+
readonly seoKeywordsTrendsLive: 0.25;
|
|
41
|
+
readonly seoKeywordsTrendsStandard: 0.2;
|
|
42
|
+
readonly seoBacklinksStandard: 1.8;
|
|
43
|
+
readonly seoBacklinksBulk: 17;
|
|
44
|
+
readonly seoLabsStandard: 0.75;
|
|
45
|
+
readonly seoLabsBulk: 5.4;
|
|
46
|
+
readonly seoLabsHistorical: 10;
|
|
47
|
+
readonly aeoLlmResponsesLive: 1.2;
|
|
48
|
+
readonly aeoLlmResponsesStandard: 1.2;
|
|
49
|
+
readonly aeoLlmScraperLive: 0.16;
|
|
50
|
+
readonly aeoLlmScraperStandard: 0.08;
|
|
51
|
+
readonly appDataAppSearches: 0.85;
|
|
52
|
+
readonly appDataAppList: 0.85;
|
|
53
|
+
readonly appDataAppInfo: 0.05;
|
|
54
|
+
readonly appDataAppReviews: 6;
|
|
55
|
+
readonly businessGoogleInfoLive: 0.13;
|
|
56
|
+
readonly businessGoogleInfoStandard: 0.09;
|
|
57
|
+
readonly businessGoogleUpdatesStandard: 3;
|
|
58
|
+
readonly businessGoogleReviewsStandard: 1.5;
|
|
59
|
+
readonly businessGoogleQaLive: 0.3;
|
|
60
|
+
readonly businessGoogleQaStandard: 0.18;
|
|
61
|
+
readonly businessGoogleHotelLive: 0.1;
|
|
62
|
+
readonly businessGoogleHotelStandard: 0.07;
|
|
63
|
+
readonly businessTrustpilotSearchStandard: 0.34;
|
|
64
|
+
readonly businessTrustpilotReviewsStandard: 0.85;
|
|
65
|
+
readonly businessTripadvisorSearchStandard: 0.85;
|
|
66
|
+
readonly businessTripadvisorReviewsStandard: 1.25;
|
|
67
|
+
readonly businessSocialLive: 0.1;
|
|
68
|
+
readonly ecommerceGoogleProducts: 0.15;
|
|
69
|
+
readonly ecommerceGoogleProductInfo: 0.14;
|
|
70
|
+
readonly ecommerceGoogleSellers: 0.24;
|
|
71
|
+
readonly ecommerceGoogleReviews: 2.2;
|
|
72
|
+
readonly ecommerceAmazonProducts: 0.14;
|
|
73
|
+
readonly ecommerceAmazonAsin: 0.04;
|
|
74
|
+
readonly ecommerceAmazonSellers: 0.14;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The two row-metered families, whose price is a base plus a per-row rate rather
|
|
78
|
+
* than a flat figure. Mirrored from the same module; `appListingsCredits` /
|
|
79
|
+
* `aeoLlmMentionsCredits` there are the functions that bill.
|
|
80
|
+
*/
|
|
81
|
+
export declare const METERED_DATA_API_CREDITS: {
|
|
82
|
+
readonly llmMentionsBase: 2.4;
|
|
83
|
+
readonly llmMentionsPerRow: 0.024;
|
|
84
|
+
readonly llmMentionsMaxRows: 1000;
|
|
85
|
+
readonly llmMentionsDefaultRows: 100;
|
|
86
|
+
readonly appListingsBase: 2.4;
|
|
87
|
+
readonly appListingsPerItem: 0.024;
|
|
88
|
+
readonly aiKeywordsBase: 0.4;
|
|
89
|
+
readonly aiKeywordsPerKeyword: 0.004;
|
|
90
|
+
};
|
|
91
|
+
/** `2.4 + 0.024 × rows`, the LLM Mentions price the API charges for `rows` rows. */
|
|
92
|
+
export declare function llmMentionsCredits(rows: number): number;
|
|
93
|
+
/** `2.4 + 0.024 × limit`, the live app-listings price for a given `--limit`. */
|
|
94
|
+
export declare function appListingsCredits(limit: number): number;
|
|
95
|
+
export declare function reportedCreditsUsed(data: unknown, fallback: number): number;
|
|
96
|
+
export interface CreditPack {
|
|
97
|
+
id: string;
|
|
98
|
+
credits: number;
|
|
99
|
+
priceInCents: number;
|
|
100
|
+
badge?: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The one-time credit packs, mirrored field-for-field from `CREDIT_PACKS` in
|
|
104
|
+
* platform/billing/src/billing.ts — the table `createTopupCheckout` bills
|
|
105
|
+
* Stripe from. The CLI ships to npm with five runtime dependencies and cannot
|
|
106
|
+
* import the billing package, so this is a mirror; `pricing-parity.test.ts`
|
|
107
|
+
* imports both and fails on any divergence.
|
|
108
|
+
*
|
|
109
|
+
* 🔴 EVERY pack figure the CLI prints must come from here. The `--help`
|
|
110
|
+
* epilogue and the `--pack` option description used to carry two independent
|
|
111
|
+
* hand-typed copies, and one of them drifted to a tenth of the real price.
|
|
112
|
+
*/
|
|
113
|
+
export declare const CREDIT_PACKS: readonly CreditPack[];
|
|
114
|
+
/** `$23` — whole dollars, matching how the API renders `getCreditPacks().price`. */
|
|
115
|
+
export declare function packPrice(pack: CreditPack): string;
|
|
116
|
+
/** `medium (500 credits, $23)` — the inline form for an option description. */
|
|
117
|
+
export declare function packInline(pack: CreditPack): string;
|
|
118
|
+
/** One column-aligned row of the pack table in `naive billing --help`. */
|
|
119
|
+
export declare function packRow(pack: CreditPack): string;
|
|
120
|
+
/**
|
|
121
|
+
* The flat 9:16 vertical-reframe / face-tracking fee, in credits, mirrored from
|
|
122
|
+
* `usdToBillableCredits(REFRAME_FEE_USD_PER_JOB)` in
|
|
123
|
+
* platform/billing/src/pricing.ts — the value clipCost() adds to a reframed
|
|
124
|
+
* job's subtotal. Charged once per job, not per clip.
|
|
125
|
+
*
|
|
126
|
+
* The CLI used to advertise this as "typically $0.05–$0.30 per job", which is
|
|
127
|
+
* the band clip-job-cost-audit.md records the CLI advertising while the code
|
|
128
|
+
* charged nothing at all. It is now a flat fee, billed in credits like every
|
|
129
|
+
* other driver, and this constant is held equal to the meter by
|
|
130
|
+
* packages/api/src/__tests__/credit-price-parity.test.ts.
|
|
131
|
+
*/
|
|
132
|
+
export declare const REFRAME_FEE_CREDITS = 4;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed public prices mirrored from the API meters, so CLI copy cannot silently
|
|
3
|
+
* drift from billing. Keep dynamic model costs out of this table.
|
|
4
|
+
*
|
|
5
|
+
* The source of truth is `FIXED_CREDIT_COSTS` in platform/billing/src/pricing.ts
|
|
6
|
+
* and `pricing-parity.test.ts` holds the two equal. This header used to name
|
|
7
|
+
* packages/api/src/lib/pricing.ts — a path the #497 restructure deleted — and
|
|
8
|
+
* to promise a "dogfood contract test" that no file in the repo implemented.
|
|
9
|
+
*/
|
|
10
|
+
export const FIXED_CREDIT_COSTS = {
|
|
11
|
+
emailSend: 0.016,
|
|
12
|
+
webSearch: 0.2,
|
|
13
|
+
urlRead: 0.05,
|
|
14
|
+
researchQuick: 0.5,
|
|
15
|
+
researchThorough: 1,
|
|
16
|
+
researchExhaustive: 1.6,
|
|
17
|
+
brainQuery: 0.08,
|
|
18
|
+
brainIngestBase: 0.1,
|
|
19
|
+
brainIngestPerKb: 0.0002,
|
|
20
|
+
brainIngestMaxCredits: 10,
|
|
21
|
+
socialPost: 2.5,
|
|
22
|
+
socialXPost: 0.5,
|
|
23
|
+
socialXPostWithLink: 5,
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The DataForSEO-backed data primitives (seo / aeo / app-data / business /
|
|
27
|
+
* ecommerce), mirrored from `DATA_API_CREDIT_COSTS` in
|
|
28
|
+
* platform/billing/src/pricing.ts, which is where the reasoning, the vendor list
|
|
29
|
+
* price behind each number and the market anchor live. Held equal to it by
|
|
30
|
+
* packages/api/src/__tests__/credit-price-parity.test.ts.
|
|
31
|
+
*
|
|
32
|
+
* These are LIST prices. A charge is additionally floored at 1.2× what the call
|
|
33
|
+
* cost us upstream, so a row-heavy response can settle above the figure quoted
|
|
34
|
+
* here — which is why every CLI hint renders the response's own `credits_used`
|
|
35
|
+
* and only the `--help` epilogues quote this table.
|
|
36
|
+
*/
|
|
37
|
+
export const DATA_API_CREDIT_COSTS = {
|
|
38
|
+
seoKeywordsAdsLive: 2,
|
|
39
|
+
seoKeywordsAdsStandard: 1.5,
|
|
40
|
+
seoKeywordsTrendsLive: 0.25,
|
|
41
|
+
seoKeywordsTrendsStandard: 0.2,
|
|
42
|
+
seoBacklinksStandard: 1.8,
|
|
43
|
+
seoBacklinksBulk: 17,
|
|
44
|
+
seoLabsStandard: 0.75,
|
|
45
|
+
seoLabsBulk: 5.4,
|
|
46
|
+
seoLabsHistorical: 10,
|
|
47
|
+
aeoLlmResponsesLive: 1.2,
|
|
48
|
+
aeoLlmResponsesStandard: 1.2,
|
|
49
|
+
aeoLlmScraperLive: 0.16,
|
|
50
|
+
aeoLlmScraperStandard: 0.08,
|
|
51
|
+
appDataAppSearches: 0.85,
|
|
52
|
+
appDataAppList: 0.85,
|
|
53
|
+
appDataAppInfo: 0.05,
|
|
54
|
+
appDataAppReviews: 6,
|
|
55
|
+
businessGoogleInfoLive: 0.13,
|
|
56
|
+
businessGoogleInfoStandard: 0.09,
|
|
57
|
+
businessGoogleUpdatesStandard: 3,
|
|
58
|
+
businessGoogleReviewsStandard: 1.5,
|
|
59
|
+
businessGoogleQaLive: 0.3,
|
|
60
|
+
businessGoogleQaStandard: 0.18,
|
|
61
|
+
businessGoogleHotelLive: 0.1,
|
|
62
|
+
businessGoogleHotelStandard: 0.07,
|
|
63
|
+
businessTrustpilotSearchStandard: 0.34,
|
|
64
|
+
businessTrustpilotReviewsStandard: 0.85,
|
|
65
|
+
businessTripadvisorSearchStandard: 0.85,
|
|
66
|
+
businessTripadvisorReviewsStandard: 1.25,
|
|
67
|
+
businessSocialLive: 0.1,
|
|
68
|
+
ecommerceGoogleProducts: 0.15,
|
|
69
|
+
ecommerceGoogleProductInfo: 0.14,
|
|
70
|
+
ecommerceGoogleSellers: 0.24,
|
|
71
|
+
ecommerceGoogleReviews: 2.2,
|
|
72
|
+
ecommerceAmazonProducts: 0.14,
|
|
73
|
+
ecommerceAmazonAsin: 0.04,
|
|
74
|
+
ecommerceAmazonSellers: 0.14,
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The two row-metered families, whose price is a base plus a per-row rate rather
|
|
78
|
+
* than a flat figure. Mirrored from the same module; `appListingsCredits` /
|
|
79
|
+
* `aeoLlmMentionsCredits` there are the functions that bill.
|
|
80
|
+
*/
|
|
81
|
+
export const METERED_DATA_API_CREDITS = {
|
|
82
|
+
llmMentionsBase: 2.4,
|
|
83
|
+
llmMentionsPerRow: 0.024,
|
|
84
|
+
llmMentionsMaxRows: 1000,
|
|
85
|
+
llmMentionsDefaultRows: 100,
|
|
86
|
+
appListingsBase: 2.4,
|
|
87
|
+
appListingsPerItem: 0.024,
|
|
88
|
+
aiKeywordsBase: 0.4,
|
|
89
|
+
aiKeywordsPerKeyword: 0.004,
|
|
90
|
+
};
|
|
91
|
+
/** `2.4 + 0.024 × rows`, the LLM Mentions price the API charges for `rows` rows. */
|
|
92
|
+
export function llmMentionsCredits(rows) {
|
|
93
|
+
const capped = Math.min(Math.max(rows, 1), METERED_DATA_API_CREDITS.llmMentionsMaxRows);
|
|
94
|
+
return Math.ceil((METERED_DATA_API_CREDITS.llmMentionsBase + METERED_DATA_API_CREDITS.llmMentionsPerRow * capped) * 100) / 100;
|
|
95
|
+
}
|
|
96
|
+
/** `2.4 + 0.024 × limit`, the live app-listings price for a given `--limit`. */
|
|
97
|
+
export function appListingsCredits(limit) {
|
|
98
|
+
return Math.ceil((METERED_DATA_API_CREDITS.appListingsBase + METERED_DATA_API_CREDITS.appListingsPerItem * Math.max(limit, 1)) * 100) / 100;
|
|
99
|
+
}
|
|
100
|
+
export function reportedCreditsUsed(data, fallback) {
|
|
101
|
+
const value = data?.credits_used;
|
|
102
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The one-time credit packs, mirrored field-for-field from `CREDIT_PACKS` in
|
|
106
|
+
* platform/billing/src/billing.ts — the table `createTopupCheckout` bills
|
|
107
|
+
* Stripe from. The CLI ships to npm with five runtime dependencies and cannot
|
|
108
|
+
* import the billing package, so this is a mirror; `pricing-parity.test.ts`
|
|
109
|
+
* imports both and fails on any divergence.
|
|
110
|
+
*
|
|
111
|
+
* 🔴 EVERY pack figure the CLI prints must come from here. The `--help`
|
|
112
|
+
* epilogue and the `--pack` option description used to carry two independent
|
|
113
|
+
* hand-typed copies, and one of them drifted to a tenth of the real price.
|
|
114
|
+
*/
|
|
115
|
+
export const CREDIT_PACKS = [
|
|
116
|
+
{ id: "small", credits: 200, priceInCents: 1000 },
|
|
117
|
+
{ id: "medium", credits: 500, priceInCents: 2300, badge: "Popular" },
|
|
118
|
+
{ id: "large", credits: 1000, priceInCents: 4400, badge: "Best Value" },
|
|
119
|
+
{ id: "xl", credits: 2500, priceInCents: 10000 },
|
|
120
|
+
];
|
|
121
|
+
/** `$23` — whole dollars, matching how the API renders `getCreditPacks().price`. */
|
|
122
|
+
export function packPrice(pack) {
|
|
123
|
+
return `$${(pack.priceInCents / 100).toFixed(0)}`;
|
|
124
|
+
}
|
|
125
|
+
/** `medium (500 credits, $23)` — the inline form for an option description. */
|
|
126
|
+
export function packInline(pack) {
|
|
127
|
+
return `${pack.id} (${pack.credits} credits, ${packPrice(pack)})`;
|
|
128
|
+
}
|
|
129
|
+
/** One column-aligned row of the pack table in `naive billing --help`. */
|
|
130
|
+
export function packRow(pack) {
|
|
131
|
+
const credits = `${pack.credits} credits`.padEnd(15);
|
|
132
|
+
const price = pack.badge ? `${packPrice(pack).padEnd(6)}(${pack.badge})` : packPrice(pack);
|
|
133
|
+
return ` ${pack.id.padEnd(10)}${credits}${price}`;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The flat 9:16 vertical-reframe / face-tracking fee, in credits, mirrored from
|
|
137
|
+
* `usdToBillableCredits(REFRAME_FEE_USD_PER_JOB)` in
|
|
138
|
+
* platform/billing/src/pricing.ts — the value clipCost() adds to a reframed
|
|
139
|
+
* job's subtotal. Charged once per job, not per clip.
|
|
140
|
+
*
|
|
141
|
+
* The CLI used to advertise this as "typically $0.05–$0.30 per job", which is
|
|
142
|
+
* the band clip-job-cost-audit.md records the CLI advertising while the code
|
|
143
|
+
* charged nothing at all. It is now a flat fee, billed in credits like every
|
|
144
|
+
* other driver, and this constant is held equal to the meter by
|
|
145
|
+
* packages/api/src/__tests__/credit-price-parity.test.ts.
|
|
146
|
+
*/
|
|
147
|
+
export const REFRAME_FEE_CREDITS = 4;
|
|
148
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/lib/pricing.ts"],"names":[],"mappings":"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"}
|