@usenaive-sdk/cli 0.12.2 → 0.13.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.
- package/README.md +76 -5
- package/dist/client.d.ts +74 -1
- package/dist/client.js +351 -17
- package/dist/client.js.map +1 -1
- package/dist/commands/aeo.js +69 -27
- 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/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 +31 -0
- package/dist/commands/auth.js +403 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/billing.js +12 -12
- package/dist/commands/billing.js.map +1 -1
- package/dist/commands/brain.d.ts +2 -0
- package/dist/commands/brain.js +1255 -0
- package/dist/commands/brain.js.map +1 -0
- package/dist/commands/browser.js +35 -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.d.ts +2 -0
- package/dist/commands/clone.js +203 -0
- package/dist/commands/clone.js.map +1 -0
- 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 +10 -3
- package/dist/commands/compute.js.map +1 -1
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +36 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/connections.d.ts +6 -0
- package/dist/commands/connections.js +29 -1
- package/dist/commands/connections.js.map +1 -1
- package/dist/commands/domains.js +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/env.d.ts +3 -3
- package/dist/commands/env.js +68 -4
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/formation.js +3 -3
- package/dist/commands/identity.js +4 -3
- package/dist/commands/identity.js.map +1 -1
- package/dist/commands/images.js +87 -13
- package/dist/commands/images.js.map +1 -1
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +39 -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/keys.js +26 -3
- package/dist/commands/keys.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 +13 -0
- 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/loops.d.ts +2 -0
- package/dist/commands/loops.js +260 -0
- package/dist/commands/loops.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 +4 -0
- package/dist/commands/mobile.js +382 -0
- package/dist/commands/mobile.js.map +1 -0
- package/dist/commands/payments.d.ts +2 -0
- package/dist/commands/payments.js +131 -0
- package/dist/commands/payments.js.map +1 -0
- package/dist/commands/people.d.ts +2 -0
- package/dist/commands/people.js +193 -0
- package/dist/commands/people.js.map +1 -0
- package/dist/commands/phone.js +3 -3
- 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 +16 -8
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/sandbox.d.ts +2 -0
- package/dist/commands/sandbox.js +245 -0
- package/dist/commands/sandbox.js.map +1 -0
- package/dist/commands/search.js +26 -12
- 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 +244 -0
- package/dist/commands/social-data.js.map +1 -0
- package/dist/commands/social.js +8 -6
- package/dist/commands/social.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 +415 -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 +28 -1
- package/dist/commands/vault.js.map +1 -1
- package/dist/commands/video.js +190 -270
- package/dist/commands/video.js.map +1 -1
- package/dist/commands/voice.d.ts +2 -0
- package/dist/commands/voice.js +516 -0
- package/dist/commands/voice.js.map +1 -0
- package/dist/commands/wallet.d.ts +2 -0
- package/dist/commands/wallet.js +244 -0
- package/dist/commands/wallet.js.map +1 -0
- package/dist/commands/whoami.js +17 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config.d.ts +24 -1
- package/dist/config.js +36 -7
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +290 -20
- 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 +57 -0
- package/dist/lib/unknown-command.js +93 -0
- package/dist/lib/unknown-command.js.map +1 -0
- package/dist/lib/version-check.d.ts +26 -0
- package/dist/lib/version-check.js +21 -0
- package/dist/lib/version-check.js.map +1 -0
- package/dist/output.d.ts +119 -10
- package/dist/output.js +309 -15
- package/dist/output.js.map +1 -1
- package/dist/prompt.d.ts +17 -0
- package/dist/prompt.js +70 -0
- package/dist/prompt.js.map +1 -0
- package/package.json +11 -6
- package/dist/commands/billing-client.d.ts +0 -2
- package/dist/commands/billing-client.js +0 -271
- package/dist/commands/billing-client.js.map +0 -1
- package/dist/commands/crm-app.d.ts +0 -2
- package/dist/commands/crm-app.js +0 -306
- package/dist/commands/crm-app.js.map +0 -1
- package/dist/commands/crm.d.ts +0 -2
- package/dist/commands/crm.js +0 -319
- package/dist/commands/crm.js.map +0 -1
- package/dist/commands/integrations.d.ts +0 -2
- package/dist/commands/integrations.js +0 -199
- package/dist/commands/integrations.js.map +0 -1
- package/dist/commands/link.d.ts +0 -3
- package/dist/commands/link.js +0 -91
- package/dist/commands/link.js.map +0 -1
- package/dist/commands/operators.d.ts +0 -11
- package/dist/commands/operators.js +0 -120
- package/dist/commands/operators.js.map +0 -1
|
@@ -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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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `naive teams watch` — the pure half (06 §1.6).
|
|
3
|
+
*
|
|
4
|
+
* Everything here is a function of its input, so the framing, the resume
|
|
5
|
+
* position, the redaction and the termination rule are tests rather than
|
|
6
|
+
* behaviour you have to run a server to observe.
|
|
7
|
+
*
|
|
8
|
+
* THE OUTPUT IS NDJSON, ONE OBJECT PER LINE — not a JSON array. A stream has no
|
|
9
|
+
* closing bracket, so an array can only be completed by a client that already
|
|
10
|
+
* knows the stream ended, which is the one thing a consumer of a live stream
|
|
11
|
+
* does not know.
|
|
12
|
+
*
|
|
13
|
+
* TERMINATION IS `{"type":"stream.end"}` WITH A REASON, NEVER `[DONE]`. That
|
|
14
|
+
* token belongs to the OpenAI-compatible lane; reusing it here would make one
|
|
15
|
+
* word mean two protocols.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Secrets that must never reach a transcript.
|
|
19
|
+
*
|
|
20
|
+
* `nv_sk_…` is the platform api key — the same shape `output.ts` already guards
|
|
21
|
+
* in `next_steps`. `vt_<company>_<hex>` is the per-team runtime credential, which
|
|
22
|
+
* `output.ts` has never seen because nothing else prints one. A transcript prints
|
|
23
|
+
* TOOL ARGUMENTS, so it is the one surface where either can arrive inside an
|
|
24
|
+
* arbitrary payload rather than in a field with a known name.
|
|
25
|
+
*/
|
|
26
|
+
export declare const SECRET_PATTERNS: readonly RegExp[];
|
|
27
|
+
/**
|
|
28
|
+
* Redact a decoded frame in place-free fashion.
|
|
29
|
+
*
|
|
30
|
+
* `showArgs` is false by default and the frame's `args` are replaced by whatever
|
|
31
|
+
* `args_digest` the server sent. That is the honest default: a digest still lets
|
|
32
|
+
* a reader correlate two frames, and it cannot leak a value nobody audited.
|
|
33
|
+
* `commands/teams.ts` additionally refuses `--show-args` outside an interactive
|
|
34
|
+
* terminal, so a pipe or a CI job cannot turn it on.
|
|
35
|
+
*/
|
|
36
|
+
export declare function redactFrame(frame: unknown, opts: {
|
|
37
|
+
showArgs: boolean;
|
|
38
|
+
}): unknown;
|
|
39
|
+
export interface SseEvent {
|
|
40
|
+
/** The `id:` field, which is what a resume sends back as `Last-Event-ID`. */
|
|
41
|
+
readonly id?: string;
|
|
42
|
+
/** The concatenated `data:` lines. */
|
|
43
|
+
readonly data: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Split a buffer into complete SSE events, returning the unconsumed tail.
|
|
47
|
+
*
|
|
48
|
+
* The tail matters: a chunk boundary lands mid-event far more often than test
|
|
49
|
+
* fixtures suggest, and a parser that discards a partial event drops exactly the
|
|
50
|
+
* frames that arrive under load.
|
|
51
|
+
*/
|
|
52
|
+
export declare function parseSse(buffer: string): {
|
|
53
|
+
events: SseEvent[];
|
|
54
|
+
rest: string;
|
|
55
|
+
};
|
|
56
|
+
/** The terminal states that are NOT success. `unverified` is the reason exit 3
|
|
57
|
+
* exists at all: a CI script reading exit 0 as "the work is done" would count an
|
|
58
|
+
* unattested task as a pass. */
|
|
59
|
+
export declare const NON_SUCCESS_TERMINAL: readonly ["unverified", "failed", "blocked"];
|
|
60
|
+
export type StreamEndReason = "run_terminal" | "client_closed" | "timeout" | "fence_closed";
|
|
61
|
+
/**
|
|
62
|
+
* The exit code for a finished stream. `--fail-on-terminal` is opt-in because
|
|
63
|
+
* changing the exit code of an existing command is a wire break; without it a
|
|
64
|
+
* watch always exits 0 and the caller reads `status` itself.
|
|
65
|
+
*/
|
|
66
|
+
export declare function watchExitCode(finalStatus: string | undefined, failOnTerminal: boolean): 0 | 3;
|
|
67
|
+
/**
|
|
68
|
+
* One board card, in the three fields this gate is allowed to read.
|
|
69
|
+
*
|
|
70
|
+
* Deliberately structural and deliberately narrow: `extractCards` hands over
|
|
71
|
+
* whatever the wire said, and a gate that reads more of a card than it needs is
|
|
72
|
+
* a gate that breaks when an unrelated field is renamed.
|
|
73
|
+
*/
|
|
74
|
+
export type GateCard = {
|
|
75
|
+
status?: string;
|
|
76
|
+
/** `durableCard`: naive adjudicated and the verdict never reached the runtime. */
|
|
77
|
+
verdict_delivery_failed?: unknown;
|
|
78
|
+
/** `durableCard`: naive granted a terminal the runtime does not hold. */
|
|
79
|
+
boards_disagree?: unknown;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Is this card's verification state anything other than SETTLED AND AGREED?
|
|
83
|
+
*
|
|
84
|
+
* 🔴 A CARD THE TWO BOARDS DISAGREE ABOUT IS NOT A VERIFIED CARD, and this gate
|
|
85
|
+
* used to say it was. It read one field -- `status === "unverified"` -- and the
|
|
86
|
+
* durable lane has two more that mean the verification did not conclude:
|
|
87
|
+
*
|
|
88
|
+
* - `verdict_delivery_failed`. naive REJECTED the card and the verdict did not
|
|
89
|
+
* reach the runtime, so the runtime still holds its own terminal. The board
|
|
90
|
+
* row carries the failure and says, in its own `meaning` field, that "the two
|
|
91
|
+
* boards disagree about it".
|
|
92
|
+
* - `boards_disagree`. naive granted a terminal the runtime does not hold, with
|
|
93
|
+
* no delivery to fail -- an accept is written on naive's own row and is never
|
|
94
|
+
* delivered, so this is the ONLY signal that case has. Its own text calls it
|
|
95
|
+
* "the disagreement that bills for work the runtime says did not finish".
|
|
96
|
+
*
|
|
97
|
+
* Measured on staging: card A carried `verdict_delivery_failed` and
|
|
98
|
+
* `naive teams tasks … --fail-on-unverified` exited 0 on it. A CI job reading
|
|
99
|
+
* that exit code as "attested" is the exact failure this flag exists to prevent,
|
|
100
|
+
* and the file's own history records it happening once already through a
|
|
101
|
+
* different field (see `extractCards`).
|
|
102
|
+
*
|
|
103
|
+
* PRESENCE, not shape. Both fields are objects the server composes and neither is
|
|
104
|
+
* ever emitted as a negative -- `durableCard` omits them entirely for a card with
|
|
105
|
+
* nothing to report -- so asking whether one is there is the whole test, and it
|
|
106
|
+
* cannot go stale when their contents change.
|
|
107
|
+
*/
|
|
108
|
+
export declare function cardIsUnverified(card: GateCard): boolean;
|
|
109
|
+
/** The same rule for a single board card, used by `tasks`/`task --fail-on-unverified`. */
|
|
110
|
+
export declare function unverifiedExitCode(cards: readonly GateCard[], failOnUnverified: boolean): 0 | 3;
|
|
111
|
+
/** The highest `seq` printed so far — the position a reconnect resumes from.
|
|
112
|
+
* `sequence >` is strict on the server, so nothing is lost and nothing is
|
|
113
|
+
* duplicated. */
|
|
114
|
+
export declare function highestSeq(current: number | undefined, frame: unknown): number | undefined;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `naive teams watch` — the pure half (06 §1.6).
|
|
3
|
+
*
|
|
4
|
+
* Everything here is a function of its input, so the framing, the resume
|
|
5
|
+
* position, the redaction and the termination rule are tests rather than
|
|
6
|
+
* behaviour you have to run a server to observe.
|
|
7
|
+
*
|
|
8
|
+
* THE OUTPUT IS NDJSON, ONE OBJECT PER LINE — not a JSON array. A stream has no
|
|
9
|
+
* closing bracket, so an array can only be completed by a client that already
|
|
10
|
+
* knows the stream ended, which is the one thing a consumer of a live stream
|
|
11
|
+
* does not know.
|
|
12
|
+
*
|
|
13
|
+
* TERMINATION IS `{"type":"stream.end"}` WITH A REASON, NEVER `[DONE]`. That
|
|
14
|
+
* token belongs to the OpenAI-compatible lane; reusing it here would make one
|
|
15
|
+
* word mean two protocols.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Secrets that must never reach a transcript.
|
|
19
|
+
*
|
|
20
|
+
* `nv_sk_…` is the platform api key — the same shape `output.ts` already guards
|
|
21
|
+
* in `next_steps`. `vt_<company>_<hex>` is the per-team runtime credential, which
|
|
22
|
+
* `output.ts` has never seen because nothing else prints one. A transcript prints
|
|
23
|
+
* TOOL ARGUMENTS, so it is the one surface where either can arrive inside an
|
|
24
|
+
* arbitrary payload rather than in a field with a known name.
|
|
25
|
+
*/
|
|
26
|
+
export const SECRET_PATTERNS = [
|
|
27
|
+
/nv_sk_[A-Za-z0-9_-]+/g,
|
|
28
|
+
/vt_[A-Za-z0-9-]+_[A-Fa-f0-9]{8,}/g,
|
|
29
|
+
];
|
|
30
|
+
/** Field names whose VALUE is a secret whatever it looks like. */
|
|
31
|
+
const SECRET_FIELDS = new Set(["api_key", "session_token", "token", "credential", "secret"]);
|
|
32
|
+
const REDACTED = "[redacted]";
|
|
33
|
+
function scrubString(s) {
|
|
34
|
+
let out = s;
|
|
35
|
+
for (const re of SECRET_PATTERNS)
|
|
36
|
+
out = out.replace(new RegExp(re.source, re.flags), REDACTED);
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Redact a decoded frame in place-free fashion.
|
|
41
|
+
*
|
|
42
|
+
* `showArgs` is false by default and the frame's `args` are replaced by whatever
|
|
43
|
+
* `args_digest` the server sent. That is the honest default: a digest still lets
|
|
44
|
+
* a reader correlate two frames, and it cannot leak a value nobody audited.
|
|
45
|
+
* `commands/teams.ts` additionally refuses `--show-args` outside an interactive
|
|
46
|
+
* terminal, so a pipe or a CI job cannot turn it on.
|
|
47
|
+
*/
|
|
48
|
+
export function redactFrame(frame, opts) {
|
|
49
|
+
const seen = new WeakSet();
|
|
50
|
+
const walk = (v, key) => {
|
|
51
|
+
if (typeof v === "string") {
|
|
52
|
+
if (key !== undefined && SECRET_FIELDS.has(key))
|
|
53
|
+
return REDACTED;
|
|
54
|
+
return scrubString(v);
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(v))
|
|
57
|
+
return v.map((e) => walk(e));
|
|
58
|
+
if (typeof v === "object" && v !== null) {
|
|
59
|
+
if (seen.has(v))
|
|
60
|
+
return "[circular]";
|
|
61
|
+
seen.add(v);
|
|
62
|
+
const out = {};
|
|
63
|
+
for (const [k, val] of Object.entries(v)) {
|
|
64
|
+
if (k === "args" && !opts.showArgs) {
|
|
65
|
+
out.args = REDACTED;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
out[k] = walk(val, k);
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
return v;
|
|
73
|
+
};
|
|
74
|
+
return walk(frame);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Split a buffer into complete SSE events, returning the unconsumed tail.
|
|
78
|
+
*
|
|
79
|
+
* The tail matters: a chunk boundary lands mid-event far more often than test
|
|
80
|
+
* fixtures suggest, and a parser that discards a partial event drops exactly the
|
|
81
|
+
* frames that arrive under load.
|
|
82
|
+
*/
|
|
83
|
+
export function parseSse(buffer) {
|
|
84
|
+
const events = [];
|
|
85
|
+
// An event ends at a blank line. \r\n is legal per the spec and some proxies
|
|
86
|
+
// rewrite line endings, so both are accepted.
|
|
87
|
+
const parts = buffer.split(/\r?\n\r?\n/);
|
|
88
|
+
const rest = parts.pop() ?? "";
|
|
89
|
+
for (const block of parts) {
|
|
90
|
+
let id;
|
|
91
|
+
const data = [];
|
|
92
|
+
for (const line of block.split(/\r?\n/)) {
|
|
93
|
+
if (line.startsWith(":"))
|
|
94
|
+
continue; // a comment / keep-alive
|
|
95
|
+
const colon = line.indexOf(":");
|
|
96
|
+
const field = colon === -1 ? line : line.slice(0, colon);
|
|
97
|
+
const value = colon === -1 ? "" : line.slice(colon + 1).replace(/^ /, "");
|
|
98
|
+
if (field === "data")
|
|
99
|
+
data.push(value);
|
|
100
|
+
else if (field === "id")
|
|
101
|
+
id = value;
|
|
102
|
+
}
|
|
103
|
+
if (data.length > 0)
|
|
104
|
+
events.push({ ...(id !== undefined && { id }), data: data.join("\n") });
|
|
105
|
+
}
|
|
106
|
+
return { events, rest };
|
|
107
|
+
}
|
|
108
|
+
/** The terminal states that are NOT success. `unverified` is the reason exit 3
|
|
109
|
+
* exists at all: a CI script reading exit 0 as "the work is done" would count an
|
|
110
|
+
* unattested task as a pass. */
|
|
111
|
+
export const NON_SUCCESS_TERMINAL = ["unverified", "failed", "blocked"];
|
|
112
|
+
/**
|
|
113
|
+
* The exit code for a finished stream. `--fail-on-terminal` is opt-in because
|
|
114
|
+
* changing the exit code of an existing command is a wire break; without it a
|
|
115
|
+
* watch always exits 0 and the caller reads `status` itself.
|
|
116
|
+
*/
|
|
117
|
+
export function watchExitCode(finalStatus, failOnTerminal) {
|
|
118
|
+
if (!failOnTerminal || finalStatus === undefined)
|
|
119
|
+
return 0;
|
|
120
|
+
return NON_SUCCESS_TERMINAL.includes(finalStatus) ? 3 : 0;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Is this card's verification state anything other than SETTLED AND AGREED?
|
|
124
|
+
*
|
|
125
|
+
* 🔴 A CARD THE TWO BOARDS DISAGREE ABOUT IS NOT A VERIFIED CARD, and this gate
|
|
126
|
+
* used to say it was. It read one field -- `status === "unverified"` -- and the
|
|
127
|
+
* durable lane has two more that mean the verification did not conclude:
|
|
128
|
+
*
|
|
129
|
+
* - `verdict_delivery_failed`. naive REJECTED the card and the verdict did not
|
|
130
|
+
* reach the runtime, so the runtime still holds its own terminal. The board
|
|
131
|
+
* row carries the failure and says, in its own `meaning` field, that "the two
|
|
132
|
+
* boards disagree about it".
|
|
133
|
+
* - `boards_disagree`. naive granted a terminal the runtime does not hold, with
|
|
134
|
+
* no delivery to fail -- an accept is written on naive's own row and is never
|
|
135
|
+
* delivered, so this is the ONLY signal that case has. Its own text calls it
|
|
136
|
+
* "the disagreement that bills for work the runtime says did not finish".
|
|
137
|
+
*
|
|
138
|
+
* Measured on staging: card A carried `verdict_delivery_failed` and
|
|
139
|
+
* `naive teams tasks … --fail-on-unverified` exited 0 on it. A CI job reading
|
|
140
|
+
* that exit code as "attested" is the exact failure this flag exists to prevent,
|
|
141
|
+
* and the file's own history records it happening once already through a
|
|
142
|
+
* different field (see `extractCards`).
|
|
143
|
+
*
|
|
144
|
+
* PRESENCE, not shape. Both fields are objects the server composes and neither is
|
|
145
|
+
* ever emitted as a negative -- `durableCard` omits them entirely for a card with
|
|
146
|
+
* nothing to report -- so asking whether one is there is the whole test, and it
|
|
147
|
+
* cannot go stale when their contents change.
|
|
148
|
+
*/
|
|
149
|
+
export function cardIsUnverified(card) {
|
|
150
|
+
return (card.status === "unverified" ||
|
|
151
|
+
card.verdict_delivery_failed != null ||
|
|
152
|
+
card.boards_disagree != null);
|
|
153
|
+
}
|
|
154
|
+
/** The same rule for a single board card, used by `tasks`/`task --fail-on-unverified`. */
|
|
155
|
+
export function unverifiedExitCode(cards, failOnUnverified) {
|
|
156
|
+
if (!failOnUnverified)
|
|
157
|
+
return 0;
|
|
158
|
+
return cards.some(cardIsUnverified) ? 3 : 0;
|
|
159
|
+
}
|
|
160
|
+
/** The highest `seq` printed so far — the position a reconnect resumes from.
|
|
161
|
+
* `sequence >` is strict on the server, so nothing is lost and nothing is
|
|
162
|
+
* duplicated. */
|
|
163
|
+
export function highestSeq(current, frame) {
|
|
164
|
+
const seq = frame?.seq;
|
|
165
|
+
if (typeof seq !== "number" || !Number.isFinite(seq))
|
|
166
|
+
return current;
|
|
167
|
+
return current === undefined || seq > current ? seq : current;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=stream-frames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-frames.js","sourceRoot":"","sources":["../../src/lib/stream-frames.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE ONE DECLARATION SITE for the `naive teams` surface (06 §1.4).
|
|
3
|
+
*
|
|
4
|
+
* Two design notes shipped two `teams` command sets and neither was a superset of
|
|
5
|
+
* the other. Two hand-written lists is exactly the drift a one-declaration rule
|
|
6
|
+
* exists to catch, so both are deleted and the union is declared once, here, as
|
|
7
|
+
* DATA. `commands/teams.ts` builds the commander tree by walking this array; it
|
|
8
|
+
* writes no subcommand of its own. A row added here is a working command, and a
|
|
9
|
+
* command that is not a row here does not exist.
|
|
10
|
+
*
|
|
11
|
+
* ── WHY THIS IS A .ts FILE IN THIS PACKAGE AND NOT A GENERATED ARTIFACT ─────
|
|
12
|
+
*
|
|
13
|
+
* 06 §1.4 puts the declaration in `@usenaive/agent-contract/capabilities` and has
|
|
14
|
+
* a generator emit `packages/cli/src/generated/teams-commands.ts` from it, so the
|
|
15
|
+
* CLI subcommand, the MCP tool, the REST path and the openapi operation are all
|
|
16
|
+
* one statement. MEASURED: there is no `packages/agent-contract` directory in
|
|
17
|
+
* this tree and no generator to run, and this task owns `packages/cli` only. A
|
|
18
|
+
* hand-written file that IMITATES a generated one — committed under `generated/`,
|
|
19
|
+
* with nothing that regenerates it — is worse than an honest source file: the
|
|
20
|
+
* next person edits it and their edit is silently the truth.
|
|
21
|
+
*
|
|
22
|
+
* So this is the honest intermediate: ONE declaration, inside the package that
|
|
23
|
+
* consumes it, shaped so a future generator emits exactly this array. The fields
|
|
24
|
+
* a generator would need and the CLI does not (`action`, `rest`, `mcp`,
|
|
25
|
+
* `because`, `fenced`, `write`) are carried anyway, so the day the contract
|
|
26
|
+
* package exists this file is deleted rather than reconciled.
|
|
27
|
+
*
|
|
28
|
+
* ── WHY IT MUST BE ONE LIST AND NOT 28 `.command()` CALLS ───────────────────
|
|
29
|
+
*
|
|
30
|
+
* `src/index.ts` calls `findUnknownSubcommand` BEFORE `parseAsync` and hard-fails
|
|
31
|
+
* on an unrecognised subcommand even with `--help` appended. A subcommand list
|
|
32
|
+
* that can drift from the thing that answers it therefore makes VALID commands
|
|
33
|
+
* fail with `cli_outdated`, rather than degrading. One array, walked once, cannot
|
|
34
|
+
* drift from itself.
|
|
35
|
+
*/
|
|
36
|
+
/** Where a flag's value goes on the wire. `client` never leaves the process. */
|
|
37
|
+
export type FlagIn = "query" | "body" | "path" | "client";
|
|
38
|
+
export interface FlagSpec {
|
|
39
|
+
/** Commander syntax, verbatim: `--status <status>` or `--follow`. */
|
|
40
|
+
readonly flag: string;
|
|
41
|
+
/** The key commander puts on the options object. */
|
|
42
|
+
readonly key: string;
|
|
43
|
+
readonly describe: string;
|
|
44
|
+
readonly in: FlagIn;
|
|
45
|
+
/** Wire field name. Defaults to `key`. */
|
|
46
|
+
readonly field?: string;
|
|
47
|
+
/** `requiredOption` rather than `option` — see `--because` below. */
|
|
48
|
+
readonly required?: boolean;
|
|
49
|
+
/** Parse the value as an integer before sending it. */
|
|
50
|
+
readonly int?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* A boolean flag that SELECTS a value for a shared wire field instead of
|
|
53
|
+
* sending its own name as a field.
|
|
54
|
+
*
|
|
55
|
+
* `--allow` is not a field this API has. The field is `decision` and `--allow`
|
|
56
|
+
* is one of its two values (`POST …/approvals/:id/decide` throws
|
|
57
|
+
* `invalid_input: decision must be "approve" or "deny"` on anything else). The
|
|
58
|
+
* first spelling of this catalog declared `--allow` and `--deny` as ordinary
|
|
59
|
+
* body flags, so the CLI sent `{"allow":true,"because":"…"}` and the one
|
|
60
|
+
* mounted write on the whole `/v1/teams` surface could not be invoked at all.
|
|
61
|
+
*
|
|
62
|
+
* A flag declaring `value` MUST also declare `field`; flags sharing a `field`
|
|
63
|
+
* form a mutually exclusive group, and `selectorGroups()` derives that group
|
|
64
|
+
* rather than listing it, so a third value cannot be added without joining the
|
|
65
|
+
* exclusion.
|
|
66
|
+
*/
|
|
67
|
+
readonly value?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface ArgSpec {
|
|
70
|
+
/** Commander syntax, verbatim: `<team>` or `[channel]`. */
|
|
71
|
+
readonly arg: string;
|
|
72
|
+
/** The bare name, for path substitution and body keys. */
|
|
73
|
+
readonly name: string;
|
|
74
|
+
readonly describe: string;
|
|
75
|
+
readonly in: "path" | "body";
|
|
76
|
+
/** Wire field name. Defaults to `name`. */
|
|
77
|
+
readonly field?: string;
|
|
78
|
+
}
|
|
79
|
+
export interface TeamOp {
|
|
80
|
+
/** The subcommand name under `naive teams`. */
|
|
81
|
+
readonly cli: string;
|
|
82
|
+
readonly describe: string;
|
|
83
|
+
/** The governance ActionId this op is evaluated as. */
|
|
84
|
+
readonly action: string;
|
|
85
|
+
readonly method: "GET" | "POST" | "DELETE";
|
|
86
|
+
/** `{name}` placeholders are filled from `{team}`, `{tenant}` and path args. */
|
|
87
|
+
readonly path: string;
|
|
88
|
+
/** Does this op need `--tenant`? True for all 28 except `list` (R-4). */
|
|
89
|
+
readonly tenant: boolean;
|
|
90
|
+
/** Does it pass through the write fence? Printed in `--help`, not enforced here. */
|
|
91
|
+
readonly fenced: boolean;
|
|
92
|
+
readonly write: boolean;
|
|
93
|
+
/** The MCP tool name, or `false` with a mandatory `because`. */
|
|
94
|
+
readonly mcp: string | false;
|
|
95
|
+
readonly because?: string;
|
|
96
|
+
readonly args: readonly ArgSpec[];
|
|
97
|
+
readonly flags: readonly FlagSpec[];
|
|
98
|
+
/** Reads a stream rather than a JSON body. Exactly one op does. */
|
|
99
|
+
readonly streams?: true;
|
|
100
|
+
}
|
|
101
|
+
export declare const TEAM_OPS: readonly TeamOp[];
|
|
102
|
+
export declare class TeamOpError extends Error {
|
|
103
|
+
}
|
|
104
|
+
/** Every `{placeholder}` this op's path expects. */
|
|
105
|
+
export declare function pathPlaceholders(op: TeamOp): string[];
|
|
106
|
+
/**
|
|
107
|
+
* Fill the path. Every value is `encodeURIComponent`'d — a team name or a card id
|
|
108
|
+
* that contains a slash must not be able to reach a different route, and an
|
|
109
|
+
* absent value is an error rather than the literal string "undefined" in a URL.
|
|
110
|
+
*/
|
|
111
|
+
export declare function buildPath(op: TeamOp, values: Readonly<Record<string, string | undefined>>): string;
|
|
112
|
+
/** The query string, including its leading `?`, or `""`. */
|
|
113
|
+
export declare function buildQuery(op: TeamOp, opts: Readonly<Record<string, unknown>>): string;
|
|
114
|
+
/**
|
|
115
|
+
* The request body: positional args declared `in: "body"`, then flags declared
|
|
116
|
+
* `in: "body"`. A GET has no body at all — a GET that carries one is a request
|
|
117
|
+
* some proxy will strip and some server will ignore, which is a silent wrong
|
|
118
|
+
* answer rather than an error.
|
|
119
|
+
*/
|
|
120
|
+
export declare function buildBody(op: TeamOp, args: Readonly<Record<string, unknown>>, opts: Readonly<Record<string, unknown>>): Record<string, unknown> | undefined;
|
|
121
|
+
/**
|
|
122
|
+
* The mutually exclusive selector groups on this op, keyed by the wire field
|
|
123
|
+
* they share. DERIVED from the flags rather than listed, so a third member added
|
|
124
|
+
* to a group joins the exclusion without anyone remembering to widen a list.
|
|
125
|
+
*/
|
|
126
|
+
export declare function selectorGroups(op: TeamOp): Map<string, FlagSpec[]>;
|
|
127
|
+
/**
|
|
128
|
+
* Refuse an ambiguous or absent decision BEFORE the request leaves the process.
|
|
129
|
+
*
|
|
130
|
+
* A selector group is a CHOICE: exactly one member must be given. Neither branch
|
|
131
|
+
* can be left to the server. `--allow --deny` would otherwise resolve by flag
|
|
132
|
+
* order in this file — an approval decided by declaration order — and giving
|
|
133
|
+
* neither would send a body with no `decision`, which `settle` (whose openapi
|
|
134
|
+
* marks nothing required) would accept as a well-formed request that settles an
|
|
135
|
+
* effect no particular way.
|
|
136
|
+
*/
|
|
137
|
+
export declare function assertSelectors(op: TeamOp, opts: Readonly<Record<string, unknown>>): void;
|
|
138
|
+
/** `failOnTerminal` -> `fail_on_terminal`. Flags are camelCase in commander and
|
|
139
|
+
* snake_case on this API's wire; converting in one place keeps the two apart. */
|
|
140
|
+
export declare function snake(key: string): string;
|
|
141
|
+
export declare function findOp(cli: string): TeamOp | undefined;
|