@primitivedotdev/cli 0.31.4 → 0.31.6
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/dist/oclif/index.js +1017 -51
- package/man/primitive.1 +94 -0
- package/package.json +9 -2
package/dist/oclif/index.js
CHANGED
|
@@ -651,6 +651,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
|
651
651
|
getEmail: () => getEmail,
|
|
652
652
|
getFunction: () => getFunction,
|
|
653
653
|
getFunctionTestRunTrace: () => getFunctionTestRunTrace,
|
|
654
|
+
getInboxStatus: () => getInboxStatus,
|
|
654
655
|
getSendPermissions: () => getSendPermissions,
|
|
655
656
|
getSentEmail: () => getSentEmail,
|
|
656
657
|
getStorageStats: () => getStorageStats,
|
|
@@ -1033,6 +1034,28 @@ const downloadDomainZoneFile = (options) => (options.client ?? client).get({
|
|
|
1033
1034
|
...options
|
|
1034
1035
|
});
|
|
1035
1036
|
/**
|
|
1037
|
+
* Get inbound inbox readiness
|
|
1038
|
+
*
|
|
1039
|
+
* Returns one consolidated view of inbound domain readiness,
|
|
1040
|
+
* webhook/function processing routes, deployed Functions, and
|
|
1041
|
+
* recent inbound email activity.
|
|
1042
|
+
*
|
|
1043
|
+
* Agents should call this before guiding a user through inbound
|
|
1044
|
+
* setup. It answers the practical questions "can I receive mail",
|
|
1045
|
+
* "will anything process that mail", and "what should I do next"
|
|
1046
|
+
* without forcing clients to stitch together domains, endpoints,
|
|
1047
|
+
* functions, and emails manually.
|
|
1048
|
+
*
|
|
1049
|
+
*/
|
|
1050
|
+
const getInboxStatus = (options) => (options?.client ?? client).get({
|
|
1051
|
+
security: [{
|
|
1052
|
+
scheme: "bearer",
|
|
1053
|
+
type: "http"
|
|
1054
|
+
}],
|
|
1055
|
+
url: "/inbox/status",
|
|
1056
|
+
...options
|
|
1057
|
+
});
|
|
1058
|
+
/**
|
|
1036
1059
|
* List inbound emails
|
|
1037
1060
|
*
|
|
1038
1061
|
* Returns a paginated list of INBOUND emails received at your
|
|
@@ -1894,6 +1917,10 @@ const openapiDocument = {
|
|
|
1894
1917
|
"name": "Domains",
|
|
1895
1918
|
"description": "Claim, verify, and manage email domains"
|
|
1896
1919
|
},
|
|
1920
|
+
{
|
|
1921
|
+
"name": "Inbox",
|
|
1922
|
+
"description": "Check inbound email setup and processing readiness"
|
|
1923
|
+
},
|
|
1897
1924
|
{
|
|
1898
1925
|
"name": "Emails",
|
|
1899
1926
|
"description": "List, inspect, and manage received emails"
|
|
@@ -2500,6 +2527,23 @@ const openapiDocument = {
|
|
|
2500
2527
|
}
|
|
2501
2528
|
}
|
|
2502
2529
|
},
|
|
2530
|
+
"/inbox/status": { "get": {
|
|
2531
|
+
"operationId": "getInboxStatus",
|
|
2532
|
+
"summary": "Get inbound inbox readiness",
|
|
2533
|
+
"description": "Returns one consolidated view of inbound domain readiness,\nwebhook/function processing routes, deployed Functions, and\nrecent inbound email activity.\n\nAgents should call this before guiding a user through inbound\nsetup. It answers the practical questions \"can I receive mail\",\n\"will anything process that mail\", and \"what should I do next\"\nwithout forcing clients to stitch together domains, endpoints,\nfunctions, and emails manually.\n",
|
|
2534
|
+
"tags": ["Inbox"],
|
|
2535
|
+
"responses": {
|
|
2536
|
+
"200": {
|
|
2537
|
+
"description": "Consolidated inbox readiness status",
|
|
2538
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
2539
|
+
"type": "object",
|
|
2540
|
+
"properties": { "data": { "$ref": "#/components/schemas/InboxStatus" } }
|
|
2541
|
+
}] } } }
|
|
2542
|
+
},
|
|
2543
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
2544
|
+
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2545
|
+
}
|
|
2546
|
+
} },
|
|
2503
2547
|
"/emails": { "get": {
|
|
2504
2548
|
"operationId": "listEmails",
|
|
2505
2549
|
"summary": "List inbound emails",
|
|
@@ -4788,6 +4832,181 @@ const openapiDocument = {
|
|
|
4788
4832
|
} },
|
|
4789
4833
|
"required": ["secret"]
|
|
4790
4834
|
},
|
|
4835
|
+
"InboxStatus": {
|
|
4836
|
+
"type": "object",
|
|
4837
|
+
"additionalProperties": false,
|
|
4838
|
+
"properties": {
|
|
4839
|
+
"ready": {
|
|
4840
|
+
"type": "boolean",
|
|
4841
|
+
"description": "True when at least one active inbound domain has an enabled processing route."
|
|
4842
|
+
},
|
|
4843
|
+
"receiving_ready": {
|
|
4844
|
+
"type": "boolean",
|
|
4845
|
+
"description": "True when at least one active verified or managed domain can receive mail."
|
|
4846
|
+
},
|
|
4847
|
+
"processing_ready": {
|
|
4848
|
+
"type": "boolean",
|
|
4849
|
+
"description": "True when at least one receiving-ready domain has an enabled webhook or function route."
|
|
4850
|
+
},
|
|
4851
|
+
"summary": {
|
|
4852
|
+
"type": "string",
|
|
4853
|
+
"description": "Short human-readable status summary."
|
|
4854
|
+
},
|
|
4855
|
+
"next_actions": {
|
|
4856
|
+
"type": "array",
|
|
4857
|
+
"items": { "$ref": "#/components/schemas/InboxStatusNextAction" }
|
|
4858
|
+
},
|
|
4859
|
+
"domains": {
|
|
4860
|
+
"type": "array",
|
|
4861
|
+
"items": { "$ref": "#/components/schemas/InboxStatusDomain" }
|
|
4862
|
+
},
|
|
4863
|
+
"endpoints": { "$ref": "#/components/schemas/InboxStatusEndpointSummary" },
|
|
4864
|
+
"functions": { "$ref": "#/components/schemas/InboxStatusFunctionSummary" },
|
|
4865
|
+
"recent_emails": { "$ref": "#/components/schemas/InboxStatusRecentEmailSummary" }
|
|
4866
|
+
},
|
|
4867
|
+
"required": [
|
|
4868
|
+
"ready",
|
|
4869
|
+
"receiving_ready",
|
|
4870
|
+
"processing_ready",
|
|
4871
|
+
"summary",
|
|
4872
|
+
"next_actions",
|
|
4873
|
+
"domains",
|
|
4874
|
+
"endpoints",
|
|
4875
|
+
"functions",
|
|
4876
|
+
"recent_emails"
|
|
4877
|
+
]
|
|
4878
|
+
},
|
|
4879
|
+
"InboxStatusNextAction": {
|
|
4880
|
+
"type": "object",
|
|
4881
|
+
"additionalProperties": false,
|
|
4882
|
+
"properties": {
|
|
4883
|
+
"kind": {
|
|
4884
|
+
"type": "string",
|
|
4885
|
+
"enum": [
|
|
4886
|
+
"add_domain",
|
|
4887
|
+
"verify_domain",
|
|
4888
|
+
"configure_processing",
|
|
4889
|
+
"send_test_email",
|
|
4890
|
+
"fix_failed_functions"
|
|
4891
|
+
]
|
|
4892
|
+
},
|
|
4893
|
+
"message": {
|
|
4894
|
+
"type": "string",
|
|
4895
|
+
"description": "Human-readable next step."
|
|
4896
|
+
},
|
|
4897
|
+
"command": {
|
|
4898
|
+
"type": "string",
|
|
4899
|
+
"description": "Suggested Primitive CLI command when there is an obvious next step."
|
|
4900
|
+
}
|
|
4901
|
+
},
|
|
4902
|
+
"required": ["kind", "message"]
|
|
4903
|
+
},
|
|
4904
|
+
"InboxStatusDomain": {
|
|
4905
|
+
"type": "object",
|
|
4906
|
+
"additionalProperties": false,
|
|
4907
|
+
"properties": {
|
|
4908
|
+
"id": { "type": "string" },
|
|
4909
|
+
"domain": { "type": "string" },
|
|
4910
|
+
"verified": { "type": "boolean" },
|
|
4911
|
+
"active": { "type": "boolean" },
|
|
4912
|
+
"managed": { "type": "boolean" },
|
|
4913
|
+
"receiving_ready": { "type": "boolean" },
|
|
4914
|
+
"processing_ready": { "type": "boolean" },
|
|
4915
|
+
"processing_route_count": { "type": "integer" },
|
|
4916
|
+
"endpoint_count": { "type": "integer" },
|
|
4917
|
+
"enabled_endpoint_count": { "type": "integer" },
|
|
4918
|
+
"function_endpoint_count": { "type": "integer" },
|
|
4919
|
+
"email_count": {
|
|
4920
|
+
"type": "integer",
|
|
4921
|
+
"description": "Number of inbound emails received for this domain in the last 30 days."
|
|
4922
|
+
},
|
|
4923
|
+
"latest_email_received_at": {
|
|
4924
|
+
"type": ["string", "null"],
|
|
4925
|
+
"format": "date-time",
|
|
4926
|
+
"description": "Most recent inbound email received for this domain in the last 30 days."
|
|
4927
|
+
},
|
|
4928
|
+
"status": {
|
|
4929
|
+
"type": "string",
|
|
4930
|
+
"enum": [
|
|
4931
|
+
"ready",
|
|
4932
|
+
"stored_only",
|
|
4933
|
+
"pending_dns",
|
|
4934
|
+
"inactive"
|
|
4935
|
+
]
|
|
4936
|
+
}
|
|
4937
|
+
},
|
|
4938
|
+
"required": [
|
|
4939
|
+
"id",
|
|
4940
|
+
"domain",
|
|
4941
|
+
"verified",
|
|
4942
|
+
"active",
|
|
4943
|
+
"managed",
|
|
4944
|
+
"receiving_ready",
|
|
4945
|
+
"processing_ready",
|
|
4946
|
+
"processing_route_count",
|
|
4947
|
+
"endpoint_count",
|
|
4948
|
+
"enabled_endpoint_count",
|
|
4949
|
+
"function_endpoint_count",
|
|
4950
|
+
"email_count",
|
|
4951
|
+
"latest_email_received_at",
|
|
4952
|
+
"status"
|
|
4953
|
+
]
|
|
4954
|
+
},
|
|
4955
|
+
"InboxStatusEndpointSummary": {
|
|
4956
|
+
"type": "object",
|
|
4957
|
+
"additionalProperties": false,
|
|
4958
|
+
"properties": {
|
|
4959
|
+
"total": { "type": "integer" },
|
|
4960
|
+
"enabled": { "type": "integer" },
|
|
4961
|
+
"disabled": { "type": "integer" },
|
|
4962
|
+
"fallback_enabled": { "type": "integer" },
|
|
4963
|
+
"domain_scoped_enabled": { "type": "integer" },
|
|
4964
|
+
"http_enabled": { "type": "integer" },
|
|
4965
|
+
"function_enabled": { "type": "integer" }
|
|
4966
|
+
},
|
|
4967
|
+
"required": [
|
|
4968
|
+
"total",
|
|
4969
|
+
"enabled",
|
|
4970
|
+
"disabled",
|
|
4971
|
+
"fallback_enabled",
|
|
4972
|
+
"domain_scoped_enabled",
|
|
4973
|
+
"http_enabled",
|
|
4974
|
+
"function_enabled"
|
|
4975
|
+
]
|
|
4976
|
+
},
|
|
4977
|
+
"InboxStatusFunctionSummary": {
|
|
4978
|
+
"type": "object",
|
|
4979
|
+
"additionalProperties": false,
|
|
4980
|
+
"properties": {
|
|
4981
|
+
"total": { "type": "integer" },
|
|
4982
|
+
"deployed": { "type": "integer" },
|
|
4983
|
+
"pending": { "type": "integer" },
|
|
4984
|
+
"failed": { "type": "integer" }
|
|
4985
|
+
},
|
|
4986
|
+
"required": [
|
|
4987
|
+
"total",
|
|
4988
|
+
"deployed",
|
|
4989
|
+
"pending",
|
|
4990
|
+
"failed"
|
|
4991
|
+
]
|
|
4992
|
+
},
|
|
4993
|
+
"InboxStatusRecentEmailSummary": {
|
|
4994
|
+
"type": "object",
|
|
4995
|
+
"description": "Inbound email activity from the last 30 days.",
|
|
4996
|
+
"additionalProperties": false,
|
|
4997
|
+
"properties": {
|
|
4998
|
+
"total": {
|
|
4999
|
+
"type": "integer",
|
|
5000
|
+
"description": "Number of inbound emails received in the last 30 days."
|
|
5001
|
+
},
|
|
5002
|
+
"latest_received_at": {
|
|
5003
|
+
"type": ["string", "null"],
|
|
5004
|
+
"format": "date-time",
|
|
5005
|
+
"description": "Most recent inbound email received in the last 30 days."
|
|
5006
|
+
}
|
|
5007
|
+
},
|
|
5008
|
+
"required": ["total", "latest_received_at"]
|
|
5009
|
+
},
|
|
4791
5010
|
"Domain": {
|
|
4792
5011
|
"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` and `dns_records` for DNS setup.\n",
|
|
4793
5012
|
"oneOf": [{ "$ref": "#/components/schemas/VerifiedDomain" }, { "$ref": "#/components/schemas/UnverifiedDomain" }]
|
|
@@ -10881,6 +11100,193 @@ const operationManifest = [
|
|
|
10881
11100
|
"tag": "Functions",
|
|
10882
11101
|
"tagCommand": "functions"
|
|
10883
11102
|
},
|
|
11103
|
+
{
|
|
11104
|
+
"binaryResponse": false,
|
|
11105
|
+
"bodyRequired": false,
|
|
11106
|
+
"command": "get-inbox-status",
|
|
11107
|
+
"description": "Returns one consolidated view of inbound domain readiness,\nwebhook/function processing routes, deployed Functions, and\nrecent inbound email activity.\n\nAgents should call this before guiding a user through inbound\nsetup. It answers the practical questions \"can I receive mail\",\n\"will anything process that mail\", and \"what should I do next\"\nwithout forcing clients to stitch together domains, endpoints,\nfunctions, and emails manually.\n",
|
|
11108
|
+
"hasJsonBody": false,
|
|
11109
|
+
"method": "GET",
|
|
11110
|
+
"operationId": "getInboxStatus",
|
|
11111
|
+
"path": "/inbox/status",
|
|
11112
|
+
"pathParams": [],
|
|
11113
|
+
"queryParams": [],
|
|
11114
|
+
"requestSchema": null,
|
|
11115
|
+
"responseSchema": {
|
|
11116
|
+
"type": "object",
|
|
11117
|
+
"additionalProperties": false,
|
|
11118
|
+
"properties": {
|
|
11119
|
+
"ready": {
|
|
11120
|
+
"type": "boolean",
|
|
11121
|
+
"description": "True when at least one active inbound domain has an enabled processing route."
|
|
11122
|
+
},
|
|
11123
|
+
"receiving_ready": {
|
|
11124
|
+
"type": "boolean",
|
|
11125
|
+
"description": "True when at least one active verified or managed domain can receive mail."
|
|
11126
|
+
},
|
|
11127
|
+
"processing_ready": {
|
|
11128
|
+
"type": "boolean",
|
|
11129
|
+
"description": "True when at least one receiving-ready domain has an enabled webhook or function route."
|
|
11130
|
+
},
|
|
11131
|
+
"summary": {
|
|
11132
|
+
"type": "string",
|
|
11133
|
+
"description": "Short human-readable status summary."
|
|
11134
|
+
},
|
|
11135
|
+
"next_actions": {
|
|
11136
|
+
"type": "array",
|
|
11137
|
+
"items": {
|
|
11138
|
+
"type": "object",
|
|
11139
|
+
"additionalProperties": false,
|
|
11140
|
+
"properties": {
|
|
11141
|
+
"kind": {
|
|
11142
|
+
"type": "string",
|
|
11143
|
+
"enum": [
|
|
11144
|
+
"add_domain",
|
|
11145
|
+
"verify_domain",
|
|
11146
|
+
"configure_processing",
|
|
11147
|
+
"send_test_email",
|
|
11148
|
+
"fix_failed_functions"
|
|
11149
|
+
]
|
|
11150
|
+
},
|
|
11151
|
+
"message": {
|
|
11152
|
+
"type": "string",
|
|
11153
|
+
"description": "Human-readable next step."
|
|
11154
|
+
},
|
|
11155
|
+
"command": {
|
|
11156
|
+
"type": "string",
|
|
11157
|
+
"description": "Suggested Primitive CLI command when there is an obvious next step."
|
|
11158
|
+
}
|
|
11159
|
+
},
|
|
11160
|
+
"required": ["kind", "message"]
|
|
11161
|
+
}
|
|
11162
|
+
},
|
|
11163
|
+
"domains": {
|
|
11164
|
+
"type": "array",
|
|
11165
|
+
"items": {
|
|
11166
|
+
"type": "object",
|
|
11167
|
+
"additionalProperties": false,
|
|
11168
|
+
"properties": {
|
|
11169
|
+
"id": { "type": "string" },
|
|
11170
|
+
"domain": { "type": "string" },
|
|
11171
|
+
"verified": { "type": "boolean" },
|
|
11172
|
+
"active": { "type": "boolean" },
|
|
11173
|
+
"managed": { "type": "boolean" },
|
|
11174
|
+
"receiving_ready": { "type": "boolean" },
|
|
11175
|
+
"processing_ready": { "type": "boolean" },
|
|
11176
|
+
"processing_route_count": { "type": "integer" },
|
|
11177
|
+
"endpoint_count": { "type": "integer" },
|
|
11178
|
+
"enabled_endpoint_count": { "type": "integer" },
|
|
11179
|
+
"function_endpoint_count": { "type": "integer" },
|
|
11180
|
+
"email_count": {
|
|
11181
|
+
"type": "integer",
|
|
11182
|
+
"description": "Number of inbound emails received for this domain in the last 30 days."
|
|
11183
|
+
},
|
|
11184
|
+
"latest_email_received_at": {
|
|
11185
|
+
"type": ["string", "null"],
|
|
11186
|
+
"format": "date-time",
|
|
11187
|
+
"description": "Most recent inbound email received for this domain in the last 30 days."
|
|
11188
|
+
},
|
|
11189
|
+
"status": {
|
|
11190
|
+
"type": "string",
|
|
11191
|
+
"enum": [
|
|
11192
|
+
"ready",
|
|
11193
|
+
"stored_only",
|
|
11194
|
+
"pending_dns",
|
|
11195
|
+
"inactive"
|
|
11196
|
+
]
|
|
11197
|
+
}
|
|
11198
|
+
},
|
|
11199
|
+
"required": [
|
|
11200
|
+
"id",
|
|
11201
|
+
"domain",
|
|
11202
|
+
"verified",
|
|
11203
|
+
"active",
|
|
11204
|
+
"managed",
|
|
11205
|
+
"receiving_ready",
|
|
11206
|
+
"processing_ready",
|
|
11207
|
+
"processing_route_count",
|
|
11208
|
+
"endpoint_count",
|
|
11209
|
+
"enabled_endpoint_count",
|
|
11210
|
+
"function_endpoint_count",
|
|
11211
|
+
"email_count",
|
|
11212
|
+
"latest_email_received_at",
|
|
11213
|
+
"status"
|
|
11214
|
+
]
|
|
11215
|
+
}
|
|
11216
|
+
},
|
|
11217
|
+
"endpoints": {
|
|
11218
|
+
"type": "object",
|
|
11219
|
+
"additionalProperties": false,
|
|
11220
|
+
"properties": {
|
|
11221
|
+
"total": { "type": "integer" },
|
|
11222
|
+
"enabled": { "type": "integer" },
|
|
11223
|
+
"disabled": { "type": "integer" },
|
|
11224
|
+
"fallback_enabled": { "type": "integer" },
|
|
11225
|
+
"domain_scoped_enabled": { "type": "integer" },
|
|
11226
|
+
"http_enabled": { "type": "integer" },
|
|
11227
|
+
"function_enabled": { "type": "integer" }
|
|
11228
|
+
},
|
|
11229
|
+
"required": [
|
|
11230
|
+
"total",
|
|
11231
|
+
"enabled",
|
|
11232
|
+
"disabled",
|
|
11233
|
+
"fallback_enabled",
|
|
11234
|
+
"domain_scoped_enabled",
|
|
11235
|
+
"http_enabled",
|
|
11236
|
+
"function_enabled"
|
|
11237
|
+
]
|
|
11238
|
+
},
|
|
11239
|
+
"functions": {
|
|
11240
|
+
"type": "object",
|
|
11241
|
+
"additionalProperties": false,
|
|
11242
|
+
"properties": {
|
|
11243
|
+
"total": { "type": "integer" },
|
|
11244
|
+
"deployed": { "type": "integer" },
|
|
11245
|
+
"pending": { "type": "integer" },
|
|
11246
|
+
"failed": { "type": "integer" }
|
|
11247
|
+
},
|
|
11248
|
+
"required": [
|
|
11249
|
+
"total",
|
|
11250
|
+
"deployed",
|
|
11251
|
+
"pending",
|
|
11252
|
+
"failed"
|
|
11253
|
+
]
|
|
11254
|
+
},
|
|
11255
|
+
"recent_emails": {
|
|
11256
|
+
"type": "object",
|
|
11257
|
+
"description": "Inbound email activity from the last 30 days.",
|
|
11258
|
+
"additionalProperties": false,
|
|
11259
|
+
"properties": {
|
|
11260
|
+
"total": {
|
|
11261
|
+
"type": "integer",
|
|
11262
|
+
"description": "Number of inbound emails received in the last 30 days."
|
|
11263
|
+
},
|
|
11264
|
+
"latest_received_at": {
|
|
11265
|
+
"type": ["string", "null"],
|
|
11266
|
+
"format": "date-time",
|
|
11267
|
+
"description": "Most recent inbound email received in the last 30 days."
|
|
11268
|
+
}
|
|
11269
|
+
},
|
|
11270
|
+
"required": ["total", "latest_received_at"]
|
|
11271
|
+
}
|
|
11272
|
+
},
|
|
11273
|
+
"required": [
|
|
11274
|
+
"ready",
|
|
11275
|
+
"receiving_ready",
|
|
11276
|
+
"processing_ready",
|
|
11277
|
+
"summary",
|
|
11278
|
+
"next_actions",
|
|
11279
|
+
"domains",
|
|
11280
|
+
"endpoints",
|
|
11281
|
+
"functions",
|
|
11282
|
+
"recent_emails"
|
|
11283
|
+
]
|
|
11284
|
+
},
|
|
11285
|
+
"sdkName": "getInboxStatus",
|
|
11286
|
+
"summary": "Get inbound inbox readiness",
|
|
11287
|
+
"tag": "Inbox",
|
|
11288
|
+
"tagCommand": "inbox"
|
|
11289
|
+
},
|
|
10884
11290
|
{
|
|
10885
11291
|
"binaryResponse": false,
|
|
10886
11292
|
"bodyRequired": false,
|
|
@@ -12973,7 +13379,7 @@ function surfaceUnauthorizedHint(params) {
|
|
|
12973
13379
|
}
|
|
12974
13380
|
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");
|
|
12975
13381
|
}
|
|
12976
|
-
function formatElapsed(ms) {
|
|
13382
|
+
function formatElapsed$1(ms) {
|
|
12977
13383
|
const seconds = ms / 1e3;
|
|
12978
13384
|
if (seconds < 60) return `${seconds.toFixed(2)}s`;
|
|
12979
13385
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -12985,7 +13391,7 @@ async function runWithTiming(enabled, fn) {
|
|
|
12985
13391
|
try {
|
|
12986
13392
|
return await fn();
|
|
12987
13393
|
} finally {
|
|
12988
|
-
process.stderr.write(`[time: ${formatElapsed(Date.now() - start)}]\n`);
|
|
13394
|
+
process.stderr.write(`[time: ${formatElapsed$1(Date.now() - start)}]\n`);
|
|
12989
13395
|
}
|
|
12990
13396
|
}
|
|
12991
13397
|
const TIME_FLAG_DESCRIPTION = "Print the wall-clock duration of this command to stderr after it completes (e.g. `[time: 1.34s]`). Useful for measuring `--wait` send latency, comparing CLI overhead, or capturing timing in scripts.";
|
|
@@ -13082,6 +13488,7 @@ const OPERATION_HINTS = {
|
|
|
13082
13488
|
addDomain: "Tip: after this returns a domain id, run `primitive domains zone-file --id <domain-id> --output <domain>.zone` when the user wants an importable DNS zone file.",
|
|
13083
13489
|
verifyDomain: "Tip: if DNS is still missing, run `primitive domains zone-file --id <domain-id> --output <domain>.zone` to give the user an importable DNS zone file.",
|
|
13084
13490
|
downloadDomainZoneFile: "Tip: prefer `primitive domains zone-file --id <domain-id> --output <domain>.zone` for CLI-friendly file output.",
|
|
13491
|
+
getInboxStatus: "Tip: prefer `primitive inbox status` for a compact readiness summary and next-step commands.",
|
|
13085
13492
|
sendEmail: "Tip: prefer `primitive send --to <address> --body <text> --attachment <file>` for file attachments. This raw command exists for callers passing JSON.",
|
|
13086
13493
|
createFunction: "Tip: prefer `primitive functions deploy --name <name> --file <bundle>` for file-input ergonomics. This raw command exists for callers passing JSON.",
|
|
13087
13494
|
updateFunction: "Tip: prefer `primitive functions redeploy --id <id> --file <bundle>` for file-input ergonomics. This raw command exists for callers passing JSON.",
|
|
@@ -13348,6 +13755,300 @@ async function readStdinToString() {
|
|
|
13348
13755
|
for await (const chunk of process.stdin) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
13349
13756
|
return Buffer.concat(chunks).toString("utf8");
|
|
13350
13757
|
}
|
|
13758
|
+
var ChatProgressIndicator = class {
|
|
13759
|
+
currentMessage = null;
|
|
13760
|
+
frameIndex = 0;
|
|
13761
|
+
lastLineLength = 0;
|
|
13762
|
+
startedAt;
|
|
13763
|
+
timer = null;
|
|
13764
|
+
constructor(stream = process.stderr, now = Date.now) {
|
|
13765
|
+
this.stream = stream;
|
|
13766
|
+
this.now = now;
|
|
13767
|
+
this.startedAt = this.now();
|
|
13768
|
+
}
|
|
13769
|
+
start(message) {
|
|
13770
|
+
this.stopTimer();
|
|
13771
|
+
this.currentMessage = message;
|
|
13772
|
+
if (this.stream.isTTY) {
|
|
13773
|
+
this.render(message);
|
|
13774
|
+
this.timer = setInterval(() => this.render(message), 120);
|
|
13775
|
+
this.timer.unref?.();
|
|
13776
|
+
return;
|
|
13777
|
+
}
|
|
13778
|
+
this.stream.write(`${message}\n`);
|
|
13779
|
+
}
|
|
13780
|
+
update(message, options = {}) {
|
|
13781
|
+
this.currentMessage = message;
|
|
13782
|
+
if (this.stream.isTTY) {
|
|
13783
|
+
this.stopTimer();
|
|
13784
|
+
this.clearLine();
|
|
13785
|
+
this.render(message);
|
|
13786
|
+
this.timer = setInterval(() => this.render(message), 120);
|
|
13787
|
+
this.timer.unref?.();
|
|
13788
|
+
return;
|
|
13789
|
+
}
|
|
13790
|
+
this.stopTimer();
|
|
13791
|
+
this.stream.write(`${message}\n`);
|
|
13792
|
+
if (options.heartbeatMs !== void 0) {
|
|
13793
|
+
this.timer = setInterval(() => {
|
|
13794
|
+
this.stream.write(`${formatWaitingHeartbeat(message, this.now() - this.startedAt, options.timeoutSeconds)}\n`);
|
|
13795
|
+
}, options.heartbeatMs);
|
|
13796
|
+
this.timer.unref?.();
|
|
13797
|
+
}
|
|
13798
|
+
}
|
|
13799
|
+
notice(message) {
|
|
13800
|
+
if (this.stream.isTTY) {
|
|
13801
|
+
const currentMessage = this.currentMessage;
|
|
13802
|
+
this.clearLine();
|
|
13803
|
+
this.stream.write(`${message}\n`);
|
|
13804
|
+
if (currentMessage !== null && this.timer !== null) this.render(currentMessage);
|
|
13805
|
+
return;
|
|
13806
|
+
}
|
|
13807
|
+
this.stream.write(`${message}\n`);
|
|
13808
|
+
}
|
|
13809
|
+
succeed(message) {
|
|
13810
|
+
this.finish(`${message} after ${formatElapsed(this.now() - this.startedAt)}.`);
|
|
13811
|
+
}
|
|
13812
|
+
fail(message) {
|
|
13813
|
+
this.finish(message);
|
|
13814
|
+
}
|
|
13815
|
+
finish(message) {
|
|
13816
|
+
this.stopTimer();
|
|
13817
|
+
this.currentMessage = null;
|
|
13818
|
+
if (this.stream.isTTY) this.clearLine();
|
|
13819
|
+
this.stream.write(`${message}\n`);
|
|
13820
|
+
}
|
|
13821
|
+
render(message) {
|
|
13822
|
+
const frames = [
|
|
13823
|
+
"-",
|
|
13824
|
+
"\\",
|
|
13825
|
+
"|",
|
|
13826
|
+
"/"
|
|
13827
|
+
];
|
|
13828
|
+
const frame = frames[this.frameIndex % frames.length];
|
|
13829
|
+
this.frameIndex += 1;
|
|
13830
|
+
const line = `${frame} ${message} (${formatElapsed(this.now() - this.startedAt)})`;
|
|
13831
|
+
this.lastLineLength = Math.max(this.lastLineLength, line.length);
|
|
13832
|
+
this.stream.write(`\r${line}`);
|
|
13833
|
+
}
|
|
13834
|
+
clearLine() {
|
|
13835
|
+
if (this.lastLineLength > 0) {
|
|
13836
|
+
this.stream.write(`\r${" ".repeat(this.lastLineLength)}\r`);
|
|
13837
|
+
this.lastLineLength = 0;
|
|
13838
|
+
}
|
|
13839
|
+
}
|
|
13840
|
+
stopTimer() {
|
|
13841
|
+
if (this.timer !== null) {
|
|
13842
|
+
clearInterval(this.timer);
|
|
13843
|
+
this.timer = null;
|
|
13844
|
+
}
|
|
13845
|
+
}
|
|
13846
|
+
};
|
|
13847
|
+
function formatElapsed(ms) {
|
|
13848
|
+
const seconds = Math.max(0, Math.round(ms / 1e3));
|
|
13849
|
+
if (seconds < 60) return `${seconds}s`;
|
|
13850
|
+
const minutes = Math.floor(seconds / 60);
|
|
13851
|
+
const remainder = seconds % 60;
|
|
13852
|
+
return remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;
|
|
13853
|
+
}
|
|
13854
|
+
function formatWaitingHeartbeat(message, elapsedMs, timeoutSeconds) {
|
|
13855
|
+
const timeout = timeoutSeconds === void 0 ? "" : timeoutSeconds === 0 ? ", no timeout" : `, timeout ${formatElapsed(timeoutSeconds * 1e3)}`;
|
|
13856
|
+
return `${message} (${formatElapsed(elapsedMs)} elapsed${timeout})`;
|
|
13857
|
+
}
|
|
13858
|
+
function shellQuote(value) {
|
|
13859
|
+
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
13860
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
13861
|
+
}
|
|
13862
|
+
function commandFromArgv(argv) {
|
|
13863
|
+
return argv.map(shellQuote).join(" ");
|
|
13864
|
+
}
|
|
13865
|
+
function resolveChatResponseBody(reply) {
|
|
13866
|
+
if (reply.body_text && reply.body_text.length > 0) return {
|
|
13867
|
+
body: reply.body_text,
|
|
13868
|
+
format: "text"
|
|
13869
|
+
};
|
|
13870
|
+
if (reply.body_html && reply.body_html.length > 0) return {
|
|
13871
|
+
body: reply.body_html,
|
|
13872
|
+
format: "html"
|
|
13873
|
+
};
|
|
13874
|
+
if (reply.body_text !== null && reply.body_text !== void 0) return {
|
|
13875
|
+
body: reply.body_text,
|
|
13876
|
+
format: "text"
|
|
13877
|
+
};
|
|
13878
|
+
if (reply.body_html !== null && reply.body_html !== void 0) return {
|
|
13879
|
+
body: reply.body_html,
|
|
13880
|
+
format: "html"
|
|
13881
|
+
};
|
|
13882
|
+
return {
|
|
13883
|
+
body: "",
|
|
13884
|
+
format: "empty"
|
|
13885
|
+
};
|
|
13886
|
+
}
|
|
13887
|
+
function matchDescription(strategy) {
|
|
13888
|
+
return strategy === "strict" ? "strict, matched by reply_to_sent_email_id" : "fallback, matched by sender/time window";
|
|
13889
|
+
}
|
|
13890
|
+
function buildCommand(kind, description, argv, options = {}) {
|
|
13891
|
+
const requiresMessage = options.requiresMessage ?? false;
|
|
13892
|
+
return {
|
|
13893
|
+
argv,
|
|
13894
|
+
description,
|
|
13895
|
+
command: commandFromArgv(argv),
|
|
13896
|
+
kind,
|
|
13897
|
+
placeholders: requiresMessage ? [{
|
|
13898
|
+
description: "Replace with the message body before running.",
|
|
13899
|
+
token: "<message>"
|
|
13900
|
+
}] : [],
|
|
13901
|
+
requires_message: requiresMessage
|
|
13902
|
+
};
|
|
13903
|
+
}
|
|
13904
|
+
function buildChatFollowUpCommands(context) {
|
|
13905
|
+
const commands = [];
|
|
13906
|
+
const continueParts = [
|
|
13907
|
+
"primitive",
|
|
13908
|
+
"chat",
|
|
13909
|
+
context.recipient,
|
|
13910
|
+
"<message>",
|
|
13911
|
+
"--from",
|
|
13912
|
+
context.from,
|
|
13913
|
+
"--subject",
|
|
13914
|
+
context.subject,
|
|
13915
|
+
"--timeout",
|
|
13916
|
+
String(context.timeoutSeconds)
|
|
13917
|
+
];
|
|
13918
|
+
if (context.reply.message_id) continueParts.push("--in-reply-to", context.reply.message_id);
|
|
13919
|
+
if (context.json) continueParts.push("--json");
|
|
13920
|
+
if (context.quiet) continueParts.push("--quiet");
|
|
13921
|
+
if (context.strictOnly) continueParts.push("--strict-only");
|
|
13922
|
+
else if (context.strictPhaseSeconds !== DEFAULT_STRICT_PHASE_SECONDS) continueParts.push("--strict-phase-seconds", String(context.strictPhaseSeconds));
|
|
13923
|
+
commands.push(buildCommand("continue_chat", "Continue this chat", continueParts, { requiresMessage: true }));
|
|
13924
|
+
commands.push(buildCommand("reply_direct", "Reply directly to the inbound email", [
|
|
13925
|
+
"primitive",
|
|
13926
|
+
"reply",
|
|
13927
|
+
"--id",
|
|
13928
|
+
context.reply.id,
|
|
13929
|
+
"--from",
|
|
13930
|
+
context.from,
|
|
13931
|
+
"--body",
|
|
13932
|
+
"<message>"
|
|
13933
|
+
], { requiresMessage: true }));
|
|
13934
|
+
commands.push(buildCommand("inspect_reply", "Inspect the full inbound email", [
|
|
13935
|
+
"primitive",
|
|
13936
|
+
"emails",
|
|
13937
|
+
"get",
|
|
13938
|
+
"--id",
|
|
13939
|
+
context.reply.id
|
|
13940
|
+
]));
|
|
13941
|
+
commands.push(buildCommand("wait_for_more", "Wait for future replies to this send", [
|
|
13942
|
+
"primitive",
|
|
13943
|
+
"emails",
|
|
13944
|
+
"wait",
|
|
13945
|
+
"--reply-to-sent-email-id",
|
|
13946
|
+
context.sent.id,
|
|
13947
|
+
"--to",
|
|
13948
|
+
context.from,
|
|
13949
|
+
"--since",
|
|
13950
|
+
context.reply.received_at,
|
|
13951
|
+
"--timeout",
|
|
13952
|
+
String(context.timeoutSeconds)
|
|
13953
|
+
]));
|
|
13954
|
+
return commands;
|
|
13955
|
+
}
|
|
13956
|
+
function buildChatRecoveryCommands(context) {
|
|
13957
|
+
return [
|
|
13958
|
+
buildCommand("wait_threaded_reply", "Wait for the threaded reply again", [
|
|
13959
|
+
"primitive",
|
|
13960
|
+
"emails",
|
|
13961
|
+
"wait",
|
|
13962
|
+
"--reply-to-sent-email-id",
|
|
13963
|
+
context.sent.id,
|
|
13964
|
+
"--to",
|
|
13965
|
+
context.from,
|
|
13966
|
+
"--since",
|
|
13967
|
+
context.sentAtIso,
|
|
13968
|
+
"--timeout",
|
|
13969
|
+
String(context.timeoutSeconds)
|
|
13970
|
+
]),
|
|
13971
|
+
buildCommand("wait_fallback_reply", "Fallback wait by sender/time window", [
|
|
13972
|
+
"primitive",
|
|
13973
|
+
"emails",
|
|
13974
|
+
"wait",
|
|
13975
|
+
"--from",
|
|
13976
|
+
context.recipient,
|
|
13977
|
+
"--to",
|
|
13978
|
+
context.from,
|
|
13979
|
+
"--since",
|
|
13980
|
+
context.sentAtIso,
|
|
13981
|
+
"--timeout",
|
|
13982
|
+
String(context.timeoutSeconds)
|
|
13983
|
+
]),
|
|
13984
|
+
buildCommand("inspect_sent_email", "Inspect the outbound send", [
|
|
13985
|
+
"primitive",
|
|
13986
|
+
"sent",
|
|
13987
|
+
"get",
|
|
13988
|
+
"--id",
|
|
13989
|
+
context.sent.id
|
|
13990
|
+
])
|
|
13991
|
+
];
|
|
13992
|
+
}
|
|
13993
|
+
function buildChatJsonEnvelope(context) {
|
|
13994
|
+
const responseBody = resolveChatResponseBody(context.reply);
|
|
13995
|
+
return {
|
|
13996
|
+
sent: context.sent,
|
|
13997
|
+
reply: context.reply,
|
|
13998
|
+
response_body: responseBody.body,
|
|
13999
|
+
response_body_format: responseBody.format,
|
|
14000
|
+
match: {
|
|
14001
|
+
description: matchDescription(context.matchStrategy),
|
|
14002
|
+
reply_to_sent_email_id: context.reply.reply_to_sent_email_id ?? null,
|
|
14003
|
+
strategy: context.matchStrategy
|
|
14004
|
+
},
|
|
14005
|
+
follow_up_commands: buildChatFollowUpCommands(context)
|
|
14006
|
+
};
|
|
14007
|
+
}
|
|
14008
|
+
function formatChatResponse(context) {
|
|
14009
|
+
const accepted = context.sent.accepted.join(", ") || context.recipient;
|
|
14010
|
+
const responseBody = resolveChatResponseBody(context.reply);
|
|
14011
|
+
const lines = [
|
|
14012
|
+
"Reply received",
|
|
14013
|
+
"",
|
|
14014
|
+
"Sent",
|
|
14015
|
+
` To: ${accepted}`,
|
|
14016
|
+
` From: ${context.sent.from || context.from}`,
|
|
14017
|
+
` Subject: ${context.subject}`,
|
|
14018
|
+
` Sent email id: ${context.sent.id}`,
|
|
14019
|
+
` Delivery status: ${context.sent.delivery_status ?? context.sent.status}`,
|
|
14020
|
+
"",
|
|
14021
|
+
"Reply",
|
|
14022
|
+
` Email id: ${context.reply.id}`,
|
|
14023
|
+
` From: ${context.reply.from_email}`,
|
|
14024
|
+
` To: ${context.reply.to_email}`,
|
|
14025
|
+
` Subject: ${context.reply.subject ?? "(no subject)"}`,
|
|
14026
|
+
` Received: ${context.reply.received_at}`,
|
|
14027
|
+
` Match: ${matchDescription(context.matchStrategy)}`
|
|
14028
|
+
];
|
|
14029
|
+
if (context.reply.reply_to_sent_email_id) lines.push(` Reply to sent email id: ${context.reply.reply_to_sent_email_id}`);
|
|
14030
|
+
if (context.reply.message_id) lines.push(` Message-Id: ${context.reply.message_id}`);
|
|
14031
|
+
lines.push("", "Helpful follow-up commands", " Replace <message> before running commands that include it.", " Commands are templates; use --json for parse-safe output.");
|
|
14032
|
+
for (const { description, command } of buildChatFollowUpCommands(context)) lines.push(` ${description}:`, ` ${command}`);
|
|
14033
|
+
lines.push("", `Response body (${responseBody.format}; use --json for parsing)`, "----- BEGIN RESPONSE -----", responseBody.body || "(empty response)", "----- END RESPONSE -----");
|
|
14034
|
+
return lines.join("\n");
|
|
14035
|
+
}
|
|
14036
|
+
function formatChatRecoveryContext(context) {
|
|
14037
|
+
const lines = [
|
|
14038
|
+
"",
|
|
14039
|
+
"Sent message context",
|
|
14040
|
+
` To: ${context.sent.accepted.join(", ") || context.recipient}`,
|
|
14041
|
+
` From: ${context.sent.from || context.from}`,
|
|
14042
|
+
` Subject: ${context.subject}`,
|
|
14043
|
+
` Sent email id: ${context.sent.id}`,
|
|
14044
|
+
` Delivery status: ${context.sent.delivery_status ?? context.sent.status}`,
|
|
14045
|
+
` Poll since: ${context.sentAtIso}`,
|
|
14046
|
+
"",
|
|
14047
|
+
"Helpful recovery commands"
|
|
14048
|
+
];
|
|
14049
|
+
for (const { description, command } of buildChatRecoveryCommands(context)) lines.push(` ${description}:`, ` ${command}`);
|
|
14050
|
+
return lines.join("\n");
|
|
14051
|
+
}
|
|
13351
14052
|
var ChatCommand = class ChatCommand extends Command {
|
|
13352
14053
|
static description = `Send a message to an address and wait for the reply.
|
|
13353
14054
|
|
|
@@ -13356,13 +14057,24 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
13356
14057
|
\`primitive chat\` is semantic (send + wait for the threaded reply).
|
|
13357
14058
|
|
|
13358
14059
|
The message body can be given as the second positional argument or
|
|
13359
|
-
piped via stdin. The
|
|
13360
|
-
|
|
14060
|
+
piped via stdin. The default output confirms the reply was received,
|
|
14061
|
+
prints exchange metadata, shows the response body, and lists helpful
|
|
14062
|
+
follow-up commands as templates. The default transcript is for humans;
|
|
14063
|
+
agents and scripts should pass --json for parse-safe output.
|
|
14064
|
+
|
|
14065
|
+
--json emits a structured envelope with both sides of the exchange,
|
|
14066
|
+
a direct response_body field, match details, and follow-up command
|
|
14067
|
+
metadata such as kind, argv, placeholders, and requires_message.
|
|
13361
14068
|
|
|
13362
|
-
Matching the reply:
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
14069
|
+
Matching the reply: chat first waits in strict threading mode by
|
|
14070
|
+
filtering inbound mail with reply_to_sent_email_id=<sent id>. If
|
|
14071
|
+
no strict match arrives before the strict phase ends, and
|
|
14072
|
+
--strict-only is not set, it falls back to a weaker sender/time
|
|
14073
|
+
window match: from=<recipient>, to=<sender>, and since=<send time>.
|
|
14074
|
+
The fallback can catch clients that strip threading headers, but it
|
|
14075
|
+
is less exact than strict matching. Progress is written to stderr
|
|
14076
|
+
while the CLI waits. Exits non-zero on timeout and prints recovery
|
|
14077
|
+
commands when the send succeeded but no reply was returned.`;
|
|
13366
14078
|
static summary = "Chat with an agent over email (send and wait for the reply)";
|
|
13367
14079
|
static examples = [
|
|
13368
14080
|
"<%= config.bin %> chat help@agent.acme.dev 'how do I rotate my API key?'",
|
|
@@ -13395,7 +14107,8 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
13395
14107
|
from: Flags.string({ description: "Sender address. Defaults to agent@<your-first-verified-outbound-domain>." }),
|
|
13396
14108
|
subject: Flags.string({ description: "Subject line. Defaults to the first line of the message when omitted." }),
|
|
13397
14109
|
"in-reply-to": Flags.string({ description: "Message-Id of the parent email to thread this against. Use when continuing a prior conversation from outside the CLI; for an inbound you received via Primitive, prefer `primitive reply --id <inbound-id>`." }),
|
|
13398
|
-
json: Flags.boolean({ description: "Emit a structured JSON envelope { sent, reply } on stdout instead of
|
|
14110
|
+
json: Flags.boolean({ description: "Emit a structured JSON envelope { sent, reply, response_body, response_body_format, match, follow_up_commands } on stdout instead of the human-readable transcript." }),
|
|
14111
|
+
quiet: Flags.boolean({ description: "Suppress stderr progress updates while sending and waiting. Errors and recovery commands are still written to stderr." }),
|
|
13399
14112
|
timeout: Flags.integer({
|
|
13400
14113
|
default: DEFAULT_CHAT_TIMEOUT_SECONDS,
|
|
13401
14114
|
description: "Seconds to wait for a reply before exiting non-zero; 0 waits forever.",
|
|
@@ -13440,6 +14153,8 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
13440
14153
|
const from = flags.from ?? await pickDefaultFromAddress(apiClient, authFailureContext);
|
|
13441
14154
|
const subject = flags.subject ?? deriveSubject(message);
|
|
13442
14155
|
const sentAtIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
14156
|
+
const progress = flags.quiet ? null : new ChatProgressIndicator(process.stderr);
|
|
14157
|
+
progress?.start(`Sending message to ${args.recipient}`);
|
|
13443
14158
|
const sendResult = await sendEmail({
|
|
13444
14159
|
body: {
|
|
13445
14160
|
from,
|
|
@@ -13452,6 +14167,7 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
13452
14167
|
responseStyle: "fields"
|
|
13453
14168
|
});
|
|
13454
14169
|
if (sendResult.error) {
|
|
14170
|
+
progress?.fail("Message send failed.");
|
|
13455
14171
|
const errorPayload = extractErrorPayload(sendResult.error);
|
|
13456
14172
|
writeErrorWithHints(errorPayload);
|
|
13457
14173
|
surfaceUnauthorizedHint({
|
|
@@ -13462,39 +14178,76 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
13462
14178
|
return;
|
|
13463
14179
|
}
|
|
13464
14180
|
const sent = sendResult.data?.data;
|
|
13465
|
-
if (!sent)
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
14181
|
+
if (!sent) {
|
|
14182
|
+
progress?.fail("Send succeeded but the API returned no data.");
|
|
14183
|
+
throw cliError$6("Send succeeded but the API returned no data.");
|
|
14184
|
+
}
|
|
14185
|
+
progress?.update(`Message sent; waiting for reply from ${args.recipient}`, {
|
|
14186
|
+
heartbeatMs: 15e3,
|
|
14187
|
+
timeoutSeconds: flags.timeout
|
|
14188
|
+
});
|
|
14189
|
+
const baseContext = {
|
|
13469
14190
|
from,
|
|
13470
|
-
|
|
13471
|
-
|
|
14191
|
+
json: flags.json,
|
|
14192
|
+
quiet: flags.quiet,
|
|
13472
14193
|
recipient: args.recipient,
|
|
14194
|
+
sent,
|
|
13473
14195
|
sentAtIso,
|
|
13474
|
-
sentId: sent.id,
|
|
13475
14196
|
strictOnly: flags["strict-only"],
|
|
13476
14197
|
strictPhaseSeconds: flags["strict-phase-seconds"],
|
|
14198
|
+
subject,
|
|
13477
14199
|
timeoutSeconds: flags.timeout
|
|
13478
|
-
}
|
|
13479
|
-
|
|
13480
|
-
|
|
14200
|
+
};
|
|
14201
|
+
let replyResult;
|
|
14202
|
+
try {
|
|
14203
|
+
replyResult = await waitForReply({
|
|
14204
|
+
apiClient,
|
|
14205
|
+
authFailureContext,
|
|
14206
|
+
from,
|
|
14207
|
+
interval: flags.interval,
|
|
14208
|
+
notice: (message) => {
|
|
14209
|
+
if (progress) {
|
|
14210
|
+
progress.notice(message);
|
|
14211
|
+
return;
|
|
14212
|
+
}
|
|
14213
|
+
process.stderr.write(`${message}\n`);
|
|
14214
|
+
},
|
|
14215
|
+
pageSize: flags["page-size"],
|
|
14216
|
+
recipient: args.recipient,
|
|
14217
|
+
sentAtIso,
|
|
14218
|
+
sentId: sent.id,
|
|
14219
|
+
strictOnly: flags["strict-only"],
|
|
14220
|
+
strictPhaseSeconds: flags["strict-phase-seconds"],
|
|
14221
|
+
timeoutSeconds: flags.timeout
|
|
14222
|
+
});
|
|
14223
|
+
} catch (error) {
|
|
14224
|
+
progress?.fail("Reply polling failed.");
|
|
14225
|
+
process.stderr.write(`${formatChatRecoveryContext(baseContext)}\n`);
|
|
14226
|
+
throw error;
|
|
14227
|
+
}
|
|
14228
|
+
if (replyResult === null) {
|
|
14229
|
+
const timeoutMessage = `Timed out after ${flags.timeout}s waiting for a reply from ${args.recipient}.`;
|
|
14230
|
+
progress?.fail(timeoutMessage);
|
|
14231
|
+
if (progress === null) process.stderr.write(`${timeoutMessage}\n`);
|
|
14232
|
+
process.stderr.write(`${formatChatRecoveryContext(baseContext)}\n`);
|
|
13481
14233
|
process.exitCode = 1;
|
|
13482
14234
|
return;
|
|
13483
14235
|
}
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
this.log(body);
|
|
13493
|
-
}
|
|
14236
|
+
progress?.succeed(`Reply received from ${replyResult.reply.from_email}`);
|
|
14237
|
+
const outputContext = {
|
|
14238
|
+
...baseContext,
|
|
14239
|
+
matchStrategy: replyResult.matchStrategy,
|
|
14240
|
+
reply: replyResult.reply
|
|
14241
|
+
};
|
|
14242
|
+
if (flags.json) this.log(JSON.stringify(buildChatJsonEnvelope(outputContext), null, 2));
|
|
14243
|
+
else this.log(formatChatResponse(outputContext));
|
|
13494
14244
|
});
|
|
13495
14245
|
}
|
|
13496
14246
|
};
|
|
13497
14247
|
async function waitForReply(params) {
|
|
14248
|
+
const notice = params.notice ?? ((message) => {
|
|
14249
|
+
process.stderr.write(`${message}\n`);
|
|
14250
|
+
});
|
|
13498
14251
|
const totalDeadline = params.timeoutSeconds === 0 ? null : Date.now() + params.timeoutSeconds * 1e3;
|
|
13499
14252
|
const strictDeadlineFromBudget = Date.now() + params.strictPhaseSeconds * 1e3;
|
|
13500
14253
|
const strictDeadline = params.strictOnly ? totalDeadline : totalDeadline === null ? strictDeadlineFromBudget : Math.min(strictDeadlineFromBudget, totalDeadline);
|
|
@@ -13563,11 +14316,14 @@ async function waitForReply(params) {
|
|
|
13563
14316
|
const detail = envelope?.data ?? envelope ?? null;
|
|
13564
14317
|
if (!detail) throw new Errors.CLIError(`Reply landed but the email body could not be loaded (id=${match.id}).`, { exit: 1 });
|
|
13565
14318
|
if (phase.label === "strict" && detail.reply_to_sent_email_id !== params.sentId) {
|
|
13566
|
-
if (!strictFilterUnsupported)
|
|
14319
|
+
if (!strictFilterUnsupported) notice(params.strictOnly ? "Strict-phase reply matching is not supported by this Primitive API host; --strict-only requires server support so the command will exit without a match." : "Strict-phase reply matching is not supported by this Primitive API host; falling back to time-window matching.");
|
|
13567
14320
|
strictFilterUnsupported = true;
|
|
13568
14321
|
continue;
|
|
13569
14322
|
}
|
|
13570
|
-
return
|
|
14323
|
+
return {
|
|
14324
|
+
reply: detail,
|
|
14325
|
+
matchStrategy: phase.label
|
|
14326
|
+
};
|
|
13571
14327
|
}
|
|
13572
14328
|
if (strictFilterUnsupported && phase.label === "strict") break;
|
|
13573
14329
|
if (lastAccepted !== void 0) continue;
|
|
@@ -13589,6 +14345,33 @@ function redactConfig(config) {
|
|
|
13589
14345
|
environments: Object.fromEntries(Object.entries(config.environments).map(([name, environment]) => [name, redactCliEnvironment(environment)]))
|
|
13590
14346
|
};
|
|
13591
14347
|
}
|
|
14348
|
+
function switchCliEnvironment(configDir, environmentName) {
|
|
14349
|
+
const environment = normalizeCliEnvironmentName(environmentName);
|
|
14350
|
+
const config = loadOrCreateConfig(configDir);
|
|
14351
|
+
if (!config.environments[environment]) throw new Errors.CLIError(`Primitive CLI environment ${environment} is not configured.`, { exit: 1 });
|
|
14352
|
+
const previousEnvironment = resolveConfigEnvironment(config)?.name ?? null;
|
|
14353
|
+
const nextConfig = {
|
|
14354
|
+
...config,
|
|
14355
|
+
current_environment: environment
|
|
14356
|
+
};
|
|
14357
|
+
const shouldClearCredentials = previousEnvironment !== environment;
|
|
14358
|
+
let removedCredentials = false;
|
|
14359
|
+
if (shouldClearCredentials) {
|
|
14360
|
+
const releaseLock = acquireCliCredentialsLock(configDir);
|
|
14361
|
+
try {
|
|
14362
|
+
saveCliConfig(configDir, nextConfig);
|
|
14363
|
+
removedCredentials = existsSync(credentialsPath(configDir));
|
|
14364
|
+
deleteCliCredentials(configDir);
|
|
14365
|
+
} finally {
|
|
14366
|
+
releaseLock();
|
|
14367
|
+
}
|
|
14368
|
+
} else saveCliConfig(configDir, nextConfig);
|
|
14369
|
+
return {
|
|
14370
|
+
environment,
|
|
14371
|
+
previousEnvironment,
|
|
14372
|
+
removedCredentials
|
|
14373
|
+
};
|
|
14374
|
+
}
|
|
13592
14375
|
var ConfigSetCommand = class ConfigSetCommand extends Command {
|
|
13593
14376
|
static summary = "Set a Primitive CLI request environment";
|
|
13594
14377
|
static flags = {
|
|
@@ -13625,20 +14408,16 @@ var ConfigSetCommand = class ConfigSetCommand extends Command {
|
|
|
13625
14408
|
};
|
|
13626
14409
|
var ConfigUseCommand = class ConfigUseCommand extends Command {
|
|
13627
14410
|
static summary = "Switch the active Primitive CLI request environment";
|
|
14411
|
+
static description = "Switch the active Primitive CLI request environment. When this switches to a different environment, the CLI removes saved OAuth credentials so the next authenticated command signs in against the newly active API host.";
|
|
13628
14412
|
static args = { environment: Args.string({
|
|
13629
14413
|
description: "Environment name to use",
|
|
13630
14414
|
required: true
|
|
13631
14415
|
}) };
|
|
13632
14416
|
async run() {
|
|
13633
14417
|
const { args } = await this.parse(ConfigUseCommand);
|
|
13634
|
-
const environment =
|
|
13635
|
-
const config = loadOrCreateConfig(this.config.configDir);
|
|
13636
|
-
if (!config.environments[environment]) throw new Errors.CLIError(`Primitive CLI environment ${environment} is not configured.`, { exit: 1 });
|
|
13637
|
-
saveCliConfig(this.config.configDir, {
|
|
13638
|
-
...config,
|
|
13639
|
-
current_environment: environment
|
|
13640
|
-
});
|
|
14418
|
+
const { environment, removedCredentials } = switchCliEnvironment(this.config.configDir, args.environment);
|
|
13641
14419
|
process.stderr.write(`Primitive CLI environment ${environment} is active.\n`);
|
|
14420
|
+
if (removedCredentials) process.stderr.write("Removed saved Primitive CLI credentials. Run `primitive signin` to authenticate in the active environment.\n");
|
|
13642
14421
|
}
|
|
13643
14422
|
};
|
|
13644
14423
|
var ConfigListCommand = class ConfigListCommand extends Command {
|
|
@@ -14108,7 +14887,7 @@ const ADDRESS_DISPLAY_WIDTH = 32;
|
|
|
14108
14887
|
const ID_DISPLAY_WIDTH_SHORT = 8;
|
|
14109
14888
|
const ID_DISPLAY_WIDTH_FULL = 36;
|
|
14110
14889
|
const RECEIVED_DISPLAY_WIDTH = 19;
|
|
14111
|
-
function truncate(value, width) {
|
|
14890
|
+
function truncate$1(value, width) {
|
|
14112
14891
|
if (value.length <= width) return value.padEnd(width);
|
|
14113
14892
|
return `${value.slice(0, width - 3)}...`;
|
|
14114
14893
|
}
|
|
@@ -14123,7 +14902,7 @@ function pickIdWidth(isTty) {
|
|
|
14123
14902
|
return isTty ? ID_DISPLAY_WIDTH_SHORT : ID_DISPLAY_WIDTH_FULL;
|
|
14124
14903
|
}
|
|
14125
14904
|
function formatRow(email, idWidth) {
|
|
14126
|
-
return `${truncate(email.id.slice(0, idWidth), idWidth)} ${formatReceivedAt(email.received_at)} ${truncate(email.sender ?? "", ADDRESS_DISPLAY_WIDTH)} ${truncate(email.recipient ?? "", ADDRESS_DISPLAY_WIDTH)} ${truncate((email.subject ?? "").replace(/\s+/g, " "), SUBJECT_DISPLAY_WIDTH)}`;
|
|
14905
|
+
return `${truncate$1(email.id.slice(0, idWidth), idWidth)} ${formatReceivedAt(email.received_at)} ${truncate$1(email.sender ?? "", ADDRESS_DISPLAY_WIDTH)} ${truncate$1(email.recipient ?? "", ADDRESS_DISPLAY_WIDTH)} ${truncate$1((email.subject ?? "").replace(/\s+/g, " "), SUBJECT_DISPLAY_WIDTH)}`;
|
|
14127
14906
|
}
|
|
14128
14907
|
function formatHeader(idWidth) {
|
|
14129
14908
|
return `${"ID".padEnd(idWidth)} ${"RECEIVED (UTC)".padEnd(RECEIVED_DISPLAY_WIDTH)} ${"FROM".padEnd(ADDRESS_DISPLAY_WIDTH)} ${"TO".padEnd(ADDRESS_DISPLAY_WIDTH)} SUBJECT`;
|
|
@@ -16509,6 +17288,174 @@ var FunctionsTestFunctionCommand = class FunctionsTestFunctionCommand extends Co
|
|
|
16509
17288
|
}
|
|
16510
17289
|
};
|
|
16511
17290
|
//#endregion
|
|
17291
|
+
//#region src/oclif/commands/inbox-status.ts
|
|
17292
|
+
const DOMAIN_DISPLAY_WIDTH = 34;
|
|
17293
|
+
const STATUS_DISPLAY_WIDTH = 12;
|
|
17294
|
+
const BOOL_DISPLAY_WIDTH = 7;
|
|
17295
|
+
const NUM_DISPLAY_WIDTH = 6;
|
|
17296
|
+
function plural(count, singular, pluralValue = `${singular}s`) {
|
|
17297
|
+
return `${count} ${count === 1 ? singular : pluralValue}`;
|
|
17298
|
+
}
|
|
17299
|
+
function statusText(status) {
|
|
17300
|
+
switch (status) {
|
|
17301
|
+
case "ready": return "ready";
|
|
17302
|
+
case "stored_only": return "stored-only";
|
|
17303
|
+
case "pending_dns": return "pending-dns";
|
|
17304
|
+
case "inactive": return "inactive";
|
|
17305
|
+
default: return String(status);
|
|
17306
|
+
}
|
|
17307
|
+
}
|
|
17308
|
+
function yesNo(value) {
|
|
17309
|
+
return value ? "yes" : "no";
|
|
17310
|
+
}
|
|
17311
|
+
function formatInboxDate(value) {
|
|
17312
|
+
if (!value) return "never";
|
|
17313
|
+
const d = new Date(value);
|
|
17314
|
+
if (Number.isNaN(d.getTime())) return value;
|
|
17315
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
17316
|
+
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())} UTC`;
|
|
17317
|
+
}
|
|
17318
|
+
function truncate(value, width) {
|
|
17319
|
+
if (value.length <= width) return value.padEnd(width);
|
|
17320
|
+
return `${value.slice(0, width - 3)}...`;
|
|
17321
|
+
}
|
|
17322
|
+
function domainSummary(domain) {
|
|
17323
|
+
switch (domain.status) {
|
|
17324
|
+
case "ready": return `${domain.domain} can receive mail and has ${plural(domain.processing_route_count, "processing route")}.`;
|
|
17325
|
+
case "stored_only": return `${domain.domain} can receive and store mail, but has no enabled processing route.`;
|
|
17326
|
+
case "pending_dns": return `${domain.domain} is waiting on DNS verification before it can receive mail.`;
|
|
17327
|
+
case "inactive": return `${domain.domain} is verified but inactive.`;
|
|
17328
|
+
default: return `${domain.domain} has status ${String(domain.status)}.`;
|
|
17329
|
+
}
|
|
17330
|
+
}
|
|
17331
|
+
function focusInboxStatus(status, domainName) {
|
|
17332
|
+
const normalized = domainName.toLowerCase();
|
|
17333
|
+
const domain = status.domains.find((entry) => entry.domain.toLowerCase() === normalized);
|
|
17334
|
+
if (!domain) throw new Errors.CLIError(`Domain ${domainName} was not found.`, { exit: 1 });
|
|
17335
|
+
return {
|
|
17336
|
+
...status,
|
|
17337
|
+
domains: [domain],
|
|
17338
|
+
ready: domain.receiving_ready && domain.processing_ready,
|
|
17339
|
+
receiving_ready: domain.receiving_ready,
|
|
17340
|
+
processing_ready: domain.processing_ready,
|
|
17341
|
+
summary: domainSummary(domain),
|
|
17342
|
+
recent_emails: {
|
|
17343
|
+
total: domain.email_count,
|
|
17344
|
+
latest_received_at: domain.latest_email_received_at
|
|
17345
|
+
}
|
|
17346
|
+
};
|
|
17347
|
+
}
|
|
17348
|
+
function formatDomainHeader() {
|
|
17349
|
+
return [
|
|
17350
|
+
"DOMAIN".padEnd(DOMAIN_DISPLAY_WIDTH),
|
|
17351
|
+
"STATUS".padEnd(STATUS_DISPLAY_WIDTH),
|
|
17352
|
+
"RECEIVE".padEnd(BOOL_DISPLAY_WIDTH),
|
|
17353
|
+
"PROCESS".padEnd(BOOL_DISPLAY_WIDTH),
|
|
17354
|
+
"EMAILS".padStart(NUM_DISPLAY_WIDTH),
|
|
17355
|
+
"ROUTES".padStart(NUM_DISPLAY_WIDTH)
|
|
17356
|
+
].join(" ");
|
|
17357
|
+
}
|
|
17358
|
+
function formatDomainRow(domain) {
|
|
17359
|
+
return [
|
|
17360
|
+
truncate(domain.domain, DOMAIN_DISPLAY_WIDTH),
|
|
17361
|
+
statusText(domain.status).padEnd(STATUS_DISPLAY_WIDTH),
|
|
17362
|
+
yesNo(domain.receiving_ready).padEnd(BOOL_DISPLAY_WIDTH),
|
|
17363
|
+
yesNo(domain.processing_ready).padEnd(BOOL_DISPLAY_WIDTH),
|
|
17364
|
+
String(domain.email_count).padStart(NUM_DISPLAY_WIDTH),
|
|
17365
|
+
String(domain.processing_route_count).padStart(NUM_DISPLAY_WIDTH)
|
|
17366
|
+
].join(" ");
|
|
17367
|
+
}
|
|
17368
|
+
function formatNextAction(action) {
|
|
17369
|
+
return action.command ? `- ${action.message}\n ${action.command}` : `- ${action.message}`;
|
|
17370
|
+
}
|
|
17371
|
+
function formatInboxStatus(status) {
|
|
17372
|
+
const lines = [
|
|
17373
|
+
status.summary,
|
|
17374
|
+
"",
|
|
17375
|
+
"Domains"
|
|
17376
|
+
];
|
|
17377
|
+
if (status.domains.length === 0) lines.push("No domains configured.");
|
|
17378
|
+
else {
|
|
17379
|
+
lines.push(formatDomainHeader());
|
|
17380
|
+
for (const domain of status.domains) lines.push(formatDomainRow(domain));
|
|
17381
|
+
}
|
|
17382
|
+
lines.push("", `Endpoints: ${status.endpoints.enabled}/${status.endpoints.total} enabled (${status.endpoints.fallback_enabled} fallback, ${status.endpoints.domain_scoped_enabled} domain-scoped, ${status.endpoints.function_enabled} function)`, `Functions: ${status.functions.deployed}/${status.functions.total} deployed (${status.functions.pending} pending, ${status.functions.failed} failed)`, `Recent inbound: ${plural(status.recent_emails.total, "email")} latest ${formatInboxDate(status.recent_emails.latest_received_at)}`);
|
|
17383
|
+
if (status.next_actions.length > 0) {
|
|
17384
|
+
lines.push("", "Next actions");
|
|
17385
|
+
for (const action of status.next_actions) lines.push(formatNextAction(action));
|
|
17386
|
+
}
|
|
17387
|
+
return lines.join("\n");
|
|
17388
|
+
}
|
|
17389
|
+
var InboxStatusCommand = class InboxStatusCommand extends Command {
|
|
17390
|
+
static description = `Show consolidated inbound email readiness.
|
|
17391
|
+
|
|
17392
|
+
This checks the server-owned inbox status API instead of reconstructing readiness locally from separate domain, endpoint, function, and email lists. Use it before testing inbound email setup: it tells you whether mail can be received, whether anything will process it, and which next command is most useful.`;
|
|
17393
|
+
static summary = "Show inbound email readiness";
|
|
17394
|
+
static examples = [
|
|
17395
|
+
"<%= config.bin %> inbox status",
|
|
17396
|
+
"<%= config.bin %> inbox status --domain example.com",
|
|
17397
|
+
"<%= config.bin %> inbox status --json | jq '.data.next_actions'"
|
|
17398
|
+
];
|
|
17399
|
+
static flags = {
|
|
17400
|
+
"api-key": Flags.string({
|
|
17401
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
17402
|
+
env: "PRIMITIVE_API_KEY"
|
|
17403
|
+
}),
|
|
17404
|
+
"api-base-url-1": Flags.string({
|
|
17405
|
+
description: API_BASE_URL_1_FLAG_DESCRIPTION,
|
|
17406
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
17407
|
+
hidden: true
|
|
17408
|
+
}),
|
|
17409
|
+
"api-base-url-2": Flags.string({
|
|
17410
|
+
description: API_BASE_URL_2_FLAG_DESCRIPTION,
|
|
17411
|
+
env: "PRIMITIVE_API_BASE_URL_2",
|
|
17412
|
+
hidden: true
|
|
17413
|
+
}),
|
|
17414
|
+
domain: Flags.string({ description: "Focus domain readiness and recent email fields on one domain returned by the inbox status API." }),
|
|
17415
|
+
json: Flags.boolean({ description: "Print the raw response envelope as JSON. With --domain, domain readiness and recent email fields are focused while endpoint, function, and next-action summaries remain account-level." }),
|
|
17416
|
+
time: Flags.boolean({ description: TIME_FLAG_DESCRIPTION })
|
|
17417
|
+
};
|
|
17418
|
+
async run() {
|
|
17419
|
+
const { flags } = await this.parse(InboxStatusCommand);
|
|
17420
|
+
await runWithTiming(flags.time, async () => {
|
|
17421
|
+
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
17422
|
+
apiKey: flags["api-key"],
|
|
17423
|
+
apiBaseUrl1: flags["api-base-url-1"],
|
|
17424
|
+
apiBaseUrl2: flags["api-base-url-2"],
|
|
17425
|
+
configDir: this.config.configDir
|
|
17426
|
+
});
|
|
17427
|
+
const result = await getInboxStatus({
|
|
17428
|
+
client: apiClient.client,
|
|
17429
|
+
responseStyle: "fields"
|
|
17430
|
+
});
|
|
17431
|
+
if (result.error) {
|
|
17432
|
+
const errorPayload = extractErrorPayload(result.error);
|
|
17433
|
+
writeErrorWithHints(errorPayload);
|
|
17434
|
+
surfaceUnauthorizedHint({
|
|
17435
|
+
auth,
|
|
17436
|
+
baseUrlOverridden,
|
|
17437
|
+
configDir: this.config.configDir,
|
|
17438
|
+
payload: errorPayload
|
|
17439
|
+
});
|
|
17440
|
+
process.exitCode = 1;
|
|
17441
|
+
return;
|
|
17442
|
+
}
|
|
17443
|
+
const envelope = result.data ?? {};
|
|
17444
|
+
const status = envelope.data;
|
|
17445
|
+
if (!status) throw new Errors.CLIError("Primitive API returned no inbox status.", { exit: 1 });
|
|
17446
|
+
const outputStatus = flags.domain ? focusInboxStatus(status, flags.domain) : status;
|
|
17447
|
+
if (flags.json) {
|
|
17448
|
+
this.log(JSON.stringify({
|
|
17449
|
+
...envelope,
|
|
17450
|
+
data: outputStatus
|
|
17451
|
+
}, null, 2));
|
|
17452
|
+
return;
|
|
17453
|
+
}
|
|
17454
|
+
this.log(formatInboxStatus(outputStatus));
|
|
17455
|
+
});
|
|
17456
|
+
}
|
|
17457
|
+
};
|
|
17458
|
+
//#endregion
|
|
16512
17459
|
//#region src/oclif/commands/login.ts
|
|
16513
17460
|
const MAX_CLI_LOGIN_POLL_INTERVAL_SECONDS = 60;
|
|
16514
17461
|
function cliError$3(message) {
|
|
@@ -17915,25 +18862,39 @@ var SigninOtpResendCommand = class SigninOtpResendCommand extends Command {
|
|
|
17915
18862
|
};
|
|
17916
18863
|
//#endregion
|
|
17917
18864
|
//#region src/oclif/commands/whoami.ts
|
|
18865
|
+
function formatWhoamiSummary(account) {
|
|
18866
|
+
return [
|
|
18867
|
+
`Authenticated as ${account.email}`,
|
|
18868
|
+
`Account id: ${account.id}`,
|
|
18869
|
+
`Plan: ${account.plan}`
|
|
18870
|
+
].join("\n");
|
|
18871
|
+
}
|
|
17918
18872
|
var WhoamiCommand = class WhoamiCommand extends Command {
|
|
17919
|
-
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
|
|
18873
|
+
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.
|
|
18874
|
+
|
|
18875
|
+
The default output is a concise human summary. Pass --json only when a script intentionally needs the full /account response.`;
|
|
17920
18876
|
static summary = "Print the authenticated account (credentials smoke test)";
|
|
17921
|
-
static examples = [
|
|
18877
|
+
static examples = [
|
|
18878
|
+
"<%= config.bin %> whoami",
|
|
18879
|
+
"<%= config.bin %> whoami --api-key prim_...",
|
|
18880
|
+
"<%= config.bin %> whoami --json | jq .id"
|
|
18881
|
+
];
|
|
17922
18882
|
static flags = {
|
|
17923
18883
|
"api-key": Flags.string({
|
|
17924
18884
|
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
17925
18885
|
env: "PRIMITIVE_API_KEY"
|
|
17926
18886
|
}),
|
|
17927
18887
|
"api-base-url-1": Flags.string({
|
|
17928
|
-
description:
|
|
18888
|
+
description: API_BASE_URL_1_FLAG_DESCRIPTION,
|
|
17929
18889
|
env: "PRIMITIVE_API_BASE_URL_1",
|
|
17930
18890
|
hidden: true
|
|
17931
18891
|
}),
|
|
17932
18892
|
"api-base-url-2": Flags.string({
|
|
17933
|
-
description:
|
|
18893
|
+
description: API_BASE_URL_2_FLAG_DESCRIPTION,
|
|
17934
18894
|
env: "PRIMITIVE_API_BASE_URL_2",
|
|
17935
18895
|
hidden: true
|
|
17936
18896
|
}),
|
|
18897
|
+
json: Flags.boolean({ description: "Print the full account JSON response. Default output hides setup and billing internals." }),
|
|
17937
18898
|
time: Flags.boolean({ description: TIME_FLAG_DESCRIPTION })
|
|
17938
18899
|
};
|
|
17939
18900
|
async run() {
|
|
@@ -17966,12 +18927,11 @@ var WhoamiCommand = class WhoamiCommand extends Command {
|
|
|
17966
18927
|
process.stderr.write("Server returned an empty account body; this should not happen for a valid key.\n");
|
|
17967
18928
|
throw new Errors.CLIError("unexpected empty response");
|
|
17968
18929
|
}
|
|
17969
|
-
|
|
17970
|
-
|
|
17971
|
-
|
|
17972
|
-
|
|
17973
|
-
|
|
17974
|
-
this.log(JSON.stringify(account, null, 2));
|
|
18930
|
+
if (flags.json) {
|
|
18931
|
+
this.log(JSON.stringify(account, null, 2));
|
|
18932
|
+
return;
|
|
18933
|
+
}
|
|
18934
|
+
this.log(formatWhoamiSummary(account));
|
|
17975
18935
|
});
|
|
17976
18936
|
}
|
|
17977
18937
|
};
|
|
@@ -18225,7 +19185,11 @@ const DESCRIBE_OPERATION_ALIASES = {
|
|
|
18225
19185
|
function resolveOperationAlias(id) {
|
|
18226
19186
|
return DESCRIBE_OPERATION_ALIASES[id] ?? id;
|
|
18227
19187
|
}
|
|
18228
|
-
const OVERRIDDEN_OPERATION_IDS = new Set([
|
|
19188
|
+
const OVERRIDDEN_OPERATION_IDS = new Set([
|
|
19189
|
+
"domains:download-domain-zone-file",
|
|
19190
|
+
"functions:test-function",
|
|
19191
|
+
"inbox:get-inbox-status"
|
|
19192
|
+
]);
|
|
18229
19193
|
const generatedCommands = Object.fromEntries(operationManifest.filter((operation) => !OVERRIDDEN_OPERATION_IDS.has(operationId(operation))).map((operation) => [operationId(operation), createOperationCommand(operation)]));
|
|
18230
19194
|
const COMMANDS = {
|
|
18231
19195
|
completion: CompletionCommand,
|
|
@@ -18257,6 +19221,8 @@ const COMMANDS = {
|
|
|
18257
19221
|
"emails:wait": EmailsWaitCommand,
|
|
18258
19222
|
"domains:zone-file": DomainsZoneFileCommand,
|
|
18259
19223
|
"domains:download-domain-zone-file": DomainsZoneFileCommand,
|
|
19224
|
+
"inbox:status": InboxStatusCommand,
|
|
19225
|
+
"inbox:get-inbox-status": InboxStatusCommand,
|
|
18260
19226
|
"functions:init": FunctionsInitCommand,
|
|
18261
19227
|
"functions:templates": FunctionsTemplatesCommand,
|
|
18262
19228
|
"functions:deploy": FunctionsDeployCommand,
|