@primitivedotdev/cli 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,6 +16,8 @@ primitive whoami
16
16
  prim whoami
17
17
  ```
18
18
 
19
+ The same CLI is also published unscoped as [`primcli`](https://www.npmjs.com/package/primcli) — `npm install -g primcli` installs an identical build with the same `primitive`/`prim` commands. Use whichever name you prefer; they track the same version.
20
+
19
21
  Or with no install:
20
22
 
21
23
  ```bash
@@ -2,7 +2,7 @@ import { A as PrimitiveApiClient, C as saveCliCredentials, D as loadActiveChatSt
2
2
  import { Args, Command, Errors, Flags, ux } from "@oclif/core";
3
3
  import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
4
4
  import { randomUUID } from "node:crypto";
5
- import { basename, dirname, join, relative, resolve, sep } from "node:path";
5
+ import path, { basename, dirname, join, relative, resolve, sep } from "node:path";
6
6
  import { hostname } from "node:os";
7
7
  import process$1 from "node:process";
8
8
  import { createInterface } from "node:readline/promises";
@@ -26,6 +26,8 @@ const client = createClient(createConfig({ baseUrl: "https://api.primitive.dev/v
26
26
  var sdk_gen_exports = /* @__PURE__ */ __exportAll({
27
27
  addDomain: () => addDomain,
28
28
  cliLogout: () => cliLogout,
29
+ createAgentAccount: () => createAgentAccount,
30
+ createAgentClaimLink: () => createAgentClaimLink,
29
31
  createEndpoint: () => createEndpoint,
30
32
  createFilter: () => createFilter,
31
33
  createFunction: () => createFunction,
@@ -74,6 +76,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
74
76
  sendEmail: () => sendEmail,
75
77
  setFunctionRoute: () => setFunctionRoute,
76
78
  setFunctionSecret: () => setFunctionSecret,
79
+ startAgentClaim: () => startAgentClaim,
77
80
  startAgentSignup: () => startAgentSignup,
78
81
  startCliLogin: () => startCliLogin,
79
82
  startCliSignup: () => startCliSignup,
@@ -85,6 +88,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
85
88
  updateEndpoint: () => updateEndpoint,
86
89
  updateFilter: () => updateFilter,
87
90
  updateFunction: () => updateFunction,
91
+ verifyAgentClaim: () => verifyAgentClaim,
88
92
  verifyAgentSignup: () => verifyAgentSignup,
89
93
  verifyCliSignup: () => verifyCliSignup,
90
94
  verifyDomain: () => verifyDomain
@@ -229,6 +233,92 @@ const verifyAgentSignup = (options) => (options.client ?? client).post({
229
233
  }
230
234
  });
231
235
  /**
236
+ * Create an emailless agent account
237
+ *
238
+ * Creates an emailless agent account without authentication and returns a
239
+ * one-time API key (prefixed `prim_`) plus a provisioned managed inbox.
240
+ * The account is on the `agent` plan: reply-only (it can send only to
241
+ * addresses that have already sent it authenticated mail) with tight send
242
+ * limits. Use the returned `api_key` as a Bearer token on later calls. The
243
+ * account can be upgraded to a full developer account by confirming an
244
+ * email through the claim flow. This endpoint does not require an API key.
245
+ *
246
+ */
247
+ const createAgentAccount = (options) => (options.client ?? client).post({
248
+ url: "/agent/accounts",
249
+ ...options,
250
+ headers: {
251
+ ...options.body !== void 0 && { "Content-Type": "application/json" },
252
+ ...options.headers
253
+ }
254
+ });
255
+ /**
256
+ * Start an agent account email claim
257
+ *
258
+ * Begins upgrading an emailless `agent` account into a full `developer`
259
+ * account by confirming an email address. Authenticated by the agent's own
260
+ * API key (the org is taken from the credential). Sends a verification
261
+ * code to the supplied email and returns the claim session id plus resend
262
+ * timing. Submit the code to `/agent/claim/verify` to complete the
263
+ * upgrade. Confirming an email that already belongs to a Primitive account
264
+ * is rejected.
265
+ *
266
+ */
267
+ const startAgentClaim = (options) => (options.client ?? client).post({
268
+ security: [{
269
+ scheme: "bearer",
270
+ type: "http"
271
+ }],
272
+ url: "/agent/claim/start",
273
+ ...options,
274
+ headers: {
275
+ ...options.body !== void 0 && { "Content-Type": "application/json" },
276
+ ...options.headers
277
+ }
278
+ });
279
+ /**
280
+ * Verify an agent account email claim
281
+ *
282
+ * Confirms the verification code emailed by `/agent/claim/start` and
283
+ * upgrades the account to the `developer` plan. The org id, API key, and
284
+ * managed inbox all carry over; the send cap lifts. Authenticated by the
285
+ * agent's own API key.
286
+ *
287
+ */
288
+ const verifyAgentClaim = (options) => (options.client ?? client).post({
289
+ security: [{
290
+ scheme: "bearer",
291
+ type: "http"
292
+ }],
293
+ url: "/agent/claim/verify",
294
+ ...options,
295
+ headers: {
296
+ ...options.body !== void 0 && { "Content-Type": "application/json" },
297
+ ...options.headers
298
+ }
299
+ });
300
+ /**
301
+ * Create a browser claim link
302
+ *
303
+ * Mints an opaque, single-use link an agent can hand to a human to
304
+ * complete the email-confirmation upgrade in a browser. Authenticated by
305
+ * the agent's own API key. `claim_url` is null when the API host cannot
306
+ * resolve a web origin to build the link.
307
+ *
308
+ */
309
+ const createAgentClaimLink = (options) => (options?.client ?? client).post({
310
+ security: [{
311
+ scheme: "bearer",
312
+ type: "http"
313
+ }],
314
+ url: "/agent/claim/link",
315
+ ...options,
316
+ headers: {
317
+ "Content-Type": "application/json",
318
+ ...options?.headers
319
+ }
320
+ });
321
+ /**
232
322
  * Revoke the current CLI OAuth session
233
323
  *
234
324
  * Revokes the OAuth grant used to authenticate the request. API-key
@@ -1834,6 +1924,128 @@ const openapiDocument = {
1834
1924
  "429": { "$ref": "#/components/responses/RateLimited" }
1835
1925
  }
1836
1926
  } },
1927
+ "/agent/accounts": { "post": {
1928
+ "operationId": "createAgentAccount",
1929
+ "summary": "Create an emailless agent account",
1930
+ "description": "Creates an emailless agent account without authentication and returns a\none-time API key (prefixed `prim_`) plus a provisioned managed inbox.\nThe account is on the `agent` plan: reply-only (it can send only to\naddresses that have already sent it authenticated mail) with tight send\nlimits. Use the returned `api_key` as a Bearer token on later calls. The\naccount can be upgraded to a full developer account by confirming an\nemail through the claim flow. This endpoint does not require an API key.\n",
1931
+ "tags": ["Agent"],
1932
+ "security": [],
1933
+ "requestBody": {
1934
+ "required": true,
1935
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateAgentAccountInput" } } }
1936
+ },
1937
+ "responses": {
1938
+ "200": {
1939
+ "description": "Agent account created; the API key is returned once",
1940
+ "headers": { "Cache-Control": {
1941
+ "schema": { "type": "string" },
1942
+ "description": "Always `no-store`"
1943
+ } },
1944
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
1945
+ "type": "object",
1946
+ "properties": { "data": { "$ref": "#/components/schemas/AgentAccountResult" } }
1947
+ }] } } }
1948
+ },
1949
+ "400": { "$ref": "#/components/responses/ValidationError" },
1950
+ "429": { "$ref": "#/components/responses/RateLimited" }
1951
+ }
1952
+ } },
1953
+ "/agent/claim/start": { "post": {
1954
+ "operationId": "startAgentClaim",
1955
+ "summary": "Start an agent account email claim",
1956
+ "description": "Begins upgrading an emailless `agent` account into a full `developer`\naccount by confirming an email address. Authenticated by the agent's own\nAPI key (the org is taken from the credential). Sends a verification\ncode to the supplied email and returns the claim session id plus resend\ntiming. Submit the code to `/agent/claim/verify` to complete the\nupgrade. Confirming an email that already belongs to a Primitive account\nis rejected.\n",
1957
+ "tags": ["Agent"],
1958
+ "requestBody": {
1959
+ "required": true,
1960
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StartAgentClaimInput" } } }
1961
+ },
1962
+ "responses": {
1963
+ "200": {
1964
+ "description": "Claim started and verification email sent",
1965
+ "headers": { "Cache-Control": {
1966
+ "schema": { "type": "string" },
1967
+ "description": "Always `no-store`"
1968
+ } },
1969
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
1970
+ "type": "object",
1971
+ "properties": { "data": { "$ref": "#/components/schemas/AgentClaimStartResult" } }
1972
+ }] } } }
1973
+ },
1974
+ "400": { "$ref": "#/components/responses/ValidationError" },
1975
+ "401": { "$ref": "#/components/responses/Unauthorized" },
1976
+ "404": { "$ref": "#/components/responses/NotFound" },
1977
+ "409": {
1978
+ "description": "The email is already in use, or the account is not claimable",
1979
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
1980
+ },
1981
+ "429": { "$ref": "#/components/responses/RateLimited" }
1982
+ }
1983
+ } },
1984
+ "/agent/claim/verify": { "post": {
1985
+ "operationId": "verifyAgentClaim",
1986
+ "summary": "Verify an agent account email claim",
1987
+ "description": "Confirms the verification code emailed by `/agent/claim/start` and\nupgrades the account to the `developer` plan. The org id, API key, and\nmanaged inbox all carry over; the send cap lifts. Authenticated by the\nagent's own API key.\n",
1988
+ "tags": ["Agent"],
1989
+ "requestBody": {
1990
+ "required": true,
1991
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VerifyAgentClaimInput" } } }
1992
+ },
1993
+ "responses": {
1994
+ "200": {
1995
+ "description": "Claim verified; account upgraded to developer",
1996
+ "headers": { "Cache-Control": {
1997
+ "schema": { "type": "string" },
1998
+ "description": "Always `no-store`"
1999
+ } },
2000
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2001
+ "type": "object",
2002
+ "properties": { "data": { "$ref": "#/components/schemas/AgentClaimResult" } }
2003
+ }] } } }
2004
+ },
2005
+ "400": { "$ref": "#/components/responses/ValidationError" },
2006
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2007
+ "404": { "$ref": "#/components/responses/NotFound" },
2008
+ "409": {
2009
+ "description": "The account is already claimed, or the email is in use",
2010
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
2011
+ },
2012
+ "410": {
2013
+ "description": "The claim or its verification code has expired",
2014
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
2015
+ },
2016
+ "429": { "$ref": "#/components/responses/RateLimited" }
2017
+ }
2018
+ } },
2019
+ "/agent/claim/link": { "post": {
2020
+ "operationId": "createAgentClaimLink",
2021
+ "summary": "Create a browser claim link",
2022
+ "description": "Mints an opaque, single-use link an agent can hand to a human to\ncomplete the email-confirmation upgrade in a browser. Authenticated by\nthe agent's own API key. `claim_url` is null when the API host cannot\nresolve a web origin to build the link.\n",
2023
+ "tags": ["Agent"],
2024
+ "requestBody": {
2025
+ "required": false,
2026
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateAgentClaimLinkInput" } } }
2027
+ },
2028
+ "responses": {
2029
+ "200": {
2030
+ "description": "Claim link created",
2031
+ "headers": { "Cache-Control": {
2032
+ "schema": { "type": "string" },
2033
+ "description": "Always `no-store`"
2034
+ } },
2035
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2036
+ "type": "object",
2037
+ "properties": { "data": { "$ref": "#/components/schemas/AgentClaimLinkResult" } }
2038
+ }] } } }
2039
+ },
2040
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2041
+ "404": { "$ref": "#/components/responses/NotFound" },
2042
+ "409": {
2043
+ "description": "The account is not claimable (not an agent account, or already claimed)",
2044
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
2045
+ },
2046
+ "429": { "$ref": "#/components/responses/RateLimited" }
2047
+ }
2048
+ } },
1837
2049
  "/cli/logout": { "post": {
1838
2050
  "operationId": "cliLogout",
1839
2051
  "summary": "Revoke the current CLI OAuth session",
@@ -4428,6 +4640,177 @@ const openapiDocument = {
4428
4640
  "orgs"
4429
4641
  ]
4430
4642
  },
4643
+ "PlanLimits": {
4644
+ "type": "object",
4645
+ "description": "Plan-derived quota limits for an account.",
4646
+ "properties": {
4647
+ "storage_mb": { "type": "number" },
4648
+ "send_per_hour": { "type": "number" },
4649
+ "send_per_day": { "type": "number" },
4650
+ "api_per_minute": { "type": "number" },
4651
+ "webhooks_max_global": { "type": ["number", "null"] },
4652
+ "webhooks_per_domain": { "type": "boolean" },
4653
+ "filters_per_domain": { "type": "boolean" },
4654
+ "spam_thresholds_per_domain": { "type": "boolean" }
4655
+ },
4656
+ "required": [
4657
+ "storage_mb",
4658
+ "send_per_hour",
4659
+ "send_per_day",
4660
+ "api_per_minute",
4661
+ "webhooks_max_global",
4662
+ "webhooks_per_domain",
4663
+ "filters_per_domain",
4664
+ "spam_thresholds_per_domain"
4665
+ ]
4666
+ },
4667
+ "CreateAgentAccountInput": {
4668
+ "type": "object",
4669
+ "additionalProperties": false,
4670
+ "properties": {
4671
+ "terms_accepted": {
4672
+ "type": "boolean",
4673
+ "enum": [true],
4674
+ "description": "Must be true to accept the Terms of Service and Privacy Policy."
4675
+ },
4676
+ "device_name": {
4677
+ "type": "string",
4678
+ "minLength": 1,
4679
+ "maxLength": 80,
4680
+ "description": "Optional label for the device or agent creating the account."
4681
+ }
4682
+ },
4683
+ "required": ["terms_accepted"]
4684
+ },
4685
+ "AgentAccountUpgradeHint": {
4686
+ "type": "object",
4687
+ "description": "In-band pointer to the upgrade path for an agent account.",
4688
+ "properties": {
4689
+ "plan": {
4690
+ "type": "string",
4691
+ "enum": ["developer"]
4692
+ },
4693
+ "description": { "type": "string" },
4694
+ "claim_path": { "type": "string" }
4695
+ },
4696
+ "required": [
4697
+ "plan",
4698
+ "description",
4699
+ "claim_path"
4700
+ ]
4701
+ },
4702
+ "AgentAccountResult": {
4703
+ "type": "object",
4704
+ "properties": {
4705
+ "api_key": {
4706
+ "type": "string",
4707
+ "description": "One-time API key (prefixed `prim_`). Shown once; store it securely."
4708
+ },
4709
+ "org_id": {
4710
+ "type": "string",
4711
+ "format": "uuid"
4712
+ },
4713
+ "address": {
4714
+ "type": ["string", "null"],
4715
+ "description": "Provisioned managed inbox FQDN, or null if the inbox publish was deferred."
4716
+ },
4717
+ "plan": {
4718
+ "type": "string",
4719
+ "enum": ["agent"]
4720
+ },
4721
+ "limits": { "$ref": "#/components/schemas/PlanLimits" },
4722
+ "upgrade": { "$ref": "#/components/schemas/AgentAccountUpgradeHint" }
4723
+ },
4724
+ "required": [
4725
+ "api_key",
4726
+ "org_id",
4727
+ "address",
4728
+ "plan",
4729
+ "limits",
4730
+ "upgrade"
4731
+ ]
4732
+ },
4733
+ "StartAgentClaimInput": {
4734
+ "type": "object",
4735
+ "additionalProperties": false,
4736
+ "properties": { "email": {
4737
+ "type": "string",
4738
+ "format": "email",
4739
+ "maxLength": 254,
4740
+ "description": "Email to confirm. Must not already belong to a Primitive account."
4741
+ } },
4742
+ "required": ["email"]
4743
+ },
4744
+ "AgentClaimStartResult": {
4745
+ "type": "object",
4746
+ "properties": {
4747
+ "claim_session_id": { "type": "string" },
4748
+ "resend_after_seconds": { "type": "integer" },
4749
+ "expires_in_seconds": { "type": "integer" }
4750
+ },
4751
+ "required": [
4752
+ "claim_session_id",
4753
+ "resend_after_seconds",
4754
+ "expires_in_seconds"
4755
+ ]
4756
+ },
4757
+ "VerifyAgentClaimInput": {
4758
+ "type": "object",
4759
+ "additionalProperties": false,
4760
+ "properties": { "verification_code": {
4761
+ "type": "string",
4762
+ "minLength": 1,
4763
+ "maxLength": 32,
4764
+ "description": "The verification code emailed by the claim start step."
4765
+ } },
4766
+ "required": ["verification_code"]
4767
+ },
4768
+ "AgentClaimResult": {
4769
+ "type": "object",
4770
+ "properties": {
4771
+ "org_id": {
4772
+ "type": "string",
4773
+ "format": "uuid"
4774
+ },
4775
+ "plan": {
4776
+ "type": "string",
4777
+ "enum": ["developer"]
4778
+ },
4779
+ "email": {
4780
+ "type": "string",
4781
+ "format": "email"
4782
+ },
4783
+ "limits": { "$ref": "#/components/schemas/PlanLimits" }
4784
+ },
4785
+ "required": [
4786
+ "org_id",
4787
+ "plan",
4788
+ "email",
4789
+ "limits"
4790
+ ]
4791
+ },
4792
+ "CreateAgentClaimLinkInput": {
4793
+ "type": "object",
4794
+ "additionalProperties": false,
4795
+ "description": "No fields; an empty object is accepted.",
4796
+ "properties": {}
4797
+ },
4798
+ "AgentClaimLinkResult": {
4799
+ "type": "object",
4800
+ "properties": {
4801
+ "claim_token": { "type": "string" },
4802
+ "claim_url": {
4803
+ "type": ["string", "null"],
4804
+ "description": "Browser URL to hand to a human, or null if no web origin is configured."
4805
+ },
4806
+ "expires_in_seconds": { "type": "integer" }
4807
+ },
4808
+ "required": [
4809
+ "claim_token",
4810
+ "claim_url",
4811
+ "expires_in_seconds"
4812
+ ]
4813
+ },
4431
4814
  "CliLogoutInput": {
4432
4815
  "type": "object",
4433
4816
  "additionalProperties": false,
@@ -7727,6 +8110,148 @@ const operationManifest = [
7727
8110
  "tag": "Account",
7728
8111
  "tagCommand": "account"
7729
8112
  },
8113
+ {
8114
+ "binaryResponse": false,
8115
+ "bodyRequired": true,
8116
+ "command": "create-agent-account",
8117
+ "description": "Creates an emailless agent account without authentication and returns a\none-time API key (prefixed `prim_`) plus a provisioned managed inbox.\nThe account is on the `agent` plan: reply-only (it can send only to\naddresses that have already sent it authenticated mail) with tight send\nlimits. Use the returned `api_key` as a Bearer token on later calls. The\naccount can be upgraded to a full developer account by confirming an\nemail through the claim flow. This endpoint does not require an API key.\n",
8118
+ "hasJsonBody": true,
8119
+ "method": "POST",
8120
+ "operationId": "createAgentAccount",
8121
+ "path": "/agent/accounts",
8122
+ "pathParams": [],
8123
+ "queryParams": [],
8124
+ "requestSchema": {
8125
+ "type": "object",
8126
+ "additionalProperties": false,
8127
+ "properties": {
8128
+ "terms_accepted": {
8129
+ "type": "boolean",
8130
+ "enum": [true],
8131
+ "description": "Must be true to accept the Terms of Service and Privacy Policy."
8132
+ },
8133
+ "device_name": {
8134
+ "type": "string",
8135
+ "minLength": 1,
8136
+ "maxLength": 80,
8137
+ "description": "Optional label for the device or agent creating the account."
8138
+ }
8139
+ },
8140
+ "required": ["terms_accepted"]
8141
+ },
8142
+ "responseSchema": {
8143
+ "type": "object",
8144
+ "properties": {
8145
+ "api_key": {
8146
+ "type": "string",
8147
+ "description": "One-time API key (prefixed `prim_`). Shown once; store it securely."
8148
+ },
8149
+ "org_id": {
8150
+ "type": "string",
8151
+ "format": "uuid"
8152
+ },
8153
+ "address": {
8154
+ "type": ["string", "null"],
8155
+ "description": "Provisioned managed inbox FQDN, or null if the inbox publish was deferred."
8156
+ },
8157
+ "plan": {
8158
+ "type": "string",
8159
+ "enum": ["agent"]
8160
+ },
8161
+ "limits": {
8162
+ "type": "object",
8163
+ "description": "Plan-derived quota limits for an account.",
8164
+ "properties": {
8165
+ "storage_mb": { "type": "number" },
8166
+ "send_per_hour": { "type": "number" },
8167
+ "send_per_day": { "type": "number" },
8168
+ "api_per_minute": { "type": "number" },
8169
+ "webhooks_max_global": { "type": ["number", "null"] },
8170
+ "webhooks_per_domain": { "type": "boolean" },
8171
+ "filters_per_domain": { "type": "boolean" },
8172
+ "spam_thresholds_per_domain": { "type": "boolean" }
8173
+ },
8174
+ "required": [
8175
+ "storage_mb",
8176
+ "send_per_hour",
8177
+ "send_per_day",
8178
+ "api_per_minute",
8179
+ "webhooks_max_global",
8180
+ "webhooks_per_domain",
8181
+ "filters_per_domain",
8182
+ "spam_thresholds_per_domain"
8183
+ ]
8184
+ },
8185
+ "upgrade": {
8186
+ "type": "object",
8187
+ "description": "In-band pointer to the upgrade path for an agent account.",
8188
+ "properties": {
8189
+ "plan": {
8190
+ "type": "string",
8191
+ "enum": ["developer"]
8192
+ },
8193
+ "description": { "type": "string" },
8194
+ "claim_path": { "type": "string" }
8195
+ },
8196
+ "required": [
8197
+ "plan",
8198
+ "description",
8199
+ "claim_path"
8200
+ ]
8201
+ }
8202
+ },
8203
+ "required": [
8204
+ "api_key",
8205
+ "org_id",
8206
+ "address",
8207
+ "plan",
8208
+ "limits",
8209
+ "upgrade"
8210
+ ]
8211
+ },
8212
+ "sdkName": "createAgentAccount",
8213
+ "summary": "Create an emailless agent account",
8214
+ "tag": "Agent",
8215
+ "tagCommand": "agent"
8216
+ },
8217
+ {
8218
+ "binaryResponse": false,
8219
+ "bodyRequired": false,
8220
+ "command": "create-agent-claim-link",
8221
+ "description": "Mints an opaque, single-use link an agent can hand to a human to\ncomplete the email-confirmation upgrade in a browser. Authenticated by\nthe agent's own API key. `claim_url` is null when the API host cannot\nresolve a web origin to build the link.\n",
8222
+ "hasJsonBody": true,
8223
+ "method": "POST",
8224
+ "operationId": "createAgentClaimLink",
8225
+ "path": "/agent/claim/link",
8226
+ "pathParams": [],
8227
+ "queryParams": [],
8228
+ "requestSchema": {
8229
+ "type": "object",
8230
+ "additionalProperties": false,
8231
+ "description": "No fields; an empty object is accepted.",
8232
+ "properties": {}
8233
+ },
8234
+ "responseSchema": {
8235
+ "type": "object",
8236
+ "properties": {
8237
+ "claim_token": { "type": "string" },
8238
+ "claim_url": {
8239
+ "type": ["string", "null"],
8240
+ "description": "Browser URL to hand to a human, or null if no web origin is configured."
8241
+ },
8242
+ "expires_in_seconds": { "type": "integer" }
8243
+ },
8244
+ "required": [
8245
+ "claim_token",
8246
+ "claim_url",
8247
+ "expires_in_seconds"
8248
+ ]
8249
+ },
8250
+ "sdkName": "createAgentClaimLink",
8251
+ "summary": "Create a browser claim link",
8252
+ "tag": "Agent",
8253
+ "tagCommand": "agent"
8254
+ },
7730
8255
  {
7731
8256
  "binaryResponse": false,
7732
8257
  "bodyRequired": true,
@@ -7779,6 +8304,46 @@ const operationManifest = [
7779
8304
  "tag": "Agent",
7780
8305
  "tagCommand": "agent"
7781
8306
  },
8307
+ {
8308
+ "binaryResponse": false,
8309
+ "bodyRequired": true,
8310
+ "command": "start-agent-claim",
8311
+ "description": "Begins upgrading an emailless `agent` account into a full `developer`\naccount by confirming an email address. Authenticated by the agent's own\nAPI key (the org is taken from the credential). Sends a verification\ncode to the supplied email and returns the claim session id plus resend\ntiming. Submit the code to `/agent/claim/verify` to complete the\nupgrade. Confirming an email that already belongs to a Primitive account\nis rejected.\n",
8312
+ "hasJsonBody": true,
8313
+ "method": "POST",
8314
+ "operationId": "startAgentClaim",
8315
+ "path": "/agent/claim/start",
8316
+ "pathParams": [],
8317
+ "queryParams": [],
8318
+ "requestSchema": {
8319
+ "type": "object",
8320
+ "additionalProperties": false,
8321
+ "properties": { "email": {
8322
+ "type": "string",
8323
+ "format": "email",
8324
+ "maxLength": 254,
8325
+ "description": "Email to confirm. Must not already belong to a Primitive account."
8326
+ } },
8327
+ "required": ["email"]
8328
+ },
8329
+ "responseSchema": {
8330
+ "type": "object",
8331
+ "properties": {
8332
+ "claim_session_id": { "type": "string" },
8333
+ "resend_after_seconds": { "type": "integer" },
8334
+ "expires_in_seconds": { "type": "integer" }
8335
+ },
8336
+ "required": [
8337
+ "claim_session_id",
8338
+ "resend_after_seconds",
8339
+ "expires_in_seconds"
8340
+ ]
8341
+ },
8342
+ "sdkName": "startAgentClaim",
8343
+ "summary": "Start an agent account email claim",
8344
+ "tag": "Agent",
8345
+ "tagCommand": "agent"
8346
+ },
7782
8347
  {
7783
8348
  "binaryResponse": false,
7784
8349
  "bodyRequired": true,
@@ -7861,6 +8426,80 @@ const operationManifest = [
7861
8426
  "tag": "Agent",
7862
8427
  "tagCommand": "agent"
7863
8428
  },
8429
+ {
8430
+ "binaryResponse": false,
8431
+ "bodyRequired": true,
8432
+ "command": "verify-agent-claim",
8433
+ "description": "Confirms the verification code emailed by `/agent/claim/start` and\nupgrades the account to the `developer` plan. The org id, API key, and\nmanaged inbox all carry over; the send cap lifts. Authenticated by the\nagent's own API key.\n",
8434
+ "hasJsonBody": true,
8435
+ "method": "POST",
8436
+ "operationId": "verifyAgentClaim",
8437
+ "path": "/agent/claim/verify",
8438
+ "pathParams": [],
8439
+ "queryParams": [],
8440
+ "requestSchema": {
8441
+ "type": "object",
8442
+ "additionalProperties": false,
8443
+ "properties": { "verification_code": {
8444
+ "type": "string",
8445
+ "minLength": 1,
8446
+ "maxLength": 32,
8447
+ "description": "The verification code emailed by the claim start step."
8448
+ } },
8449
+ "required": ["verification_code"]
8450
+ },
8451
+ "responseSchema": {
8452
+ "type": "object",
8453
+ "properties": {
8454
+ "org_id": {
8455
+ "type": "string",
8456
+ "format": "uuid"
8457
+ },
8458
+ "plan": {
8459
+ "type": "string",
8460
+ "enum": ["developer"]
8461
+ },
8462
+ "email": {
8463
+ "type": "string",
8464
+ "format": "email"
8465
+ },
8466
+ "limits": {
8467
+ "type": "object",
8468
+ "description": "Plan-derived quota limits for an account.",
8469
+ "properties": {
8470
+ "storage_mb": { "type": "number" },
8471
+ "send_per_hour": { "type": "number" },
8472
+ "send_per_day": { "type": "number" },
8473
+ "api_per_minute": { "type": "number" },
8474
+ "webhooks_max_global": { "type": ["number", "null"] },
8475
+ "webhooks_per_domain": { "type": "boolean" },
8476
+ "filters_per_domain": { "type": "boolean" },
8477
+ "spam_thresholds_per_domain": { "type": "boolean" }
8478
+ },
8479
+ "required": [
8480
+ "storage_mb",
8481
+ "send_per_hour",
8482
+ "send_per_day",
8483
+ "api_per_minute",
8484
+ "webhooks_max_global",
8485
+ "webhooks_per_domain",
8486
+ "filters_per_domain",
8487
+ "spam_thresholds_per_domain"
8488
+ ]
8489
+ }
8490
+ },
8491
+ "required": [
8492
+ "org_id",
8493
+ "plan",
8494
+ "email",
8495
+ "limits"
8496
+ ]
8497
+ },
8498
+ "sdkName": "verifyAgentClaim",
8499
+ "summary": "Verify an agent account email claim",
8500
+ "tag": "Agent",
8501
+ "tagCommand": "agent"
8502
+ },
7864
8503
  {
7865
8504
  "binaryResponse": false,
7866
8505
  "bodyRequired": true,
@@ -18138,8 +18777,8 @@ const PRIMITIVE_TEAM_AUTHOR = {
18138
18777
  name: "Primitive Team",
18139
18778
  url: "https://primitive.dev"
18140
18779
  };
18141
- const SDK_VERSION_RANGE = "^1.2.0";
18142
- const CLI_VERSION_RANGE = "^1.2.0";
18780
+ const SDK_VERSION_RANGE = "^1.3.0";
18781
+ const CLI_VERSION_RANGE = "^1.3.0";
18143
18782
  const ESBUILD_VERSION_RANGE = "^0.27.0";
18144
18783
  function renderHandler() {
18145
18784
  return `// env.PRIMITIVE_API_KEY, env.PRIMITIVE_WEBHOOK_SECRET, and
@@ -20942,6 +21581,74 @@ var SignupCommand = class SignupCommand extends Command {
20942
21581
  }
20943
21582
  }
20944
21583
  };
21584
+ function resolveVerificationCode(input) {
21585
+ const sources = [
21586
+ input.positional !== void 0 ? "positional" : null,
21587
+ input.fromStdin === true ? "--code-from-stdin" : null,
21588
+ input.fromFile !== void 0 ? "--code-from-file" : null,
21589
+ input.fromEnv !== void 0 ? "--code-from-env" : null
21590
+ ].filter((v) => v !== null);
21591
+ if (sources.length === 0) return {
21592
+ kind: "error",
21593
+ message: "Pass the verification code as a positional argument or via one of --code-from-stdin, --code-from-file, or --code-from-env."
21594
+ };
21595
+ if (sources.length > 1) return {
21596
+ kind: "error",
21597
+ message: `Pass exactly one source for the verification code; got ${sources.join(", ")}.`
21598
+ };
21599
+ if (input.positional !== void 0) return {
21600
+ kind: "ok",
21601
+ code: input.positional
21602
+ };
21603
+ if (input.fromEnv !== void 0) {
21604
+ const value = (input.env ?? process$1.env)[input.fromEnv];
21605
+ if (value === void 0) return {
21606
+ kind: "error",
21607
+ message: `--code-from-env ${input.fromEnv}: environment variable is not set.`
21608
+ };
21609
+ return {
21610
+ kind: "ok",
21611
+ code: stripTrailingNewline(value)
21612
+ };
21613
+ }
21614
+ if (input.fromFile !== void 0) {
21615
+ const readFile = input.readFile ?? defaultReadCodeFile;
21616
+ try {
21617
+ return {
21618
+ kind: "ok",
21619
+ code: stripTrailingNewline(readFile(input.fromFile))
21620
+ };
21621
+ } catch (error) {
21622
+ const detail = error instanceof Error ? error.message : String(error);
21623
+ return {
21624
+ kind: "error",
21625
+ message: `--code-from-file ${input.fromFile}: could not read file: ${detail}`
21626
+ };
21627
+ }
21628
+ }
21629
+ const readStdin = input.readStdin ?? defaultReadCodeStdin;
21630
+ try {
21631
+ return {
21632
+ kind: "ok",
21633
+ code: stripTrailingNewline(readStdin())
21634
+ };
21635
+ } catch (error) {
21636
+ return {
21637
+ kind: "error",
21638
+ message: `--code-from-stdin: ${error instanceof Error ? error.message : String(error)}`
21639
+ };
21640
+ }
21641
+ }
21642
+ function stripTrailingNewline(value) {
21643
+ return value.replace(/\r?\n$/, "");
21644
+ }
21645
+ function defaultReadCodeFile(path) {
21646
+ return readFileSync(path, "utf8");
21647
+ }
21648
+ function defaultReadCodeStdin() {
21649
+ if (process$1.stdin.isTTY) throw new Error("stdin is a TTY; pipe the code into this command or use --code-from-file / --code-from-env instead.");
21650
+ return readFileSync(0, "utf8");
21651
+ }
20945
21652
  var SignupConfirmCommand = class SignupConfirmCommand extends Command {
20946
21653
  static args = {
20947
21654
  email: Args.string({
@@ -20949,19 +21656,28 @@ var SignupConfirmCommand = class SignupConfirmCommand extends Command {
20949
21656
  required: true
20950
21657
  }),
20951
21658
  code: Args.string({
20952
- description: "Verification code from the signup email",
20953
- required: true
21659
+ description: "Verification code from the signup email. Optional when one of --code-from-stdin / --code-from-file / --code-from-env is passed; exactly one source must be set.",
21660
+ required: false
20954
21661
  })
20955
21662
  };
20956
21663
  static description = "Confirm a pending Primitive signup, create an OAuth session, and save CLI credentials locally.";
20957
21664
  static summary = "Confirm account signup";
20958
- 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"];
21665
+ static examples = [
21666
+ "<%= config.bin %> signup confirm user@example.com 123456",
21667
+ "<%= config.bin %> signup confirm user@example.com 123456 --org-id 00000000-0000-4000-8000-000000000000",
21668
+ "read -rs CODE && CODE=\"$CODE\" <%= config.bin %> signup confirm user@example.com --code-from-env CODE && unset CODE",
21669
+ "read -rs CODE && printf '%s' \"$CODE\" | <%= config.bin %> signup confirm user@example.com --code-from-stdin && unset CODE",
21670
+ "<%= config.bin %> signup confirm user@example.com --code-from-file /run/user/$(id -u)/verification-code"
21671
+ ];
20959
21672
  static flags = {
20960
21673
  "api-base-url": Flags.string({
20961
21674
  description: "Override the primary API base URL. Internal testing only; not documented to customers.",
20962
21675
  env: "PRIMITIVE_API_BASE_URL",
20963
21676
  hidden: true
20964
21677
  }),
21678
+ "code-from-stdin": Flags.boolean({ description: "Read the verification code from stdin instead of the positional argument. Use when an agent is constructing the command for the user to run, so the code never enters the agent's prompt context." }),
21679
+ "code-from-file": Flags.string({ description: "Read the verification code from a UTF-8 file at this path. Trailing newlines are stripped." }),
21680
+ "code-from-env": Flags.string({ description: "Read the verification code from this environment variable. Pair with `read -rs CODE && CODE=\"$CODE\" primitive signup confirm <email> --code-from-env CODE && unset CODE` so the value never appears on the command line or in shell history. Plain `read` creates a shell-local variable that child processes cannot see; the inline `CODE=\"$CODE\"` exports it for just the one command." }),
20965
21681
  force: Flags.boolean({
20966
21682
  char: "f",
20967
21683
  description: "Replace saved credentials after verification"
@@ -20970,6 +21686,13 @@ var SignupConfirmCommand = class SignupConfirmCommand extends Command {
20970
21686
  };
20971
21687
  async run() {
20972
21688
  const { args, flags } = await this.parse(SignupConfirmCommand);
21689
+ const resolvedCode = resolveVerificationCode({
21690
+ positional: args.code,
21691
+ fromStdin: flags["code-from-stdin"] === true,
21692
+ fromFile: flags["code-from-file"],
21693
+ fromEnv: flags["code-from-env"]
21694
+ });
21695
+ if (resolvedCode.kind === "error") throw cliError$2(resolvedCode.message);
20973
21696
  let releaseCredentialsLock;
20974
21697
  try {
20975
21698
  releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
@@ -20978,7 +21701,7 @@ var SignupConfirmCommand = class SignupConfirmCommand extends Command {
20978
21701
  }
20979
21702
  try {
20980
21703
  await runSignupConfirmWithCredentialLock({
20981
- code: args.code,
21704
+ code: resolvedCode.code,
20982
21705
  configDir: this.config.configDir,
20983
21706
  email: args.email,
20984
21707
  flags
@@ -22383,6 +23106,43 @@ function renderFishCompletion(binName) {
22383
23106
  return `${lines.join("\n")}\n`;
22384
23107
  }
22385
23108
  //#endregion
23109
+ //#region src/oclif/shell-completion-script.ts
23110
+ /**
23111
+ * Path to the sourceable completion *function* file that
23112
+ * `@oclif/plugin-autocomplete` writes under the CLI cache dir when its cache is
23113
+ * built. This is the artifact a shell is meant to source -- a package manager
23114
+ * dropping a file into `bash_completion.d/` or zsh's `site-functions/` wants
23115
+ * this, NOT the human-readable setup instructions printed by
23116
+ * `<bin> autocomplete <shell>`. The layout mirrors the plugin's own
23117
+ * `Create.bashCompletionFunctionPath` / `zshCompletionFunctionPath` getters:
23118
+ * <cacheDir>/autocomplete/functions/bash/<bin>.bash
23119
+ * <cacheDir>/autocomplete/functions/zsh/_<bin>
23120
+ *
23121
+ * This couples to a private path layout in `@oclif/plugin-autocomplete`
23122
+ * (pinned `^3.2.45` in package.json). If a major bump reorganises that cache
23123
+ * dir, `readCompletionFunction` will fail even after a successful
23124
+ * `--refresh-cache`; re-verify this layout when bumping the plugin.
23125
+ */
23126
+ function completionFunctionPath(cacheDir, bin, shell) {
23127
+ const functionsDir = path.join(cacheDir, "autocomplete", "functions", shell);
23128
+ const fileName = shell === "bash" ? `${bin}.bash` : `_${bin}`;
23129
+ return path.join(functionsDir, fileName);
23130
+ }
23131
+ /**
23132
+ * Read the generated completion function script, trimmed of trailing
23133
+ * whitespace so the caller can re-add a single newline. Throws an actionable
23134
+ * error (rather than a bare `ENOENT`) if the cached script is missing -- e.g.
23135
+ * the cache build failed, or the plugin changed its path layout.
23136
+ */
23137
+ function readCompletionFunction(cacheDir, bin, shell) {
23138
+ const filePath = completionFunctionPath(cacheDir, bin, shell);
23139
+ try {
23140
+ return readFileSync(filePath, "utf8").trimEnd();
23141
+ } catch (cause) {
23142
+ throw new Error(`Could not read the generated ${shell} completion script at ${filePath}. Run \`${bin} autocomplete ${shell} --refresh-cache\` and try again.`, { cause });
23143
+ }
23144
+ }
23145
+ //#endregion
22386
23146
  //#region src/oclif/index.ts
22387
23147
  var ListOperationsCommand = class extends Command {
22388
23148
  static description = "List all generated API operations as JSON. Useful for piping to `jq` to discover available commands, their request/response schemas, and per-field descriptions. For inspecting a single operation in detail, prefer `primitive describe <command-or-operation-name>`.";
@@ -22503,14 +23263,32 @@ var CompletionCommand = class CompletionCommand extends Command {
22503
23263
  ],
22504
23264
  required: true
22505
23265
  }) };
22506
- static description = "Show shell completion output or installation instructions for supported shells";
22507
- static summary = "Show shell completion output or installation instructions";
23266
+ static description = `Output a sourceable shell completion script, or print setup instructions.
23267
+
23268
+ For fish, and for bash/zsh when the output is piped or redirected (e.g. into a
23269
+ completion file under bash_completion.d or zsh's site-functions), this emits
23270
+ the raw completion script. For bash/zsh in an interactive terminal it prints
23271
+ the human-readable setup instructions instead. This keeps a redirected
23272
+ \`<%= config.bin %> completion bash > <file>\` safe to source -- the file holds an
23273
+ actual completion function, never instructional prose a shell would choke on.`;
23274
+ static summary = "Output a shell completion script or print setup instructions";
23275
+ static examples = [
23276
+ "<%= config.bin %> completion bash >> /etc/bash_completion.d/primitive",
23277
+ "<%= config.bin %> completion zsh > /usr/local/share/zsh/site-functions/_primitive",
23278
+ "<%= config.bin %> completion fish > ~/.config/fish/completions/primitive.fish"
23279
+ ];
22508
23280
  async run() {
22509
23281
  const { args } = await this.parse(CompletionCommand);
22510
- if (args.shell === "fish") {
23282
+ const shell = args.shell;
23283
+ if (shell === "fish") {
22511
23284
  this.log(renderFishCompletion(this.config.bin));
22512
23285
  return;
22513
23286
  }
23287
+ if ((shell === "bash" || shell === "zsh") && !process.stdout.isTTY) {
23288
+ await this.config.runCommand("autocomplete", [shell, "--refresh-cache"]);
23289
+ this.log(readCompletionFunction(this.config.cacheDir, this.config.bin, shell));
23290
+ return;
23291
+ }
22514
23292
  await this.config.runCommand("autocomplete", [args.shell]);
22515
23293
  }
22516
23294
  };
@@ -22518,6 +23296,10 @@ const CANONICAL_OPERATION_ALIASES = {
22518
23296
  "account:show": "account:get-account",
22519
23297
  "account:storage": "account:get-storage-stats",
22520
23298
  "account:webhook-secret": "account:get-webhook-secret",
23299
+ "agent:claim": "agent:start-agent-claim",
23300
+ "agent:claim-link": "agent:create-agent-claim-link",
23301
+ "agent:claim-verify": "agent:verify-agent-claim",
23302
+ "agent:create": "agent:create-agent-account",
22521
23303
  "deliveries:list": "webhook-deliveries:list-deliveries",
22522
23304
  "deliveries:replay": "webhook-deliveries:replay-delivery",
22523
23305
  "domains:add": "domains:add-domain",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primitivedotdev/cli",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
5
5
  "type": "module",
6
6
  "sideEffects": false,