@primitivedotdev/cli 0.31.1 → 0.31.3
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 +9 -2
- package/dist/oclif/index.js +1986 -690
- package/package.json +7 -1
package/dist/oclif/index.js
CHANGED
|
@@ -667,11 +667,13 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
|
667
667
|
replayDelivery: () => replayDelivery,
|
|
668
668
|
replayEmailWebhooks: () => replayEmailWebhooks,
|
|
669
669
|
replyToEmail: () => replyToEmail,
|
|
670
|
+
resendAgentSignupVerification: () => resendAgentSignupVerification,
|
|
670
671
|
resendCliSignupVerification: () => resendCliSignupVerification,
|
|
671
672
|
rotateWebhookSecret: () => rotateWebhookSecret,
|
|
672
673
|
searchEmails: () => searchEmails,
|
|
673
674
|
sendEmail: () => sendEmail,
|
|
674
675
|
setFunctionSecret: () => setFunctionSecret,
|
|
676
|
+
startAgentSignup: () => startAgentSignup,
|
|
675
677
|
startCliLogin: () => startCliLogin,
|
|
676
678
|
startCliSignup: () => startCliSignup,
|
|
677
679
|
testEndpoint: () => testEndpoint,
|
|
@@ -681,6 +683,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
|
681
683
|
updateEndpoint: () => updateEndpoint,
|
|
682
684
|
updateFilter: () => updateFilter,
|
|
683
685
|
updateFunction: () => updateFunction,
|
|
686
|
+
verifyAgentSignup: () => verifyAgentSignup,
|
|
684
687
|
verifyCliSignup: () => verifyCliSignup,
|
|
685
688
|
verifyDomain: () => verifyDomain
|
|
686
689
|
});
|
|
@@ -704,8 +707,8 @@ const startCliLogin = (options) => (options?.client ?? client).post({
|
|
|
704
707
|
* Poll CLI browser login
|
|
705
708
|
*
|
|
706
709
|
* Polls a CLI login session until the browser approval either succeeds,
|
|
707
|
-
* is denied, expires, or is polled too quickly. The
|
|
708
|
-
* only after approval and is returned exactly once.
|
|
710
|
+
* is denied, expires, or is polled too quickly. The OAuth token set is
|
|
711
|
+
* created only after approval and is returned exactly once.
|
|
709
712
|
*
|
|
710
713
|
*/
|
|
711
714
|
const pollCliLogin = (options) => (options.client ?? client).post({
|
|
@@ -749,11 +752,12 @@ const resendCliSignupVerification = (options) => (options.client ?? client).post
|
|
|
749
752
|
}
|
|
750
753
|
});
|
|
751
754
|
/**
|
|
752
|
-
* Verify CLI signup and create
|
|
755
|
+
* Verify CLI signup and create OAuth session
|
|
753
756
|
*
|
|
754
757
|
* Verifies the email code for a CLI signup session, creates the account,
|
|
755
|
-
* redeems the reserved signup code,
|
|
756
|
-
* returns the
|
|
758
|
+
* redeems the reserved signup code, creates an org-scoped OAuth CLI
|
|
759
|
+
* session, and returns the token set exactly once. This endpoint does not
|
|
760
|
+
* require an API key.
|
|
757
761
|
*
|
|
758
762
|
*/
|
|
759
763
|
const verifyCliSignup = (options) => (options.client ?? client).post({
|
|
@@ -765,10 +769,61 @@ const verifyCliSignup = (options) => (options.client ?? client).post({
|
|
|
765
769
|
}
|
|
766
770
|
});
|
|
767
771
|
/**
|
|
768
|
-
*
|
|
772
|
+
* Start agent account signup
|
|
769
773
|
*
|
|
770
|
-
*
|
|
771
|
-
*
|
|
774
|
+
* Starts an agent-native signup session. The API validates the signup code,
|
|
775
|
+
* creates a pending signup session, sends an email verification code, and
|
|
776
|
+
* returns an opaque signup token used by the resend and verify steps. This
|
|
777
|
+
* endpoint does not require an API key.
|
|
778
|
+
*
|
|
779
|
+
*/
|
|
780
|
+
const startAgentSignup = (options) => (options.client ?? client).post({
|
|
781
|
+
url: "/agent/signup/start",
|
|
782
|
+
...options,
|
|
783
|
+
headers: {
|
|
784
|
+
...options.body !== void 0 && { "Content-Type": "application/json" },
|
|
785
|
+
...options.headers
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
/**
|
|
789
|
+
* Resend agent signup verification code
|
|
790
|
+
*
|
|
791
|
+
* Sends a new email verification code for a pending agent signup session.
|
|
792
|
+
* This endpoint does not require an API key.
|
|
793
|
+
*
|
|
794
|
+
*/
|
|
795
|
+
const resendAgentSignupVerification = (options) => (options.client ?? client).post({
|
|
796
|
+
url: "/agent/signup/resend",
|
|
797
|
+
...options,
|
|
798
|
+
headers: {
|
|
799
|
+
...options.body !== void 0 && { "Content-Type": "application/json" },
|
|
800
|
+
...options.headers
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
/**
|
|
804
|
+
* Verify agent signup and create OAuth tokens
|
|
805
|
+
*
|
|
806
|
+
* Verifies the email code for an agent signup session, creates the account
|
|
807
|
+
* when needed, redeems the reserved signup code, mints an org-scoped OAuth
|
|
808
|
+
* session for CLI authentication, and returns the raw tokens exactly once.
|
|
809
|
+
* For existing users, the optional `org_id` selects which accessible
|
|
810
|
+
* workspace should receive the new session.
|
|
811
|
+
*
|
|
812
|
+
*/
|
|
813
|
+
const verifyAgentSignup = (options) => (options.client ?? client).post({
|
|
814
|
+
url: "/agent/signup/verify",
|
|
815
|
+
...options,
|
|
816
|
+
headers: {
|
|
817
|
+
...options.body !== void 0 && { "Content-Type": "application/json" },
|
|
818
|
+
...options.headers
|
|
819
|
+
}
|
|
820
|
+
});
|
|
821
|
+
/**
|
|
822
|
+
* Revoke the current CLI OAuth session
|
|
823
|
+
*
|
|
824
|
+
* Revokes the OAuth grant used to authenticate the request. API-key
|
|
825
|
+
* authenticated legacy logout requests succeed without deleting server API
|
|
826
|
+
* keys so old local CLI state can be cleared safely.
|
|
772
827
|
*
|
|
773
828
|
*/
|
|
774
829
|
const cliLogout = (options) => (options?.client ?? client).post({
|
|
@@ -1778,7 +1833,7 @@ const openapiDocument = {
|
|
|
1778
1833
|
"info": {
|
|
1779
1834
|
"title": "Primitive API",
|
|
1780
1835
|
"version": "1.0.0",
|
|
1781
|
-
"description": "The Primitive API lets you manage domains, emails, webhook endpoints,\nfilters, and account settings programmatically.\n\n## Authentication\n\nMost endpoints require a Bearer token in the `Authorization` header:\n\n```\nAuthorization: Bearer prim_<your_api_key>\n```\n\nAPI keys are org-scoped. Create and manage them in your dashboard\nunder Settings > API Keys. CLI login
|
|
1836
|
+
"description": "The Primitive API lets you manage domains, emails, webhook endpoints,\nfilters, and account settings programmatically.\n\n## Authentication\n\nMost endpoints require a Bearer token in the `Authorization` header:\n\n```\nAuthorization: Bearer prim_<your_api_key>\n```\n\nAPI keys are org-scoped. Create and manage them in your dashboard\nunder Settings > API Keys. CLI login plus CLI/agent signup endpoints\nexplicitly declare `security: []`; they do not require an API key because\nthey are used to create OAuth CLI sessions.\n\n## Rate Limiting\n\nThe API enforces a sliding window rate limit of **120 requests per\n60 seconds** per organization. When exceeded, the API returns `429`\nwith a `Retry-After` header indicating how many seconds to wait.\n\n## Pagination\n\nList endpoints use cursor-based pagination. Responses include a\n`meta` object with `total`, `limit`, and `cursor` fields. Pass the\n`cursor` value as a query parameter to fetch the next page. When\n`cursor` is `null`, there are no more results.\n\n## Response Format\n\nAll responses use a consistent envelope:\n\n```json\n{\n \"success\": true,\n \"data\": { ... },\n \"meta\": { \"total\": 42, \"limit\": 50, \"cursor\": \"...\" }\n}\n```\n\nErrors follow the same pattern:\n\n```json\n{\n \"success\": false,\n \"error\": { \"code\": \"not_found\", \"message\": \"Email not found\" }\n}\n```\n\n## Webhook signing\n\nOutbound webhook deliveries (configured via the `endpoints` API)\nare signed so receivers can verify they came from Primitive and\nhave not been tampered with in transit. The signing scheme is\ndeliberately simple so it can be reimplemented in any language\nin a few lines. The Node SDK's `verifyWebhookSignature` helper\nis the reference implementation; the wire details below let you\nwrite a verifier in Python, Go, Ruby, etc. without reading our\nsource.\n\n**Header**: `Primitive-Signature: t=<unix-seconds>,v1=<hex>`\n\nA legacy `MyMX-Signature` header is also sent on every delivery\nwith the same value, retained for back-compatibility with\nintegrations written before the rename. New code should read\n`Primitive-Signature`.\n\n**Signed string**: `${timestamp}.${rawBody}` where `timestamp`\nis the Unix-seconds integer from the `t=` parameter and\n`rawBody` is the exact bytes of the HTTP request body BEFORE\nany JSON decoding. Verify against the raw body, not a\nre-serialized parse, or you will silently mismatch on\ninsignificant whitespace.\n\n**Signature**: HMAC-SHA256 of the signed string, hex-encoded\n(lowercase). Use the account's webhook secret as the HMAC key,\nas a UTF-8 byte sequence.\n\n**Secret**: returned by `GET /account/webhook-secret`. The\nstring looks base64-shaped (e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`)\nbut is NOT base64; use it AS-IS as a UTF-8 string for the HMAC\nkey. Base64-decoding before HMAC will silently produce\nmismatched signatures.\n\n**Tolerance**: by convention, reject deliveries whose `t=`\ntimestamp is more than 5 minutes off your wall-clock to defend\nagainst replay attacks. The Node SDK's helper enforces this by\ndefault.\n\n**Verification recipe** (any language):\n\n```\n1. Read the raw HTTP body (do not parse).\n2. Read `Primitive-Signature: t=<ts>,v1=<sig>`.\n3. Reject if abs(now - ts) > 300 seconds.\n4. expected = HMAC_SHA256_hex(secret_utf8, f\"{ts}.{rawBody}\")\n5. Constant-time compare expected to sig. Reject if not equal.\n```\n\nFor Node, use `verifyWebhookSignature` from\n`@primitivedotdev/sdk/webhook` (or the higher-level\n`handleWebhook` helper if you want a one-liner). For other\nlanguages, the recipe above is everything you need.\n\nTest deliveries: `POST /endpoints/{id}/test` triggers a fake\ndelivery to your endpoint URL, signed with your real account\nsecret, so you can confirm verification end-to-end without\nneeding real inbound mail. The test response carries the exact\n`signature` header value sent on the wire so you can compare\nstrings directly.\n",
|
|
1782
1837
|
"contact": {
|
|
1783
1838
|
"name": "Primitive",
|
|
1784
1839
|
"url": "https://primitive.dev"
|
|
@@ -1801,6 +1856,10 @@ const openapiDocument = {
|
|
|
1801
1856
|
"name": "CLI",
|
|
1802
1857
|
"description": "Browser-assisted CLI authentication"
|
|
1803
1858
|
},
|
|
1859
|
+
{
|
|
1860
|
+
"name": "Agent",
|
|
1861
|
+
"description": "Agent signup and authentication"
|
|
1862
|
+
},
|
|
1804
1863
|
{
|
|
1805
1864
|
"name": "Account",
|
|
1806
1865
|
"description": "Manage your account settings, storage, and webhook secret"
|
|
@@ -1864,7 +1923,7 @@ const openapiDocument = {
|
|
|
1864
1923
|
"/cli/login/poll": { "post": {
|
|
1865
1924
|
"operationId": "pollCliLogin",
|
|
1866
1925
|
"summary": "Poll CLI browser login",
|
|
1867
|
-
"description": "Polls a CLI login session until the browser approval either succeeds,\nis denied, expires, or is polled too quickly. The
|
|
1926
|
+
"description": "Polls a CLI login session until the browser approval either succeeds,\nis denied, expires, or is polled too quickly. The OAuth token set is\ncreated only after approval and is returned exactly once.\n",
|
|
1868
1927
|
"tags": ["CLI"],
|
|
1869
1928
|
"security": [],
|
|
1870
1929
|
"requestBody": {
|
|
@@ -1873,7 +1932,7 @@ const openapiDocument = {
|
|
|
1873
1932
|
},
|
|
1874
1933
|
"responses": {
|
|
1875
1934
|
"200": {
|
|
1876
|
-
"description": "CLI login approved and
|
|
1935
|
+
"description": "CLI login approved and OAuth token set created",
|
|
1877
1936
|
"headers": { "Cache-Control": {
|
|
1878
1937
|
"schema": { "type": "string" },
|
|
1879
1938
|
"description": "Always `no-store`"
|
|
@@ -2014,8 +2073,8 @@ const openapiDocument = {
|
|
|
2014
2073
|
} },
|
|
2015
2074
|
"/cli/signup/verify": { "post": {
|
|
2016
2075
|
"operationId": "verifyCliSignup",
|
|
2017
|
-
"summary": "Verify CLI signup and create
|
|
2018
|
-
"description": "Verifies the email code for a CLI signup session, creates the account,\nredeems the reserved signup code,
|
|
2076
|
+
"summary": "Verify CLI signup and create OAuth session",
|
|
2077
|
+
"description": "Verifies the email code for a CLI signup session, creates the account,\nredeems the reserved signup code, creates an org-scoped OAuth CLI\nsession, and returns the token set exactly once. This endpoint does not\nrequire an API key.\n",
|
|
2019
2078
|
"tags": ["CLI"],
|
|
2020
2079
|
"security": [],
|
|
2021
2080
|
"requestBody": {
|
|
@@ -2024,7 +2083,7 @@ const openapiDocument = {
|
|
|
2024
2083
|
},
|
|
2025
2084
|
"responses": {
|
|
2026
2085
|
"200": {
|
|
2027
|
-
"description": "CLI signup verified and
|
|
2086
|
+
"description": "CLI signup verified and OAuth token set created",
|
|
2028
2087
|
"headers": { "Cache-Control": {
|
|
2029
2088
|
"schema": { "type": "string" },
|
|
2030
2089
|
"description": "Always `no-store`"
|
|
@@ -2041,10 +2100,106 @@ const openapiDocument = {
|
|
|
2041
2100
|
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2042
2101
|
}
|
|
2043
2102
|
} },
|
|
2103
|
+
"/agent/signup/start": { "post": {
|
|
2104
|
+
"operationId": "startAgentSignup",
|
|
2105
|
+
"summary": "Start agent account signup",
|
|
2106
|
+
"description": "Starts an agent-native signup session. The API validates the signup code,\ncreates a pending signup session, sends an email verification code, and\nreturns an opaque signup token used by the resend and verify steps. This\nendpoint does not require an API key.\n",
|
|
2107
|
+
"tags": ["Agent"],
|
|
2108
|
+
"security": [],
|
|
2109
|
+
"requestBody": {
|
|
2110
|
+
"required": true,
|
|
2111
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/StartAgentSignupInput" } } }
|
|
2112
|
+
},
|
|
2113
|
+
"responses": {
|
|
2114
|
+
"201": {
|
|
2115
|
+
"description": "Agent signup session created and verification email sent",
|
|
2116
|
+
"headers": { "Cache-Control": {
|
|
2117
|
+
"schema": { "type": "string" },
|
|
2118
|
+
"description": "Always `no-store`"
|
|
2119
|
+
} },
|
|
2120
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2121
|
+
"type": "object",
|
|
2122
|
+
"properties": { "data": { "$ref": "#/components/schemas/AgentSignupStartResult" } }
|
|
2123
|
+
}] } } }
|
|
2124
|
+
},
|
|
2125
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
2126
|
+
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2127
|
+
}
|
|
2128
|
+
} },
|
|
2129
|
+
"/agent/signup/resend": { "post": {
|
|
2130
|
+
"operationId": "resendAgentSignupVerification",
|
|
2131
|
+
"summary": "Resend agent signup verification code",
|
|
2132
|
+
"description": "Sends a new email verification code for a pending agent signup session.\nThis endpoint does not require an API key.\n",
|
|
2133
|
+
"tags": ["Agent"],
|
|
2134
|
+
"security": [],
|
|
2135
|
+
"requestBody": {
|
|
2136
|
+
"required": true,
|
|
2137
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResendAgentSignupVerificationInput" } } }
|
|
2138
|
+
},
|
|
2139
|
+
"responses": {
|
|
2140
|
+
"200": {
|
|
2141
|
+
"description": "Verification email resent",
|
|
2142
|
+
"headers": { "Cache-Control": {
|
|
2143
|
+
"schema": { "type": "string" },
|
|
2144
|
+
"description": "Always `no-store`"
|
|
2145
|
+
} },
|
|
2146
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2147
|
+
"type": "object",
|
|
2148
|
+
"properties": { "data": { "$ref": "#/components/schemas/AgentSignupResendResult" } }
|
|
2149
|
+
}] } } }
|
|
2150
|
+
},
|
|
2151
|
+
"400": {
|
|
2152
|
+
"description": "Invalid token or expired token",
|
|
2153
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
|
|
2154
|
+
},
|
|
2155
|
+
"429": {
|
|
2156
|
+
"description": "Global rate limit exceeded or resend requested too quickly",
|
|
2157
|
+
"headers": { "Retry-After": {
|
|
2158
|
+
"schema": { "type": "integer" },
|
|
2159
|
+
"description": "Seconds to wait before retrying"
|
|
2160
|
+
} },
|
|
2161
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
} },
|
|
2165
|
+
"/agent/signup/verify": { "post": {
|
|
2166
|
+
"operationId": "verifyAgentSignup",
|
|
2167
|
+
"summary": "Verify agent signup and create OAuth tokens",
|
|
2168
|
+
"description": "Verifies the email code for an agent signup session, creates the account\nwhen needed, redeems the reserved signup code, mints an org-scoped OAuth\nsession for CLI authentication, and returns the raw tokens exactly once.\nFor existing users, the optional `org_id` selects which accessible\nworkspace should receive the new session.\n",
|
|
2169
|
+
"tags": ["Agent"],
|
|
2170
|
+
"security": [],
|
|
2171
|
+
"requestBody": {
|
|
2172
|
+
"required": true,
|
|
2173
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/VerifyAgentSignupInput" } } }
|
|
2174
|
+
},
|
|
2175
|
+
"responses": {
|
|
2176
|
+
"200": {
|
|
2177
|
+
"description": "Agent signup verified and OAuth tokens created",
|
|
2178
|
+
"headers": { "Cache-Control": {
|
|
2179
|
+
"schema": { "type": "string" },
|
|
2180
|
+
"description": "Always `no-store`"
|
|
2181
|
+
} },
|
|
2182
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2183
|
+
"type": "object",
|
|
2184
|
+
"properties": { "data": { "$ref": "#/components/schemas/AgentSignupVerifyResult" } }
|
|
2185
|
+
}] } } }
|
|
2186
|
+
},
|
|
2187
|
+
"400": {
|
|
2188
|
+
"description": "Invalid request, invalid verification code, expired token, invalid signup code, or account creation failure",
|
|
2189
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
|
|
2190
|
+
},
|
|
2191
|
+
"403": { "$ref": "#/components/responses/Forbidden" },
|
|
2192
|
+
"409": {
|
|
2193
|
+
"description": "Existing account is not in a usable workspace state",
|
|
2194
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
|
|
2195
|
+
},
|
|
2196
|
+
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2197
|
+
}
|
|
2198
|
+
} },
|
|
2044
2199
|
"/cli/logout": { "post": {
|
|
2045
2200
|
"operationId": "cliLogout",
|
|
2046
|
-
"summary": "Revoke the current CLI
|
|
2047
|
-
"description": "Revokes the
|
|
2201
|
+
"summary": "Revoke the current CLI OAuth session",
|
|
2202
|
+
"description": "Revokes the OAuth grant used to authenticate the request. API-key\nauthenticated legacy logout requests succeed without deleting server API\nkeys so old local CLI state can be cleared safely.\n",
|
|
2048
2203
|
"tags": ["CLI"],
|
|
2049
2204
|
"requestBody": {
|
|
2050
2205
|
"required": false,
|
|
@@ -2052,7 +2207,7 @@ const openapiDocument = {
|
|
|
2052
2207
|
},
|
|
2053
2208
|
"responses": {
|
|
2054
2209
|
"200": {
|
|
2055
|
-
"description": "CLI
|
|
2210
|
+
"description": "CLI logout completed",
|
|
2056
2211
|
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2057
2212
|
"type": "object",
|
|
2058
2213
|
"properties": { "data": { "$ref": "#/components/schemas/CliLogoutResult" } }
|
|
@@ -3780,7 +3935,14 @@ const openapiDocument = {
|
|
|
3780
3935
|
"slow_down",
|
|
3781
3936
|
"access_denied",
|
|
3782
3937
|
"expired_token",
|
|
3783
|
-
"invalid_device_code"
|
|
3938
|
+
"invalid_device_code",
|
|
3939
|
+
"invalid_signup_code",
|
|
3940
|
+
"invalid_signup_token",
|
|
3941
|
+
"invalid_verification_code",
|
|
3942
|
+
"email_delivery_failed",
|
|
3943
|
+
"clerk_signup_failed",
|
|
3944
|
+
"no_orgs_for_user",
|
|
3945
|
+
"org_not_accessible"
|
|
3784
3946
|
]
|
|
3785
3947
|
},
|
|
3786
3948
|
"message": { "type": "string" },
|
|
@@ -3964,13 +4126,42 @@ const openapiDocument = {
|
|
|
3964
4126
|
"properties": {
|
|
3965
4127
|
"api_key": {
|
|
3966
4128
|
"type": "string",
|
|
3967
|
-
"description": "
|
|
4129
|
+
"description": "Legacy alias for access_token. New CLI builds should persist access_token and refresh_token."
|
|
3968
4130
|
},
|
|
3969
4131
|
"key_id": {
|
|
4132
|
+
"type": "string",
|
|
4133
|
+
"format": "uuid",
|
|
4134
|
+
"description": "Legacy alias for oauth_grant_id"
|
|
4135
|
+
},
|
|
4136
|
+
"key_prefix": {
|
|
4137
|
+
"type": "string",
|
|
4138
|
+
"description": "Legacy display prefix derived from access_token"
|
|
4139
|
+
},
|
|
4140
|
+
"access_token": {
|
|
4141
|
+
"type": "string",
|
|
4142
|
+
"description": "OAuth access token for CLI API authentication"
|
|
4143
|
+
},
|
|
4144
|
+
"refresh_token": {
|
|
4145
|
+
"type": "string",
|
|
4146
|
+
"description": "OAuth refresh token used by the CLI to renew access"
|
|
4147
|
+
},
|
|
4148
|
+
"token_type": {
|
|
4149
|
+
"type": "string",
|
|
4150
|
+
"enum": ["Bearer"]
|
|
4151
|
+
},
|
|
4152
|
+
"expires_in": {
|
|
4153
|
+
"type": "integer",
|
|
4154
|
+
"description": "Seconds until access_token expires"
|
|
4155
|
+
},
|
|
4156
|
+
"auth_method": {
|
|
4157
|
+
"type": "string",
|
|
4158
|
+
"enum": ["oauth"]
|
|
4159
|
+
},
|
|
4160
|
+
"oauth_grant_id": {
|
|
3970
4161
|
"type": "string",
|
|
3971
4162
|
"format": "uuid"
|
|
3972
4163
|
},
|
|
3973
|
-
"
|
|
4164
|
+
"oauth_client_id": { "type": "string" },
|
|
3974
4165
|
"org_id": {
|
|
3975
4166
|
"type": "string",
|
|
3976
4167
|
"format": "uuid"
|
|
@@ -3981,6 +4172,13 @@ const openapiDocument = {
|
|
|
3981
4172
|
"api_key",
|
|
3982
4173
|
"key_id",
|
|
3983
4174
|
"key_prefix",
|
|
4175
|
+
"access_token",
|
|
4176
|
+
"refresh_token",
|
|
4177
|
+
"token_type",
|
|
4178
|
+
"expires_in",
|
|
4179
|
+
"auth_method",
|
|
4180
|
+
"oauth_grant_id",
|
|
4181
|
+
"oauth_client_id",
|
|
3984
4182
|
"org_id",
|
|
3985
4183
|
"org_name"
|
|
3986
4184
|
]
|
|
@@ -4008,7 +4206,7 @@ const openapiDocument = {
|
|
|
4008
4206
|
"type": "string",
|
|
4009
4207
|
"minLength": 1,
|
|
4010
4208
|
"maxLength": 80,
|
|
4011
|
-
"description": "Human-readable device name used for the created CLI
|
|
4209
|
+
"description": "Human-readable device name used for the created CLI OAuth grant"
|
|
4012
4210
|
},
|
|
4013
4211
|
"metadata": {
|
|
4014
4212
|
"type": "object",
|
|
@@ -4109,24 +4307,49 @@ const openapiDocument = {
|
|
|
4109
4307
|
"maxLength": 1024
|
|
4110
4308
|
}
|
|
4111
4309
|
},
|
|
4112
|
-
"required": [
|
|
4113
|
-
"signup_token",
|
|
4114
|
-
"verification_code",
|
|
4115
|
-
"password"
|
|
4116
|
-
]
|
|
4310
|
+
"required": ["signup_token", "verification_code"]
|
|
4117
4311
|
},
|
|
4118
4312
|
"CliSignupVerifyResult": {
|
|
4119
4313
|
"type": "object",
|
|
4120
4314
|
"properties": {
|
|
4121
4315
|
"api_key": {
|
|
4122
4316
|
"type": "string",
|
|
4123
|
-
"description": "
|
|
4317
|
+
"description": "Legacy alias for access_token. New CLI builds should persist access_token and refresh_token."
|
|
4124
4318
|
},
|
|
4125
4319
|
"key_id": {
|
|
4320
|
+
"type": "string",
|
|
4321
|
+
"format": "uuid",
|
|
4322
|
+
"description": "Legacy alias for oauth_grant_id"
|
|
4323
|
+
},
|
|
4324
|
+
"key_prefix": {
|
|
4325
|
+
"type": "string",
|
|
4326
|
+
"description": "Legacy display prefix derived from access_token"
|
|
4327
|
+
},
|
|
4328
|
+
"access_token": {
|
|
4329
|
+
"type": "string",
|
|
4330
|
+
"description": "OAuth access token for CLI API authentication"
|
|
4331
|
+
},
|
|
4332
|
+
"refresh_token": {
|
|
4333
|
+
"type": "string",
|
|
4334
|
+
"description": "OAuth refresh token used by the CLI to renew access"
|
|
4335
|
+
},
|
|
4336
|
+
"token_type": {
|
|
4337
|
+
"type": "string",
|
|
4338
|
+
"enum": ["Bearer"]
|
|
4339
|
+
},
|
|
4340
|
+
"expires_in": {
|
|
4341
|
+
"type": "integer",
|
|
4342
|
+
"description": "Seconds until access_token expires"
|
|
4343
|
+
},
|
|
4344
|
+
"auth_method": {
|
|
4345
|
+
"type": "string",
|
|
4346
|
+
"enum": ["oauth"]
|
|
4347
|
+
},
|
|
4348
|
+
"oauth_grant_id": {
|
|
4126
4349
|
"type": "string",
|
|
4127
4350
|
"format": "uuid"
|
|
4128
4351
|
},
|
|
4129
|
-
"
|
|
4352
|
+
"oauth_client_id": { "type": "string" },
|
|
4130
4353
|
"org_id": {
|
|
4131
4354
|
"type": "string",
|
|
4132
4355
|
"format": "uuid"
|
|
@@ -4137,93 +4360,311 @@ const openapiDocument = {
|
|
|
4137
4360
|
"api_key",
|
|
4138
4361
|
"key_id",
|
|
4139
4362
|
"key_prefix",
|
|
4363
|
+
"access_token",
|
|
4364
|
+
"refresh_token",
|
|
4365
|
+
"token_type",
|
|
4366
|
+
"expires_in",
|
|
4367
|
+
"auth_method",
|
|
4368
|
+
"oauth_grant_id",
|
|
4369
|
+
"oauth_client_id",
|
|
4140
4370
|
"org_id",
|
|
4141
4371
|
"org_name"
|
|
4142
4372
|
]
|
|
4143
4373
|
},
|
|
4144
|
-
"
|
|
4374
|
+
"StartAgentSignupInput": {
|
|
4145
4375
|
"type": "object",
|
|
4146
4376
|
"additionalProperties": false,
|
|
4147
|
-
"properties": { "key_id": {
|
|
4148
|
-
"type": "string",
|
|
4149
|
-
"format": "uuid",
|
|
4150
|
-
"description": "Optional key id guard; when provided it must match the authenticated API key"
|
|
4151
|
-
} }
|
|
4152
|
-
},
|
|
4153
|
-
"CliLogoutResult": {
|
|
4154
|
-
"type": "object",
|
|
4155
4377
|
"properties": {
|
|
4156
|
-
"
|
|
4378
|
+
"email": {
|
|
4379
|
+
"type": "string",
|
|
4380
|
+
"format": "email",
|
|
4381
|
+
"maxLength": 254
|
|
4382
|
+
},
|
|
4383
|
+
"signup_code": {
|
|
4384
|
+
"type": "string",
|
|
4385
|
+
"minLength": 1,
|
|
4386
|
+
"maxLength": 128
|
|
4387
|
+
},
|
|
4388
|
+
"terms_accepted": {
|
|
4157
4389
|
"type": "boolean",
|
|
4158
|
-
"const": true
|
|
4390
|
+
"const": true,
|
|
4391
|
+
"description": "Must be true to confirm acceptance of Primitive's Terms of Service and Privacy Policy"
|
|
4159
4392
|
},
|
|
4160
|
-
"
|
|
4393
|
+
"device_name": {
|
|
4161
4394
|
"type": "string",
|
|
4162
|
-
"
|
|
4395
|
+
"minLength": 1,
|
|
4396
|
+
"maxLength": 80,
|
|
4397
|
+
"description": "Human-readable device name used for the created agent OAuth session"
|
|
4398
|
+
},
|
|
4399
|
+
"metadata": {
|
|
4400
|
+
"type": "object",
|
|
4401
|
+
"additionalProperties": true,
|
|
4402
|
+
"description": "Optional client metadata stored with the signup session; serialized JSON must be 2048 bytes or fewer"
|
|
4163
4403
|
}
|
|
4164
4404
|
},
|
|
4165
|
-
"required": [
|
|
4405
|
+
"required": [
|
|
4406
|
+
"email",
|
|
4407
|
+
"signup_code",
|
|
4408
|
+
"terms_accepted"
|
|
4409
|
+
]
|
|
4166
4410
|
},
|
|
4167
|
-
"
|
|
4411
|
+
"AgentSignupStartResult": {
|
|
4168
4412
|
"type": "object",
|
|
4169
4413
|
"properties": {
|
|
4170
|
-
"
|
|
4414
|
+
"signup_token": {
|
|
4171
4415
|
"type": "string",
|
|
4172
|
-
"
|
|
4416
|
+
"description": "Opaque token used to verify or resend the pending agent signup"
|
|
4173
4417
|
},
|
|
4174
|
-
"email": {
|
|
4175
|
-
"plan": { "type": "string" },
|
|
4176
|
-
"created_at": {
|
|
4418
|
+
"email": {
|
|
4177
4419
|
"type": "string",
|
|
4178
|
-
"format": "
|
|
4420
|
+
"format": "email"
|
|
4179
4421
|
},
|
|
4180
|
-
"
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
"subscription_current_period_end": {
|
|
4184
|
-
"type": ["string", "null"],
|
|
4185
|
-
"format": "date-time"
|
|
4422
|
+
"expires_in": {
|
|
4423
|
+
"type": "integer",
|
|
4424
|
+
"description": "Seconds until the pending signup expires"
|
|
4186
4425
|
},
|
|
4187
|
-
"
|
|
4188
|
-
|
|
4189
|
-
"
|
|
4190
|
-
"minimum": 0,
|
|
4191
|
-
"maximum": 15
|
|
4426
|
+
"resend_after": {
|
|
4427
|
+
"type": "integer",
|
|
4428
|
+
"description": "Minimum seconds before requesting another verification email"
|
|
4192
4429
|
},
|
|
4193
|
-
"
|
|
4194
|
-
|
|
4195
|
-
"
|
|
4196
|
-
"format": "date-time"
|
|
4430
|
+
"verification_code_length": {
|
|
4431
|
+
"type": "integer",
|
|
4432
|
+
"description": "Number of digits in the emailed verification code"
|
|
4197
4433
|
}
|
|
4198
4434
|
},
|
|
4199
4435
|
"required": [
|
|
4200
|
-
"
|
|
4436
|
+
"signup_token",
|
|
4201
4437
|
"email",
|
|
4202
|
-
"
|
|
4203
|
-
"
|
|
4204
|
-
"
|
|
4438
|
+
"expires_in",
|
|
4439
|
+
"resend_after",
|
|
4440
|
+
"verification_code_length"
|
|
4205
4441
|
]
|
|
4206
4442
|
},
|
|
4207
|
-
"
|
|
4443
|
+
"ResendAgentSignupVerificationInput": {
|
|
4444
|
+
"type": "object",
|
|
4445
|
+
"additionalProperties": false,
|
|
4446
|
+
"properties": { "signup_token": {
|
|
4447
|
+
"type": "string",
|
|
4448
|
+
"minLength": 1
|
|
4449
|
+
} },
|
|
4450
|
+
"required": ["signup_token"]
|
|
4451
|
+
},
|
|
4452
|
+
"AgentSignupResendResult": {
|
|
4208
4453
|
"type": "object",
|
|
4209
4454
|
"properties": {
|
|
4210
|
-
"
|
|
4455
|
+
"email": {
|
|
4211
4456
|
"type": "string",
|
|
4212
|
-
"format": "
|
|
4457
|
+
"format": "email"
|
|
4213
4458
|
},
|
|
4214
|
-
"
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
"type": ["number", "null"],
|
|
4218
|
-
"minimum": 0,
|
|
4219
|
-
"maximum": 15
|
|
4459
|
+
"expires_in": {
|
|
4460
|
+
"type": "integer",
|
|
4461
|
+
"description": "Seconds until the pending signup expires"
|
|
4220
4462
|
},
|
|
4221
|
-
"
|
|
4463
|
+
"resend_after": {
|
|
4464
|
+
"type": "integer",
|
|
4465
|
+
"description": "Minimum seconds before requesting another verification email"
|
|
4466
|
+
},
|
|
4467
|
+
"verification_code_length": {
|
|
4468
|
+
"type": "integer",
|
|
4469
|
+
"description": "Number of digits in the emailed verification code"
|
|
4470
|
+
}
|
|
4222
4471
|
},
|
|
4223
4472
|
"required": [
|
|
4224
|
-
"id",
|
|
4225
4473
|
"email",
|
|
4226
|
-
"
|
|
4474
|
+
"expires_in",
|
|
4475
|
+
"resend_after",
|
|
4476
|
+
"verification_code_length"
|
|
4477
|
+
]
|
|
4478
|
+
},
|
|
4479
|
+
"VerifyAgentSignupInput": {
|
|
4480
|
+
"type": "object",
|
|
4481
|
+
"additionalProperties": false,
|
|
4482
|
+
"properties": {
|
|
4483
|
+
"signup_token": {
|
|
4484
|
+
"type": "string",
|
|
4485
|
+
"minLength": 1
|
|
4486
|
+
},
|
|
4487
|
+
"verification_code": {
|
|
4488
|
+
"type": "string",
|
|
4489
|
+
"minLength": 1,
|
|
4490
|
+
"maxLength": 32
|
|
4491
|
+
},
|
|
4492
|
+
"org_id": {
|
|
4493
|
+
"type": "string",
|
|
4494
|
+
"format": "uuid",
|
|
4495
|
+
"description": "Optional workspace id to target when the verified email already belongs to multiple workspaces"
|
|
4496
|
+
}
|
|
4497
|
+
},
|
|
4498
|
+
"required": ["signup_token", "verification_code"]
|
|
4499
|
+
},
|
|
4500
|
+
"AgentOrgRef": {
|
|
4501
|
+
"type": "object",
|
|
4502
|
+
"properties": {
|
|
4503
|
+
"id": {
|
|
4504
|
+
"type": "string",
|
|
4505
|
+
"format": "uuid"
|
|
4506
|
+
},
|
|
4507
|
+
"name": { "type": ["string", "null"] }
|
|
4508
|
+
},
|
|
4509
|
+
"required": ["id", "name"]
|
|
4510
|
+
},
|
|
4511
|
+
"AgentSignupVerifyResult": {
|
|
4512
|
+
"type": "object",
|
|
4513
|
+
"properties": {
|
|
4514
|
+
"api_key": {
|
|
4515
|
+
"type": "string",
|
|
4516
|
+
"description": "Legacy alias for access_token. New CLI builds should persist access_token and refresh_token."
|
|
4517
|
+
},
|
|
4518
|
+
"key_id": {
|
|
4519
|
+
"type": "string",
|
|
4520
|
+
"format": "uuid",
|
|
4521
|
+
"description": "Legacy alias for oauth_grant_id"
|
|
4522
|
+
},
|
|
4523
|
+
"key_prefix": {
|
|
4524
|
+
"type": "string",
|
|
4525
|
+
"description": "Legacy display prefix derived from access_token"
|
|
4526
|
+
},
|
|
4527
|
+
"access_token": {
|
|
4528
|
+
"type": "string",
|
|
4529
|
+
"description": "OAuth access token for CLI API authentication"
|
|
4530
|
+
},
|
|
4531
|
+
"refresh_token": {
|
|
4532
|
+
"type": "string",
|
|
4533
|
+
"description": "OAuth refresh token used by the CLI to renew access"
|
|
4534
|
+
},
|
|
4535
|
+
"token_type": {
|
|
4536
|
+
"type": "string",
|
|
4537
|
+
"enum": ["Bearer"]
|
|
4538
|
+
},
|
|
4539
|
+
"expires_in": {
|
|
4540
|
+
"type": "integer",
|
|
4541
|
+
"description": "Seconds until access_token expires"
|
|
4542
|
+
},
|
|
4543
|
+
"auth_method": {
|
|
4544
|
+
"type": "string",
|
|
4545
|
+
"enum": ["oauth"]
|
|
4546
|
+
},
|
|
4547
|
+
"oauth_grant_id": {
|
|
4548
|
+
"type": "string",
|
|
4549
|
+
"format": "uuid"
|
|
4550
|
+
},
|
|
4551
|
+
"oauth_client_id": { "type": "string" },
|
|
4552
|
+
"org_id": {
|
|
4553
|
+
"type": "string",
|
|
4554
|
+
"format": "uuid"
|
|
4555
|
+
},
|
|
4556
|
+
"org_name": { "type": ["string", "null"] },
|
|
4557
|
+
"orgs": {
|
|
4558
|
+
"type": "array",
|
|
4559
|
+
"items": { "$ref": "#/components/schemas/AgentOrgRef" },
|
|
4560
|
+
"description": "Workspaces available to the verified email. The minted session targets `org_id`."
|
|
4561
|
+
}
|
|
4562
|
+
},
|
|
4563
|
+
"required": [
|
|
4564
|
+
"api_key",
|
|
4565
|
+
"key_id",
|
|
4566
|
+
"key_prefix",
|
|
4567
|
+
"access_token",
|
|
4568
|
+
"refresh_token",
|
|
4569
|
+
"token_type",
|
|
4570
|
+
"expires_in",
|
|
4571
|
+
"auth_method",
|
|
4572
|
+
"oauth_grant_id",
|
|
4573
|
+
"oauth_client_id",
|
|
4574
|
+
"org_id",
|
|
4575
|
+
"org_name",
|
|
4576
|
+
"orgs"
|
|
4577
|
+
]
|
|
4578
|
+
},
|
|
4579
|
+
"CliLogoutInput": {
|
|
4580
|
+
"type": "object",
|
|
4581
|
+
"additionalProperties": false,
|
|
4582
|
+
"properties": { "key_id": {
|
|
4583
|
+
"type": "string",
|
|
4584
|
+
"format": "uuid",
|
|
4585
|
+
"description": "Optional id guard; when provided it must match the authenticated OAuth grant id or API key id"
|
|
4586
|
+
} }
|
|
4587
|
+
},
|
|
4588
|
+
"CliLogoutResult": {
|
|
4589
|
+
"type": "object",
|
|
4590
|
+
"properties": {
|
|
4591
|
+
"revoked": {
|
|
4592
|
+
"type": "boolean",
|
|
4593
|
+
"description": "True when an OAuth grant was revoked. False for API-key-authenticated legacy logout, which only clears local CLI state."
|
|
4594
|
+
},
|
|
4595
|
+
"key_id": {
|
|
4596
|
+
"type": "string",
|
|
4597
|
+
"format": "uuid",
|
|
4598
|
+
"description": "API key id for API-key-authenticated legacy logout"
|
|
4599
|
+
},
|
|
4600
|
+
"oauth_grant_id": {
|
|
4601
|
+
"type": "string",
|
|
4602
|
+
"format": "uuid",
|
|
4603
|
+
"description": "OAuth grant id revoked by OAuth-authenticated logout"
|
|
4604
|
+
}
|
|
4605
|
+
},
|
|
4606
|
+
"required": ["revoked"]
|
|
4607
|
+
},
|
|
4608
|
+
"Account": {
|
|
4609
|
+
"type": "object",
|
|
4610
|
+
"properties": {
|
|
4611
|
+
"id": {
|
|
4612
|
+
"type": "string",
|
|
4613
|
+
"format": "uuid"
|
|
4614
|
+
},
|
|
4615
|
+
"email": { "type": "string" },
|
|
4616
|
+
"plan": { "type": "string" },
|
|
4617
|
+
"created_at": {
|
|
4618
|
+
"type": "string",
|
|
4619
|
+
"format": "date-time"
|
|
4620
|
+
},
|
|
4621
|
+
"onboarding_completed": { "type": "boolean" },
|
|
4622
|
+
"onboarding_step": { "type": ["string", "null"] },
|
|
4623
|
+
"stripe_subscription_status": { "type": ["string", "null"] },
|
|
4624
|
+
"subscription_current_period_end": {
|
|
4625
|
+
"type": ["string", "null"],
|
|
4626
|
+
"format": "date-time"
|
|
4627
|
+
},
|
|
4628
|
+
"subscription_cancel_at_period_end": { "type": ["boolean", "null"] },
|
|
4629
|
+
"spam_threshold": {
|
|
4630
|
+
"type": ["number", "null"],
|
|
4631
|
+
"minimum": 0,
|
|
4632
|
+
"maximum": 15
|
|
4633
|
+
},
|
|
4634
|
+
"discard_content_on_webhook_confirmed": { "type": "boolean" },
|
|
4635
|
+
"webhook_secret_rotated_at": {
|
|
4636
|
+
"type": ["string", "null"],
|
|
4637
|
+
"format": "date-time"
|
|
4638
|
+
}
|
|
4639
|
+
},
|
|
4640
|
+
"required": [
|
|
4641
|
+
"id",
|
|
4642
|
+
"email",
|
|
4643
|
+
"plan",
|
|
4644
|
+
"created_at",
|
|
4645
|
+
"discard_content_on_webhook_confirmed"
|
|
4646
|
+
]
|
|
4647
|
+
},
|
|
4648
|
+
"AccountUpdated": {
|
|
4649
|
+
"type": "object",
|
|
4650
|
+
"properties": {
|
|
4651
|
+
"id": {
|
|
4652
|
+
"type": "string",
|
|
4653
|
+
"format": "uuid"
|
|
4654
|
+
},
|
|
4655
|
+
"email": { "type": "string" },
|
|
4656
|
+
"plan": { "type": "string" },
|
|
4657
|
+
"spam_threshold": {
|
|
4658
|
+
"type": ["number", "null"],
|
|
4659
|
+
"minimum": 0,
|
|
4660
|
+
"maximum": 15
|
|
4661
|
+
},
|
|
4662
|
+
"discard_content_on_webhook_confirmed": { "type": "boolean" }
|
|
4663
|
+
},
|
|
4664
|
+
"required": [
|
|
4665
|
+
"id",
|
|
4666
|
+
"email",
|
|
4667
|
+
"plan",
|
|
4227
4668
|
"discard_content_on_webhook_confirmed"
|
|
4228
4669
|
]
|
|
4229
4670
|
},
|
|
@@ -6366,105 +6807,15 @@ const operationManifest = [
|
|
|
6366
6807
|
"tag": "Account",
|
|
6367
6808
|
"tagCommand": "account"
|
|
6368
6809
|
},
|
|
6369
|
-
{
|
|
6370
|
-
"binaryResponse": false,
|
|
6371
|
-
"bodyRequired": false,
|
|
6372
|
-
"command": "cli-logout",
|
|
6373
|
-
"description": "Revokes the API key used to authenticate the request. CLI clients use\nthis endpoint during `primitive logout` before removing local credentials.\n",
|
|
6374
|
-
"hasJsonBody": true,
|
|
6375
|
-
"method": "POST",
|
|
6376
|
-
"operationId": "cliLogout",
|
|
6377
|
-
"path": "/cli/logout",
|
|
6378
|
-
"pathParams": [],
|
|
6379
|
-
"queryParams": [],
|
|
6380
|
-
"requestSchema": {
|
|
6381
|
-
"type": "object",
|
|
6382
|
-
"additionalProperties": false,
|
|
6383
|
-
"properties": { "key_id": {
|
|
6384
|
-
"type": "string",
|
|
6385
|
-
"format": "uuid",
|
|
6386
|
-
"description": "Optional key id guard; when provided it must match the authenticated API key"
|
|
6387
|
-
} }
|
|
6388
|
-
},
|
|
6389
|
-
"responseSchema": {
|
|
6390
|
-
"type": "object",
|
|
6391
|
-
"properties": {
|
|
6392
|
-
"revoked": {
|
|
6393
|
-
"type": "boolean",
|
|
6394
|
-
"const": true
|
|
6395
|
-
},
|
|
6396
|
-
"key_id": {
|
|
6397
|
-
"type": "string",
|
|
6398
|
-
"format": "uuid"
|
|
6399
|
-
}
|
|
6400
|
-
},
|
|
6401
|
-
"required": ["revoked", "key_id"]
|
|
6402
|
-
},
|
|
6403
|
-
"sdkName": "cliLogout",
|
|
6404
|
-
"summary": "Revoke the current CLI API key",
|
|
6405
|
-
"tag": "CLI",
|
|
6406
|
-
"tagCommand": "cli"
|
|
6407
|
-
},
|
|
6408
|
-
{
|
|
6409
|
-
"binaryResponse": false,
|
|
6410
|
-
"bodyRequired": true,
|
|
6411
|
-
"command": "poll-cli-login",
|
|
6412
|
-
"description": "Polls a CLI login session until the browser approval either succeeds,\nis denied, expires, or is polled too quickly. The API key is generated\nonly after approval and is returned exactly once.\n",
|
|
6413
|
-
"hasJsonBody": true,
|
|
6414
|
-
"method": "POST",
|
|
6415
|
-
"operationId": "pollCliLogin",
|
|
6416
|
-
"path": "/cli/login/poll",
|
|
6417
|
-
"pathParams": [],
|
|
6418
|
-
"queryParams": [],
|
|
6419
|
-
"requestSchema": {
|
|
6420
|
-
"type": "object",
|
|
6421
|
-
"additionalProperties": false,
|
|
6422
|
-
"properties": { "device_code": {
|
|
6423
|
-
"type": "string",
|
|
6424
|
-
"minLength": 1
|
|
6425
|
-
} },
|
|
6426
|
-
"required": ["device_code"]
|
|
6427
|
-
},
|
|
6428
|
-
"responseSchema": {
|
|
6429
|
-
"type": "object",
|
|
6430
|
-
"properties": {
|
|
6431
|
-
"api_key": {
|
|
6432
|
-
"type": "string",
|
|
6433
|
-
"description": "Newly-created API key for CLI authentication"
|
|
6434
|
-
},
|
|
6435
|
-
"key_id": {
|
|
6436
|
-
"type": "string",
|
|
6437
|
-
"format": "uuid"
|
|
6438
|
-
},
|
|
6439
|
-
"key_prefix": { "type": "string" },
|
|
6440
|
-
"org_id": {
|
|
6441
|
-
"type": "string",
|
|
6442
|
-
"format": "uuid"
|
|
6443
|
-
},
|
|
6444
|
-
"org_name": { "type": ["string", "null"] }
|
|
6445
|
-
},
|
|
6446
|
-
"required": [
|
|
6447
|
-
"api_key",
|
|
6448
|
-
"key_id",
|
|
6449
|
-
"key_prefix",
|
|
6450
|
-
"org_id",
|
|
6451
|
-
"org_name"
|
|
6452
|
-
]
|
|
6453
|
-
},
|
|
6454
|
-
"sdkName": "pollCliLogin",
|
|
6455
|
-
"summary": "Poll CLI browser login",
|
|
6456
|
-
"tag": "CLI",
|
|
6457
|
-
"tagCommand": "cli"
|
|
6458
|
-
},
|
|
6459
6810
|
{
|
|
6460
6811
|
"binaryResponse": false,
|
|
6461
6812
|
"bodyRequired": true,
|
|
6462
|
-
"command": "resend-
|
|
6463
|
-
"description": "Sends a new email verification code for a pending
|
|
6813
|
+
"command": "resend-agent-signup-verification",
|
|
6814
|
+
"description": "Sends a new email verification code for a pending agent signup session.\nThis endpoint does not require an API key.\n",
|
|
6464
6815
|
"hasJsonBody": true,
|
|
6465
6816
|
"method": "POST",
|
|
6466
|
-
"operationId": "
|
|
6467
|
-
"path": "/
|
|
6817
|
+
"operationId": "resendAgentSignupVerification",
|
|
6818
|
+
"path": "/agent/signup/resend",
|
|
6468
6819
|
"pathParams": [],
|
|
6469
6820
|
"queryParams": [],
|
|
6470
6821
|
"requestSchema": {
|
|
@@ -6503,98 +6854,27 @@ const operationManifest = [
|
|
|
6503
6854
|
"verification_code_length"
|
|
6504
6855
|
]
|
|
6505
6856
|
},
|
|
6506
|
-
"sdkName": "
|
|
6507
|
-
"summary": "Resend
|
|
6508
|
-
"tag": "
|
|
6509
|
-
"tagCommand": "
|
|
6857
|
+
"sdkName": "resendAgentSignupVerification",
|
|
6858
|
+
"summary": "Resend agent signup verification code",
|
|
6859
|
+
"tag": "Agent",
|
|
6860
|
+
"tagCommand": "agent"
|
|
6510
6861
|
},
|
|
6511
6862
|
{
|
|
6512
6863
|
"binaryResponse": false,
|
|
6513
|
-
"bodyRequired":
|
|
6514
|
-
"command": "start-
|
|
6515
|
-
"description": "Starts
|
|
6864
|
+
"bodyRequired": true,
|
|
6865
|
+
"command": "start-agent-signup",
|
|
6866
|
+
"description": "Starts an agent-native signup session. The API validates the signup code,\ncreates a pending signup session, sends an email verification code, and\nreturns an opaque signup token used by the resend and verify steps. This\nendpoint does not require an API key.\n",
|
|
6516
6867
|
"hasJsonBody": true,
|
|
6517
6868
|
"method": "POST",
|
|
6518
|
-
"operationId": "
|
|
6519
|
-
"path": "/
|
|
6869
|
+
"operationId": "startAgentSignup",
|
|
6870
|
+
"path": "/agent/signup/start",
|
|
6520
6871
|
"pathParams": [],
|
|
6521
6872
|
"queryParams": [],
|
|
6522
6873
|
"requestSchema": {
|
|
6523
6874
|
"type": "object",
|
|
6524
6875
|
"additionalProperties": false,
|
|
6525
6876
|
"properties": {
|
|
6526
|
-
"
|
|
6527
|
-
"type": "string",
|
|
6528
|
-
"minLength": 1,
|
|
6529
|
-
"maxLength": 80,
|
|
6530
|
-
"description": "Human-readable device name shown during browser approval"
|
|
6531
|
-
},
|
|
6532
|
-
"metadata": {
|
|
6533
|
-
"type": "object",
|
|
6534
|
-
"additionalProperties": true,
|
|
6535
|
-
"description": "Optional client metadata stored with the login session; serialized JSON must be 2048 bytes or fewer"
|
|
6536
|
-
}
|
|
6537
|
-
}
|
|
6538
|
-
},
|
|
6539
|
-
"responseSchema": {
|
|
6540
|
-
"type": "object",
|
|
6541
|
-
"properties": {
|
|
6542
|
-
"device_code": {
|
|
6543
|
-
"type": "string",
|
|
6544
|
-
"description": "Opaque code used by the CLI to poll for approval"
|
|
6545
|
-
},
|
|
6546
|
-
"user_code": {
|
|
6547
|
-
"type": "string",
|
|
6548
|
-
"pattern": "^[BCDFGHJKLMNPQRSTVWXZ]{4}-[BCDFGHJKLMNPQRSTVWXZ]{4}$",
|
|
6549
|
-
"description": "Short code the user confirms in the browser"
|
|
6550
|
-
},
|
|
6551
|
-
"verification_uri": {
|
|
6552
|
-
"type": "string",
|
|
6553
|
-
"description": "Browser URL where the user approves the login"
|
|
6554
|
-
},
|
|
6555
|
-
"verification_uri_complete": {
|
|
6556
|
-
"type": "string",
|
|
6557
|
-
"description": "Browser URL with the user code prefilled"
|
|
6558
|
-
},
|
|
6559
|
-
"expires_in": {
|
|
6560
|
-
"type": "integer",
|
|
6561
|
-
"description": "Seconds until the login session expires"
|
|
6562
|
-
},
|
|
6563
|
-
"interval": {
|
|
6564
|
-
"type": "integer",
|
|
6565
|
-
"description": "Minimum seconds between poll requests"
|
|
6566
|
-
}
|
|
6567
|
-
},
|
|
6568
|
-
"required": [
|
|
6569
|
-
"device_code",
|
|
6570
|
-
"user_code",
|
|
6571
|
-
"verification_uri",
|
|
6572
|
-
"verification_uri_complete",
|
|
6573
|
-
"expires_in",
|
|
6574
|
-
"interval"
|
|
6575
|
-
]
|
|
6576
|
-
},
|
|
6577
|
-
"sdkName": "startCliLogin",
|
|
6578
|
-
"summary": "Start CLI browser login",
|
|
6579
|
-
"tag": "CLI",
|
|
6580
|
-
"tagCommand": "cli"
|
|
6581
|
-
},
|
|
6582
|
-
{
|
|
6583
|
-
"binaryResponse": false,
|
|
6584
|
-
"bodyRequired": true,
|
|
6585
|
-
"command": "start-cli-signup",
|
|
6586
|
-
"description": "Starts a terminal-native CLI signup. The API validates the signup code,\ncreates a pending signup session, sends an email verification code, and\nreturns an opaque signup token used by the resend and verify steps. This\nendpoint does not require an API key.\n",
|
|
6587
|
-
"hasJsonBody": true,
|
|
6588
|
-
"method": "POST",
|
|
6589
|
-
"operationId": "startCliSignup",
|
|
6590
|
-
"path": "/cli/signup/start",
|
|
6591
|
-
"pathParams": [],
|
|
6592
|
-
"queryParams": [],
|
|
6593
|
-
"requestSchema": {
|
|
6594
|
-
"type": "object",
|
|
6595
|
-
"additionalProperties": false,
|
|
6596
|
-
"properties": {
|
|
6597
|
-
"email": {
|
|
6877
|
+
"email": {
|
|
6598
6878
|
"type": "string",
|
|
6599
6879
|
"format": "email",
|
|
6600
6880
|
"maxLength": 254
|
|
@@ -6613,7 +6893,7 @@ const operationManifest = [
|
|
|
6613
6893
|
"type": "string",
|
|
6614
6894
|
"minLength": 1,
|
|
6615
6895
|
"maxLength": 80,
|
|
6616
|
-
"description": "Human-readable device name used for the created
|
|
6896
|
+
"description": "Human-readable device name used for the created agent OAuth session"
|
|
6617
6897
|
},
|
|
6618
6898
|
"metadata": {
|
|
6619
6899
|
"type": "object",
|
|
@@ -6632,7 +6912,7 @@ const operationManifest = [
|
|
|
6632
6912
|
"properties": {
|
|
6633
6913
|
"signup_token": {
|
|
6634
6914
|
"type": "string",
|
|
6635
|
-
"description": "Opaque token used to verify or resend the pending
|
|
6915
|
+
"description": "Opaque token used to verify or resend the pending agent signup"
|
|
6636
6916
|
},
|
|
6637
6917
|
"email": {
|
|
6638
6918
|
"type": "string",
|
|
@@ -6659,20 +6939,20 @@ const operationManifest = [
|
|
|
6659
6939
|
"verification_code_length"
|
|
6660
6940
|
]
|
|
6661
6941
|
},
|
|
6662
|
-
"sdkName": "
|
|
6663
|
-
"summary": "Start
|
|
6664
|
-
"tag": "
|
|
6665
|
-
"tagCommand": "
|
|
6942
|
+
"sdkName": "startAgentSignup",
|
|
6943
|
+
"summary": "Start agent account signup",
|
|
6944
|
+
"tag": "Agent",
|
|
6945
|
+
"tagCommand": "agent"
|
|
6666
6946
|
},
|
|
6667
6947
|
{
|
|
6668
6948
|
"binaryResponse": false,
|
|
6669
6949
|
"bodyRequired": true,
|
|
6670
|
-
"command": "verify-
|
|
6671
|
-
"description": "Verifies the email code for
|
|
6950
|
+
"command": "verify-agent-signup",
|
|
6951
|
+
"description": "Verifies the email code for an agent signup session, creates the account\nwhen needed, redeems the reserved signup code, mints an org-scoped OAuth\nsession for CLI authentication, and returns the raw tokens exactly once.\nFor existing users, the optional `org_id` selects which accessible\nworkspace should receive the new session.\n",
|
|
6672
6952
|
"hasJsonBody": true,
|
|
6673
6953
|
"method": "POST",
|
|
6674
|
-
"operationId": "
|
|
6675
|
-
"path": "/
|
|
6954
|
+
"operationId": "verifyAgentSignup",
|
|
6955
|
+
"path": "/agent/signup/verify",
|
|
6676
6956
|
"pathParams": [],
|
|
6677
6957
|
"queryParams": [],
|
|
6678
6958
|
"requestSchema": {
|
|
@@ -6688,147 +6968,634 @@ const operationManifest = [
|
|
|
6688
6968
|
"minLength": 1,
|
|
6689
6969
|
"maxLength": 32
|
|
6690
6970
|
},
|
|
6691
|
-
"
|
|
6971
|
+
"org_id": {
|
|
6692
6972
|
"type": "string",
|
|
6693
|
-
"
|
|
6694
|
-
"
|
|
6973
|
+
"format": "uuid",
|
|
6974
|
+
"description": "Optional workspace id to target when the verified email already belongs to multiple workspaces"
|
|
6695
6975
|
}
|
|
6696
6976
|
},
|
|
6697
|
-
"required": [
|
|
6698
|
-
"signup_token",
|
|
6699
|
-
"verification_code",
|
|
6700
|
-
"password"
|
|
6701
|
-
]
|
|
6977
|
+
"required": ["signup_token", "verification_code"]
|
|
6702
6978
|
},
|
|
6703
6979
|
"responseSchema": {
|
|
6704
6980
|
"type": "object",
|
|
6705
6981
|
"properties": {
|
|
6706
6982
|
"api_key": {
|
|
6707
6983
|
"type": "string",
|
|
6708
|
-
"description": "
|
|
6984
|
+
"description": "Legacy alias for access_token. New CLI builds should persist access_token and refresh_token."
|
|
6709
6985
|
},
|
|
6710
6986
|
"key_id": {
|
|
6987
|
+
"type": "string",
|
|
6988
|
+
"format": "uuid",
|
|
6989
|
+
"description": "Legacy alias for oauth_grant_id"
|
|
6990
|
+
},
|
|
6991
|
+
"key_prefix": {
|
|
6992
|
+
"type": "string",
|
|
6993
|
+
"description": "Legacy display prefix derived from access_token"
|
|
6994
|
+
},
|
|
6995
|
+
"access_token": {
|
|
6996
|
+
"type": "string",
|
|
6997
|
+
"description": "OAuth access token for CLI API authentication"
|
|
6998
|
+
},
|
|
6999
|
+
"refresh_token": {
|
|
7000
|
+
"type": "string",
|
|
7001
|
+
"description": "OAuth refresh token used by the CLI to renew access"
|
|
7002
|
+
},
|
|
7003
|
+
"token_type": {
|
|
7004
|
+
"type": "string",
|
|
7005
|
+
"enum": ["Bearer"]
|
|
7006
|
+
},
|
|
7007
|
+
"expires_in": {
|
|
7008
|
+
"type": "integer",
|
|
7009
|
+
"description": "Seconds until access_token expires"
|
|
7010
|
+
},
|
|
7011
|
+
"auth_method": {
|
|
7012
|
+
"type": "string",
|
|
7013
|
+
"enum": ["oauth"]
|
|
7014
|
+
},
|
|
7015
|
+
"oauth_grant_id": {
|
|
6711
7016
|
"type": "string",
|
|
6712
7017
|
"format": "uuid"
|
|
6713
7018
|
},
|
|
6714
|
-
"
|
|
7019
|
+
"oauth_client_id": { "type": "string" },
|
|
6715
7020
|
"org_id": {
|
|
6716
7021
|
"type": "string",
|
|
6717
7022
|
"format": "uuid"
|
|
6718
7023
|
},
|
|
6719
|
-
"org_name": { "type": ["string", "null"] }
|
|
7024
|
+
"org_name": { "type": ["string", "null"] },
|
|
7025
|
+
"orgs": {
|
|
7026
|
+
"type": "array",
|
|
7027
|
+
"items": {
|
|
7028
|
+
"type": "object",
|
|
7029
|
+
"properties": {
|
|
7030
|
+
"id": {
|
|
7031
|
+
"type": "string",
|
|
7032
|
+
"format": "uuid"
|
|
7033
|
+
},
|
|
7034
|
+
"name": { "type": ["string", "null"] }
|
|
7035
|
+
},
|
|
7036
|
+
"required": ["id", "name"]
|
|
7037
|
+
},
|
|
7038
|
+
"description": "Workspaces available to the verified email. The minted session targets `org_id`."
|
|
7039
|
+
}
|
|
6720
7040
|
},
|
|
6721
7041
|
"required": [
|
|
6722
7042
|
"api_key",
|
|
6723
7043
|
"key_id",
|
|
6724
7044
|
"key_prefix",
|
|
7045
|
+
"access_token",
|
|
7046
|
+
"refresh_token",
|
|
7047
|
+
"token_type",
|
|
7048
|
+
"expires_in",
|
|
7049
|
+
"auth_method",
|
|
7050
|
+
"oauth_grant_id",
|
|
7051
|
+
"oauth_client_id",
|
|
6725
7052
|
"org_id",
|
|
6726
|
-
"org_name"
|
|
7053
|
+
"org_name",
|
|
7054
|
+
"orgs"
|
|
6727
7055
|
]
|
|
6728
7056
|
},
|
|
6729
|
-
"sdkName": "
|
|
6730
|
-
"summary": "Verify
|
|
7057
|
+
"sdkName": "verifyAgentSignup",
|
|
7058
|
+
"summary": "Verify agent signup and create OAuth tokens",
|
|
7059
|
+
"tag": "Agent",
|
|
7060
|
+
"tagCommand": "agent"
|
|
7061
|
+
},
|
|
7062
|
+
{
|
|
7063
|
+
"binaryResponse": false,
|
|
7064
|
+
"bodyRequired": false,
|
|
7065
|
+
"command": "cli-logout",
|
|
7066
|
+
"description": "Revokes the OAuth grant used to authenticate the request. API-key\nauthenticated legacy logout requests succeed without deleting server API\nkeys so old local CLI state can be cleared safely.\n",
|
|
7067
|
+
"hasJsonBody": true,
|
|
7068
|
+
"method": "POST",
|
|
7069
|
+
"operationId": "cliLogout",
|
|
7070
|
+
"path": "/cli/logout",
|
|
7071
|
+
"pathParams": [],
|
|
7072
|
+
"queryParams": [],
|
|
7073
|
+
"requestSchema": {
|
|
7074
|
+
"type": "object",
|
|
7075
|
+
"additionalProperties": false,
|
|
7076
|
+
"properties": { "key_id": {
|
|
7077
|
+
"type": "string",
|
|
7078
|
+
"format": "uuid",
|
|
7079
|
+
"description": "Optional id guard; when provided it must match the authenticated OAuth grant id or API key id"
|
|
7080
|
+
} }
|
|
7081
|
+
},
|
|
7082
|
+
"responseSchema": {
|
|
7083
|
+
"type": "object",
|
|
7084
|
+
"properties": {
|
|
7085
|
+
"revoked": {
|
|
7086
|
+
"type": "boolean",
|
|
7087
|
+
"description": "True when an OAuth grant was revoked. False for API-key-authenticated legacy logout, which only clears local CLI state."
|
|
7088
|
+
},
|
|
7089
|
+
"key_id": {
|
|
7090
|
+
"type": "string",
|
|
7091
|
+
"format": "uuid",
|
|
7092
|
+
"description": "API key id for API-key-authenticated legacy logout"
|
|
7093
|
+
},
|
|
7094
|
+
"oauth_grant_id": {
|
|
7095
|
+
"type": "string",
|
|
7096
|
+
"format": "uuid",
|
|
7097
|
+
"description": "OAuth grant id revoked by OAuth-authenticated logout"
|
|
7098
|
+
}
|
|
7099
|
+
},
|
|
7100
|
+
"required": ["revoked"]
|
|
7101
|
+
},
|
|
7102
|
+
"sdkName": "cliLogout",
|
|
7103
|
+
"summary": "Revoke the current CLI OAuth session",
|
|
6731
7104
|
"tag": "CLI",
|
|
6732
7105
|
"tagCommand": "cli"
|
|
6733
7106
|
},
|
|
6734
7107
|
{
|
|
6735
7108
|
"binaryResponse": false,
|
|
6736
7109
|
"bodyRequired": true,
|
|
6737
|
-
"command": "
|
|
6738
|
-
"description": "
|
|
7110
|
+
"command": "poll-cli-login",
|
|
7111
|
+
"description": "Polls a CLI login session until the browser approval either succeeds,\nis denied, expires, or is polled too quickly. The OAuth token set is\ncreated only after approval and is returned exactly once.\n",
|
|
6739
7112
|
"hasJsonBody": true,
|
|
6740
7113
|
"method": "POST",
|
|
6741
|
-
"operationId": "
|
|
6742
|
-
"path": "/
|
|
7114
|
+
"operationId": "pollCliLogin",
|
|
7115
|
+
"path": "/cli/login/poll",
|
|
6743
7116
|
"pathParams": [],
|
|
6744
7117
|
"queryParams": [],
|
|
6745
7118
|
"requestSchema": {
|
|
6746
7119
|
"type": "object",
|
|
6747
7120
|
"additionalProperties": false,
|
|
6748
|
-
"properties": { "
|
|
7121
|
+
"properties": { "device_code": {
|
|
6749
7122
|
"type": "string",
|
|
6750
|
-
"minLength": 1
|
|
6751
|
-
"maxLength": 253,
|
|
6752
|
-
"description": "The domain name to claim (e.g. \"example.com\")"
|
|
7123
|
+
"minLength": 1
|
|
6753
7124
|
} },
|
|
6754
|
-
"required": ["
|
|
7125
|
+
"required": ["device_code"]
|
|
6755
7126
|
},
|
|
6756
7127
|
"responseSchema": {
|
|
6757
7128
|
"type": "object",
|
|
6758
7129
|
"properties": {
|
|
6759
|
-
"
|
|
7130
|
+
"api_key": {
|
|
6760
7131
|
"type": "string",
|
|
6761
|
-
"
|
|
7132
|
+
"description": "Legacy alias for access_token. New CLI builds should persist access_token and refresh_token."
|
|
6762
7133
|
},
|
|
6763
|
-
"
|
|
7134
|
+
"key_id": {
|
|
6764
7135
|
"type": "string",
|
|
6765
|
-
"format": "uuid"
|
|
7136
|
+
"format": "uuid",
|
|
7137
|
+
"description": "Legacy alias for oauth_grant_id"
|
|
6766
7138
|
},
|
|
6767
|
-
"
|
|
6768
|
-
|
|
6769
|
-
"
|
|
6770
|
-
"const": false
|
|
7139
|
+
"key_prefix": {
|
|
7140
|
+
"type": "string",
|
|
7141
|
+
"description": "Legacy display prefix derived from access_token"
|
|
6771
7142
|
},
|
|
6772
|
-
"
|
|
7143
|
+
"access_token": {
|
|
6773
7144
|
"type": "string",
|
|
6774
|
-
"description": "
|
|
7145
|
+
"description": "OAuth access token for CLI API authentication"
|
|
6775
7146
|
},
|
|
6776
|
-
"
|
|
7147
|
+
"refresh_token": {
|
|
6777
7148
|
"type": "string",
|
|
6778
|
-
"
|
|
6779
|
-
}
|
|
7149
|
+
"description": "OAuth refresh token used by the CLI to renew access"
|
|
7150
|
+
},
|
|
7151
|
+
"token_type": {
|
|
7152
|
+
"type": "string",
|
|
7153
|
+
"enum": ["Bearer"]
|
|
7154
|
+
},
|
|
7155
|
+
"expires_in": {
|
|
7156
|
+
"type": "integer",
|
|
7157
|
+
"description": "Seconds until access_token expires"
|
|
7158
|
+
},
|
|
7159
|
+
"auth_method": {
|
|
7160
|
+
"type": "string",
|
|
7161
|
+
"enum": ["oauth"]
|
|
7162
|
+
},
|
|
7163
|
+
"oauth_grant_id": {
|
|
7164
|
+
"type": "string",
|
|
7165
|
+
"format": "uuid"
|
|
7166
|
+
},
|
|
7167
|
+
"oauth_client_id": { "type": "string" },
|
|
7168
|
+
"org_id": {
|
|
7169
|
+
"type": "string",
|
|
7170
|
+
"format": "uuid"
|
|
7171
|
+
},
|
|
7172
|
+
"org_name": { "type": ["string", "null"] }
|
|
6780
7173
|
},
|
|
6781
7174
|
"required": [
|
|
6782
|
-
"
|
|
7175
|
+
"api_key",
|
|
7176
|
+
"key_id",
|
|
7177
|
+
"key_prefix",
|
|
7178
|
+
"access_token",
|
|
7179
|
+
"refresh_token",
|
|
7180
|
+
"token_type",
|
|
7181
|
+
"expires_in",
|
|
7182
|
+
"auth_method",
|
|
7183
|
+
"oauth_grant_id",
|
|
7184
|
+
"oauth_client_id",
|
|
6783
7185
|
"org_id",
|
|
6784
|
-
"
|
|
6785
|
-
"verified",
|
|
6786
|
-
"verification_token",
|
|
6787
|
-
"created_at"
|
|
7186
|
+
"org_name"
|
|
6788
7187
|
]
|
|
6789
7188
|
},
|
|
6790
|
-
"sdkName": "
|
|
6791
|
-
"summary": "
|
|
6792
|
-
"tag": "
|
|
6793
|
-
"tagCommand": "
|
|
6794
|
-
},
|
|
6795
|
-
{
|
|
6796
|
-
"binaryResponse": false,
|
|
6797
|
-
"bodyRequired": false,
|
|
6798
|
-
"command": "delete-domain",
|
|
6799
|
-
"description": "Deletes a verified or unverified domain claim.",
|
|
6800
|
-
"hasJsonBody": false,
|
|
6801
|
-
"method": "DELETE",
|
|
6802
|
-
"operationId": "deleteDomain",
|
|
6803
|
-
"path": "/domains/{id}",
|
|
6804
|
-
"pathParams": [{
|
|
6805
|
-
"description": "Resource UUID",
|
|
6806
|
-
"enum": null,
|
|
6807
|
-
"name": "id",
|
|
6808
|
-
"required": true,
|
|
6809
|
-
"type": "string"
|
|
6810
|
-
}],
|
|
6811
|
-
"queryParams": [],
|
|
6812
|
-
"requestSchema": null,
|
|
6813
|
-
"responseSchema": null,
|
|
6814
|
-
"sdkName": "deleteDomain",
|
|
6815
|
-
"summary": "Delete a domain",
|
|
6816
|
-
"tag": "Domains",
|
|
6817
|
-
"tagCommand": "domains"
|
|
7189
|
+
"sdkName": "pollCliLogin",
|
|
7190
|
+
"summary": "Poll CLI browser login",
|
|
7191
|
+
"tag": "CLI",
|
|
7192
|
+
"tagCommand": "cli"
|
|
6818
7193
|
},
|
|
6819
7194
|
{
|
|
6820
7195
|
"binaryResponse": false,
|
|
6821
|
-
"bodyRequired":
|
|
6822
|
-
"command": "
|
|
6823
|
-
"description": "
|
|
6824
|
-
"hasJsonBody":
|
|
6825
|
-
"method": "
|
|
6826
|
-
"operationId": "
|
|
6827
|
-
"path": "/
|
|
7196
|
+
"bodyRequired": true,
|
|
7197
|
+
"command": "resend-cli-signup-verification",
|
|
7198
|
+
"description": "Sends a new email verification code for a pending CLI signup session.\nThis endpoint does not require an API key.\n",
|
|
7199
|
+
"hasJsonBody": true,
|
|
7200
|
+
"method": "POST",
|
|
7201
|
+
"operationId": "resendCliSignupVerification",
|
|
7202
|
+
"path": "/cli/signup/resend",
|
|
6828
7203
|
"pathParams": [],
|
|
6829
7204
|
"queryParams": [],
|
|
6830
|
-
"requestSchema":
|
|
6831
|
-
|
|
7205
|
+
"requestSchema": {
|
|
7206
|
+
"type": "object",
|
|
7207
|
+
"additionalProperties": false,
|
|
7208
|
+
"properties": { "signup_token": {
|
|
7209
|
+
"type": "string",
|
|
7210
|
+
"minLength": 1
|
|
7211
|
+
} },
|
|
7212
|
+
"required": ["signup_token"]
|
|
7213
|
+
},
|
|
7214
|
+
"responseSchema": {
|
|
7215
|
+
"type": "object",
|
|
7216
|
+
"properties": {
|
|
7217
|
+
"email": {
|
|
7218
|
+
"type": "string",
|
|
7219
|
+
"format": "email"
|
|
7220
|
+
},
|
|
7221
|
+
"expires_in": {
|
|
7222
|
+
"type": "integer",
|
|
7223
|
+
"description": "Seconds until the pending signup expires"
|
|
7224
|
+
},
|
|
7225
|
+
"resend_after": {
|
|
7226
|
+
"type": "integer",
|
|
7227
|
+
"description": "Minimum seconds before requesting another verification email"
|
|
7228
|
+
},
|
|
7229
|
+
"verification_code_length": {
|
|
7230
|
+
"type": "integer",
|
|
7231
|
+
"description": "Number of digits in the emailed verification code"
|
|
7232
|
+
}
|
|
7233
|
+
},
|
|
7234
|
+
"required": [
|
|
7235
|
+
"email",
|
|
7236
|
+
"expires_in",
|
|
7237
|
+
"resend_after",
|
|
7238
|
+
"verification_code_length"
|
|
7239
|
+
]
|
|
7240
|
+
},
|
|
7241
|
+
"sdkName": "resendCliSignupVerification",
|
|
7242
|
+
"summary": "Resend CLI signup verification code",
|
|
7243
|
+
"tag": "CLI",
|
|
7244
|
+
"tagCommand": "cli"
|
|
7245
|
+
},
|
|
7246
|
+
{
|
|
7247
|
+
"binaryResponse": false,
|
|
7248
|
+
"bodyRequired": false,
|
|
7249
|
+
"command": "start-cli-login",
|
|
7250
|
+
"description": "Starts a browser-assisted CLI login session. The response includes a\ndevice code for polling and a user code that the user approves in the\nbrowser. This endpoint does not require an API key.\n",
|
|
7251
|
+
"hasJsonBody": true,
|
|
7252
|
+
"method": "POST",
|
|
7253
|
+
"operationId": "startCliLogin",
|
|
7254
|
+
"path": "/cli/login/start",
|
|
7255
|
+
"pathParams": [],
|
|
7256
|
+
"queryParams": [],
|
|
7257
|
+
"requestSchema": {
|
|
7258
|
+
"type": "object",
|
|
7259
|
+
"additionalProperties": false,
|
|
7260
|
+
"properties": {
|
|
7261
|
+
"device_name": {
|
|
7262
|
+
"type": "string",
|
|
7263
|
+
"minLength": 1,
|
|
7264
|
+
"maxLength": 80,
|
|
7265
|
+
"description": "Human-readable device name shown during browser approval"
|
|
7266
|
+
},
|
|
7267
|
+
"metadata": {
|
|
7268
|
+
"type": "object",
|
|
7269
|
+
"additionalProperties": true,
|
|
7270
|
+
"description": "Optional client metadata stored with the login session; serialized JSON must be 2048 bytes or fewer"
|
|
7271
|
+
}
|
|
7272
|
+
}
|
|
7273
|
+
},
|
|
7274
|
+
"responseSchema": {
|
|
7275
|
+
"type": "object",
|
|
7276
|
+
"properties": {
|
|
7277
|
+
"device_code": {
|
|
7278
|
+
"type": "string",
|
|
7279
|
+
"description": "Opaque code used by the CLI to poll for approval"
|
|
7280
|
+
},
|
|
7281
|
+
"user_code": {
|
|
7282
|
+
"type": "string",
|
|
7283
|
+
"pattern": "^[BCDFGHJKLMNPQRSTVWXZ]{4}-[BCDFGHJKLMNPQRSTVWXZ]{4}$",
|
|
7284
|
+
"description": "Short code the user confirms in the browser"
|
|
7285
|
+
},
|
|
7286
|
+
"verification_uri": {
|
|
7287
|
+
"type": "string",
|
|
7288
|
+
"description": "Browser URL where the user approves the login"
|
|
7289
|
+
},
|
|
7290
|
+
"verification_uri_complete": {
|
|
7291
|
+
"type": "string",
|
|
7292
|
+
"description": "Browser URL with the user code prefilled"
|
|
7293
|
+
},
|
|
7294
|
+
"expires_in": {
|
|
7295
|
+
"type": "integer",
|
|
7296
|
+
"description": "Seconds until the login session expires"
|
|
7297
|
+
},
|
|
7298
|
+
"interval": {
|
|
7299
|
+
"type": "integer",
|
|
7300
|
+
"description": "Minimum seconds between poll requests"
|
|
7301
|
+
}
|
|
7302
|
+
},
|
|
7303
|
+
"required": [
|
|
7304
|
+
"device_code",
|
|
7305
|
+
"user_code",
|
|
7306
|
+
"verification_uri",
|
|
7307
|
+
"verification_uri_complete",
|
|
7308
|
+
"expires_in",
|
|
7309
|
+
"interval"
|
|
7310
|
+
]
|
|
7311
|
+
},
|
|
7312
|
+
"sdkName": "startCliLogin",
|
|
7313
|
+
"summary": "Start CLI browser login",
|
|
7314
|
+
"tag": "CLI",
|
|
7315
|
+
"tagCommand": "cli"
|
|
7316
|
+
},
|
|
7317
|
+
{
|
|
7318
|
+
"binaryResponse": false,
|
|
7319
|
+
"bodyRequired": true,
|
|
7320
|
+
"command": "start-cli-signup",
|
|
7321
|
+
"description": "Starts a terminal-native CLI signup. The API validates the signup code,\ncreates a pending signup session, sends an email verification code, and\nreturns an opaque signup token used by the resend and verify steps. This\nendpoint does not require an API key.\n",
|
|
7322
|
+
"hasJsonBody": true,
|
|
7323
|
+
"method": "POST",
|
|
7324
|
+
"operationId": "startCliSignup",
|
|
7325
|
+
"path": "/cli/signup/start",
|
|
7326
|
+
"pathParams": [],
|
|
7327
|
+
"queryParams": [],
|
|
7328
|
+
"requestSchema": {
|
|
7329
|
+
"type": "object",
|
|
7330
|
+
"additionalProperties": false,
|
|
7331
|
+
"properties": {
|
|
7332
|
+
"email": {
|
|
7333
|
+
"type": "string",
|
|
7334
|
+
"format": "email",
|
|
7335
|
+
"maxLength": 254
|
|
7336
|
+
},
|
|
7337
|
+
"signup_code": {
|
|
7338
|
+
"type": "string",
|
|
7339
|
+
"minLength": 1,
|
|
7340
|
+
"maxLength": 128
|
|
7341
|
+
},
|
|
7342
|
+
"terms_accepted": {
|
|
7343
|
+
"type": "boolean",
|
|
7344
|
+
"const": true,
|
|
7345
|
+
"description": "Must be true to confirm acceptance of Primitive's Terms of Service and Privacy Policy"
|
|
7346
|
+
},
|
|
7347
|
+
"device_name": {
|
|
7348
|
+
"type": "string",
|
|
7349
|
+
"minLength": 1,
|
|
7350
|
+
"maxLength": 80,
|
|
7351
|
+
"description": "Human-readable device name used for the created CLI OAuth grant"
|
|
7352
|
+
},
|
|
7353
|
+
"metadata": {
|
|
7354
|
+
"type": "object",
|
|
7355
|
+
"additionalProperties": true,
|
|
7356
|
+
"description": "Optional client metadata stored with the signup session; serialized JSON must be 2048 bytes or fewer"
|
|
7357
|
+
}
|
|
7358
|
+
},
|
|
7359
|
+
"required": [
|
|
7360
|
+
"email",
|
|
7361
|
+
"signup_code",
|
|
7362
|
+
"terms_accepted"
|
|
7363
|
+
]
|
|
7364
|
+
},
|
|
7365
|
+
"responseSchema": {
|
|
7366
|
+
"type": "object",
|
|
7367
|
+
"properties": {
|
|
7368
|
+
"signup_token": {
|
|
7369
|
+
"type": "string",
|
|
7370
|
+
"description": "Opaque token used to verify or resend the pending CLI signup"
|
|
7371
|
+
},
|
|
7372
|
+
"email": {
|
|
7373
|
+
"type": "string",
|
|
7374
|
+
"format": "email"
|
|
7375
|
+
},
|
|
7376
|
+
"expires_in": {
|
|
7377
|
+
"type": "integer",
|
|
7378
|
+
"description": "Seconds until the pending signup expires"
|
|
7379
|
+
},
|
|
7380
|
+
"resend_after": {
|
|
7381
|
+
"type": "integer",
|
|
7382
|
+
"description": "Minimum seconds before requesting another verification email"
|
|
7383
|
+
},
|
|
7384
|
+
"verification_code_length": {
|
|
7385
|
+
"type": "integer",
|
|
7386
|
+
"description": "Number of digits in the emailed verification code"
|
|
7387
|
+
}
|
|
7388
|
+
},
|
|
7389
|
+
"required": [
|
|
7390
|
+
"signup_token",
|
|
7391
|
+
"email",
|
|
7392
|
+
"expires_in",
|
|
7393
|
+
"resend_after",
|
|
7394
|
+
"verification_code_length"
|
|
7395
|
+
]
|
|
7396
|
+
},
|
|
7397
|
+
"sdkName": "startCliSignup",
|
|
7398
|
+
"summary": "Start CLI account signup",
|
|
7399
|
+
"tag": "CLI",
|
|
7400
|
+
"tagCommand": "cli"
|
|
7401
|
+
},
|
|
7402
|
+
{
|
|
7403
|
+
"binaryResponse": false,
|
|
7404
|
+
"bodyRequired": true,
|
|
7405
|
+
"command": "verify-cli-signup",
|
|
7406
|
+
"description": "Verifies the email code for a CLI signup session, creates the account,\nredeems the reserved signup code, creates an org-scoped OAuth CLI\nsession, and returns the token set exactly once. This endpoint does not\nrequire an API key.\n",
|
|
7407
|
+
"hasJsonBody": true,
|
|
7408
|
+
"method": "POST",
|
|
7409
|
+
"operationId": "verifyCliSignup",
|
|
7410
|
+
"path": "/cli/signup/verify",
|
|
7411
|
+
"pathParams": [],
|
|
7412
|
+
"queryParams": [],
|
|
7413
|
+
"requestSchema": {
|
|
7414
|
+
"type": "object",
|
|
7415
|
+
"additionalProperties": false,
|
|
7416
|
+
"properties": {
|
|
7417
|
+
"signup_token": {
|
|
7418
|
+
"type": "string",
|
|
7419
|
+
"minLength": 1
|
|
7420
|
+
},
|
|
7421
|
+
"verification_code": {
|
|
7422
|
+
"type": "string",
|
|
7423
|
+
"minLength": 1,
|
|
7424
|
+
"maxLength": 32
|
|
7425
|
+
},
|
|
7426
|
+
"password": {
|
|
7427
|
+
"type": "string",
|
|
7428
|
+
"minLength": 1,
|
|
7429
|
+
"maxLength": 1024
|
|
7430
|
+
}
|
|
7431
|
+
},
|
|
7432
|
+
"required": ["signup_token", "verification_code"]
|
|
7433
|
+
},
|
|
7434
|
+
"responseSchema": {
|
|
7435
|
+
"type": "object",
|
|
7436
|
+
"properties": {
|
|
7437
|
+
"api_key": {
|
|
7438
|
+
"type": "string",
|
|
7439
|
+
"description": "Legacy alias for access_token. New CLI builds should persist access_token and refresh_token."
|
|
7440
|
+
},
|
|
7441
|
+
"key_id": {
|
|
7442
|
+
"type": "string",
|
|
7443
|
+
"format": "uuid",
|
|
7444
|
+
"description": "Legacy alias for oauth_grant_id"
|
|
7445
|
+
},
|
|
7446
|
+
"key_prefix": {
|
|
7447
|
+
"type": "string",
|
|
7448
|
+
"description": "Legacy display prefix derived from access_token"
|
|
7449
|
+
},
|
|
7450
|
+
"access_token": {
|
|
7451
|
+
"type": "string",
|
|
7452
|
+
"description": "OAuth access token for CLI API authentication"
|
|
7453
|
+
},
|
|
7454
|
+
"refresh_token": {
|
|
7455
|
+
"type": "string",
|
|
7456
|
+
"description": "OAuth refresh token used by the CLI to renew access"
|
|
7457
|
+
},
|
|
7458
|
+
"token_type": {
|
|
7459
|
+
"type": "string",
|
|
7460
|
+
"enum": ["Bearer"]
|
|
7461
|
+
},
|
|
7462
|
+
"expires_in": {
|
|
7463
|
+
"type": "integer",
|
|
7464
|
+
"description": "Seconds until access_token expires"
|
|
7465
|
+
},
|
|
7466
|
+
"auth_method": {
|
|
7467
|
+
"type": "string",
|
|
7468
|
+
"enum": ["oauth"]
|
|
7469
|
+
},
|
|
7470
|
+
"oauth_grant_id": {
|
|
7471
|
+
"type": "string",
|
|
7472
|
+
"format": "uuid"
|
|
7473
|
+
},
|
|
7474
|
+
"oauth_client_id": { "type": "string" },
|
|
7475
|
+
"org_id": {
|
|
7476
|
+
"type": "string",
|
|
7477
|
+
"format": "uuid"
|
|
7478
|
+
},
|
|
7479
|
+
"org_name": { "type": ["string", "null"] }
|
|
7480
|
+
},
|
|
7481
|
+
"required": [
|
|
7482
|
+
"api_key",
|
|
7483
|
+
"key_id",
|
|
7484
|
+
"key_prefix",
|
|
7485
|
+
"access_token",
|
|
7486
|
+
"refresh_token",
|
|
7487
|
+
"token_type",
|
|
7488
|
+
"expires_in",
|
|
7489
|
+
"auth_method",
|
|
7490
|
+
"oauth_grant_id",
|
|
7491
|
+
"oauth_client_id",
|
|
7492
|
+
"org_id",
|
|
7493
|
+
"org_name"
|
|
7494
|
+
]
|
|
7495
|
+
},
|
|
7496
|
+
"sdkName": "verifyCliSignup",
|
|
7497
|
+
"summary": "Verify CLI signup and create OAuth session",
|
|
7498
|
+
"tag": "CLI",
|
|
7499
|
+
"tagCommand": "cli"
|
|
7500
|
+
},
|
|
7501
|
+
{
|
|
7502
|
+
"binaryResponse": false,
|
|
7503
|
+
"bodyRequired": true,
|
|
7504
|
+
"command": "add-domain",
|
|
7505
|
+
"description": "Creates an unverified domain claim. You will receive a\n`verification_token` to add as a DNS TXT record before\ncalling the verify endpoint.\n",
|
|
7506
|
+
"hasJsonBody": true,
|
|
7507
|
+
"method": "POST",
|
|
7508
|
+
"operationId": "addDomain",
|
|
7509
|
+
"path": "/domains",
|
|
7510
|
+
"pathParams": [],
|
|
7511
|
+
"queryParams": [],
|
|
7512
|
+
"requestSchema": {
|
|
7513
|
+
"type": "object",
|
|
7514
|
+
"additionalProperties": false,
|
|
7515
|
+
"properties": { "domain": {
|
|
7516
|
+
"type": "string",
|
|
7517
|
+
"minLength": 1,
|
|
7518
|
+
"maxLength": 253,
|
|
7519
|
+
"description": "The domain name to claim (e.g. \"example.com\")"
|
|
7520
|
+
} },
|
|
7521
|
+
"required": ["domain"]
|
|
7522
|
+
},
|
|
7523
|
+
"responseSchema": {
|
|
7524
|
+
"type": "object",
|
|
7525
|
+
"properties": {
|
|
7526
|
+
"id": {
|
|
7527
|
+
"type": "string",
|
|
7528
|
+
"format": "uuid"
|
|
7529
|
+
},
|
|
7530
|
+
"org_id": {
|
|
7531
|
+
"type": "string",
|
|
7532
|
+
"format": "uuid"
|
|
7533
|
+
},
|
|
7534
|
+
"domain": { "type": "string" },
|
|
7535
|
+
"verified": {
|
|
7536
|
+
"type": "boolean",
|
|
7537
|
+
"const": false
|
|
7538
|
+
},
|
|
7539
|
+
"verification_token": {
|
|
7540
|
+
"type": "string",
|
|
7541
|
+
"description": "Add this value as a TXT record to verify ownership"
|
|
7542
|
+
},
|
|
7543
|
+
"created_at": {
|
|
7544
|
+
"type": "string",
|
|
7545
|
+
"format": "date-time"
|
|
7546
|
+
}
|
|
7547
|
+
},
|
|
7548
|
+
"required": [
|
|
7549
|
+
"id",
|
|
7550
|
+
"org_id",
|
|
7551
|
+
"domain",
|
|
7552
|
+
"verified",
|
|
7553
|
+
"verification_token",
|
|
7554
|
+
"created_at"
|
|
7555
|
+
]
|
|
7556
|
+
},
|
|
7557
|
+
"sdkName": "addDomain",
|
|
7558
|
+
"summary": "Claim a new domain",
|
|
7559
|
+
"tag": "Domains",
|
|
7560
|
+
"tagCommand": "domains"
|
|
7561
|
+
},
|
|
7562
|
+
{
|
|
7563
|
+
"binaryResponse": false,
|
|
7564
|
+
"bodyRequired": false,
|
|
7565
|
+
"command": "delete-domain",
|
|
7566
|
+
"description": "Deletes a verified or unverified domain claim.",
|
|
7567
|
+
"hasJsonBody": false,
|
|
7568
|
+
"method": "DELETE",
|
|
7569
|
+
"operationId": "deleteDomain",
|
|
7570
|
+
"path": "/domains/{id}",
|
|
7571
|
+
"pathParams": [{
|
|
7572
|
+
"description": "Resource UUID",
|
|
7573
|
+
"enum": null,
|
|
7574
|
+
"name": "id",
|
|
7575
|
+
"required": true,
|
|
7576
|
+
"type": "string"
|
|
7577
|
+
}],
|
|
7578
|
+
"queryParams": [],
|
|
7579
|
+
"requestSchema": null,
|
|
7580
|
+
"responseSchema": null,
|
|
7581
|
+
"sdkName": "deleteDomain",
|
|
7582
|
+
"summary": "Delete a domain",
|
|
7583
|
+
"tag": "Domains",
|
|
7584
|
+
"tagCommand": "domains"
|
|
7585
|
+
},
|
|
7586
|
+
{
|
|
7587
|
+
"binaryResponse": false,
|
|
7588
|
+
"bodyRequired": false,
|
|
7589
|
+
"command": "list-domains",
|
|
7590
|
+
"description": "Returns all verified and unverified domains for your organization,\nsorted by creation date (newest first). Each domain includes a\n`verified` boolean to distinguish between the two states.\n",
|
|
7591
|
+
"hasJsonBody": false,
|
|
7592
|
+
"method": "GET",
|
|
7593
|
+
"operationId": "listDomains",
|
|
7594
|
+
"path": "/domains",
|
|
7595
|
+
"pathParams": [],
|
|
7596
|
+
"queryParams": [],
|
|
7597
|
+
"requestSchema": null,
|
|
7598
|
+
"responseSchema": {
|
|
6832
7599
|
"type": "array",
|
|
6833
7600
|
"items": {
|
|
6834
7601
|
"description": "A domain can be either verified or unverified. Verified domains have\n`is_active` and `spam_threshold` fields. Unverified domains have a\n`verification_token` for DNS verification.\n",
|
|
@@ -10741,7 +11508,7 @@ var PrimitiveApiClient = class {
|
|
|
10741
11508
|
const CREDENTIALS_FILE = "credentials.json";
|
|
10742
11509
|
const CREDENTIALS_LOCK_DIR = "credentials.lock";
|
|
10743
11510
|
const CREDENTIALS_LOCK_STALE_MS = 1800 * 1e3;
|
|
10744
|
-
const MALFORMED_CREDENTIALS_HINT = "Run `primitive logout` and then `primitive
|
|
11511
|
+
const MALFORMED_CREDENTIALS_HINT = "Run `primitive logout` and then `primitive signin`.";
|
|
10745
11512
|
function isRecord$2(value) {
|
|
10746
11513
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
10747
11514
|
}
|
|
@@ -10751,28 +11518,34 @@ function requireString(value, key) {
|
|
|
10751
11518
|
return raw;
|
|
10752
11519
|
}
|
|
10753
11520
|
/**
|
|
10754
|
-
* Sentinel returned by parseCredentials when the on-disk credentials
|
|
10755
|
-
*
|
|
10756
|
-
*
|
|
10757
|
-
*
|
|
10758
|
-
* as a class-tagged error so loadCliCredentials can distinguish it
|
|
10759
|
-
* from a genuine malformed-credentials error.
|
|
11521
|
+
* Sentinel returned by parseCredentials when the on-disk credentials were
|
|
11522
|
+
* written by an API-key-based CLI. The caller treats this as "not logged in"
|
|
11523
|
+
* after clearing the local file. The backing API key is intentionally not
|
|
11524
|
+
* revoked; API keys still work when passed explicitly via --api-key/env.
|
|
10760
11525
|
*/
|
|
10761
|
-
var
|
|
11526
|
+
var LegacyApiKeyCredentialFormatError = class extends Error {
|
|
10762
11527
|
constructor() {
|
|
10763
|
-
super("
|
|
10764
|
-
this.name = "
|
|
11528
|
+
super("legacy_api_key_credential_format");
|
|
11529
|
+
this.name = "LegacyApiKeyCredentialFormatError";
|
|
10765
11530
|
}
|
|
10766
11531
|
};
|
|
10767
11532
|
function parseCredentials(raw) {
|
|
10768
11533
|
if (!isRecord$2(raw)) throw new Error(`Stored Primitive CLI credentials are malformed: expected a JSON object. ${MALFORMED_CREDENTIALS_HINT}`);
|
|
10769
|
-
if (
|
|
11534
|
+
if (raw.auth_method !== "oauth") {
|
|
11535
|
+
if (typeof raw.api_key === "string" || typeof raw.key_id === "string" || typeof raw.base_url === "string") throw new LegacyApiKeyCredentialFormatError();
|
|
11536
|
+
throw new Error(`Stored Primitive CLI credentials are malformed: auth_method must be oauth. ${MALFORMED_CREDENTIALS_HINT}`);
|
|
11537
|
+
}
|
|
10770
11538
|
const orgName = raw.org_name;
|
|
10771
11539
|
if (orgName !== null && typeof orgName !== "string") throw new Error(`Stored Primitive CLI credentials are malformed: org_name must be a string or null. ${MALFORMED_CREDENTIALS_HINT}`);
|
|
11540
|
+
if (requireString(raw, "token_type") !== "Bearer") throw new Error(`Stored Primitive CLI credentials are malformed: token_type must be Bearer. ${MALFORMED_CREDENTIALS_HINT}`);
|
|
10772
11541
|
return {
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
11542
|
+
auth_method: "oauth",
|
|
11543
|
+
access_token: requireString(raw, "access_token"),
|
|
11544
|
+
refresh_token: requireString(raw, "refresh_token"),
|
|
11545
|
+
token_type: "Bearer",
|
|
11546
|
+
expires_at: requireString(raw, "expires_at"),
|
|
11547
|
+
oauth_grant_id: requireString(raw, "oauth_grant_id"),
|
|
11548
|
+
oauth_client_id: requireString(raw, "oauth_client_id"),
|
|
10776
11549
|
org_id: requireString(raw, "org_id"),
|
|
10777
11550
|
org_name: orgName,
|
|
10778
11551
|
api_base_url_1: requireString(raw, "api_base_url_1"),
|
|
@@ -10793,6 +11566,9 @@ function normalizeApiBaseUrl1(url) {
|
|
|
10793
11566
|
function normalizeApiBaseUrl2(url) {
|
|
10794
11567
|
return normalize(url, DEFAULT_API_BASE_URL_2);
|
|
10795
11568
|
}
|
|
11569
|
+
function cliAccessTokenExpiresAt(expiresInSeconds, now = Date.now) {
|
|
11570
|
+
return new Date(now() + expiresInSeconds * 1e3).toISOString();
|
|
11571
|
+
}
|
|
10796
11572
|
function loadCliCredentials(configDir) {
|
|
10797
11573
|
const path = credentialsPath(configDir);
|
|
10798
11574
|
let contents;
|
|
@@ -10806,14 +11582,14 @@ function loadCliCredentials(configDir) {
|
|
|
10806
11582
|
try {
|
|
10807
11583
|
return parseCredentials(JSON.parse(contents));
|
|
10808
11584
|
} catch (error) {
|
|
10809
|
-
if (error instanceof
|
|
11585
|
+
if (error instanceof LegacyApiKeyCredentialFormatError) {
|
|
10810
11586
|
try {
|
|
10811
11587
|
rmSync(path, { force: true });
|
|
10812
11588
|
} catch {}
|
|
10813
|
-
process.stderr.write("
|
|
11589
|
+
process.stderr.write("Removed local Primitive CLI API-key login state. API keys are still valid when passed explicitly, but saved CLI auth now uses OAuth. Run `primitive signin` to create an OAuth session. No API key was revoked.\n");
|
|
10814
11590
|
return null;
|
|
10815
11591
|
}
|
|
10816
|
-
if (error instanceof SyntaxError) throw new Error("Stored Primitive CLI credentials are not valid JSON. Run `primitive logout` and then `primitive
|
|
11592
|
+
if (error instanceof SyntaxError) throw new Error("Stored Primitive CLI credentials are not valid JSON. Run `primitive logout` and then `primitive signin`.");
|
|
10817
11593
|
throw error;
|
|
10818
11594
|
}
|
|
10819
11595
|
}
|
|
@@ -10895,7 +11671,7 @@ function resolveCliAuth(params) {
|
|
|
10895
11671
|
};
|
|
10896
11672
|
const credentials = loadCliCredentials(params.configDir);
|
|
10897
11673
|
if (credentials) return {
|
|
10898
|
-
apiKey: credentials.
|
|
11674
|
+
apiKey: credentials.access_token,
|
|
10899
11675
|
apiBaseUrl1: params.apiBaseUrl1 ? normalizeApiBaseUrl1(params.apiBaseUrl1) : credentials.api_base_url_1,
|
|
10900
11676
|
apiBaseUrl2,
|
|
10901
11677
|
credentials,
|
|
@@ -10933,7 +11709,7 @@ function validateCliHeaderName(name) {
|
|
|
10933
11709
|
const trimmed = name.trim();
|
|
10934
11710
|
if (!trimmed) throw new Errors.CLIError("Header name must be a non-empty string.", { exit: 1 });
|
|
10935
11711
|
if (!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(trimmed)) throw new Errors.CLIError(`Invalid header name: ${name}`, { exit: 1 });
|
|
10936
|
-
if (trimmed.toLowerCase() === "authorization") throw new Errors.CLIError("The Authorization header is managed by PRIMITIVE_API_KEY or saved CLI credentials.", { exit: 1 });
|
|
11712
|
+
if (trimmed.toLowerCase() === "authorization") throw new Errors.CLIError("The Authorization header is managed by PRIMITIVE_API_KEY or saved OAuth CLI credentials.", { exit: 1 });
|
|
10937
11713
|
return trimmed;
|
|
10938
11714
|
}
|
|
10939
11715
|
function validateCliHeaderValue(value, name) {
|
|
@@ -11095,6 +11871,8 @@ function redactCliEnvironment(environment) {
|
|
|
11095
11871
|
//#endregion
|
|
11096
11872
|
//#region src/oclif/api-client.ts
|
|
11097
11873
|
const API_HEADERS_ENV = "PRIMITIVE_API_HEADERS";
|
|
11874
|
+
const OAUTH_REFRESH_SKEW_MS = 60 * 1e3;
|
|
11875
|
+
const SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE = "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive signin` to authenticate again.";
|
|
11098
11876
|
function mergeHeaders(...headers) {
|
|
11099
11877
|
const merged = {};
|
|
11100
11878
|
for (const headerSet of headers) {
|
|
@@ -11153,14 +11931,115 @@ function createCliApiClient(params) {
|
|
|
11153
11931
|
requestConfig
|
|
11154
11932
|
};
|
|
11155
11933
|
}
|
|
11156
|
-
function
|
|
11934
|
+
function oauthTokenEndpoint(apiBaseUrl1) {
|
|
11935
|
+
const url = new URL(apiBaseUrl1);
|
|
11936
|
+
url.pathname = "/oauth/token";
|
|
11937
|
+
url.search = "";
|
|
11938
|
+
url.hash = "";
|
|
11939
|
+
return url.toString();
|
|
11940
|
+
}
|
|
11941
|
+
function shouldRefresh(credentials, now) {
|
|
11942
|
+
const expiresAt = Date.parse(credentials.expires_at);
|
|
11943
|
+
if (!Number.isFinite(expiresAt)) return true;
|
|
11944
|
+
return expiresAt <= now() + OAUTH_REFRESH_SKEW_MS;
|
|
11945
|
+
}
|
|
11946
|
+
function isOAuthRefreshSuccess(value) {
|
|
11947
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
11948
|
+
const row = value;
|
|
11949
|
+
return typeof row.access_token === "string" && typeof row.refresh_token === "string" && row.token_type === "Bearer" && typeof row.expires_in === "number" && Number.isFinite(row.expires_in) && row.expires_in > 0;
|
|
11950
|
+
}
|
|
11951
|
+
function oauthErrorCode(value) {
|
|
11952
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
|
|
11953
|
+
const raw = value.error;
|
|
11954
|
+
return typeof raw === "string" ? raw : null;
|
|
11955
|
+
}
|
|
11956
|
+
function oauthErrorDescription(value) {
|
|
11957
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
|
|
11958
|
+
const raw = value.error_description;
|
|
11959
|
+
return typeof raw === "string" && raw.trim() ? raw : null;
|
|
11960
|
+
}
|
|
11961
|
+
async function refreshStoredCliCredentials(params) {
|
|
11962
|
+
const now = params.now ?? Date.now;
|
|
11963
|
+
if (!shouldRefresh(params.credentials, now)) return params.credentials;
|
|
11964
|
+
let releaseLock;
|
|
11965
|
+
try {
|
|
11966
|
+
if (!params.credentialsLockHeld) try {
|
|
11967
|
+
releaseLock = acquireCliCredentialsLock(params.configDir);
|
|
11968
|
+
} catch (error) {
|
|
11969
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
11970
|
+
throw new Errors.CLIError(detail, { exit: 1 });
|
|
11971
|
+
}
|
|
11972
|
+
const current = loadCliCredentials(params.configDir);
|
|
11973
|
+
if (!current) throw new Errors.CLIError("Saved Primitive CLI OAuth session is no longer available. Run `primitive signin` to authenticate again.", { exit: 1 });
|
|
11974
|
+
if (!shouldRefresh(current, now)) return current;
|
|
11975
|
+
const fetchImpl = params.fetch ?? fetch;
|
|
11976
|
+
const body = new URLSearchParams({
|
|
11977
|
+
client_id: current.oauth_client_id,
|
|
11978
|
+
grant_type: "refresh_token",
|
|
11979
|
+
refresh_token: current.refresh_token
|
|
11980
|
+
});
|
|
11981
|
+
let response;
|
|
11982
|
+
try {
|
|
11983
|
+
response = await fetchImpl(oauthTokenEndpoint(params.apiBaseUrl1), {
|
|
11984
|
+
body,
|
|
11985
|
+
headers: {
|
|
11986
|
+
...params.headers ?? {},
|
|
11987
|
+
"content-type": "application/x-www-form-urlencoded"
|
|
11988
|
+
},
|
|
11989
|
+
method: "POST"
|
|
11990
|
+
});
|
|
11991
|
+
} catch (error) {
|
|
11992
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
11993
|
+
throw new Errors.CLIError(`Could not refresh saved Primitive CLI OAuth credentials: ${detail}`, { exit: 1 });
|
|
11994
|
+
}
|
|
11995
|
+
const payload = await response.json().catch(() => null);
|
|
11996
|
+
if (!response.ok) {
|
|
11997
|
+
const code = oauthErrorCode(payload);
|
|
11998
|
+
const description = oauthErrorDescription(payload);
|
|
11999
|
+
if (code === "invalid_grant") {
|
|
12000
|
+
deleteCliCredentials(params.configDir);
|
|
12001
|
+
throw new Errors.CLIError(SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE, { exit: 1 });
|
|
12002
|
+
}
|
|
12003
|
+
throw new Errors.CLIError(`Could not refresh saved Primitive CLI OAuth credentials${description ? `: ${description}` : "."}`, { exit: 1 });
|
|
12004
|
+
}
|
|
12005
|
+
if (!isOAuthRefreshSuccess(payload)) throw new Errors.CLIError("Primitive OAuth token endpoint returned an unexpected refresh response.", { exit: 1 });
|
|
12006
|
+
const next = {
|
|
12007
|
+
...current,
|
|
12008
|
+
access_token: payload.access_token,
|
|
12009
|
+
expires_at: cliAccessTokenExpiresAt(payload.expires_in, now),
|
|
12010
|
+
refresh_token: payload.refresh_token,
|
|
12011
|
+
token_type: payload.token_type
|
|
12012
|
+
};
|
|
12013
|
+
saveCliCredentials(params.configDir, next);
|
|
12014
|
+
return next;
|
|
12015
|
+
} finally {
|
|
12016
|
+
releaseLock?.();
|
|
12017
|
+
}
|
|
12018
|
+
}
|
|
12019
|
+
async function createAuthenticatedCliApiClient(params) {
|
|
11157
12020
|
const requestConfig = resolveCliApiRequestConfig(params);
|
|
11158
|
-
|
|
12021
|
+
let auth = resolveCliAuth({
|
|
11159
12022
|
apiKey: params.apiKey,
|
|
11160
12023
|
apiBaseUrl1: requestConfig.apiBaseUrl1,
|
|
11161
12024
|
apiBaseUrl2: requestConfig.apiBaseUrl2,
|
|
11162
12025
|
configDir: params.configDir
|
|
11163
12026
|
});
|
|
12027
|
+
if (auth.source === "stored" && auth.credentials) {
|
|
12028
|
+
const refreshed = await refreshStoredCliCredentials({
|
|
12029
|
+
apiBaseUrl1: auth.apiBaseUrl1,
|
|
12030
|
+
configDir: params.configDir,
|
|
12031
|
+
credentials: auth.credentials,
|
|
12032
|
+
credentialsLockHeld: params.credentialsLockHeld,
|
|
12033
|
+
fetch: params.fetch,
|
|
12034
|
+
headers: requestConfig.headers,
|
|
12035
|
+
now: params.now
|
|
12036
|
+
});
|
|
12037
|
+
auth = {
|
|
12038
|
+
...auth,
|
|
12039
|
+
apiKey: refreshed.access_token,
|
|
12040
|
+
credentials: refreshed
|
|
12041
|
+
};
|
|
12042
|
+
}
|
|
11164
12043
|
return {
|
|
11165
12044
|
apiClient: new PrimitiveApiClient({
|
|
11166
12045
|
apiKey: auth.apiKey,
|
|
@@ -11400,26 +12279,26 @@ function coerceParameterValue(parameter, value) {
|
|
|
11400
12279
|
if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") return value;
|
|
11401
12280
|
throw new Errors.CLIError(`Unsupported flag value for --${parameter.name}`);
|
|
11402
12281
|
}
|
|
11403
|
-
function cliError$
|
|
12282
|
+
function cliError$7(message) {
|
|
11404
12283
|
return new Errors.CLIError(message, { exit: 1 });
|
|
11405
12284
|
}
|
|
11406
12285
|
function parseJson(source, flagLabel) {
|
|
11407
12286
|
try {
|
|
11408
12287
|
return JSON.parse(source);
|
|
11409
12288
|
} catch (error) {
|
|
11410
|
-
throw cliError$
|
|
12289
|
+
throw cliError$7(`${flagLabel} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
11411
12290
|
}
|
|
11412
12291
|
}
|
|
11413
12292
|
function readJsonBody(flags) {
|
|
11414
12293
|
const bodyFile = flags["body-file"];
|
|
11415
12294
|
const rawBody = flags["raw-body"];
|
|
11416
|
-
if (bodyFile && rawBody) throw cliError$
|
|
12295
|
+
if (bodyFile && rawBody) throw cliError$7("Use either --raw-body or --body-file, not both");
|
|
11417
12296
|
if (typeof bodyFile === "string") {
|
|
11418
12297
|
let contents;
|
|
11419
12298
|
try {
|
|
11420
12299
|
contents = readFileSync(bodyFile, "utf8");
|
|
11421
12300
|
} catch (error) {
|
|
11422
|
-
throw cliError$
|
|
12301
|
+
throw cliError$7(`Could not read --body-file ${bodyFile}: ${error instanceof Error ? error.message : String(error)}`);
|
|
11423
12302
|
}
|
|
11424
12303
|
return parseJson(contents, `--body-file ${bodyFile}`);
|
|
11425
12304
|
}
|
|
@@ -11429,7 +12308,7 @@ function readTextFileFlag(path, flagLabel) {
|
|
|
11429
12308
|
try {
|
|
11430
12309
|
return readFileSync(path, "utf8");
|
|
11431
12310
|
} catch (error) {
|
|
11432
|
-
throw cliError$
|
|
12311
|
+
throw cliError$7(`Could not read ${flagLabel} ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
11433
12312
|
}
|
|
11434
12313
|
}
|
|
11435
12314
|
function extractErrorPayload(raw) {
|
|
@@ -11476,7 +12355,7 @@ function extractErrorCode(payload) {
|
|
|
11476
12355
|
if (typeof direct === "string") return direct;
|
|
11477
12356
|
}
|
|
11478
12357
|
}
|
|
11479
|
-
const ERROR_CODE_HINTS = { [API_ERROR_CODES.unauthorized]: "Hint: run `primitive
|
|
12358
|
+
const ERROR_CODE_HINTS = { [API_ERROR_CODES.unauthorized]: "Hint: run `primitive signin`, pass --api-key explicitly, or set PRIMITIVE_API_KEY in your environment. `primitive whoami` is the fastest way to verify auth is live." };
|
|
11480
12359
|
const NETWORK_ERROR_HINTS = {
|
|
11481
12360
|
ENETUNREACH: "Hint: the network is unreachable. If you're behind a proxy and set HTTP(S)_PROXY, re-run with NODE_USE_ENV_PROXY=1 (Node 22+ ignores those env vars by default). `primitive doctor` reports the local environment in one shot.",
|
|
11482
12361
|
ECONNREFUSED: "Hint: the server refused the connection. Check that your firewall allows egress to *.primitive.dev, that your PRIMITIVE_API_BASE_URL_* overrides (if any) point at a reachable host, and re-run with NODE_USE_ENV_PROXY=1 if you're behind a proxy. `primitive doctor` reports the local environment in one shot.",
|
|
@@ -11514,7 +12393,7 @@ function surfaceUnauthorizedHint(params) {
|
|
|
11514
12393
|
process.stderr.write("Saved Primitive CLI credentials were rejected by the overridden API base URL. The saved credential is preserved; unset PRIMITIVE_API_BASE_URL_1, run `primitive config reset` to clear configured URL overrides, or run `primitive logout` to remove the stored credential.\n");
|
|
11515
12394
|
return;
|
|
11516
12395
|
}
|
|
11517
|
-
process.stderr.write("Your saved Primitive CLI
|
|
12396
|
+
process.stderr.write("Your saved Primitive CLI OAuth session was rejected. If the command was working a moment ago, please retry; brief retries often clear transient rejections. If it keeps failing, run `primitive logout && primitive signin` to mint a fresh session.\n");
|
|
11518
12397
|
}
|
|
11519
12398
|
function formatElapsed(ms) {
|
|
11520
12399
|
const seconds = ms / 1e3;
|
|
@@ -11564,7 +12443,7 @@ function bodyFieldFlag(field) {
|
|
|
11564
12443
|
function buildFlags(operation) {
|
|
11565
12444
|
const flags = {
|
|
11566
12445
|
"api-key": Flags.string({
|
|
11567
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
12446
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
11568
12447
|
env: "PRIMITIVE_API_KEY"
|
|
11569
12448
|
}),
|
|
11570
12449
|
"api-base-url-1": Flags.string({
|
|
@@ -11642,7 +12521,7 @@ function createOperationCommand(operation) {
|
|
|
11642
12521
|
const { flags } = await this.parse(OperationCommand);
|
|
11643
12522
|
const parsedFlags = flags;
|
|
11644
12523
|
await runWithTiming(parsedFlags.time === true, async () => {
|
|
11645
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
12524
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
11646
12525
|
apiKey: typeof parsedFlags["api-key"] === "string" ? parsedFlags["api-key"] : void 0,
|
|
11647
12526
|
apiBaseUrl1: typeof parsedFlags["api-base-url-1"] === "string" ? parsedFlags["api-base-url-1"] : void 0,
|
|
11648
12527
|
apiBaseUrl2: typeof parsedFlags["api-base-url-2"] === "string" ? parsedFlags["api-base-url-2"] : void 0,
|
|
@@ -11765,7 +12644,7 @@ async function pickDefaultFromAddress(apiClient, authFailureContext) {
|
|
|
11765
12644
|
...authFailureContext,
|
|
11766
12645
|
payload: errorPayload
|
|
11767
12646
|
});
|
|
11768
|
-
throw new Errors.CLIError("Cannot send:
|
|
12647
|
+
throw new Errors.CLIError("Cannot send: CLI auth is missing or invalid (see hint above).", { exit: 1 });
|
|
11769
12648
|
}
|
|
11770
12649
|
throw new Errors.CLIError(`Could not look up your verified domains to default --from. Pass --from explicitly. Underlying error: ${formatErrorPayload(errorPayload)}`);
|
|
11771
12650
|
}
|
|
@@ -11877,11 +12756,11 @@ function sleep$1(ms) {
|
|
|
11877
12756
|
//#region src/oclif/commands/chat.ts
|
|
11878
12757
|
const DEFAULT_CHAT_TIMEOUT_SECONDS = 120;
|
|
11879
12758
|
const DEFAULT_STRICT_PHASE_SECONDS = 60;
|
|
11880
|
-
function cliError$
|
|
12759
|
+
function cliError$6(message) {
|
|
11881
12760
|
return new Errors.CLIError(message, { exit: 1 });
|
|
11882
12761
|
}
|
|
11883
12762
|
async function readStdinToString() {
|
|
11884
|
-
if (process.stdin.isTTY) throw cliError$
|
|
12763
|
+
if (process.stdin.isTTY) throw cliError$6("No message provided. Pass the message as the second positional argument or pipe it via stdin.");
|
|
11885
12764
|
const chunks = [];
|
|
11886
12765
|
for await (const chunk of process.stdin) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
11887
12766
|
return Buffer.concat(chunks).toString("utf8");
|
|
@@ -11917,7 +12796,7 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
11917
12796
|
};
|
|
11918
12797
|
static flags = {
|
|
11919
12798
|
"api-key": Flags.string({
|
|
11920
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved `primitive
|
|
12799
|
+
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved `primitive signin` credentials)",
|
|
11921
12800
|
env: "PRIMITIVE_API_KEY"
|
|
11922
12801
|
}),
|
|
11923
12802
|
"api-base-url-1": Flags.string({
|
|
@@ -11962,9 +12841,9 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
11962
12841
|
async run() {
|
|
11963
12842
|
const { args, flags } = await this.parse(ChatCommand);
|
|
11964
12843
|
const message = args.message !== void 0 && args.message !== "" ? args.message : await readStdinToString();
|
|
11965
|
-
if (!message.trim()) throw cliError$
|
|
12844
|
+
if (!message.trim()) throw cliError$6("Message body is empty.");
|
|
11966
12845
|
await runWithTiming(flags.time, async () => {
|
|
11967
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
12846
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
11968
12847
|
apiKey: flags["api-key"],
|
|
11969
12848
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
11970
12849
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -12000,7 +12879,7 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
12000
12879
|
return;
|
|
12001
12880
|
}
|
|
12002
12881
|
const sent = sendResult.data?.data;
|
|
12003
|
-
if (!sent) throw cliError$
|
|
12882
|
+
if (!sent) throw cliError$6("Send succeeded but the API returned no data.");
|
|
12004
12883
|
const reply = await waitForReply({
|
|
12005
12884
|
apiClient,
|
|
12006
12885
|
authFailureContext,
|
|
@@ -12317,25 +13196,30 @@ function checkApiKey(opts) {
|
|
|
12317
13196
|
} catch (error) {
|
|
12318
13197
|
parseError = error instanceof Error ? error.message : String(error);
|
|
12319
13198
|
}
|
|
12320
|
-
if (parsed?.
|
|
13199
|
+
if (parsed?.auth_method === "oauth" && typeof parsed.access_token === "string" && parsed.access_token.length > 0) return {
|
|
12321
13200
|
status: "ok",
|
|
12322
|
-
message: `loaded from ${credsPath}`
|
|
13201
|
+
message: `loaded OAuth session from ${credsPath}`
|
|
13202
|
+
};
|
|
13203
|
+
if (typeof parsed?.api_key === "string" && parsed.api_key.length > 0) return {
|
|
13204
|
+
status: "fail",
|
|
13205
|
+
message: `${credsPath} contains legacy API-key login state`,
|
|
13206
|
+
hint: "Run `primitive signin` to create saved OAuth credentials. Existing API keys still work with --api-key or PRIMITIVE_API_KEY."
|
|
12323
13207
|
};
|
|
12324
13208
|
if (parsed) return {
|
|
12325
13209
|
status: "fail",
|
|
12326
|
-
message: `${credsPath} exists but contains no
|
|
12327
|
-
hint: "Run `primitive logout` to clear it, then `primitive
|
|
13210
|
+
message: `${credsPath} exists but contains no OAuth access_token`,
|
|
13211
|
+
hint: "Run `primitive logout` to clear it, then `primitive signin` to recreate."
|
|
12328
13212
|
};
|
|
12329
13213
|
return {
|
|
12330
13214
|
status: "fail",
|
|
12331
13215
|
message: `${credsPath} exists but is unreadable or malformed${parseError ? ` (${parseError})` : ""}`,
|
|
12332
|
-
hint: "Run `primitive logout` to clear it, then `primitive
|
|
13216
|
+
hint: "Run `primitive logout` to clear it, then `primitive signin` to recreate."
|
|
12333
13217
|
};
|
|
12334
13218
|
}
|
|
12335
13219
|
return {
|
|
12336
13220
|
status: "fail",
|
|
12337
|
-
message: "no API key found",
|
|
12338
|
-
hint: "Run `primitive
|
|
13221
|
+
message: "no CLI OAuth session or explicit API key found",
|
|
13222
|
+
hint: "Run `primitive signin`, pass --api-key explicitly, or export PRIMITIVE_API_KEY=prim_..."
|
|
12339
13223
|
};
|
|
12340
13224
|
}
|
|
12341
13225
|
async function checkAccount(client) {
|
|
@@ -12417,12 +13301,12 @@ async function checkDomains(client) {
|
|
|
12417
13301
|
}
|
|
12418
13302
|
}
|
|
12419
13303
|
var DoctorCommand = class DoctorCommand extends Command {
|
|
12420
|
-
static description = `Run a one-shot environment health check: Node version, proxy env,
|
|
13304
|
+
static description = `Run a one-shot environment health check: Node version, proxy env, CLI auth resolution, /account reachability, and verified-domain status. Fails fast on anything that would block other commands and prints actionable hints for each warning or failure.`;
|
|
12421
13305
|
static summary = "Check the local environment and live API for common problems";
|
|
12422
13306
|
static examples = ["<%= config.bin %> doctor", "<%= config.bin %> doctor --api-key prim_..."];
|
|
12423
13307
|
static flags = {
|
|
12424
13308
|
"api-key": Flags.string({
|
|
12425
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
13309
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
12426
13310
|
env: "PRIMITIVE_API_KEY"
|
|
12427
13311
|
}),
|
|
12428
13312
|
"api-base-url-1": Flags.string({
|
|
@@ -12452,11 +13336,11 @@ var DoctorCommand = class DoctorCommand extends Command {
|
|
|
12452
13336
|
configDir: this.config.configDir
|
|
12453
13337
|
});
|
|
12454
13338
|
rows.push({
|
|
12455
|
-
label: "
|
|
13339
|
+
label: "Auth",
|
|
12456
13340
|
outcome: apiKeyCheck
|
|
12457
13341
|
});
|
|
12458
13342
|
if (apiKeyCheck.status !== "fail") {
|
|
12459
|
-
const { apiClient, auth } = createAuthenticatedCliApiClient({
|
|
13343
|
+
const { apiClient, auth } = await createAuthenticatedCliApiClient({
|
|
12460
13344
|
apiKey: flags["api-key"],
|
|
12461
13345
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
12462
13346
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -12538,7 +13422,7 @@ var EmailsLatestCommand = class EmailsLatestCommand extends Command {
|
|
|
12538
13422
|
];
|
|
12539
13423
|
static flags = {
|
|
12540
13424
|
"api-key": Flags.string({
|
|
12541
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
13425
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
12542
13426
|
env: "PRIMITIVE_API_KEY"
|
|
12543
13427
|
}),
|
|
12544
13428
|
"api-base-url-1": Flags.string({
|
|
@@ -12563,7 +13447,7 @@ var EmailsLatestCommand = class EmailsLatestCommand extends Command {
|
|
|
12563
13447
|
async run() {
|
|
12564
13448
|
const { flags } = await this.parse(EmailsLatestCommand);
|
|
12565
13449
|
await runWithTiming(flags.time, async () => {
|
|
12566
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
13450
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
12567
13451
|
apiKey: flags["api-key"],
|
|
12568
13452
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
12569
13453
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -12605,7 +13489,7 @@ var EmailsLatestCommand = class EmailsLatestCommand extends Command {
|
|
|
12605
13489
|
//#endregion
|
|
12606
13490
|
//#region src/oclif/commands/emails-wait.ts
|
|
12607
13491
|
const DEFAULT_WAIT_TIMEOUT_SECONDS$1 = 300;
|
|
12608
|
-
function cliError$
|
|
13492
|
+
function cliError$5(message) {
|
|
12609
13493
|
return new Errors.CLIError(message, { exit: 1 });
|
|
12610
13494
|
}
|
|
12611
13495
|
var EmailsWaitCommand = class EmailsWaitCommand extends Command {
|
|
@@ -12618,7 +13502,7 @@ var EmailsWaitCommand = class EmailsWaitCommand extends Command {
|
|
|
12618
13502
|
];
|
|
12619
13503
|
static flags = {
|
|
12620
13504
|
"api-key": Flags.string({
|
|
12621
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
13505
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
12622
13506
|
env: "PRIMITIVE_API_KEY"
|
|
12623
13507
|
}),
|
|
12624
13508
|
"api-base-url-1": Flags.string({
|
|
@@ -12670,7 +13554,7 @@ var EmailsWaitCommand = class EmailsWaitCommand extends Command {
|
|
|
12670
13554
|
};
|
|
12671
13555
|
async run() {
|
|
12672
13556
|
const { flags } = await this.parse(EmailsWaitCommand);
|
|
12673
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
13557
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
12674
13558
|
apiKey: flags["api-key"],
|
|
12675
13559
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
12676
13560
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -12680,7 +13564,7 @@ var EmailsWaitCommand = class EmailsWaitCommand extends Command {
|
|
|
12680
13564
|
try {
|
|
12681
13565
|
since = sinceFromFlags(flags);
|
|
12682
13566
|
} catch (error) {
|
|
12683
|
-
throw cliError$
|
|
13567
|
+
throw cliError$5(error instanceof Error ? error.message : String(error));
|
|
12684
13568
|
}
|
|
12685
13569
|
const filters = filtersFromFlags(flags);
|
|
12686
13570
|
const deadline = flags.timeout === 0 ? null : Date.now() + flags.timeout * 1e3;
|
|
@@ -12731,7 +13615,7 @@ var EmailsWaitCommand = class EmailsWaitCommand extends Command {
|
|
|
12731
13615
|
};
|
|
12732
13616
|
//#endregion
|
|
12733
13617
|
//#region src/oclif/commands/emails-watch.ts
|
|
12734
|
-
function cliError$
|
|
13618
|
+
function cliError$4(message) {
|
|
12735
13619
|
return new Errors.CLIError(message, { exit: 1 });
|
|
12736
13620
|
}
|
|
12737
13621
|
var EmailsWatchCommand = class EmailsWatchCommand extends Command {
|
|
@@ -12744,7 +13628,7 @@ var EmailsWatchCommand = class EmailsWatchCommand extends Command {
|
|
|
12744
13628
|
];
|
|
12745
13629
|
static flags = {
|
|
12746
13630
|
"api-key": Flags.string({
|
|
12747
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
13631
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
12748
13632
|
env: "PRIMITIVE_API_KEY"
|
|
12749
13633
|
}),
|
|
12750
13634
|
"api-base-url-1": Flags.string({
|
|
@@ -12792,7 +13676,7 @@ var EmailsWatchCommand = class EmailsWatchCommand extends Command {
|
|
|
12792
13676
|
};
|
|
12793
13677
|
async run() {
|
|
12794
13678
|
const { flags } = await this.parse(EmailsWatchCommand);
|
|
12795
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
13679
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
12796
13680
|
apiKey: flags["api-key"],
|
|
12797
13681
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
12798
13682
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -12802,7 +13686,7 @@ var EmailsWatchCommand = class EmailsWatchCommand extends Command {
|
|
|
12802
13686
|
try {
|
|
12803
13687
|
since = sinceFromFlags(flags);
|
|
12804
13688
|
} catch (error) {
|
|
12805
|
-
throw cliError$
|
|
13689
|
+
throw cliError$4(error instanceof Error ? error.message : String(error));
|
|
12806
13690
|
}
|
|
12807
13691
|
const filters = filtersFromFlags(flags);
|
|
12808
13692
|
const deadline = flags.seconds ? Date.now() + flags.seconds * 1e3 : null;
|
|
@@ -13410,7 +14294,7 @@ var FunctionsDeployCommand = class FunctionsDeployCommand extends Command {
|
|
|
13410
14294
|
];
|
|
13411
14295
|
static flags = {
|
|
13412
14296
|
"api-key": Flags.string({
|
|
13413
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
14297
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
13414
14298
|
env: "PRIMITIVE_API_KEY"
|
|
13415
14299
|
}),
|
|
13416
14300
|
"api-base-url-1": Flags.string({
|
|
@@ -13487,7 +14371,7 @@ var FunctionsDeployCommand = class FunctionsDeployCommand extends Command {
|
|
|
13487
14371
|
const code = readTextFileFlag(flags.file, "--file");
|
|
13488
14372
|
const sourceMap = flags["source-map-file"] ? readTextFileFlag(flags["source-map-file"], "--source-map-file") : void 0;
|
|
13489
14373
|
emitRawSendMailFetchWarning(code, (chunk) => process.stderr.write(chunk));
|
|
13490
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
14374
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
13491
14375
|
apiKey: flags["api-key"],
|
|
13492
14376
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
13493
14377
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -13847,7 +14731,7 @@ The deploy step calls \`primitive functions deploy\` (provided by the
|
|
|
13847
14731
|
\`npm install -g @primitivedotdev/cli\` or run via
|
|
13848
14732
|
\`npx @primitivedotdev/cli@latest <command>\`). It requires
|
|
13849
14733
|
\`PRIMITIVE_API_KEY\` to be set in your shell (or pass \`--api-key\`).
|
|
13850
|
-
Run \`primitive
|
|
14734
|
+
Run \`primitive signin\` once to save a key in your CLI config if you
|
|
13851
14735
|
prefer that to an env var.
|
|
13852
14736
|
`;
|
|
13853
14737
|
}
|
|
@@ -14073,7 +14957,7 @@ var FunctionsLogsCommand = class FunctionsLogsCommand extends Command {
|
|
|
14073
14957
|
];
|
|
14074
14958
|
static flags = {
|
|
14075
14959
|
"api-key": Flags.string({
|
|
14076
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
14960
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
14077
14961
|
env: "PRIMITIVE_API_KEY"
|
|
14078
14962
|
}),
|
|
14079
14963
|
"api-base-url-1": Flags.string({
|
|
@@ -14112,7 +14996,7 @@ var FunctionsLogsCommand = class FunctionsLogsCommand extends Command {
|
|
|
14112
14996
|
if (flags["poll-interval"] <= 0) this.error("--poll-interval must be greater than 0.", { exit: 2 });
|
|
14113
14997
|
if (flags.follow && flags.cursor) this.error("--cursor cannot be combined with --follow.", { exit: 2 });
|
|
14114
14998
|
await runWithTiming(flags.time, async () => {
|
|
14115
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
14999
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
14116
15000
|
apiKey: flags["api-key"],
|
|
14117
15001
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
14118
15002
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -14271,7 +15155,7 @@ var FunctionsRedeployCommand = class FunctionsRedeployCommand extends Command {
|
|
|
14271
15155
|
];
|
|
14272
15156
|
static flags = {
|
|
14273
15157
|
"api-key": Flags.string({
|
|
14274
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
15158
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
14275
15159
|
env: "PRIMITIVE_API_KEY"
|
|
14276
15160
|
}),
|
|
14277
15161
|
"api-base-url-1": Flags.string({
|
|
@@ -14348,7 +15232,7 @@ var FunctionsRedeployCommand = class FunctionsRedeployCommand extends Command {
|
|
|
14348
15232
|
const code = readTextFileFlag(flags.file, "--file");
|
|
14349
15233
|
const sourceMap = flags["source-map-file"] ? readTextFileFlag(flags["source-map-file"], "--source-map-file") : void 0;
|
|
14350
15234
|
emitRawSendMailFetchWarning(code, (chunk) => process.stderr.write(chunk));
|
|
14351
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
15235
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
14352
15236
|
apiKey: flags["api-key"],
|
|
14353
15237
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
14354
15238
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -14531,7 +15415,7 @@ var FunctionsSetSecretCommand = class FunctionsSetSecretCommand extends Command
|
|
|
14531
15415
|
];
|
|
14532
15416
|
static flags = {
|
|
14533
15417
|
"api-key": Flags.string({
|
|
14534
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
15418
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
14535
15419
|
env: "PRIMITIVE_API_KEY"
|
|
14536
15420
|
}),
|
|
14537
15421
|
"api-base-url-1": Flags.string({
|
|
@@ -14563,7 +15447,7 @@ var FunctionsSetSecretCommand = class FunctionsSetSecretCommand extends Command
|
|
|
14563
15447
|
async run() {
|
|
14564
15448
|
const { flags } = await this.parse(FunctionsSetSecretCommand);
|
|
14565
15449
|
await runWithTiming(flags.time, async () => {
|
|
14566
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
15450
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
14567
15451
|
apiKey: flags["api-key"],
|
|
14568
15452
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
14569
15453
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -14754,7 +15638,7 @@ var FunctionsTestFunctionCommand = class FunctionsTestFunctionCommand extends Co
|
|
|
14754
15638
|
];
|
|
14755
15639
|
static flags = {
|
|
14756
15640
|
"api-key": Flags.string({
|
|
14757
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
15641
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
14758
15642
|
env: "PRIMITIVE_API_KEY"
|
|
14759
15643
|
}),
|
|
14760
15644
|
"api-base-url-1": Flags.string({
|
|
@@ -14790,7 +15674,7 @@ var FunctionsTestFunctionCommand = class FunctionsTestFunctionCommand extends Co
|
|
|
14790
15674
|
const { flags } = await this.parse(FunctionsTestFunctionCommand);
|
|
14791
15675
|
const shouldWait = flags.wait || flags["show-sends"];
|
|
14792
15676
|
const shouldShowSends = flags["show-sends"];
|
|
14793
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
15677
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
14794
15678
|
apiKey: flags["api-key"],
|
|
14795
15679
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
14796
15680
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -14906,7 +15790,7 @@ var FunctionsTestFunctionCommand = class FunctionsTestFunctionCommand extends Co
|
|
|
14906
15790
|
//#endregion
|
|
14907
15791
|
//#region src/oclif/commands/login.ts
|
|
14908
15792
|
const MAX_CLI_LOGIN_POLL_INTERVAL_SECONDS = 60;
|
|
14909
|
-
function cliError$
|
|
15793
|
+
function cliError$3(message) {
|
|
14910
15794
|
return new Errors.CLIError(message, { exit: 1 });
|
|
14911
15795
|
}
|
|
14912
15796
|
function sleep(ms) {
|
|
@@ -14940,8 +15824,25 @@ async function checkExistingLogin(params) {
|
|
|
14940
15824
|
configDir: params.configDir
|
|
14941
15825
|
});
|
|
14942
15826
|
const probeApiBaseUrl1 = requestConfig.apiBaseUrl1 ?? params.credentials.api_base_url_1;
|
|
15827
|
+
let credentials = params.credentials;
|
|
15828
|
+
try {
|
|
15829
|
+
credentials = await refreshStoredCliCredentials({
|
|
15830
|
+
apiBaseUrl1: probeApiBaseUrl1,
|
|
15831
|
+
configDir: params.configDir,
|
|
15832
|
+
credentials,
|
|
15833
|
+
credentialsLockHeld: params.credentialsLockHeld,
|
|
15834
|
+
headers: requestConfig.headers
|
|
15835
|
+
});
|
|
15836
|
+
} catch (error) {
|
|
15837
|
+
if (loadCliCredentials(params.configDir) === null) return { status: "removed_stale" };
|
|
15838
|
+
return {
|
|
15839
|
+
status: "blocked",
|
|
15840
|
+
payload: error,
|
|
15841
|
+
message: "A saved Primitive CLI OAuth session exists, but the CLI could not refresh it. Run `primitive logout` before logging in again."
|
|
15842
|
+
};
|
|
15843
|
+
}
|
|
14943
15844
|
const apiClient = new PrimitiveApiClient({
|
|
14944
|
-
apiKey:
|
|
15845
|
+
apiKey: credentials.access_token,
|
|
14945
15846
|
apiBaseUrl1: probeApiBaseUrl1,
|
|
14946
15847
|
apiBaseUrl2: requestConfig.resolvedApiBaseUrl2,
|
|
14947
15848
|
headers: requestConfig.headers
|
|
@@ -14956,17 +15857,17 @@ async function checkExistingLogin(params) {
|
|
|
14956
15857
|
const baseUrlDiffersFromSaved = requestConfig.baseUrlOverridden && requestConfig.apiBaseUrl1 !== params.credentials.api_base_url_1;
|
|
14957
15858
|
if (code === API_ERROR_CODES.unauthorized && !baseUrlDiffersFromSaved) {
|
|
14958
15859
|
deleteCliCredentials(params.configDir);
|
|
14959
|
-
process.stderr.write("Removed saved Primitive CLI credentials because the existing
|
|
15860
|
+
process.stderr.write("Removed saved Primitive CLI OAuth credentials because the existing session was rejected during login. Continuing with a fresh login.\n");
|
|
14960
15861
|
return { status: "removed_stale" };
|
|
14961
15862
|
}
|
|
14962
15863
|
return {
|
|
14963
15864
|
status: "blocked",
|
|
14964
15865
|
payload,
|
|
14965
|
-
message: code === API_ERROR_CODES.unauthorized ? "Saved Primitive CLI credentials were rejected by an API URL different from the one they were saved with. Run `primitive logout` to remove them, or switch back to the original environment before logging in again." : "A saved Primitive CLI
|
|
15866
|
+
message: code === API_ERROR_CODES.unauthorized ? "Saved Primitive CLI OAuth credentials were rejected by an API URL different from the one they were saved with. Run `primitive logout` to remove them, or switch back to the original environment before logging in again." : "A saved Primitive CLI OAuth session exists, but the CLI could not verify whether it is still valid. Run `primitive logout` before logging in again."
|
|
14966
15867
|
};
|
|
14967
15868
|
}
|
|
14968
|
-
var LoginCommand = class
|
|
14969
|
-
static description = "Log in by opening Primitive in your browser and saving an org-scoped
|
|
15869
|
+
var LoginCommand = class extends Command {
|
|
15870
|
+
static description = "Log in by opening Primitive in your browser and saving an org-scoped OAuth session locally.";
|
|
14970
15871
|
static summary = "Log in with browser approval";
|
|
14971
15872
|
static examples = [
|
|
14972
15873
|
"<%= config.bin %> login",
|
|
@@ -14983,24 +15884,28 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
14983
15884
|
"no-browser": Flags.boolean({ description: "Do not attempt to open the browser automatically" }),
|
|
14984
15885
|
force: Flags.boolean({
|
|
14985
15886
|
char: "f",
|
|
14986
|
-
description: "Replace saved credentials without first verifying the existing
|
|
15887
|
+
description: "Replace saved credentials without first verifying the existing session"
|
|
14987
15888
|
})
|
|
14988
15889
|
};
|
|
14989
15890
|
async run() {
|
|
14990
|
-
const
|
|
15891
|
+
const commandClass = this.constructor;
|
|
15892
|
+
const { flags } = await this.parse(commandClass);
|
|
14991
15893
|
let releaseCredentialsLock;
|
|
14992
15894
|
try {
|
|
14993
15895
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
14994
15896
|
} catch (error) {
|
|
14995
|
-
throw cliError$
|
|
15897
|
+
throw cliError$3(error instanceof Error ? error.message : String(error));
|
|
14996
15898
|
}
|
|
14997
15899
|
try {
|
|
14998
|
-
await this.runWithCredentialLock(flags);
|
|
15900
|
+
await this.runWithCredentialLock(flags, this.retryCommand());
|
|
14999
15901
|
} finally {
|
|
15000
15902
|
releaseCredentialsLock();
|
|
15001
15903
|
}
|
|
15002
15904
|
}
|
|
15003
|
-
|
|
15905
|
+
retryCommand() {
|
|
15906
|
+
return "login";
|
|
15907
|
+
}
|
|
15908
|
+
async runWithCredentialLock(flags, retryCommand) {
|
|
15004
15909
|
const { apiClient, requestConfig } = createCliApiClient({
|
|
15005
15910
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
15006
15911
|
configDir: this.config.configDir
|
|
@@ -15020,13 +15925,14 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15020
15925
|
const existingStatus = await checkExistingLogin({
|
|
15021
15926
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
15022
15927
|
configDir: this.config.configDir,
|
|
15023
|
-
credentials: existing
|
|
15928
|
+
credentials: existing,
|
|
15929
|
+
credentialsLockHeld: true
|
|
15024
15930
|
});
|
|
15025
15931
|
if (existingStatus.status === "removed_stale") process.stderr.write("Continuing with a new Primitive CLI login...\n");
|
|
15026
15932
|
else if (existingStatus.status === "blocked") {
|
|
15027
15933
|
writeErrorWithHints(existingStatus.payload);
|
|
15028
|
-
throw cliError$
|
|
15029
|
-
} else throw cliError$
|
|
15934
|
+
throw cliError$3(existingStatus.message);
|
|
15935
|
+
} else throw cliError$3(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before logging in again.`);
|
|
15030
15936
|
}
|
|
15031
15937
|
const started = await startCliLogin({
|
|
15032
15938
|
body: { device_name: flags["device-name"] ?? hostname() },
|
|
@@ -15035,11 +15941,11 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15035
15941
|
});
|
|
15036
15942
|
if (started.error) {
|
|
15037
15943
|
writeErrorWithHints(extractErrorPayload(started.error));
|
|
15038
|
-
throw cliError$
|
|
15944
|
+
throw cliError$3("Could not start Primitive CLI login.");
|
|
15039
15945
|
}
|
|
15040
15946
|
const start = unwrapData$2(started.data);
|
|
15041
|
-
if (!start) throw cliError$
|
|
15042
|
-
process.stderr.write(`Your
|
|
15947
|
+
if (!start) throw cliError$3("Primitive API returned an empty CLI login response.");
|
|
15948
|
+
process.stderr.write(`Your sign-in code is: ${start.user_code}\n`);
|
|
15043
15949
|
if (!flags["no-browser"]) {
|
|
15044
15950
|
openBrowser(start.verification_uri_complete);
|
|
15045
15951
|
process.stderr.write("Opening Primitive in your browser...\n");
|
|
@@ -15059,15 +15965,19 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15059
15965
|
});
|
|
15060
15966
|
if (polled.data) {
|
|
15061
15967
|
const login = unwrapData$2(polled.data);
|
|
15062
|
-
if (!login) throw cliError$
|
|
15968
|
+
if (!login) throw cliError$3("Primitive API returned an empty CLI poll response.");
|
|
15063
15969
|
saveCliCredentials(this.config.configDir, {
|
|
15064
|
-
|
|
15970
|
+
access_token: login.access_token,
|
|
15065
15971
|
api_base_url_1: apiBaseUrl1,
|
|
15972
|
+
auth_method: "oauth",
|
|
15066
15973
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15067
|
-
|
|
15068
|
-
|
|
15974
|
+
expires_at: cliAccessTokenExpiresAt(login.expires_in),
|
|
15975
|
+
oauth_client_id: login.oauth_client_id,
|
|
15976
|
+
oauth_grant_id: login.oauth_grant_id,
|
|
15069
15977
|
org_id: login.org_id,
|
|
15070
|
-
org_name: login.org_name
|
|
15978
|
+
org_name: login.org_name,
|
|
15979
|
+
refresh_token: login.refresh_token,
|
|
15980
|
+
token_type: login.token_type
|
|
15071
15981
|
});
|
|
15072
15982
|
const org = login.org_name ? ` (${login.org_name})` : "";
|
|
15073
15983
|
process.stderr.write(`Logged in to org ${login.org_id}${org}.\n`);
|
|
@@ -15085,26 +15995,84 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15085
15995
|
nextPollDelay = interval;
|
|
15086
15996
|
continue;
|
|
15087
15997
|
}
|
|
15088
|
-
if (code === API_ERROR_CODES.accessDenied) throw cliError$
|
|
15089
|
-
if (code === API_ERROR_CODES.expiredToken) throw cliError$
|
|
15090
|
-
if (code === API_ERROR_CODES.invalidDeviceCode) throw cliError$
|
|
15998
|
+
if (code === API_ERROR_CODES.accessDenied) throw cliError$3("Primitive CLI login was denied in the browser.");
|
|
15999
|
+
if (code === API_ERROR_CODES.expiredToken) throw cliError$3(`Primitive CLI login expired. Run \`primitive ${retryCommand}\` again.`);
|
|
16000
|
+
if (code === API_ERROR_CODES.invalidDeviceCode) throw cliError$3(`Primitive CLI login device code is invalid. Run \`primitive ${retryCommand}\` again.`);
|
|
15091
16001
|
writeErrorWithHints(payload);
|
|
15092
|
-
throw cliError$
|
|
16002
|
+
throw cliError$3("Primitive CLI login failed while polling for approval.");
|
|
15093
16003
|
}
|
|
15094
|
-
throw cliError$
|
|
16004
|
+
throw cliError$3(`Primitive CLI login expired. Run \`primitive ${retryCommand}\` again.`);
|
|
15095
16005
|
}
|
|
15096
16006
|
};
|
|
15097
16007
|
//#endregion
|
|
15098
16008
|
//#region src/oclif/commands/logout.ts
|
|
15099
|
-
function cliError$
|
|
16009
|
+
function cliError$2(message) {
|
|
15100
16010
|
return new Errors.CLIError(message, { exit: 1 });
|
|
15101
16011
|
}
|
|
15102
16012
|
function unwrapData$1(value) {
|
|
15103
16013
|
return value?.data ?? null;
|
|
15104
16014
|
}
|
|
16015
|
+
function isSavedOAuthSessionExpiredError(error) {
|
|
16016
|
+
return error instanceof Error && error.message === "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive signin` to authenticate again.";
|
|
16017
|
+
}
|
|
16018
|
+
async function runLogoutWithCredentialLock(params) {
|
|
16019
|
+
const deps = {
|
|
16020
|
+
cliLogout,
|
|
16021
|
+
createAuthenticatedCliApiClient,
|
|
16022
|
+
...params.deps
|
|
16023
|
+
};
|
|
16024
|
+
let credentials;
|
|
16025
|
+
try {
|
|
16026
|
+
credentials = loadCliCredentials(params.configDir);
|
|
16027
|
+
} catch (error) {
|
|
16028
|
+
deleteCliCredentials(params.configDir);
|
|
16029
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
16030
|
+
process.stderr.write(`Removed unreadable Primitive CLI credentials. Backing OAuth grant was not revoked: ${detail}\n`);
|
|
16031
|
+
process.exitCode = 1;
|
|
16032
|
+
return;
|
|
16033
|
+
}
|
|
16034
|
+
if (!credentials) throw cliError$2("Not logged in. Run `primitive signin` to create saved CLI credentials.");
|
|
16035
|
+
let authenticated;
|
|
16036
|
+
try {
|
|
16037
|
+
authenticated = await deps.createAuthenticatedCliApiClient({
|
|
16038
|
+
apiBaseUrl1: params.flags["api-base-url-1"],
|
|
16039
|
+
configDir: params.configDir,
|
|
16040
|
+
credentialsLockHeld: true
|
|
16041
|
+
});
|
|
16042
|
+
} catch (error) {
|
|
16043
|
+
if (isSavedOAuthSessionExpiredError(error) && loadCliCredentials(params.configDir) === null) {
|
|
16044
|
+
process.stderr.write("Logged out (OAuth session was already expired or revoked on the server).\n");
|
|
16045
|
+
return;
|
|
16046
|
+
}
|
|
16047
|
+
throw error;
|
|
16048
|
+
}
|
|
16049
|
+
const freshCredentials = authenticated.auth.credentials ?? credentials;
|
|
16050
|
+
const result = await deps.cliLogout({
|
|
16051
|
+
body: { key_id: freshCredentials.oauth_grant_id },
|
|
16052
|
+
client: authenticated.apiClient.client,
|
|
16053
|
+
responseStyle: "fields"
|
|
16054
|
+
});
|
|
16055
|
+
if (result.error) {
|
|
16056
|
+
const payload = extractErrorPayload(result.error);
|
|
16057
|
+
const code = extractErrorCode(payload);
|
|
16058
|
+
if (code === API_ERROR_CODES.unauthorized || code === API_ERROR_CODES.notFound) {
|
|
16059
|
+
deleteCliCredentials(params.configDir);
|
|
16060
|
+
writeErrorWithHints(payload);
|
|
16061
|
+
process.stderr.write("Removed saved Primitive CLI credentials because the backing OAuth grant is already unavailable.\n");
|
|
16062
|
+
process.exitCode = 1;
|
|
16063
|
+
return;
|
|
16064
|
+
}
|
|
16065
|
+
writeErrorWithHints(payload);
|
|
16066
|
+
throw cliError$2("Could not revoke the saved Primitive CLI OAuth grant.");
|
|
16067
|
+
}
|
|
16068
|
+
const logout = unwrapData$1(result.data);
|
|
16069
|
+
deleteCliCredentials(params.configDir);
|
|
16070
|
+
const grantId = logout?.oauth_grant_id ?? freshCredentials.oauth_grant_id;
|
|
16071
|
+
process.stderr.write(`Logged out and revoked OAuth grant ${grantId}.\n`);
|
|
16072
|
+
}
|
|
15105
16073
|
var LogoutCommand = class LogoutCommand extends Command {
|
|
15106
|
-
static description = "Log out by revoking the saved Primitive CLI
|
|
15107
|
-
static summary = "Log out and revoke the saved CLI
|
|
16074
|
+
static description = "Log out by revoking the saved Primitive CLI OAuth grant and deleting local credentials.";
|
|
16075
|
+
static summary = "Log out and revoke the saved CLI OAuth grant";
|
|
15108
16076
|
static examples = ["<%= config.bin %> logout"];
|
|
15109
16077
|
static flags = { "api-base-url-1": Flags.string({
|
|
15110
16078
|
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
@@ -15117,59 +16085,17 @@ var LogoutCommand = class LogoutCommand extends Command {
|
|
|
15117
16085
|
try {
|
|
15118
16086
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
15119
16087
|
} catch (error) {
|
|
15120
|
-
throw cliError$
|
|
16088
|
+
throw cliError$2(error instanceof Error ? error.message : String(error));
|
|
15121
16089
|
}
|
|
15122
16090
|
try {
|
|
15123
|
-
await
|
|
16091
|
+
await runLogoutWithCredentialLock({
|
|
16092
|
+
configDir: this.config.configDir,
|
|
16093
|
+
flags
|
|
16094
|
+
});
|
|
15124
16095
|
} finally {
|
|
15125
16096
|
releaseCredentialsLock();
|
|
15126
16097
|
}
|
|
15127
16098
|
}
|
|
15128
|
-
async runWithCredentialLock(flags) {
|
|
15129
|
-
let credentials;
|
|
15130
|
-
try {
|
|
15131
|
-
credentials = loadCliCredentials(this.config.configDir);
|
|
15132
|
-
} catch (error) {
|
|
15133
|
-
deleteCliCredentials(this.config.configDir);
|
|
15134
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
15135
|
-
process.stderr.write(`Removed unreadable Primitive CLI credentials. Backing API key was not revoked: ${detail}\n`);
|
|
15136
|
-
process.exitCode = 1;
|
|
15137
|
-
return;
|
|
15138
|
-
}
|
|
15139
|
-
if (!credentials) throw cliError$1("Not logged in. Run `primitive login` to create saved CLI credentials.");
|
|
15140
|
-
const requestConfig = resolveCliApiRequestConfig({
|
|
15141
|
-
apiBaseUrl1: flags["api-base-url-1"],
|
|
15142
|
-
configDir: this.config.configDir
|
|
15143
|
-
});
|
|
15144
|
-
const apiBaseUrl1 = requestConfig.apiBaseUrl1 ? normalizeApiBaseUrl1(requestConfig.apiBaseUrl1) : credentials.api_base_url_1;
|
|
15145
|
-
const apiClient = new PrimitiveApiClient({
|
|
15146
|
-
apiKey: credentials.api_key,
|
|
15147
|
-
apiBaseUrl1,
|
|
15148
|
-
headers: requestConfig.headers
|
|
15149
|
-
});
|
|
15150
|
-
const result = await cliLogout({
|
|
15151
|
-
body: { key_id: credentials.key_id },
|
|
15152
|
-
client: apiClient.client,
|
|
15153
|
-
responseStyle: "fields"
|
|
15154
|
-
});
|
|
15155
|
-
if (result.error) {
|
|
15156
|
-
const payload = extractErrorPayload(result.error);
|
|
15157
|
-
const code = extractErrorCode(payload);
|
|
15158
|
-
if (code === API_ERROR_CODES.unauthorized || code === API_ERROR_CODES.notFound) {
|
|
15159
|
-
deleteCliCredentials(this.config.configDir);
|
|
15160
|
-
writeErrorWithHints(payload);
|
|
15161
|
-
process.stderr.write("Removed saved Primitive CLI credentials because the backing API key is already unavailable.\n");
|
|
15162
|
-
process.exitCode = 1;
|
|
15163
|
-
return;
|
|
15164
|
-
}
|
|
15165
|
-
writeErrorWithHints(payload);
|
|
15166
|
-
throw cliError$1("Could not revoke the saved Primitive CLI API key.");
|
|
15167
|
-
}
|
|
15168
|
-
const logout = unwrapData$1(result.data);
|
|
15169
|
-
deleteCliCredentials(this.config.configDir);
|
|
15170
|
-
const keyId = logout?.key_id ?? credentials.key_id;
|
|
15171
|
-
process.stderr.write(`Logged out and revoked API key ${keyId}.\n`);
|
|
15172
|
-
}
|
|
15173
16099
|
};
|
|
15174
16100
|
//#endregion
|
|
15175
16101
|
//#region src/oclif/message-body-sources.ts
|
|
@@ -15286,7 +16212,7 @@ var ReplyCommand = class ReplyCommand extends Command {
|
|
|
15286
16212
|
];
|
|
15287
16213
|
static flags = {
|
|
15288
16214
|
"api-key": Flags.string({
|
|
15289
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
16215
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
15290
16216
|
env: "PRIMITIVE_API_KEY"
|
|
15291
16217
|
}),
|
|
15292
16218
|
"api-base-url-1": Flags.string({
|
|
@@ -15326,7 +16252,7 @@ var ReplyCommand = class ReplyCommand extends Command {
|
|
|
15326
16252
|
});
|
|
15327
16253
|
if (bodies.kind === "error") throw new Errors.CLIError(bodies.message);
|
|
15328
16254
|
await runWithTiming(flags.time, async () => {
|
|
15329
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
16255
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
15330
16256
|
apiKey: flags["api-key"],
|
|
15331
16257
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
15332
16258
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -15385,7 +16311,7 @@ var SendCommand = class SendCommand extends Command {
|
|
|
15385
16311
|
];
|
|
15386
16312
|
static flags = {
|
|
15387
16313
|
"api-key": Flags.string({
|
|
15388
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
16314
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
15389
16315
|
env: "PRIMITIVE_API_KEY"
|
|
15390
16316
|
}),
|
|
15391
16317
|
"api-base-url-1": Flags.string({
|
|
@@ -15427,7 +16353,7 @@ var SendCommand = class SendCommand extends Command {
|
|
|
15427
16353
|
});
|
|
15428
16354
|
if (bodies.kind === "error") throw new Errors.CLIError(bodies.message);
|
|
15429
16355
|
await runWithTiming(flags.time, async () => {
|
|
15430
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
16356
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
15431
16357
|
apiKey: flags["api-key"],
|
|
15432
16358
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
15433
16359
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -15475,12 +16401,18 @@ var SendCommand = class SendCommand extends Command {
|
|
|
15475
16401
|
//#endregion
|
|
15476
16402
|
//#region src/oclif/commands/signup.ts
|
|
15477
16403
|
const INVALID_VERIFICATION_CODE = "invalid_verification_code";
|
|
15478
|
-
const CLERK_PASSWORD_REJECTED = "clerk_password_rejected";
|
|
15479
16404
|
const EXPIRED_TOKEN = "expired_token";
|
|
15480
16405
|
const INVALID_SIGNUP_TOKEN = "invalid_signup_token";
|
|
15481
16406
|
const SLOW_DOWN = "slow_down";
|
|
15482
16407
|
const PENDING_SIGNUP_FILE = "signup.json";
|
|
15483
|
-
|
|
16408
|
+
const DEFAULT_SIGNUP_COMMAND_COPY = {
|
|
16409
|
+
actionNoun: "signup",
|
|
16410
|
+
actionGerund: "creating a new account",
|
|
16411
|
+
confirmCommand: (email) => `signup confirm ${email} <code>`,
|
|
16412
|
+
resendCommand: (email) => `signup resend ${email}`,
|
|
16413
|
+
startCommand: (email) => `signup ${email}`
|
|
16414
|
+
};
|
|
16415
|
+
function cliError$1(message) {
|
|
15484
16416
|
return new Errors.CLIError(message, { exit: 1 });
|
|
15485
16417
|
}
|
|
15486
16418
|
function unwrapData(value) {
|
|
@@ -15489,6 +16421,9 @@ function unwrapData(value) {
|
|
|
15489
16421
|
function isRecord(value) {
|
|
15490
16422
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
15491
16423
|
}
|
|
16424
|
+
function normalizeEmail(email) {
|
|
16425
|
+
return email.trim().toLowerCase();
|
|
16426
|
+
}
|
|
15492
16427
|
function pendingSignupFromJson(value) {
|
|
15493
16428
|
if (!isRecord(value)) return null;
|
|
15494
16429
|
if (typeof value.signup_token !== "string" || typeof value.email !== "string" || typeof value.expires_in !== "number" || typeof value.resend_after !== "number" || typeof value.verification_code_length !== "number" || typeof value.api_base_url_1 !== "string" || typeof value.created_at !== "string" || typeof value.expires_at !== "string") return null;
|
|
@@ -15506,7 +16441,7 @@ function pendingSignupFromJson(value) {
|
|
|
15506
16441
|
function pendingSignupPath(configDir) {
|
|
15507
16442
|
return join(configDir, PENDING_SIGNUP_FILE);
|
|
15508
16443
|
}
|
|
15509
|
-
function
|
|
16444
|
+
function deletePendingAgentSignup(configDir) {
|
|
15510
16445
|
rmSync(pendingSignupPath(configDir), { force: true });
|
|
15511
16446
|
}
|
|
15512
16447
|
function pendingSignupFromStart(start, apiBaseUrl1) {
|
|
@@ -15517,7 +16452,7 @@ function pendingSignupFromStart(start, apiBaseUrl1) {
|
|
|
15517
16452
|
expires_at: new Date(Date.now() + start.expires_in * 1e3).toISOString()
|
|
15518
16453
|
};
|
|
15519
16454
|
}
|
|
15520
|
-
function
|
|
16455
|
+
function savePendingAgentSignup(configDir, start, apiBaseUrl1) {
|
|
15521
16456
|
mkdirSync(configDir, {
|
|
15522
16457
|
mode: 448,
|
|
15523
16458
|
recursive: true
|
|
@@ -15536,7 +16471,7 @@ function savePendingCliSignup(configDir, start, apiBaseUrl1) {
|
|
|
15536
16471
|
throw error;
|
|
15537
16472
|
}
|
|
15538
16473
|
}
|
|
15539
|
-
function
|
|
16474
|
+
function loadPendingAgentSignup(configDir, apiBaseUrl1) {
|
|
15540
16475
|
const path = pendingSignupPath(configDir);
|
|
15541
16476
|
let contents;
|
|
15542
16477
|
try {
|
|
@@ -15552,12 +16487,12 @@ function loadPendingCliSignup(configDir, apiBaseUrl1) {
|
|
|
15552
16487
|
pending = null;
|
|
15553
16488
|
}
|
|
15554
16489
|
if (!pending) {
|
|
15555
|
-
|
|
16490
|
+
deletePendingAgentSignup(configDir);
|
|
15556
16491
|
return null;
|
|
15557
16492
|
}
|
|
15558
16493
|
if (pending.api_base_url_1 !== apiBaseUrl1) return null;
|
|
15559
16494
|
if (new Date(pending.expires_at).getTime() <= Date.now()) {
|
|
15560
|
-
|
|
16495
|
+
deletePendingAgentSignup(configDir);
|
|
15561
16496
|
return null;
|
|
15562
16497
|
}
|
|
15563
16498
|
return {
|
|
@@ -15565,6 +16500,13 @@ function loadPendingCliSignup(configDir, apiBaseUrl1) {
|
|
|
15565
16500
|
expires_in: Math.max(0, Math.ceil((new Date(pending.expires_at).getTime() - Date.now()) / 1e3))
|
|
15566
16501
|
};
|
|
15567
16502
|
}
|
|
16503
|
+
function requirePendingSignupForEmail(params) {
|
|
16504
|
+
const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
|
|
16505
|
+
const pending = loadPendingAgentSignup(params.configDir, params.apiBaseUrl1);
|
|
16506
|
+
if (!pending) throw cliError$1(`No pending ${copy.actionNoun} for ${params.email}. Run \`primitive ${copy.startCommand(params.email)}\` first.`);
|
|
16507
|
+
if (normalizeEmail(pending.email) !== normalizeEmail(params.email)) throw cliError$1(`Pending ${copy.actionNoun} is for ${pending.email}, not ${params.email}. Run \`primitive ${copy.startCommand(params.email)} --force\` to replace it.`);
|
|
16508
|
+
return pending;
|
|
16509
|
+
}
|
|
15568
16510
|
function retryAfterSeconds(result) {
|
|
15569
16511
|
const raw = result.response?.headers.get("retry-after");
|
|
15570
16512
|
if (!raw) return null;
|
|
@@ -15585,61 +16527,12 @@ async function promptLine(question) {
|
|
|
15585
16527
|
rl.close();
|
|
15586
16528
|
}
|
|
15587
16529
|
}
|
|
15588
|
-
async function promptHidden(question) {
|
|
15589
|
-
if (!process$1.stdin.isTTY || !process$1.stderr.isTTY || !process$1.stdin.setRawMode) throw cliError("Password input requires an interactive terminal with hidden input support.");
|
|
15590
|
-
return new Promise((resolve, reject) => {
|
|
15591
|
-
const input = process$1.stdin;
|
|
15592
|
-
let value = "";
|
|
15593
|
-
const cleanup = () => {
|
|
15594
|
-
input.setRawMode(false);
|
|
15595
|
-
input.pause();
|
|
15596
|
-
input.off("data", onData);
|
|
15597
|
-
};
|
|
15598
|
-
const finish = () => {
|
|
15599
|
-
cleanup();
|
|
15600
|
-
process$1.stderr.write("\n");
|
|
15601
|
-
resolve(value);
|
|
15602
|
-
};
|
|
15603
|
-
const onData = (chunk) => {
|
|
15604
|
-
const text = chunk.toString("utf8");
|
|
15605
|
-
for (const char of text) {
|
|
15606
|
-
if (char === "") {
|
|
15607
|
-
cleanup();
|
|
15608
|
-
process$1.stderr.write("\n");
|
|
15609
|
-
reject(cliError("Signup cancelled."));
|
|
15610
|
-
return;
|
|
15611
|
-
}
|
|
15612
|
-
if (char === "\r" || char === "\n") {
|
|
15613
|
-
finish();
|
|
15614
|
-
return;
|
|
15615
|
-
}
|
|
15616
|
-
if (char === "\b" || char === "") {
|
|
15617
|
-
value = value.slice(0, -1);
|
|
15618
|
-
continue;
|
|
15619
|
-
}
|
|
15620
|
-
value += char;
|
|
15621
|
-
}
|
|
15622
|
-
};
|
|
15623
|
-
process$1.stderr.write(question);
|
|
15624
|
-
input.setRawMode(true);
|
|
15625
|
-
input.resume();
|
|
15626
|
-
input.on("data", onData);
|
|
15627
|
-
});
|
|
15628
|
-
}
|
|
15629
16530
|
function formatSignupSeconds(seconds) {
|
|
15630
16531
|
if (typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) return "soon";
|
|
15631
16532
|
if (seconds < 60) return `${Math.ceil(seconds)} seconds`;
|
|
15632
16533
|
const minutes = Math.ceil(seconds / 60);
|
|
15633
16534
|
return `${minutes} minute${minutes === 1 ? "" : "s"}`;
|
|
15634
16535
|
}
|
|
15635
|
-
function shouldRetrySignupPassword(errorCode) {
|
|
15636
|
-
return errorCode === CLERK_PASSWORD_REJECTED;
|
|
15637
|
-
}
|
|
15638
|
-
function signupErrorMessage(payload) {
|
|
15639
|
-
if (!isRecord(payload)) return null;
|
|
15640
|
-
const message = (isRecord(payload.error) ? payload.error : payload).message;
|
|
15641
|
-
return typeof message === "string" && message.trim() ? message : null;
|
|
15642
|
-
}
|
|
15643
16536
|
async function promptRequired(question) {
|
|
15644
16537
|
while (true) {
|
|
15645
16538
|
const value = await promptLine(question);
|
|
@@ -15647,29 +16540,109 @@ async function promptRequired(question) {
|
|
|
15647
16540
|
process$1.stderr.write("Please enter a value.\n");
|
|
15648
16541
|
}
|
|
15649
16542
|
}
|
|
15650
|
-
async function
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
|
|
16543
|
+
async function confirmTerms() {
|
|
16544
|
+
process$1.stderr.write("By continuing, you agree to Primitive's Terms of Service and Privacy Policy:\n");
|
|
16545
|
+
process$1.stderr.write(" https://primitive.dev/terms\n");
|
|
16546
|
+
process$1.stderr.write(" https://primitive.dev/privacy\n");
|
|
16547
|
+
const answer = (await promptRequired("Type 'yes' to continue: ")).toLowerCase();
|
|
16548
|
+
if (answer !== "yes" && answer !== "y") throw cliError$1("You must accept the terms to create an account.");
|
|
16549
|
+
}
|
|
16550
|
+
async function checkExistingCredentials(params) {
|
|
16551
|
+
const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
|
|
16552
|
+
const checkExistingLoginFn = params.deps.checkExistingLogin ?? checkExistingLogin;
|
|
16553
|
+
let existing;
|
|
16554
|
+
try {
|
|
16555
|
+
existing = loadCliCredentials(params.configDir);
|
|
16556
|
+
} catch (error) {
|
|
16557
|
+
if (!params.flags.force) throw error;
|
|
16558
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
16559
|
+
process$1.stderr.write(`Replacing unreadable Primitive CLI credentials because --force was set: ${detail}\n`);
|
|
16560
|
+
existing = null;
|
|
16561
|
+
}
|
|
16562
|
+
if (existing && params.flags.force) {
|
|
16563
|
+
process$1.stderr.write(`Replacing saved Primitive CLI credentials after ${copy.actionNoun} because --force was set.\n`);
|
|
16564
|
+
return;
|
|
16565
|
+
}
|
|
16566
|
+
if (!existing) return;
|
|
16567
|
+
const existingStatus = await checkExistingLoginFn({
|
|
16568
|
+
apiBaseUrl1: params.apiBaseUrl1,
|
|
16569
|
+
configDir: params.configDir,
|
|
16570
|
+
credentials: existing,
|
|
16571
|
+
credentialsLockHeld: true
|
|
16572
|
+
});
|
|
16573
|
+
if (existingStatus.status === "removed_stale") {
|
|
16574
|
+
process$1.stderr.write("Continuing with Primitive signup...\n");
|
|
16575
|
+
return;
|
|
16576
|
+
}
|
|
16577
|
+
if (existingStatus.status === "blocked") {
|
|
16578
|
+
writeErrorWithHints(existingStatus.payload);
|
|
16579
|
+
throw cliError$1(existingStatus.message);
|
|
16580
|
+
}
|
|
16581
|
+
throw cliError$1(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before ${copy.actionGerund}.`);
|
|
16582
|
+
}
|
|
16583
|
+
function saveSignupCredentials(params) {
|
|
16584
|
+
saveCliCredentials(params.configDir, {
|
|
16585
|
+
access_token: params.signup.access_token,
|
|
16586
|
+
api_base_url_1: params.apiBaseUrl1,
|
|
16587
|
+
auth_method: "oauth",
|
|
16588
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16589
|
+
expires_at: cliAccessTokenExpiresAt(params.signup.expires_in),
|
|
16590
|
+
oauth_client_id: params.signup.oauth_client_id,
|
|
16591
|
+
oauth_grant_id: params.signup.oauth_grant_id,
|
|
16592
|
+
org_id: params.signup.org_id,
|
|
16593
|
+
org_name: params.signup.org_name,
|
|
16594
|
+
refresh_token: params.signup.refresh_token,
|
|
16595
|
+
token_type: params.signup.token_type
|
|
16596
|
+
});
|
|
16597
|
+
}
|
|
16598
|
+
function writeStartInstructions(start, copy = DEFAULT_SIGNUP_COMMAND_COPY) {
|
|
16599
|
+
process$1.stderr.write(`Sent a ${start.verification_code_length}-digit verification code to ${start.email}.\n`);
|
|
16600
|
+
process$1.stderr.write(`The code expires in ${formatSignupSeconds(start.expires_in)}.\n`);
|
|
16601
|
+
process$1.stderr.write(`Run \`primitive ${copy.confirmCommand(start.email)}\` to finish.\n`);
|
|
15656
16602
|
}
|
|
15657
|
-
async function
|
|
15658
|
-
|
|
15659
|
-
|
|
15660
|
-
|
|
15661
|
-
|
|
16603
|
+
async function startSignup(params) {
|
|
16604
|
+
const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
|
|
16605
|
+
const existingPending = loadPendingAgentSignup(params.configDir, params.apiBaseUrl1);
|
|
16606
|
+
if (existingPending && !params.flags.force) {
|
|
16607
|
+
if (normalizeEmail(existingPending.email) === normalizeEmail(params.email)) {
|
|
16608
|
+
process$1.stderr.write(`Continuing pending Primitive ${copy.actionNoun} for ${existingPending.email}.\n`);
|
|
16609
|
+
process$1.stderr.write(`Run \`primitive ${copy.confirmCommand(existingPending.email)}\` to finish, or \`primitive ${copy.resendCommand(existingPending.email)}\` to send a new code.\n`);
|
|
16610
|
+
return {
|
|
16611
|
+
pending: existingPending,
|
|
16612
|
+
started: false
|
|
16613
|
+
};
|
|
16614
|
+
}
|
|
16615
|
+
throw cliError$1(`Pending ${copy.actionNoun} is for ${existingPending.email}. Run \`primitive ${copy.startCommand(params.email)} --force\` to replace it.`);
|
|
15662
16616
|
}
|
|
15663
|
-
|
|
15664
|
-
|
|
15665
|
-
|
|
15666
|
-
|
|
15667
|
-
|
|
15668
|
-
|
|
15669
|
-
|
|
16617
|
+
if (params.flags.force) deletePendingAgentSignup(params.configDir);
|
|
16618
|
+
const promptRequiredFn = params.deps.promptRequired ?? promptRequired;
|
|
16619
|
+
const confirmTermsFn = params.deps.confirmTerms ?? confirmTerms;
|
|
16620
|
+
const startFn = params.deps.startAgentSignup ?? startAgentSignup;
|
|
16621
|
+
const signupCode = params.flags["signup-code"] ?? await promptRequiredFn("Signup code: ");
|
|
16622
|
+
if (!params.flags["accept-terms"]) await confirmTermsFn();
|
|
16623
|
+
const started = await startFn({
|
|
16624
|
+
body: {
|
|
16625
|
+
device_name: params.flags["device-name"] ?? hostname(),
|
|
16626
|
+
email: params.email,
|
|
16627
|
+
signup_code: signupCode,
|
|
16628
|
+
terms_accepted: true
|
|
16629
|
+
},
|
|
16630
|
+
client: params.apiClient.client,
|
|
16631
|
+
responseStyle: "fields"
|
|
16632
|
+
});
|
|
16633
|
+
if (started.error) {
|
|
16634
|
+
writeErrorWithHints(extractErrorPayload(started.error));
|
|
16635
|
+
throw cliError$1("Could not start Primitive agent signup.");
|
|
16636
|
+
}
|
|
16637
|
+
const startResult = unwrapData(started.data);
|
|
16638
|
+
if (!startResult) throw cliError$1("Primitive API returned an empty agent signup response.");
|
|
16639
|
+
return {
|
|
16640
|
+
pending: savePendingAgentSignup(params.configDir, startResult, params.apiBaseUrl1),
|
|
16641
|
+
started: true
|
|
16642
|
+
};
|
|
15670
16643
|
}
|
|
15671
16644
|
async function resendVerificationCode(params) {
|
|
15672
|
-
const resent = await (params.deps.
|
|
16645
|
+
const resent = await (params.deps.resendAgentSignupVerification ?? resendAgentSignupVerification)({
|
|
15673
16646
|
body: { signup_token: params.start.signup_token },
|
|
15674
16647
|
client: params.apiClient.client,
|
|
15675
16648
|
responseStyle: "fields"
|
|
@@ -15683,195 +16656,510 @@ async function resendVerificationCode(params) {
|
|
|
15683
16656
|
signup_token: params.start.signup_token,
|
|
15684
16657
|
verification_code_length: resend.verification_code_length
|
|
15685
16658
|
} : params.start;
|
|
15686
|
-
|
|
15687
|
-
|
|
15688
|
-
|
|
16659
|
+
return {
|
|
16660
|
+
pending: savePendingAgentSignup(params.configDir, next, params.apiBaseUrl1),
|
|
16661
|
+
resent: true
|
|
16662
|
+
};
|
|
15689
16663
|
}
|
|
15690
16664
|
const payload = extractErrorPayload(resent.error);
|
|
15691
|
-
|
|
15692
|
-
|
|
15693
|
-
|
|
15694
|
-
|
|
16665
|
+
const code = extractErrorCode(payload);
|
|
16666
|
+
if (code === SLOW_DOWN) {
|
|
16667
|
+
const retryAfter = retryAfterSeconds(resent) ?? params.start.resend_after;
|
|
16668
|
+
process$1.stderr.write(`Verification email was sent recently. Wait ${formatSignupSeconds(retryAfter)} before trying again.\n`);
|
|
16669
|
+
return {
|
|
16670
|
+
pending: params.start,
|
|
16671
|
+
resent: false
|
|
16672
|
+
};
|
|
15695
16673
|
}
|
|
16674
|
+
if (code === EXPIRED_TOKEN || code === INVALID_SIGNUP_TOKEN) deletePendingAgentSignup(params.configDir);
|
|
15696
16675
|
writeErrorWithHints(payload);
|
|
15697
|
-
throw cliError("Could not resend Primitive
|
|
16676
|
+
throw cliError$1("Could not resend Primitive agent signup verification email.");
|
|
15698
16677
|
}
|
|
15699
|
-
async function
|
|
16678
|
+
async function runSignupStartWithCredentialLock(params) {
|
|
15700
16679
|
const { configDir, flags } = params;
|
|
15701
16680
|
const deps = params.deps ?? {};
|
|
15702
16681
|
const promptRequiredFn = deps.promptRequired ?? promptRequired;
|
|
15703
|
-
const
|
|
15704
|
-
|
|
15705
|
-
|
|
15706
|
-
|
|
15707
|
-
|
|
16682
|
+
const email = params.email ?? await promptRequiredFn("Email: ");
|
|
16683
|
+
await checkExistingCredentials({
|
|
16684
|
+
apiBaseUrl1: flags["api-base-url-1"],
|
|
16685
|
+
configDir,
|
|
16686
|
+
copy: params.copy,
|
|
16687
|
+
deps,
|
|
16688
|
+
flags
|
|
16689
|
+
});
|
|
16690
|
+
const { apiClient, requestConfig } = createCliApiClient({
|
|
16691
|
+
apiBaseUrl1: flags["api-base-url-1"],
|
|
16692
|
+
configDir
|
|
16693
|
+
});
|
|
16694
|
+
const start = await startSignup({
|
|
16695
|
+
apiBaseUrl1: requestConfig.resolvedApiBaseUrl1,
|
|
16696
|
+
apiClient,
|
|
16697
|
+
configDir,
|
|
16698
|
+
copy: params.copy,
|
|
16699
|
+
deps,
|
|
16700
|
+
email,
|
|
16701
|
+
flags
|
|
16702
|
+
});
|
|
16703
|
+
if (start.started) writeStartInstructions(start.pending, params.copy);
|
|
16704
|
+
}
|
|
16705
|
+
async function runSignupConfirmWithCredentialLock(params) {
|
|
16706
|
+
const { configDir, flags } = params;
|
|
16707
|
+
const deps = params.deps ?? {};
|
|
16708
|
+
if (!params.skipExistingCredentialCheck) await checkExistingCredentials({
|
|
16709
|
+
apiBaseUrl1: flags["api-base-url-1"],
|
|
16710
|
+
configDir,
|
|
16711
|
+
copy: params.copy,
|
|
16712
|
+
deps,
|
|
16713
|
+
flags
|
|
16714
|
+
});
|
|
15708
16715
|
const { apiClient, requestConfig } = createCliApiClient({
|
|
15709
16716
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
15710
16717
|
configDir
|
|
15711
16718
|
});
|
|
15712
16719
|
const apiBaseUrl1 = requestConfig.resolvedApiBaseUrl1;
|
|
15713
|
-
|
|
15714
|
-
|
|
15715
|
-
|
|
15716
|
-
|
|
15717
|
-
|
|
15718
|
-
|
|
15719
|
-
|
|
15720
|
-
|
|
15721
|
-
|
|
15722
|
-
|
|
15723
|
-
|
|
15724
|
-
|
|
15725
|
-
|
|
16720
|
+
const pending = requirePendingSignupForEmail({
|
|
16721
|
+
apiBaseUrl1,
|
|
16722
|
+
copy: params.copy,
|
|
16723
|
+
configDir,
|
|
16724
|
+
email: params.email
|
|
16725
|
+
});
|
|
16726
|
+
const verified = await (deps.verifyAgentSignup ?? verifyAgentSignup)({
|
|
16727
|
+
body: {
|
|
16728
|
+
...flags["org-id"] ? { org_id: flags["org-id"] } : {},
|
|
16729
|
+
signup_token: pending.signup_token,
|
|
16730
|
+
verification_code: params.code
|
|
16731
|
+
},
|
|
16732
|
+
client: apiClient.client,
|
|
16733
|
+
responseStyle: "fields"
|
|
16734
|
+
});
|
|
16735
|
+
if (verified.data) {
|
|
16736
|
+
const signup = unwrapData(verified.data);
|
|
16737
|
+
if (!signup) throw cliError$1("Primitive API returned an empty agent signup verification response.");
|
|
16738
|
+
saveSignupCredentials({
|
|
16739
|
+
apiBaseUrl1,
|
|
15726
16740
|
configDir,
|
|
15727
|
-
|
|
15728
|
-
});
|
|
15729
|
-
if (existingStatus.status === "removed_stale") process$1.stderr.write("Continuing with Primitive CLI signup...\n");
|
|
15730
|
-
else if (existingStatus.status === "blocked") {
|
|
15731
|
-
writeErrorWithHints(existingStatus.payload);
|
|
15732
|
-
throw cliError(existingStatus.message);
|
|
15733
|
-
} else throw cliError(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before creating a new account.`);
|
|
15734
|
-
}
|
|
15735
|
-
if (flags.force) deletePendingCliSignup(configDir);
|
|
15736
|
-
let start = flags.force ? null : loadPendingCliSignup(configDir, apiBaseUrl1);
|
|
15737
|
-
const resumed = Boolean(start);
|
|
15738
|
-
if (start) process$1.stderr.write(`Continuing pending Primitive CLI signup for ${start.email}.\n`);
|
|
15739
|
-
else {
|
|
15740
|
-
const signupCode = await promptRequiredFn("Signup code: ");
|
|
15741
|
-
await confirmTermsFn();
|
|
15742
|
-
const email = await promptRequiredFn("Email: ");
|
|
15743
|
-
const started = await startFn({
|
|
15744
|
-
body: {
|
|
15745
|
-
device_name: flags["device-name"] ?? hostname(),
|
|
15746
|
-
email,
|
|
15747
|
-
signup_code: signupCode,
|
|
15748
|
-
terms_accepted: true
|
|
15749
|
-
},
|
|
15750
|
-
client: apiClient.client,
|
|
15751
|
-
responseStyle: "fields"
|
|
16741
|
+
signup
|
|
15752
16742
|
});
|
|
15753
|
-
|
|
15754
|
-
|
|
15755
|
-
|
|
15756
|
-
}
|
|
15757
|
-
|
|
15758
|
-
if (!startResult) throw cliError("Primitive API returned an empty CLI signup response.");
|
|
15759
|
-
start = savePendingCliSignup(configDir, startResult, apiBaseUrl1);
|
|
16743
|
+
deletePendingAgentSignup(configDir);
|
|
16744
|
+
const org = signup.org_name ? ` (${signup.org_name})` : "";
|
|
16745
|
+
process$1.stderr.write(`Logged in to org ${signup.org_id}${org}.\n`);
|
|
16746
|
+
process$1.stderr.write(`Saved credentials to ${credentialsPath(configDir)}.\n`);
|
|
16747
|
+
return;
|
|
15760
16748
|
}
|
|
15761
|
-
|
|
15762
|
-
|
|
16749
|
+
const payload = extractErrorPayload(verified.error);
|
|
16750
|
+
const code = extractErrorCode(payload);
|
|
16751
|
+
if (code === INVALID_VERIFICATION_CODE) throw cliError$1(`Invalid verification code. Try again or run ${(params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY).resendCommand(params.email)}.`);
|
|
16752
|
+
if (code === EXPIRED_TOKEN || code === INVALID_SIGNUP_TOKEN) deletePendingAgentSignup(configDir);
|
|
16753
|
+
writeErrorWithHints(payload);
|
|
16754
|
+
throw cliError$1("Primitive agent signup failed while verifying the account.");
|
|
16755
|
+
}
|
|
16756
|
+
async function runSignupResendWithCredentialLock(params) {
|
|
16757
|
+
const deps = params.deps ?? {};
|
|
16758
|
+
const { apiClient, requestConfig } = createCliApiClient({
|
|
16759
|
+
apiBaseUrl1: params.flags["api-base-url-1"],
|
|
16760
|
+
configDir: params.configDir
|
|
16761
|
+
});
|
|
16762
|
+
const pending = requirePendingSignupForEmail({
|
|
16763
|
+
apiBaseUrl1: requestConfig.resolvedApiBaseUrl1,
|
|
16764
|
+
copy: params.copy,
|
|
16765
|
+
configDir: params.configDir,
|
|
16766
|
+
email: params.email
|
|
16767
|
+
});
|
|
16768
|
+
const resend = await resendVerificationCode({
|
|
16769
|
+
apiBaseUrl1: requestConfig.resolvedApiBaseUrl1,
|
|
16770
|
+
apiClient,
|
|
16771
|
+
configDir: params.configDir,
|
|
16772
|
+
deps,
|
|
16773
|
+
start: pending
|
|
16774
|
+
});
|
|
16775
|
+
if (resend.resent) process$1.stderr.write(`Sent a new ${resend.pending.verification_code_length}-digit verification code to ${resend.pending.email}. It expires in ${formatSignupSeconds(resend.pending.expires_in)}.\n`);
|
|
16776
|
+
}
|
|
16777
|
+
async function runSignupInteractiveWithCredentialLock(params) {
|
|
16778
|
+
const { configDir, flags } = params;
|
|
16779
|
+
const deps = params.deps ?? {};
|
|
16780
|
+
const promptRequiredFn = deps.promptRequired ?? promptRequired;
|
|
16781
|
+
await checkExistingCredentials({
|
|
16782
|
+
apiBaseUrl1: flags["api-base-url-1"],
|
|
16783
|
+
configDir,
|
|
16784
|
+
deps,
|
|
16785
|
+
flags
|
|
16786
|
+
});
|
|
16787
|
+
const { apiClient, requestConfig } = createCliApiClient({
|
|
16788
|
+
apiBaseUrl1: flags["api-base-url-1"],
|
|
16789
|
+
configDir
|
|
16790
|
+
});
|
|
16791
|
+
const apiBaseUrl1 = requestConfig.resolvedApiBaseUrl1;
|
|
16792
|
+
let start = flags.force ? null : loadPendingAgentSignup(configDir, apiBaseUrl1);
|
|
16793
|
+
if (start) process$1.stderr.write(`Continuing pending Primitive signup for ${start.email}.\n`);
|
|
16794
|
+
else start = (await startSignup({
|
|
16795
|
+
apiBaseUrl1,
|
|
16796
|
+
apiClient,
|
|
16797
|
+
configDir,
|
|
16798
|
+
deps,
|
|
16799
|
+
email: await promptRequiredFn("Email: "),
|
|
16800
|
+
flags
|
|
16801
|
+
})).pending;
|
|
16802
|
+
process$1.stderr.write(`Check your email for the ${start.verification_code_length}-digit verification code sent to ${start.email}.\n`);
|
|
15763
16803
|
process$1.stderr.write(`The code expires in ${formatSignupSeconds(start.expires_in)}.\n`);
|
|
15764
16804
|
process$1.stderr.write(`Enter the code from the email, or type \`resend\` to send a new code after ${formatSignupSeconds(start.resend_after)}.\n`);
|
|
15765
16805
|
while (true) {
|
|
15766
16806
|
const verificationCode = await promptRequiredFn(`Verification code (${start.verification_code_length} digits): `);
|
|
15767
16807
|
if (verificationCode.toLowerCase() === "resend") {
|
|
15768
|
-
|
|
16808
|
+
const resend = await resendVerificationCode({
|
|
15769
16809
|
apiBaseUrl1,
|
|
15770
16810
|
apiClient,
|
|
15771
16811
|
configDir,
|
|
15772
16812
|
deps,
|
|
15773
16813
|
start
|
|
15774
16814
|
});
|
|
16815
|
+
start = resend.pending;
|
|
16816
|
+
if (resend.resent) process$1.stderr.write(`Sent a new ${start.verification_code_length}-digit verification code. It expires in ${formatSignupSeconds(start.expires_in)}.\n`);
|
|
15775
16817
|
continue;
|
|
15776
16818
|
}
|
|
15777
|
-
|
|
15778
|
-
|
|
15779
|
-
|
|
15780
|
-
|
|
15781
|
-
|
|
15782
|
-
|
|
15783
|
-
|
|
16819
|
+
try {
|
|
16820
|
+
await runSignupConfirmWithCredentialLock({
|
|
16821
|
+
code: verificationCode,
|
|
16822
|
+
configDir,
|
|
16823
|
+
deps,
|
|
16824
|
+
email: start.email,
|
|
16825
|
+
flags: {
|
|
16826
|
+
"api-base-url-1": flags["api-base-url-1"],
|
|
16827
|
+
force: true
|
|
15784
16828
|
},
|
|
15785
|
-
|
|
15786
|
-
responseStyle: "fields"
|
|
16829
|
+
skipExistingCredentialCheck: true
|
|
15787
16830
|
});
|
|
15788
|
-
|
|
15789
|
-
|
|
15790
|
-
|
|
15791
|
-
saveCliCredentials(configDir, {
|
|
15792
|
-
api_key: signup.api_key,
|
|
15793
|
-
api_base_url_1: apiBaseUrl1,
|
|
15794
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15795
|
-
key_id: signup.key_id,
|
|
15796
|
-
key_prefix: signup.key_prefix,
|
|
15797
|
-
org_id: signup.org_id,
|
|
15798
|
-
org_name: signup.org_name
|
|
15799
|
-
});
|
|
15800
|
-
deletePendingCliSignup(configDir);
|
|
15801
|
-
const org = signup.org_name ? ` (${signup.org_name})` : "";
|
|
15802
|
-
process$1.stderr.write(`Created account and logged in to org ${signup.org_id}${org}.\n`);
|
|
15803
|
-
process$1.stderr.write(`Saved credentials to ${credentialsPath(configDir)}.\n`);
|
|
15804
|
-
return;
|
|
15805
|
-
}
|
|
15806
|
-
const payload = extractErrorPayload(verified.error);
|
|
15807
|
-
const code = extractErrorCode(payload);
|
|
15808
|
-
if (code === INVALID_VERIFICATION_CODE) {
|
|
16831
|
+
return;
|
|
16832
|
+
} catch (error) {
|
|
16833
|
+
if (error instanceof Errors.CLIError && error.message.startsWith("Invalid verification code.")) {
|
|
15809
16834
|
process$1.stderr.write("Invalid verification code. Try again or type `resend`.\n");
|
|
15810
|
-
break;
|
|
15811
|
-
}
|
|
15812
|
-
if (shouldRetrySignupPassword(code)) {
|
|
15813
|
-
const message = signupErrorMessage(payload);
|
|
15814
|
-
if (message) process$1.stderr.write(`Password rejected: ${message}\n`);
|
|
15815
|
-
process$1.stderr.write("Choose a different password and try again.\n");
|
|
15816
|
-
password = await promptNewPasswordFn();
|
|
15817
16835
|
continue;
|
|
15818
16836
|
}
|
|
15819
|
-
|
|
15820
|
-
writeErrorWithHints(payload);
|
|
15821
|
-
throw cliError("Primitive CLI signup failed while verifying the account.");
|
|
16837
|
+
throw error;
|
|
15822
16838
|
}
|
|
15823
16839
|
}
|
|
15824
16840
|
}
|
|
16841
|
+
function commonStartFlags() {
|
|
16842
|
+
return {
|
|
16843
|
+
"accept-terms": Flags.boolean({ description: "Confirm acceptance of Primitive's Terms of Service and Privacy Policy" }),
|
|
16844
|
+
"api-base-url-1": Flags.string({
|
|
16845
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
16846
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
16847
|
+
hidden: true
|
|
16848
|
+
}),
|
|
16849
|
+
"device-name": Flags.string({ description: "Device name used for the created CLI OAuth session" }),
|
|
16850
|
+
force: Flags.boolean({
|
|
16851
|
+
char: "f",
|
|
16852
|
+
description: "Replace saved credentials or pending signup state when needed"
|
|
16853
|
+
}),
|
|
16854
|
+
"signup-code": Flags.string({
|
|
16855
|
+
description: "Signup code required to create an account",
|
|
16856
|
+
env: "PRIMITIVE_SIGNUP_CODE"
|
|
16857
|
+
})
|
|
16858
|
+
};
|
|
16859
|
+
}
|
|
15825
16860
|
var SignupCommand = class SignupCommand extends Command {
|
|
15826
|
-
static
|
|
15827
|
-
|
|
16861
|
+
static args = { email: Args.string({
|
|
16862
|
+
description: "Email address to sign up",
|
|
16863
|
+
required: false
|
|
16864
|
+
}) };
|
|
16865
|
+
static description = "Start a Primitive account signup, send an email verification code, and save a pending signup token locally.";
|
|
16866
|
+
static summary = "Start account signup";
|
|
15828
16867
|
static examples = [
|
|
15829
|
-
"<%= config.bin %> signup",
|
|
15830
|
-
"<%= config.bin %> signup --
|
|
15831
|
-
"<%= config.bin %> signup
|
|
16868
|
+
"<%= config.bin %> signup user@example.com",
|
|
16869
|
+
"<%= config.bin %> signup user@example.com --signup-code invite-code --accept-terms",
|
|
16870
|
+
"<%= config.bin %> signup confirm user@example.com 123456"
|
|
15832
16871
|
];
|
|
16872
|
+
static flags = commonStartFlags();
|
|
16873
|
+
async run() {
|
|
16874
|
+
const { args, flags } = await this.parse(SignupCommand);
|
|
16875
|
+
let releaseCredentialsLock;
|
|
16876
|
+
try {
|
|
16877
|
+
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
16878
|
+
} catch (error) {
|
|
16879
|
+
throw cliError$1(error instanceof Error ? error.message : String(error));
|
|
16880
|
+
}
|
|
16881
|
+
try {
|
|
16882
|
+
await runSignupStartWithCredentialLock({
|
|
16883
|
+
configDir: this.config.configDir,
|
|
16884
|
+
email: args.email,
|
|
16885
|
+
flags
|
|
16886
|
+
});
|
|
16887
|
+
} finally {
|
|
16888
|
+
releaseCredentialsLock();
|
|
16889
|
+
}
|
|
16890
|
+
}
|
|
16891
|
+
};
|
|
16892
|
+
var SignupConfirmCommand = class SignupConfirmCommand extends Command {
|
|
16893
|
+
static args = {
|
|
16894
|
+
email: Args.string({
|
|
16895
|
+
description: "Email address used to start signup",
|
|
16896
|
+
required: true
|
|
16897
|
+
}),
|
|
16898
|
+
code: Args.string({
|
|
16899
|
+
description: "Verification code from the signup email",
|
|
16900
|
+
required: true
|
|
16901
|
+
})
|
|
16902
|
+
};
|
|
16903
|
+
static description = "Confirm a pending Primitive signup, create an OAuth session, and save CLI credentials locally.";
|
|
16904
|
+
static summary = "Confirm account signup";
|
|
16905
|
+
static examples = ["<%= config.bin %> signup confirm user@example.com 123456", "<%= config.bin %> signup confirm user@example.com 123456 --org-id 00000000-0000-4000-8000-000000000000"];
|
|
15833
16906
|
static flags = {
|
|
15834
16907
|
"api-base-url-1": Flags.string({
|
|
15835
16908
|
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
15836
16909
|
env: "PRIMITIVE_API_BASE_URL_1",
|
|
15837
16910
|
hidden: true
|
|
15838
16911
|
}),
|
|
15839
|
-
"device-name": Flags.string({ description: "Device name used for the created CLI API key" }),
|
|
15840
16912
|
force: Flags.boolean({
|
|
15841
16913
|
char: "f",
|
|
15842
|
-
description: "Replace saved credentials
|
|
15843
|
-
})
|
|
16914
|
+
description: "Replace saved credentials after verification"
|
|
16915
|
+
}),
|
|
16916
|
+
"org-id": Flags.string({ description: "Workspace id to target when the email belongs to multiple workspaces" })
|
|
15844
16917
|
};
|
|
15845
16918
|
async run() {
|
|
15846
|
-
const { flags } = await this.parse(
|
|
16919
|
+
const { args, flags } = await this.parse(SignupConfirmCommand);
|
|
15847
16920
|
let releaseCredentialsLock;
|
|
15848
16921
|
try {
|
|
15849
16922
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
15850
16923
|
} catch (error) {
|
|
15851
|
-
throw cliError(error instanceof Error ? error.message : String(error));
|
|
16924
|
+
throw cliError$1(error instanceof Error ? error.message : String(error));
|
|
15852
16925
|
}
|
|
15853
16926
|
try {
|
|
15854
|
-
await
|
|
16927
|
+
await runSignupConfirmWithCredentialLock({
|
|
16928
|
+
code: args.code,
|
|
16929
|
+
configDir: this.config.configDir,
|
|
16930
|
+
email: args.email,
|
|
16931
|
+
flags
|
|
16932
|
+
});
|
|
15855
16933
|
} finally {
|
|
15856
16934
|
releaseCredentialsLock();
|
|
15857
16935
|
}
|
|
15858
16936
|
}
|
|
15859
|
-
|
|
15860
|
-
|
|
15861
|
-
|
|
15862
|
-
|
|
15863
|
-
|
|
16937
|
+
};
|
|
16938
|
+
var SignupResendCommand = class SignupResendCommand extends Command {
|
|
16939
|
+
static args = { email: Args.string({
|
|
16940
|
+
description: "Email address used to start signup",
|
|
16941
|
+
required: true
|
|
16942
|
+
}) };
|
|
16943
|
+
static description = "Resend the verification code for a pending signup.";
|
|
16944
|
+
static summary = "Resend signup verification code";
|
|
16945
|
+
static examples = ["<%= config.bin %> signup resend user@example.com"];
|
|
16946
|
+
static flags = { "api-base-url-1": Flags.string({
|
|
16947
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
16948
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
16949
|
+
hidden: true
|
|
16950
|
+
}) };
|
|
16951
|
+
async run() {
|
|
16952
|
+
const { args, flags } = await this.parse(SignupResendCommand);
|
|
16953
|
+
let releaseCredentialsLock;
|
|
16954
|
+
try {
|
|
16955
|
+
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
16956
|
+
} catch (error) {
|
|
16957
|
+
throw cliError$1(error instanceof Error ? error.message : String(error));
|
|
16958
|
+
}
|
|
16959
|
+
try {
|
|
16960
|
+
await runSignupResendWithCredentialLock({
|
|
16961
|
+
configDir: this.config.configDir,
|
|
16962
|
+
email: args.email,
|
|
16963
|
+
flags
|
|
16964
|
+
});
|
|
16965
|
+
} finally {
|
|
16966
|
+
releaseCredentialsLock();
|
|
16967
|
+
}
|
|
16968
|
+
}
|
|
16969
|
+
};
|
|
16970
|
+
var SignupInteractiveCommand = class SignupInteractiveCommand extends Command {
|
|
16971
|
+
static description = "Run the full signup flow in one interactive terminal session.";
|
|
16972
|
+
static summary = "Run interactive account signup";
|
|
16973
|
+
static examples = ["<%= config.bin %> signup interactive"];
|
|
16974
|
+
static flags = commonStartFlags();
|
|
16975
|
+
async run() {
|
|
16976
|
+
const { flags } = await this.parse(SignupInteractiveCommand);
|
|
16977
|
+
let releaseCredentialsLock;
|
|
16978
|
+
try {
|
|
16979
|
+
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
16980
|
+
} catch (error) {
|
|
16981
|
+
throw cliError$1(error instanceof Error ? error.message : String(error));
|
|
16982
|
+
}
|
|
16983
|
+
try {
|
|
16984
|
+
await runSignupInteractiveWithCredentialLock({
|
|
16985
|
+
configDir: this.config.configDir,
|
|
16986
|
+
flags
|
|
16987
|
+
});
|
|
16988
|
+
} finally {
|
|
16989
|
+
releaseCredentialsLock();
|
|
16990
|
+
}
|
|
16991
|
+
}
|
|
16992
|
+
};
|
|
16993
|
+
//#endregion
|
|
16994
|
+
//#region src/oclif/commands/signin.ts
|
|
16995
|
+
function cliError(message) {
|
|
16996
|
+
return new Errors.CLIError(message, { exit: 1 });
|
|
16997
|
+
}
|
|
16998
|
+
const SIGNIN_OTP_COPY = {
|
|
16999
|
+
actionNoun: "sign-in",
|
|
17000
|
+
actionGerund: "signing in",
|
|
17001
|
+
confirmCommand: (email) => `signin otp confirm ${email} <code>`,
|
|
17002
|
+
resendCommand: (email) => `signin otp resend ${email}`,
|
|
17003
|
+
startCommand: (email) => `signin otp ${email}`
|
|
17004
|
+
};
|
|
17005
|
+
function acquireCredentialsLock(configDir) {
|
|
17006
|
+
try {
|
|
17007
|
+
return acquireCliCredentialsLock(configDir);
|
|
17008
|
+
} catch (error) {
|
|
17009
|
+
throw cliError(error instanceof Error ? error.message : String(error));
|
|
17010
|
+
}
|
|
17011
|
+
}
|
|
17012
|
+
function commonOtpStartFlags() {
|
|
17013
|
+
return {
|
|
17014
|
+
"accept-terms": Flags.boolean({ description: "Confirm acceptance of Primitive's Terms of Service and Privacy Policy" }),
|
|
17015
|
+
"api-base-url-1": Flags.string({
|
|
17016
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
17017
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
17018
|
+
hidden: true
|
|
17019
|
+
}),
|
|
17020
|
+
"device-name": Flags.string({ description: "Device name used for the created CLI OAuth session" }),
|
|
17021
|
+
force: Flags.boolean({
|
|
17022
|
+
char: "f",
|
|
17023
|
+
description: "Replace saved credentials or pending sign-in state when needed"
|
|
17024
|
+
}),
|
|
17025
|
+
"signup-code": Flags.string({
|
|
17026
|
+
description: "Signup code required to start OTP sign-in",
|
|
17027
|
+
env: "PRIMITIVE_SIGNUP_CODE"
|
|
17028
|
+
})
|
|
17029
|
+
};
|
|
17030
|
+
}
|
|
17031
|
+
var SigninCommand = class extends LoginCommand {
|
|
17032
|
+
static description = `Sign in to an existing Primitive account with browser approval and save an org-scoped OAuth session locally.
|
|
17033
|
+
|
|
17034
|
+
This is the canonical sign-in command. It defaults to the same browser approval flow as \`primitive signin browser\`. For email-code sign-in, use \`primitive signin otp <email> --signup-code <code>\`, then \`primitive signin otp confirm <email> <code>\`. For new account creation, use \`primitive signup <email>\`.`;
|
|
17035
|
+
static summary = "Sign in to an existing account";
|
|
17036
|
+
static examples = [
|
|
17037
|
+
"<%= config.bin %> signin",
|
|
17038
|
+
"<%= config.bin %> signin browser",
|
|
17039
|
+
"<%= config.bin %> signin --no-browser",
|
|
17040
|
+
"<%= config.bin %> signin otp user@example.com --signup-code invite-code --accept-terms",
|
|
17041
|
+
"<%= config.bin %> signin otp confirm user@example.com 123456"
|
|
17042
|
+
];
|
|
17043
|
+
retryCommand() {
|
|
17044
|
+
return "signin";
|
|
17045
|
+
}
|
|
17046
|
+
};
|
|
17047
|
+
var SigninBrowserCommand = class extends LoginCommand {
|
|
17048
|
+
static description = "Sign in to an existing Primitive account by opening Primitive in your browser and saving an org-scoped OAuth session locally.";
|
|
17049
|
+
static summary = "Sign in with browser approval";
|
|
17050
|
+
static examples = [
|
|
17051
|
+
"<%= config.bin %> signin browser",
|
|
17052
|
+
"<%= config.bin %> signin browser --device-name work-laptop",
|
|
17053
|
+
"<%= config.bin %> signin browser --no-browser",
|
|
17054
|
+
"<%= config.bin %> signin browser --force"
|
|
17055
|
+
];
|
|
17056
|
+
retryCommand() {
|
|
17057
|
+
return "signin browser";
|
|
17058
|
+
}
|
|
17059
|
+
};
|
|
17060
|
+
var SigninOtpCommand = class SigninOtpCommand extends Command {
|
|
17061
|
+
static args = { email: Args.string({
|
|
17062
|
+
description: "Email address to sign in with",
|
|
17063
|
+
required: false
|
|
17064
|
+
}) };
|
|
17065
|
+
static description = "Start email-code sign-in using Primitive's signup/auth OTP flow, send a verification code, and save the pending token locally. Requires a signup code.";
|
|
17066
|
+
static summary = "Start OTP sign-in";
|
|
17067
|
+
static examples = ["<%= config.bin %> signin otp user@example.com --signup-code invite-code --accept-terms", "<%= config.bin %> signin otp confirm user@example.com 123456"];
|
|
17068
|
+
static flags = commonOtpStartFlags();
|
|
17069
|
+
async run() {
|
|
17070
|
+
const { args, flags } = await this.parse(SigninOtpCommand);
|
|
17071
|
+
const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
|
|
17072
|
+
try {
|
|
17073
|
+
await runSignupStartWithCredentialLock({
|
|
17074
|
+
configDir: this.config.configDir,
|
|
17075
|
+
copy: SIGNIN_OTP_COPY,
|
|
17076
|
+
email: args.email,
|
|
17077
|
+
flags
|
|
17078
|
+
});
|
|
17079
|
+
} finally {
|
|
17080
|
+
releaseCredentialsLock();
|
|
17081
|
+
}
|
|
17082
|
+
}
|
|
17083
|
+
};
|
|
17084
|
+
var SigninOtpConfirmCommand = class SigninOtpConfirmCommand extends Command {
|
|
17085
|
+
static args = {
|
|
17086
|
+
email: Args.string({
|
|
17087
|
+
description: "Email address used to start OTP sign-in",
|
|
17088
|
+
required: true
|
|
17089
|
+
}),
|
|
17090
|
+
code: Args.string({
|
|
17091
|
+
description: "Verification code from the sign-in email",
|
|
17092
|
+
required: true
|
|
17093
|
+
})
|
|
17094
|
+
};
|
|
17095
|
+
static description = "Confirm a pending OTP sign-in, create an OAuth session, and save CLI credentials locally.";
|
|
17096
|
+
static summary = "Confirm OTP sign-in";
|
|
17097
|
+
static examples = ["<%= config.bin %> signin otp confirm user@example.com 123456", "<%= config.bin %> signin otp confirm user@example.com 123456 --org-id 00000000-0000-4000-8000-000000000000"];
|
|
17098
|
+
static flags = {
|
|
17099
|
+
"api-base-url-1": Flags.string({
|
|
17100
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
17101
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
17102
|
+
hidden: true
|
|
17103
|
+
}),
|
|
17104
|
+
force: Flags.boolean({
|
|
17105
|
+
char: "f",
|
|
17106
|
+
description: "Replace saved credentials after verification"
|
|
17107
|
+
}),
|
|
17108
|
+
"org-id": Flags.string({ description: "Workspace id to target when the email belongs to multiple workspaces" })
|
|
17109
|
+
};
|
|
17110
|
+
async run() {
|
|
17111
|
+
const { args, flags } = await this.parse(SigninOtpConfirmCommand);
|
|
17112
|
+
const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
|
|
17113
|
+
try {
|
|
17114
|
+
await runSignupConfirmWithCredentialLock({
|
|
17115
|
+
code: args.code,
|
|
17116
|
+
configDir: this.config.configDir,
|
|
17117
|
+
copy: SIGNIN_OTP_COPY,
|
|
17118
|
+
email: args.email,
|
|
17119
|
+
flags
|
|
17120
|
+
});
|
|
17121
|
+
} finally {
|
|
17122
|
+
releaseCredentialsLock();
|
|
17123
|
+
}
|
|
17124
|
+
}
|
|
17125
|
+
};
|
|
17126
|
+
var SigninOtpResendCommand = class SigninOtpResendCommand extends Command {
|
|
17127
|
+
static args = { email: Args.string({
|
|
17128
|
+
description: "Email address used to start OTP sign-in",
|
|
17129
|
+
required: true
|
|
17130
|
+
}) };
|
|
17131
|
+
static description = "Resend the verification code for a pending OTP sign-in.";
|
|
17132
|
+
static summary = "Resend OTP sign-in code";
|
|
17133
|
+
static examples = ["<%= config.bin %> signin otp resend user@example.com"];
|
|
17134
|
+
static flags = { "api-base-url-1": Flags.string({
|
|
17135
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
17136
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
17137
|
+
hidden: true
|
|
17138
|
+
}) };
|
|
17139
|
+
async run() {
|
|
17140
|
+
const { args, flags } = await this.parse(SigninOtpResendCommand);
|
|
17141
|
+
const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
|
|
17142
|
+
try {
|
|
17143
|
+
await runSignupResendWithCredentialLock({
|
|
17144
|
+
configDir: this.config.configDir,
|
|
17145
|
+
copy: SIGNIN_OTP_COPY,
|
|
17146
|
+
email: args.email,
|
|
17147
|
+
flags
|
|
17148
|
+
});
|
|
17149
|
+
} finally {
|
|
17150
|
+
releaseCredentialsLock();
|
|
17151
|
+
}
|
|
15864
17152
|
}
|
|
15865
17153
|
};
|
|
15866
17154
|
//#endregion
|
|
15867
17155
|
//#region src/oclif/commands/whoami.ts
|
|
15868
17156
|
var WhoamiCommand = class WhoamiCommand extends Command {
|
|
15869
|
-
static description = `Print the account currently authenticated by
|
|
17157
|
+
static description = `Print the account currently authenticated by saved OAuth credentials or an explicit API key. Useful as a credentials smoke test: confirms auth is live and shows which account it belongs to.`;
|
|
15870
17158
|
static summary = "Print the authenticated account (credentials smoke test)";
|
|
15871
17159
|
static examples = ["<%= config.bin %> whoami", "<%= config.bin %> whoami --api-key prim_..."];
|
|
15872
17160
|
static flags = {
|
|
15873
17161
|
"api-key": Flags.string({
|
|
15874
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
17162
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
15875
17163
|
env: "PRIMITIVE_API_KEY"
|
|
15876
17164
|
}),
|
|
15877
17165
|
"api-base-url-1": Flags.string({
|
|
@@ -15889,7 +17177,7 @@ var WhoamiCommand = class WhoamiCommand extends Command {
|
|
|
15889
17177
|
async run() {
|
|
15890
17178
|
const { flags } = await this.parse(WhoamiCommand);
|
|
15891
17179
|
await runWithTiming(flags.time, async () => {
|
|
15892
|
-
const { apiClient, auth, baseUrlOverridden } = createAuthenticatedCliApiClient({
|
|
17180
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
15893
17181
|
apiKey: flags["api-key"],
|
|
15894
17182
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
15895
17183
|
apiBaseUrl2: flags["api-base-url-2"],
|
|
@@ -15983,7 +17271,7 @@ function renderFishCompletion(binName) {
|
|
|
15983
17271
|
for (const operation of topicOperations) {
|
|
15984
17272
|
lines.push(`complete -c ${binName} -f -n '__fish_${binName}_topic_needs_subcommand ${fishEscape(topic)}' -a '${fishEscape(operation.command)}' -d '${fishEscape(operation.summary ?? `${operation.method} ${operation.path}`)}'`);
|
|
15985
17273
|
for (const parameter of [...operation.pathParams, ...operation.queryParams]) lines.push(`complete -c ${binName} -n '${operationCondition(operation).replace(BIN_PLACEHOLDER, binName)}' -l '${fishEscape(parameter.name.replace(/_/g, "-"))}' -r -d '${fishEscape(parameter.description ?? parameter.name)}'`);
|
|
15986
|
-
lines.push(`complete -c ${binName} -n '${operationCondition(operation).replace(BIN_PLACEHOLDER, binName)}' -l 'api-key' -r -d 'Primitive API key (defaults to PRIMITIVE_API_KEY or saved
|
|
17274
|
+
lines.push(`complete -c ${binName} -n '${operationCondition(operation).replace(BIN_PLACEHOLDER, binName)}' -l 'api-key' -r -d 'Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)'`);
|
|
15987
17275
|
if (!operation.binaryResponse) lines.push(`complete -c ${binName} -n '${operationCondition(operation).replace(BIN_PLACEHOLDER, binName)}' -l 'envelope' -d 'Print the full response envelope, including pagination metadata'`);
|
|
15988
17276
|
if (operation.hasJsonBody) lines.push(`complete -c ${binName} -n '${operationCondition(operation).replace(BIN_PLACEHOLDER, binName)}' -l 'body' -r -d 'JSON request body'`, `complete -c ${binName} -n '${operationCondition(operation).replace(BIN_PLACEHOLDER, binName)}' -l 'body-file' -r -d 'Path to a JSON file used as the request body'`);
|
|
15989
17277
|
if (operation.binaryResponse) lines.push(`complete -c ${binName} -n '${operationCondition(operation).replace(BIN_PLACEHOLDER, binName)}' -l 'output' -r -d 'Write binary response bytes to a file'`);
|
|
@@ -16135,7 +17423,15 @@ const COMMANDS = {
|
|
|
16135
17423
|
reply: ReplyCommand,
|
|
16136
17424
|
chat: ChatCommand,
|
|
16137
17425
|
login: LoginCommand,
|
|
17426
|
+
signin: SigninCommand,
|
|
17427
|
+
"signin:browser": SigninBrowserCommand,
|
|
17428
|
+
"signin:otp": SigninOtpCommand,
|
|
17429
|
+
"signin:otp:confirm": SigninOtpConfirmCommand,
|
|
17430
|
+
"signin:otp:resend": SigninOtpResendCommand,
|
|
16138
17431
|
signup: SignupCommand,
|
|
17432
|
+
"signup:confirm": SignupConfirmCommand,
|
|
17433
|
+
"signup:interactive": SignupInteractiveCommand,
|
|
17434
|
+
"signup:resend": SignupResendCommand,
|
|
16139
17435
|
logout: LogoutCommand,
|
|
16140
17436
|
whoami: WhoamiCommand,
|
|
16141
17437
|
doctor: DoctorCommand,
|