primcli 3.0.0-preview.5 → 3.0.0-preview.7

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.
@@ -1 +1 @@
1
- export { s as runBackgroundListenSupervisor } from "../listen-background-C0F9gNDD.js";
1
+ export { l as runBackgroundListenSupervisor } from "../listen-background-DyBYca28.js";
@@ -1,4 +1,4 @@
1
- import { r as jsonOutputRequested } from "../json-output-DWrJMakZ.js";
1
+ import { r as jsonOutputRequested } from "../json-output-ch756TXV.js";
2
2
  import { spawnSync } from "node:child_process";
3
3
  // src/oclif/proxy-auto-detect.ts
4
4
  const PROXY_ENV_VARS = [
@@ -1,7 +1,7 @@
1
1
  import { N as agentProfileDirectory, P as agentProfileName, R as loadConnectedAgentProfile, j as AGENT_PROFILE_ENV } from "../cli-config-Ms_0vNjq.js";
2
- import { a as claimBackgroundListenRestart, n as backgroundListenRestartable, r as backgroundListenStatus } from "../listen-background-C0F9gNDD.js";
3
- import { d as SESSION_UUID, t as notificationScope } from "../notify-session-o9hEtJ_c.js";
4
- import { It as detectAgentRuntime } from "../api-command-DIo8Rg0w.js";
2
+ import { a as backgroundListenStatus, i as backgroundListenRestartable, s as claimBackgroundListenRestart, t as BACKGROUND_LISTEN_RELAUNCH_ENV } from "../listen-background-DyBYca28.js";
3
+ import { d as SESSION_UUID, t as notificationScope } from "../notify-session-Bm59oy4j.js";
4
+ import { Lt as detectAgentRuntime } from "../api-command-BXYpylbG.js";
5
5
  import { d as readMailJson } from "../shared-mail-files-BAQSGxxz.js";
6
6
  import { join } from "node:path";
7
7
  import { spawn } from "node:child_process";
@@ -66,6 +66,7 @@ function healSelectedReceiver(options = {}) {
66
66
  PRIMITIVE_CONFIG_DIR: configDir,
67
67
  [RECEIVER_HEAL_ENV]: "0"
68
68
  };
69
+ delete childEnv[BACKGROUND_LISTEN_RELAUNCH_ENV];
69
70
  (options.spawnListener ?? spawnDetached)(listenArgv, childEnv);
70
71
  return {
71
72
  action: "restarting",
@@ -31,23 +31,23 @@ function readRootCredentials(configDir) {
31
31
  return null;
32
32
  }
33
33
  }
34
- function accountEndpoint(apiBaseUrl) {
35
- return `${apiBaseUrl.replace(/\/+$/, "")}/account`;
34
+ function whoamiEndpoint(apiBaseUrl) {
35
+ return `${apiBaseUrl.replace(/\/+$/, "")}/whoami`;
36
36
  }
37
- function parseRootAccount(payload) {
37
+ function parseRootIdentity(payload) {
38
38
  if (payload === null || typeof payload !== "object" || Array.isArray(payload)) return null;
39
39
  const data = payload.data;
40
40
  if (data === null || typeof data !== "object" || Array.isArray(data)) return null;
41
- const account = data;
42
- if (typeof account.email !== "string" || !account.email.trim()) return null;
43
- if (typeof account.id !== "string" || !account.id.trim()) return null;
41
+ const identity = data;
42
+ if (typeof identity.org_id !== "string" || !identity.org_id.trim()) return null;
43
+ const member = identity.member_address;
44
44
  return {
45
- email: account.email,
46
- id: account.id
45
+ memberAddress: member && typeof member.address === "string" && member.address.trim() ? member.address : null,
46
+ orgId: identity.org_id
47
47
  };
48
48
  }
49
- function rootAuthLine(account) {
50
- return `Signed in as ${account.email} (org ${account.id})\n\n`;
49
+ function rootAuthLine(identity) {
50
+ return identity.memberAddress ? `Signed in as ${identity.memberAddress} (org ${identity.orgId})\n\n` : `Signed in (org ${identity.orgId})\n\n`;
51
51
  }
52
52
  function rootRequestConfig(configDir, env) {
53
53
  const config = loadCliConfig(configDir);
@@ -60,11 +60,11 @@ function rootRequestConfig(configDir, env) {
60
60
  headers: currentEnvironment?.config.headers
61
61
  };
62
62
  }
63
- async function fetchRootAccount(params) {
63
+ async function fetchRootIdentity(params) {
64
64
  const controller = new AbortController();
65
65
  const timer = setTimeout(() => controller.abort(), params.timeoutMs);
66
66
  try {
67
- const response = await params.fetch(accountEndpoint(params.apiBaseUrl), {
67
+ const response = await params.fetch(whoamiEndpoint(params.apiBaseUrl), {
68
68
  headers: {
69
69
  ...params.headers ?? {},
70
70
  accept: "application/json",
@@ -73,7 +73,7 @@ async function fetchRootAccount(params) {
73
73
  signal: controller.signal
74
74
  });
75
75
  if (!response.ok) return null;
76
- return parseRootAccount(await response.json().catch(() => null));
76
+ return parseRootIdentity(await response.json().catch(() => null));
77
77
  } catch {
78
78
  return null;
79
79
  } finally {
@@ -95,14 +95,14 @@ async function rootSignedInSummary(options = {}) {
95
95
  const stored = explicitApiKey ? null : readRootCredentials(configDir);
96
96
  const apiKey = explicitApiKey || stored?.accessToken;
97
97
  if (!apiKey) return null;
98
- const account = await fetchRootAccount({
98
+ const identity = await fetchRootIdentity({
99
99
  apiBaseUrl: stored?.apiBaseUrl ?? requestConfig.apiBaseUrl,
100
100
  apiKey,
101
101
  fetch: options.fetch ?? fetch,
102
102
  headers: requestConfig.headers,
103
103
  timeoutMs: options.timeoutMs ?? ROOT_AUTH_TIMEOUT_MS
104
104
  });
105
- return account ? rootAuthLine(account) : null;
105
+ return identity ? rootAuthLine(identity) : null;
106
106
  }
107
107
  function shouldShowLoggedOutSignupHint(options = {}) {
108
108
  if ((options.argv ?? process.argv.slice(2)).length > 0) return false;
@@ -1217,9 +1217,7 @@ const listEndpoints = (options) => (options?.client ?? client).get({
1217
1217
  /**
1218
1218
  * Create a webhook endpoint
1219
1219
  *
1220
- * Creates a new webhook endpoint. If a deactivated endpoint
1221
- * with the same URL and domain exists, it is reactivated
1222
- * instead. Subject to plan limits on the number of active
1220
+ * Creates a new webhook endpoint. A URL can have one endpoint per domain, route targets included (unlike the one default destination per domain), and endpoints with no domain_id count as one domain. A disabled endpoint still holds its URL; a deleted one does not. A create at a URL another endpoint has on the same domain is refused (400). A deleted endpoint's URL can be used again: the create makes a new endpoint, with a new id, and the deleted one stays as it was. Subject to plan limits on the number of active
1223
1221
  * endpoints.
1224
1222
  *
1225
1223
  * **Signing.** A webhook is signed with the organization's webhook secret (`GET /account/webhook-secret`) unless it has its own. A webhook made as a person's own, or by an API key limited to some mailboxes, a third-party app or an agent delegate for itself, is made with its own secret: the response carries it once as `signing_secret`, and `GET /endpoints/{id}/signing-secret` returns it afterwards. Other webhooks, those a person who can read every mailbox makes among them, sign with the organization's secret until given their own. `signed_with` on the endpoint says which secret signs it. See the API-level "Webhook
@@ -1268,7 +1266,7 @@ const deleteEndpoint = (options) => (options.client ?? client).delete({
1268
1266
  /**
1269
1267
  * Get an endpoint
1270
1268
  *
1271
- * One endpoint, as GET /endpoints shows it, to a caller who would see it there. Any other id, a deleted endpoint's included, answers 404.
1269
+ * One endpoint, as GET /endpoints shows it, to a caller who would see it there. Any other id, a deleted endpoint's included, answers 404. For a webhook, delivery says whether it is being sent received mail at all, why not, and how much rule-granted mail is held while its owner cannot act.
1272
1270
  */
1273
1271
  const getEndpoint = (options) => (options.client ?? client).get({
1274
1272
  security: [{
@@ -1281,10 +1279,12 @@ const getEndpoint = (options) => (options.client ?? client).get({
1281
1279
  /**
1282
1280
  * Update a webhook endpoint
1283
1281
  *
1284
- * Updates an active webhook endpoint. Changing the URL keeps the endpoint: its id, recipient routes, signing secret, delivery history and any deliveries still owed to it stay with it, and owed deliveries go to the new URL. Another active endpoint at the new URL is refused.
1282
+ * Updates an active webhook endpoint. Changing the URL keeps the endpoint: its id, recipient routes, signing secret, delivery history and any deliveries still owed to it stay with it, and owed deliveries go to the new URL. A URL can have one endpoint per domain, route targets included (unlike the one default destination per domain), and endpoints with no domain_id count as one domain. A disabled endpoint still holds its URL; a deleted one does not. A change onto a URL another endpoint has on the same domain is refused (400), and a move onto a domain where another endpoint has this URL is refused (409).
1285
1283
  *
1286
1284
  *
1287
1285
  * Pull destinations cannot be assigned a URL, function or recipient-routing domain. Existing endpoint deletion disconnects the destination; creating a new destination does not backfill historical events.
1286
+ *
1287
+ * Giving a webhook the organization does not own to a different key (owner_key_id), or a key's webhook back to the organization (owner_key_id null), turns it off unless the request also sets enabled: its URL was chosen under its previous owner. It then reads enabled false with disabled_reason owner_changed, and turning it on or giving it a new URL starts it again. A key that carries on for the owning key through rotation (its successor, at any depth up to 16 rotations) is not a different key: the webhook stays as it was, with the same signing secret. That does not hold when the owning key was made from a key a transfer moved or rotated away, or from one that has since been deleted: no successor carries on for it. The answer's warnings name each such change (turned_off_owner_changed, turned_on_new_url), so a client can say so.
1288
1288
  */
1289
1289
  const updateEndpoint = (options) => (options.client ?? client).patch({
1290
1290
  security: [{
@@ -1341,6 +1341,8 @@ const completeWebhookEvent = (options) => (options.client ?? client).post({
1341
1341
  * Successful deliveries and verified-domain endpoints are exempt
1342
1342
  * from the rate limit.
1343
1343
  *
1344
+ *
1345
+ * The test is sent whether or not real mail would be. reachable says whether the endpoint answered it with a 2xx; delivery says, apart from that, whether real email.received events would be sent to the endpoint by its own conditions (on, not held, an owner that can receive mail, subscribed to the event), with every reason it would not be. A 200 from the test alone does not mean mail arrives.
1344
1346
  */
1345
1347
  const testEndpoint = (options) => (options.client ?? client).post({
1346
1348
  security: [{
@@ -1374,6 +1376,8 @@ const testEndpoint = (options) => (options.client ?? client).post({
1374
1376
  * delivered as if unfiltered), so `rules_valid: false` exposes a
1375
1377
  * misconfiguration that is otherwise silent.
1376
1378
  *
1379
+ *
1380
+ * would_deliver also covers the endpoint's own delivery conditions for this email (delivery): it is on, neither it nor the email's route is held, its owner may receive this email, and it subscribes to the event. Which endpoint routing sends the email to is decided separately: POST /routes/simulate answers that. A 503 means those conditions could not be read just now; retry.
1377
1381
  */
1378
1382
  const testEndpointRules = (options) => (options.client ?? client).post({
1379
1383
  security: [{
@@ -3053,7 +3057,7 @@ const putAgentContactPolicy = (options) => (options.client ?? client).put({
3053
3057
  /**
3054
3058
  * Get current caller identity
3055
3059
  *
3056
- * Current authenticated identity. member_address is null for machine credentials or an unavailable member address.
3060
+ * Current authenticated identity. member_address is null for machine credentials or an unavailable member address. email (your own sign-in email) and role_name (your role as the members list labels it) are set only when you are signed in as yourself, in the dashboard or with your own Primitive CLI or app login, and are null for API keys, Functions, connected agents, agent signup logins and other apps acting for you.
3057
3061
  */
3058
3062
  const whoami = (options) => (options?.client ?? client).get({
3059
3063
  security: [{
@@ -3593,9 +3597,9 @@ const getWebhookDeliveryStats = (options) => (options?.client ?? client).get({
3593
3597
  ...options
3594
3598
  });
3595
3599
  /**
3596
- * List what you created
3600
+ * List what you created, or what you were asked
3597
3601
  *
3598
- * The objects the caller created, newest first, each with where it stands now, including ones since disabled, deleted or revoked where the object keeps a row: Functions, endpoints, Function triggers, pull subscriptions, recipient routes, filters, wake schedules, repeating sends and scheduled sends. An API key, an app or an agent sees what it created itself; a webhook given to an API key lists under that key. A person (a dashboard session, or their own Primitive CLI or app login) sees what they created through any credential of theirs, each item naming it, and also their API keys, personal agents, email rules and rule requests. Each kind is listed only if the caller could list it through that kind's own route; a kind it could not is named in withheld, with no count. Ids, names and states only: never a webhook URL or mail content. Needs activity:read_self.
3602
+ * The objects the caller created, newest first, each with where it stands now, including ones since disabled, deleted or revoked where the object keeps a row: Functions, endpoints, Function triggers, pull subscriptions, recipient routes, filters, wake schedules, repeating sends and scheduled sends. An API key, an app or an agent sees what it created itself; a webhook given to an API key lists under that key. A person (a dashboard session, or their own Primitive CLI or app login) sees what they created through any credential of theirs, each item naming it, and also their API keys, personal agents, email rules and rule requests. Each kind is listed only if the caller could list it through that kind's own route; a kind it could not is named in withheld, with no count. Ids, names and states only: never a webhook URL or mail content. Needs activity:read_self. With relation=asked it lists instead what other members asked of the person, open or answered: the rule requests made to them, under their current membership, each naming the member who asked in created_through. A key, an app or an agent has none, and gets email_rule_request in withheld.
3599
3603
  */
3600
3604
  const listActivityObjects = (options) => (options?.client ?? client).get({
3601
3605
  security: [{
@@ -3621,7 +3625,7 @@ const getEmailRuleVocabulary = (options) => (options?.client ?? client).get({
3621
3625
  /**
3622
3626
  * Compile a rule description
3623
3627
  *
3624
- * Turns a plain-English description of which received emails to match into a rule tree over the published column contract, with a plain-English explanation of what it matches, the assumptions made, and warnings for anything the columns cannot express. Where the columns fall short the rule may carry up to three yes/no questions, asked about an email only after its conditions match. Nothing is saved. A rule with no questions has its conditions counted, read only, over the caller's recent classified mail (what a test of it covers by default), so a warning can say when it matches nearly all of it. The SQL the rule renders to is returned only when include_sql is true. kind do_not_share compiles a do-not-share rule for recall: conditions only as narrow as the description says, the judgement of what it describes put into questions, and with nothing a column decides for certain, conditions that hold for every email. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3628
+ * Turns a plain-English description of which received emails to match into a rule tree over the published column contract, with a plain-English explanation of what it matches, the assumptions made, and warnings for anything the columns cannot express. Where the columns fall short the rule may carry up to three yes/no questions, asked about an email only after its conditions match. Nothing is saved. A rule with no questions has its conditions counted, read only, over the caller's recent classified mail (what a test of it covers by default): breadth is that count, and a warning says when it matches nearly all of it. The SQL the rule renders to is returned only when include_sql is true. kind do_not_share compiles a do-not-share rule for recall: conditions only as narrow as the description says, the judgement of what it describes put into questions, and with nothing a column decides for certain, conditions that hold for every email. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3625
3629
  */
3626
3630
  const compileEmailRule = (options) => (options.client ?? client).post({
3627
3631
  security: [{
@@ -3672,7 +3676,7 @@ const testEmailRuleOnSample = (options) => (options.client ?? client).post({
3672
3676
  /**
3673
3677
  * List rules
3674
3678
  *
3675
- * The rules the caller can see, newest first: their own, or every member's rules for a caller who reads the whole organization's mail. Each carries its scope (evaluation_scope, and scope_selection for a selected rule). With matched_email_id, only the rules that matched that email. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3679
+ * The rules the caller can see, newest first: their own, or every member's rules for a caller who reads the whole organization's mail. Each carries its scope (evaluation_scope, and scope_selection for a selected rule) and current_version, but not the version's text: read that under current from GET /email-rules/{id}. With matched_email_id, only the rules that matched that email. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3676
3680
  */
3677
3681
  const listEmailRules = (options) => (options?.client ?? client).get({
3678
3682
  security: [{
@@ -3702,7 +3706,7 @@ const createEmailRule = (options) => (options.client ?? client).post({
3702
3706
  /**
3703
3707
  * Delete a rule
3704
3708
  *
3705
- * Deletes a rule with its versions, its decisions and the access it granted. The author, or a caller who reads the whole organization's mail, may delete it; while it is shared with another member, only the author or someone who manages members from the dashboard. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3709
+ * Deletes a rule with its versions, its decisions and the access it granted. A rule that was ever shared with another member keeps the record of its share: the share ends with end_reason rule_deleted, and the member who shared can still list what it handed over, while the rule is no longer shown and reads nothing. The answer lists the shares the delete ended (ended_shares) and the keys, not revoked, that still list the rule, which now read nothing through it: those you may read as key metadata by id, name and prefix (keys), and how many others (other_keys). keys and other_keys are left out when the keys could not be read. The author, or a caller who reads the whole organization's mail, may delete it; while it is shared with another member, only the author or someone who manages members from the dashboard. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3706
3710
  */
3707
3711
  const deleteEmailRule = (options) => (options.client ?? client).delete({
3708
3712
  security: [{
@@ -3715,7 +3719,7 @@ const deleteEmailRule = (options) => (options.client ?? client).delete({
3715
3719
  /**
3716
3720
  * Read a rule
3717
3721
  *
3718
- * A rule, its scope (evaluation_scope, and scope_selection for a selected rule), its current version and its saved expectations. What the scope comes to for its author now is GET /email-rules/{id}/scope. The SQL the version renders to is included only when include_sql is true. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3722
+ * A rule, its scope (evaluation_scope, and scope_selection for a selected rule), its current version and its saved expectations. The current version's text (english, tree, explanation, assumptions, warnings) is under current, and current_version is its number. What the scope comes to for its author now is GET /email-rules/{id}/scope. The SQL the version renders to is included only when include_sql is true. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3719
3723
  */
3720
3724
  const getEmailRule = (options) => (options.client ?? client).get({
3721
3725
  security: [{
@@ -3728,7 +3732,7 @@ const getEmailRule = (options) => (options.client ?? client).get({
3728
3732
  /**
3729
3733
  * Change a rule
3730
3734
  *
3731
- * Renames the rule, saves a new version (english and tree together, with an explanation or one the server writes; earlier versions stay), changes its state (draft is off; observe; active), whose mail it runs over (evaluation_scope, with scope_selection when selected) or its saved expectations (each saved version and new set is judged in expectations_check). Anyone but its author who sees it may only disable it (state draft), and while it is shared only if they manage members from the dashboard. Without evaluation_scope the scope stays; a scope change saves a new version with the same conditions, and what was granted stays. A shared rule keeps its scope; a kind never changes. Send if_version, the current_version you read, so a write never replaces a version saved since. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3735
+ * Renames the rule, saves a new version (english and tree together, with an explanation or one the server writes; earlier versions stay) or an earlier one again (restore_version), changes its state (draft is off; observe; active), whose mail it runs over (evaluation_scope, with scope_selection when selected) or its saved expectations (each saved version and new set is judged in expectations_check). Anyone but its author who sees it may only disable it (state draft), and while it is shared only if they manage members from the dashboard. Without evaluation_scope the scope stays; a scope change saves a new version with the same conditions, and what was granted stays. A shared rule keeps its scope; a kind never changes. A saved version takes effect at once (an active rule stays active); affects counts what it reaches. Send if_version, the current_version you read, so a write never replaces a version saved since, or if_revision to refuse it after any update. Without if_expectations_pass a version is saved even when its expectations_check fails. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3732
3736
  */
3733
3737
  const updateEmailRule = (options) => (options.client ?? client).patch({
3734
3738
  security: [{
@@ -3823,7 +3827,7 @@ const listEmailRuleRequests = (options) => (options?.client ?? client).get({
3823
3827
  /**
3824
3828
  * Ask a member for a rule
3825
3829
  *
3826
- * Asks another member of the organization for a rule over their own mail, from a compile response or a tree you wrote. Name them by user id, or by their member mailbox address, or by their verified work email if you can list members (at most 30 lookups by address an hour). Nothing is evaluated and nothing is shared until they accept, and they may change the rule first; they see the request and can preview what it matches in their own mail. You may have at most 5 pending requests to one member and 50 in all. If you can list members (members:read), the answer also says whether they can accept it under their role (target_can_accept), and if not, why (target_warning); the request is sent either way. To find out before asking, use POST /v1/email-rule-requests/target-check. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3830
+ * Asks another member of the organization for a rule over their own mail, from a compile response or a tree you wrote. Name them by user id, or by their member mailbox address, or by their verified work email if you can list members (at most 30 lookups by address an hour). Nothing is evaluated and nothing is shared until they accept, and they may change the rule first; they see the request and can preview what it matches in their own mail. A message (up to 500 characters) tells them why you are asking; they see it with the request, and it cannot be changed later. You may have at most 5 pending requests to one member and 50 in all. If you can list members (members:read), the answer also says whether they can accept it under their role (target_can_accept), and if not, why (target_warning); the request is sent either way. To find out before asking, use POST /v1/email-rule-requests/target-check. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3827
3831
  */
3828
3832
  const createEmailRuleRequest = (options) => (options.client ?? client).post({
3829
3833
  security: [{
@@ -3870,7 +3874,7 @@ const deleteEmailRuleRequest = (options) => (options.client ?? client).delete({
3870
3874
  /**
3871
3875
  * Read a rule request
3872
3876
  *
3873
- * A rule request: the rule as proposed, who made it and to whom, and whether each of them is still a member. A request is visible to the member who made it, the member it was made to, and the organization's owners and admins. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3877
+ * A rule request: the rule as proposed, who made it and to whom, and whether each of them is still a member. A request is visible to the member who made it, the member it was made to, and the organization's owners and admins. If you are the member asked, you can try the rule as proposed before answering: pass the request's tree to POST /v1/email-rules/test to test it on mail you have received. A test on mail already received shows only what has arrived. To see what the rule would do with an email that has not, such as one you would never want shared, pass the request's tree to POST /v1/email-rules/test-sample (testEmailRuleOnSample; in the Primitive CLI, primitive email-rules test-email-rule-on-sample --body-file sample.json) with an email you make up. Nothing is stored, and it needs no access beyond testing a rule of your own. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3874
3878
  */
3875
3879
  const getEmailRuleRequest = (options) => (options.client ?? client).get({
3876
3880
  security: [{
@@ -3883,7 +3887,7 @@ const getEmailRuleRequest = (options) => (options.client ?? client).get({
3883
3887
  /**
3884
3888
  * Decline a rule request
3885
3889
  *
3886
- * Declines a pending request made to you. Nothing is written but the decision. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3890
+ * Declines a pending request made to you. Nothing is written but the decision and, if you give one, its reason (reason, up to 500 characters), which the member who asked sees with the request. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3887
3891
  */
3888
3892
  const declineEmailRuleRequest = (options) => (options.client ?? client).post({
3889
3893
  security: [{
@@ -3891,7 +3895,11 @@ const declineEmailRuleRequest = (options) => (options.client ?? client).post({
3891
3895
  type: "http"
3892
3896
  }],
3893
3897
  url: "/email-rule-requests/{id}/decline",
3894
- ...options
3898
+ ...options,
3899
+ headers: {
3900
+ ...options.body !== void 0 && { "Content-Type": "application/json" },
3901
+ ...options.headers
3902
+ }
3895
3903
  });
3896
3904
  /**
3897
3905
  * Withdraw a rule request
@@ -3909,7 +3917,7 @@ const withdrawEmailRuleRequest = (options) => (options.client ?? client).post({
3909
3917
  /**
3910
3918
  * Accept a rule request
3911
3919
  *
3912
- * Writes the rule as yours, over your own mailboxes only, turns it on, and shares what it matches from now on with the member who asked. Send no body to accept it as asked, or change it first with english and tree together (and an explanation, or the server writes one). Because this gives your mail to someone else, it is limited to the dashboard and the Primitive CLI: other OAuth apps and agent tokens are refused. Also needs mail:share_own (sharing your own mail through email rules, which only shows it and never sends): a role without it is refused, whether or not it can send. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3920
+ * Writes the rule as yours, over your own mailboxes only, turns it on, and shares what it matches from now on with the member who asked. Send no body to accept it as asked, or change it first with english and tree together (and an explanation, or the server writes one). Because this gives your mail to someone else, it is limited to the dashboard and the Primitive CLI: other OAuth apps and agent tokens are refused. Before accepting, test it on your mail: pass the request's tree to POST /v1/email-rules/test. A test on mail already received shows only what has arrived. To see what the rule would do with an email that has not, such as one you would never want shared, pass the request's tree to POST /v1/email-rules/test-sample (testEmailRuleOnSample; in the Primitive CLI, primitive email-rules test-email-rule-on-sample --body-file sample.json) with an email you make up. Nothing is stored, and it needs no access beyond testing a rule of your own. Accepting also needs mail:share_own (sharing your own mail through email rules, which only shows it and never sends): a role without it is refused, whether or not it can send. Needs mail:read, a member's own credential with their full access (not an API key, agent key or narrowed token), and the email rules feature.
3913
3921
  */
3914
3922
  const acceptEmailRuleRequest = (options) => (options.client ?? client).post({
3915
3923
  security: [{
@@ -4809,7 +4817,7 @@ const updateGroup = (options) => (options.client ?? client).patch({
4809
4817
  /**
4810
4818
  * List every credential
4811
4819
  *
4812
- * Every credential that can act in the organization: API keys, Function keys, agent connection keys, connected apps (OAuth), agent delegates and, where enabled, CLI logins. Secrets are never returned. A key's grant.mail_scope.depth is raw only when it holds mail.raw:read and its scope lists an address or a domain, otherwise content. Filter with kind. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4820
+ * Every credential that can act in the organization: API keys, Function keys, agent connection keys, connected apps (OAuth), agent delegates and, where enabled, CLI logins. Secrets are never returned. A key's grant.mail_scope.depth is raw only when it holds mail.raw:read and its scope lists an address or a domain, otherwise content. A rule the key lists that reads nothing any more (a deleted rule, or a share that ended) is listed under grant.mail_scope.ended_rules, each with its id and reason (rule_deleted or share_ended), and not under rules. Filter with kind. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4813
4821
  *
4814
4822
  * Person only: a dashboard session. The person's role must hold credentials:read. API keys, agent connection keys and agents are refused.
4815
4823
  */
@@ -4824,7 +4832,7 @@ const listCredentials = (options) => (options?.client ?? client).get({
4824
4832
  /**
4825
4833
  * Revoke a credential
4826
4834
  *
4827
- * Revoke one credential by kind and id. A Function key is rotated, never revoked (409 rotate_instead). An API key is revoked only by a person whose own access covers the key's access (an owner covers every key); otherwise 403 grant_forbidden, details.reason target_not_covered. What the credential set up keeps working and is listed in standing_objects for review. The person's own Primitive CLI login revokes an API key (kind org_key) as the person, with no step-up unless the organization's credential policy sets cli_writes_require_approval (then it takes a keys.create step-up); every other kind (a connected key named as org_key included, 403 grant_forbidden target_not_covered), and every other app even with a step-up, is refused outside the dashboard (403). Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4835
+ * Revoke one credential by kind and id. A Function key is rotated, never revoked (409 rotate_instead). An API key is revoked only by a person whose own access covers the key's access (an owner covers every key); otherwise 403 grant_forbidden, details.reason target_not_covered. What the credential set up or owns is listed in standing_objects for review, and for an API key also what it carries on for the keys it was rotated from. An organization-owned object (org_owned true) keeps working; any other keeps working only while someone can still act for it, such as a key of the same rotation that still works, or whoever it was given to, except that a block filter an app made keeps blocking, within the reach the app had, unless the person revoking chose to stop it. An API key (kind org_key or connected_key) that is already revoked, and whose record is kept, answers 200 with already_revoked true and revoked 0, to a caller who could have revoked it; anyone else gets the answer they would get for a key that does not exist. The person's own Primitive CLI login revokes an API key (kind org_key) as the person, with no step-up unless the organization's credential policy sets cli_writes_require_approval (then it takes a keys.create step-up); every other kind (a connected key named as org_key included, 403 grant_forbidden target_not_covered), and every other app even with a step-up, is refused outside the dashboard (403). Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4828
4836
  *
4829
4837
  * Person only: a dashboard session or the person's own Primitive CLI token; no other OAuth app. The person's role must hold keys:manage. API keys, agent connection keys and agents are refused.
4830
4838
  */
@@ -4926,7 +4934,7 @@ const getKeyBuilder = (options) => (options?.client ?? client).get({
4926
4934
  /**
4927
4935
  * List API keys
4928
4936
  *
4929
- * Key metadata, never a secret: name, prefix, grant, creator, last use, expiry, suspension and whether each key works now (status). A grant's mail_scope.depth is raw only when the key holds mail.raw:read and its scope lists an address or a domain, otherwise content. The person needs access to the whole organization's mail. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4937
+ * Key metadata, never a secret: name, prefix, grant, creator, last use, expiry, suspension and whether each key works now (status). Revoked keys are left out unless include_revoked is true, which lists them too with status revoked, revoked_at and revoked_by, under the same access rules as keys that work. A grant's mail_scope.depth is raw only when the key holds mail.raw:read and its scope lists an address or a domain, otherwise content. A rule the key lists that reads nothing any more (a deleted rule, or a share that ended) is listed under grant.mail_scope.ended_rules, each with its id and reason (rule_deleted or share_ended), and not under rules. The person needs access to the whole organization's mail. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4930
4938
  *
4931
4939
  * Person only: a dashboard session or the person's own Primitive CLI token; no other OAuth app. The person's role must hold keys:read. API keys, agent connection keys and agents are refused.
4932
4940
  */
@@ -4960,7 +4968,7 @@ const createKey = (options) => (options.client ?? client).post({
4960
4968
  /**
4961
4969
  * Rotate an API key
4962
4970
  *
4963
- * Mint a successor with a new id and the same name, grant, expiry and conditions, and return its secret once. The old key keeps working for overlap_seconds, then stops: 24 hours when overlap_seconds is omitted, at most 7 days, never past its own expires_at, and at once with 0 (which is how to rotate a key whose secret leaked). previous_key_expires_at says when the old key stops. The person rotating must cover the key's access (403 grant_forbidden, details.reason target_not_covered), and a key an owner holds is rotated by an owner only (403 forbidden, details.reason owner_key_rotation), since rotating hands over the new secret. The person's own Primitive CLI login needs no step-up (it acts as the person, held to the same rules) unless the organization's credential policy sets cli_writes_require_approval; the Primitive app's token is refused, even with one. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4971
+ * Mint a successor with a new id and the same name, grant, expiry and conditions, and return its secret once. The old key keeps working for overlap_seconds, then stops: 24 hours when overlap_seconds is omitted, at most 7 days, never past its own expires_at, and at once with 0 (which is how to rotate a key whose secret leaked). previous_key_expires_at says when the old key stops. Rotating does not extend a key: the successor keeps the old expiry unless expires_at gives it a new one. That needs keys:manage (403 forbidden otherwise), is held to the credential policy (400 when past its maximum lifetime, with the latest expiry it allows now in the message), and someone limited to their own keys can only keep or bring it forward (403 grant_forbidden, details.reason own_key_tighten_only); the old key then never outlives the new one. The person rotating must cover the key's access (403 grant_forbidden, details.reason target_not_covered), and a key an owner holds is rotated by an owner only (403 forbidden, details.reason owner_key_rotation), since rotating hands over the new secret. The person's own Primitive CLI login needs no step-up (it acts as the person, held to the same rules) unless the organization's credential policy sets cli_writes_require_approval; the Primitive app's token is refused, even with one. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4964
4972
  *
4965
4973
  * Person only: a dashboard session, the person's own Primitive CLI login with no step-up (unless the organization's credential policy sets cli_writes_require_approval), or the person's own OAuth token with a step-up token for purpose `keys.create` in the Primitive-Step-Up header. Without one any other OAuth token is answered 403 step_up_required, whose details carry the dashboard URL that issues it (or 403 grant_forbidden when the person's role, or the client, could not do it anyway). The person's role must hold keys:manage. API keys and agent connection keys are refused. An agent acting for the person is refused unless it carries a step-up token the person issued in the dashboard.
4966
4974
  */
@@ -4979,7 +4987,7 @@ const rotateKey = (options) => (options.client ?? client).post({
4979
4987
  /**
4980
4988
  * Get an API key
4981
4989
  *
4982
- * One key's metadata, never its secret, with whether it works now (status). Its grant's mail_scope.depth is raw only when the key holds mail.raw:read and its scope lists an address or a domain, otherwise content. The person needs access to the whole organization's mail. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4990
+ * One key's metadata, never its secret, with whether it works now (status). A revoked key whose record is kept is answered too, with status revoked, revoked_at and revoked_by, under the same access rules as a key that works: one the caller may not read is 404, revoked or not. Its grant's mail_scope.depth is raw only when the key holds mail.raw:read and its scope lists an address or a domain, otherwise content. A rule the key lists that reads nothing any more (a deleted rule, or a share that ended) is listed under grant.mail_scope.ended_rules, each with its id and reason (rule_deleted or share_ended), and not under rules. The person needs access to the whole organization's mail. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4983
4991
  *
4984
4992
  * Person only: a dashboard session or the person's own Primitive CLI token; no other OAuth app. The person's role must hold keys:read. API keys, agent connection keys and agents are refused.
4985
4993
  */
@@ -4994,7 +5002,7 @@ const getKey = (options) => (options.client ?? client).get({
4994
5002
  /**
4995
5003
  * Change an API key
4996
5004
  *
4997
- * Rename a key, change its expiry, its grant or its conditions, or suspend it. Any change needs the person's own access to cover the key's access now (an owner covers every key); otherwise 403 grant_forbidden, details.reason target_not_covered. A grant change is a new version of the key and is held to the same rules as creating one (a custom grant that does not say which mail it reaches is refused with details.reason mail_scope_required), so it takes the same step-up. The person's own Primitive CLI login needs no step-up (it acts as the person, held to the same rules) unless the organization's credential policy sets cli_writes_require_approval; the Primitive app's token is refused, even with one. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
5005
+ * Rename a key, change its expiry, its grant or its conditions, or suspend it. A later expires_at extends the key, which is how to keep a key working past its expiry (rotating keeps it, unless the rotation gives the new key an expires_at): it is held to the credential policy (400 when past its maximum lifetime, with the latest expiry it allows now in the message), and like any loosening needs the person to be allowed to create a key with the key's access. An expired key's expiry cannot be changed (409 conflict, details.reason key_expired); make a new key instead. Any change needs the person's own access to cover the key's access now (an owner covers every key); otherwise 403 grant_forbidden, details.reason target_not_covered. A grant change is a new version of the key and is held to the same rules as creating one (a custom grant that does not say which mail it reaches is refused with details.reason mail_scope_required), so it takes the same step-up. It replaces the whole grant: send expected_grant_ref (grant.ref from GET /v1/keys/{id}) to have it refused (409 conflict, details.reason grant_changed) if the grant changed since that read; a grant change sent without it answers grant_unguarded: true. On a key limited to selected resources (grant.resources), a grant change must drop the limits on purpose with a custom grant and grant.resources {}; one that leaves them out is refused (409 conflict, details.reason key_has_resource_limits) and nothing changes. The person's own Primitive CLI login needs no step-up (it acts as the person, held to the same rules) unless the organization's credential policy sets cli_writes_require_approval; the Primitive app's token is refused, even with one. Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled, with details.feature naming the feature. Contact Primitive to turn them on.
4998
5006
  *
4999
5007
  * Person only: a dashboard session, the person's own Primitive CLI login with no step-up (unless the organization's credential policy sets cli_writes_require_approval), or the person's own OAuth token with a step-up token for purpose `keys.create` in the Primitive-Step-Up header. Without one any other OAuth token is answered 403 step_up_required, whose details carry the dashboard URL that issues it (or 403 grant_forbidden when the person's role, or the client, could not do it anyway). The person's role must hold keys:manage. API keys and agent connection keys are refused. An agent acting for the person is refused unless it carries a step-up token the person issued in the dashboard.
5000
5008
  */
@@ -7044,7 +7052,7 @@ function parseFromHeader(header) {
7044
7052
  value: { address: address.toLowerCase() }
7045
7053
  };
7046
7054
  }
7047
- // ../sdk-node/dist/understanding-CNZLYYam.js
7055
+ // ../sdk-node/dist/understanding-Dv-rAk0U.js
7048
7056
  /**
7049
7057
  * AUTO-GENERATED - DO NOT EDIT
7050
7058
  * Run `pnpm generate:validator` to regenerate.
@@ -23881,13 +23889,27 @@ const INTERACTION_EVENT_TYPES = [
23881
23889
  "interaction.ack.requested"
23882
23890
  ];
23883
23891
  /**
23892
+ * The rule request events (subject = a request one member made to another for
23893
+ * an email rule over the other's own mail). Each goes to the person who did
23894
+ * not act: `created` and `withdrawn` to the member asked, `accepted` and
23895
+ * `declined` to the member who asked. They are opt-in, and only a webhook that
23896
+ * person made for them receives them.
23897
+ */
23898
+ const EMAIL_RULE_REQUEST_EVENT_TYPES = [
23899
+ "email_rule_request.created",
23900
+ "email_rule_request.accepted",
23901
+ "email_rule_request.declined",
23902
+ "email_rule_request.withdrawn"
23903
+ ];
23904
+ /**
23884
23905
  * The full enumerated catalog of every current webhook event type: the five
23885
- * email.*, the four opt-in sent_email.*, and every
23886
- * interaction.<protocol>.<suffix>.
23906
+ * email.*, the four opt-in sent_email.*, the four opt-in
23907
+ * email_rule_request.*, and every interaction.<protocol>.<suffix>.
23887
23908
  */
23888
23909
  const WEBHOOK_EVENT_TYPES = [
23889
23910
  ...EMAIL_EVENT_TYPES,
23890
23911
  ...SENT_EMAIL_EVENT_TYPES,
23912
+ ...EMAIL_RULE_REQUEST_EVENT_TYPES,
23891
23913
  ...INTERACTION_EVENT_TYPES
23892
23914
  ];
23893
23915
  const WEBHOOK_EVENT_TYPE_SET = new Set(WEBHOOK_EVENT_TYPES);
@@ -24426,7 +24448,6 @@ function ensureSearchReportsReplyState(apiClient) {
24426
24448
  }
24427
24449
  return probe;
24428
24450
  }
24429
- // src/oclif/commands/emails-poll.ts
24430
24451
  function quoteDslValue(value) {
24431
24452
  if (/^[^\s"]+$/.test(value)) return value;
24432
24453
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
@@ -24483,7 +24504,7 @@ function buildEmailSearchQuery(params) {
24483
24504
  include_facets: "false",
24484
24505
  limit: params.pageSize,
24485
24506
  snippet: "false",
24486
- sort: "received_at_asc"
24507
+ sort: params.order ?? "received_at_asc"
24487
24508
  };
24488
24509
  const q = combineQ(params.filters.q, params.filters.domain);
24489
24510
  if (q) query.q = q;
@@ -24500,6 +24521,7 @@ function buildEmailSearchQuery(params) {
24500
24521
  if (params.filters.to) query.to = params.filters.to;
24501
24522
  if (params.since) query.date_from = params.since;
24502
24523
  if (params.cursor) query.cursor = params.cursor;
24524
+ if (params.count === false) query.count = "false";
24503
24525
  return query;
24504
24526
  }
24505
24527
  function encodeReceivedAtSearchCursor(email) {
@@ -24527,12 +24549,126 @@ function collectNewAcceptedEmails(rows, seenIds) {
24527
24549
  }
24528
24550
  return fresh;
24529
24551
  }
24552
+ /**
24553
+ * How long after arriving an email may become readable and still be reported
24554
+ * by an idle poll's re-read; how often a re-read comes; and the most pages, of
24555
+ * MAX_EMAIL_POLL_PAGE_SIZE each, one re-read reads.
24556
+ */
24557
+ const LATE_MAIL_WINDOW_MS = 6e5;
24558
+ const LATE_MAIL_REREAD_MS = 15e3;
24559
+ /** How far a re-read reads back at most, however long re-reads have been cut short, unless its interval needs more. */
24560
+ const LATE_MAIL_MAX_LOOKBACK_MS = 36e5;
24561
+ /** Read back this much further, as this clock may run ahead of the server's. */
24562
+ const LATE_MAIL_CLOCK_SLACK_MS = 6e4;
24563
+ /**
24564
+ * Mail received from `from` (LATE_MAIL_WINDOW_MS ago when not given, and
24565
+ * never before `since`), oldest first. Pages come in order of when an email
24566
+ * was received, but an email can become readable to this credential after one
24567
+ * received later: it was accepted more slowly, held while its sender was
24568
+ * checked, or granted to a key by an email rule once classified. By then the
24569
+ * cursor is past its place, so an idle poll re-reads recent mail and keeps
24570
+ * only rows it has not seen. It reads newest first, where late mail mostly
24571
+ * is, so a busy stretch that holds more than the pages read loses its oldest
24572
+ * part rather than its newest. Best effort: a page that fails ends the
24573
+ * re-read with what it has, and the poll goes on; so does reaching
24574
+ * `deadline`. `cutShort` says it did not reach as far back as it would have:
24575
+ * a page failed, the deadline came, or a search the server stopped early for
24576
+ * time returned short pages up to the page limit. `failed` is the page that
24577
+ * failed, so the caller can wait as long as the server asked (Retry-After).
24578
+ */
24579
+ async function fetchRecentEmails(params) {
24580
+ const fetchPage = params.fetchPage ?? fetchEmailSearchPage;
24581
+ const now = params.now ?? Date.now();
24582
+ const sinceMs = params.since ? Date.parse(params.since) : NaN;
24583
+ const wanted = params.from ?? now - 6e5;
24584
+ const from = Number.isNaN(sinceMs) ? wanted : Math.max(wanted, sinceMs);
24585
+ const newestFirst = [];
24586
+ const result = (cutShort) => ({
24587
+ rows: newestFirst.reverse(),
24588
+ cutShort
24589
+ });
24590
+ let cursor = null;
24591
+ for (let pages = 0; pages < 3; pages += 1) {
24592
+ if (params.deadline !== void 0 && params.deadline !== null && Date.now() >= params.deadline) return result(true);
24593
+ let page;
24594
+ try {
24595
+ page = await fetchPage({
24596
+ apiClient: params.apiClient,
24597
+ count: false,
24598
+ cursor,
24599
+ filters: params.filters,
24600
+ order: "received_at_desc",
24601
+ pageSize: 100,
24602
+ since: new Date(from).toISOString()
24603
+ });
24604
+ } catch {
24605
+ return result(true);
24606
+ }
24607
+ if (!page.ok) return {
24608
+ ...result(true),
24609
+ failed: page
24610
+ };
24611
+ newestFirst.push(...page.rows);
24612
+ if (!page.more || !page.cursor) return result(false);
24613
+ cursor = page.cursor;
24614
+ }
24615
+ return result(newestFirst.length < 300);
24616
+ }
24617
+ /**
24618
+ * An idle poll's re-reads of recent mail (fetchRecentEmails), made once the
24619
+ * poll's cursor has passed some mail, with `start` when the poll that first
24620
+ * moved it was made.
24621
+ *
24622
+ * One is due an interval after `start`, as until then the poll has read the
24623
+ * same mail itself, and then an interval after the last one ended, so a slow
24624
+ * re-read is not followed straight away by another. The interval is
24625
+ * LATE_MAIL_REREAD_MS, or LATE_MAIL_REREAD_POLLS poll intervals when that is
24626
+ * longer. A re-read is made only on a poll that brought nothing new once it
24627
+ * is due, so a wait that ends before the next one is made does not report
24628
+ * mail that became readable since the last. `deadline` stops a re-read's
24629
+ * paging (fetchRecentEmails).
24630
+ *
24631
+ * Each re-read reads from LATE_MAIL_WINDOW_MS (and LATE_MAIL_CLOCK_SLACK_MS)
24632
+ * before the last one that was not cut short began (before `start`, at
24633
+ * first), so an email that becomes readable within LATE_MAIL_WINDOW_MS of
24634
+ * arriving is read however far apart re-reads come. That holds while it is
24635
+ * among the most one re-read reads, and while a re-read that is not cut short
24636
+ * comes within the look-back limit (LATE_MAIL_MAX_LOOKBACK_MS, or more for a
24637
+ * long interval) less LATE_MAIL_WINDOW_MS of it becoming readable.
24638
+ */
24639
+ function lateMailReread(options) {
24640
+ const { pollIntervalMs, deadline, start } = options;
24641
+ const intervalMs = Math.max(LATE_MAIL_REREAD_MS, 3 * pollIntervalMs);
24642
+ const maxLookBackMs = Math.max(LATE_MAIL_MAX_LOOKBACK_MS, LATE_MAIL_WINDOW_MS + 2 * intervalMs);
24643
+ let covered = start;
24644
+ let ended = start;
24645
+ return {
24646
+ due: (now = Date.now()) => now - ended >= intervalMs,
24647
+ read: async (params) => {
24648
+ const begun = Date.now();
24649
+ const { rows, cutShort, failed } = await fetchRecentEmails({
24650
+ ...params,
24651
+ deadline,
24652
+ from: Math.max(covered - LATE_MAIL_WINDOW_MS, begun - maxLookBackMs) - LATE_MAIL_CLOCK_SLACK_MS,
24653
+ now: begun
24654
+ });
24655
+ if (!cutShort) covered = begun;
24656
+ ended = Date.now();
24657
+ return {
24658
+ rows,
24659
+ failed
24660
+ };
24661
+ }
24662
+ };
24663
+ }
24530
24664
  async function fetchEmailSearchPage(params) {
24531
24665
  const result = await searchEmails({
24532
24666
  client: params.apiClient.client,
24533
24667
  query: buildEmailSearchQuery({
24668
+ count: params.count,
24534
24669
  cursor: params.cursor,
24535
24670
  filters: params.filters,
24671
+ order: params.order,
24536
24672
  pageSize: params.pageSize,
24537
24673
  since: params.since
24538
24674
  }),
@@ -24562,6 +24698,7 @@ async function fetchEmailSearchPage(params) {
24562
24698
  return {
24563
24699
  ok: true,
24564
24700
  cursor: envelope?.meta.cursor ?? cursorFromRows(rows),
24701
+ more: Boolean(envelope?.meta.cursor),
24565
24702
  rows
24566
24703
  };
24567
24704
  }
@@ -24656,6 +24793,16 @@ async function pauseForTransientFailure(failure, attempt, options) {
24656
24793
  return deadline === null || Date.now() < deadline;
24657
24794
  }
24658
24795
  /**
24796
+ * After a failed read the caller does not retry, wait as long as the server
24797
+ * asked (Retry-After), if it did, before the caller's next request. False when
24798
+ * the deadline came first.
24799
+ */
24800
+ async function waitOutRetryAfter(result, options) {
24801
+ const failure = transientFailure(result);
24802
+ if (failure?.retryAfterMs === void 0) return true;
24803
+ return pauseForTransientFailure(failure, 0, options);
24804
+ }
24805
+ /**
24659
24806
  * Run an idempotent read, retrying transient failures until the deadline.
24660
24807
  * Resolves the first result that is not transient, or null when the
24661
24808
  * deadline passes first (or the read itself resolved null).
@@ -25498,4 +25645,4 @@ function repeatStopCommand(emailId) {
25498
25645
  if (!UUID.test(emailId)) throw new TypeError("emailId must be an email UUID");
25499
25646
  return `primitive repeat stop --id ${emailId.toLowerCase()}`;
25500
25647
  }
25501
- export { AUTOMATED_VALUES as $, stopRepeatFromEmail as $n, getWakeSchedule as $t, sinceFromFlags as A, putAgentContact as An, downloadSentAttachmentArchiveMember as At, formatRepliesCell as B, runWakeSchedule as Bn, getFunction as Bt, SINCE_VALUE_HELP as C, listSentAttachmentArchiveMembers as Cn, deleteMemory as Ct, fetchEmailSearchPage as D, listWakeSchedules as Dn, downloadEmailAttachmentArchiveMember as Dt, encodeReceivedAtSearchCursor as E, listWakeDispatches as En, deleteWakeSchedule as Et, ReplyStateUnsupportedError as F, reorderRoutes as Fn, getContact as Ft, SENT_EMAIL_EVENT_TYPES as G, sendEmail as Gn, getMemory as Gt, isAwaitingRejectedError as H, searchEmails as Hn, getFunctionTestRunTrace as Ht, assertAwaitingFilterRows as I, replyToEmail as In, getConversation as It, isTrustedSender as J, setMemory as Jn, getOwnGrant as Jt, WEBHOOK_EVENT_TYPES as K, setFunctionRoute as Kn, getOrgRoutingTopology as Kt, awaitingRejectedError as L, resendAgentSignupVerification as Ln, getCreditBalance as Lt, AWAITING_FLAG_DESCRIPTION as M, putContact as Mn, getAccessMode as Mt, AWAITING_VALUES as N, redeemCreditCode as Nn, getAccount as Nt, filtersFromFlags as O, pollCliLogin as On, downloadEmailAttachmentByFilename as Ot, REPLY_STATE_UNSUPPORTED_CODE as P, removeDefaultNetworkMember as Pn, getAgentContactPolicy as Pt, AUTOMATED_FLAG_DESCRIPTION as Q, startCliLogin as Qn, getThread as Qt, ensureSearchReportsReplyState as R, revokeCredential as Rn, getDefaultNetworkAgent as Rt, transientFailure as S, listRoutes as Sn, deleteContact as St, cursorFromAcceptedRows as T, listWakeAuthorizations as Tn, deleteWakeAuthorization as Tt, queryUsesAwaiting as U, searchMemories as Un, getInboxStatus as Ut, hasReplyState as V, sdk_gen_exports as Vn, getFunctionRouting as Vt, replyStateSurfaceForOperation as W, semanticSearch as Wn, getKey as Wt, parseFromHeader as X, startAgentClaim as Xn, getSendFrom as Xt, parseWebhookEvent as Y, simulateRoute as Yn, getRepeatingSend as Yt, AUTOMATED_FILTER_UNSUPPORTED_CODE as Z, startAgentSignup as Zn, getSentEmail as Zt, describeApiFailure as _, listKeys as _n, createKey as _t, REPEAT_IDLE_MAX_MINUTES as a, listAgentNetworks as an, updateRepeatingSend as ar, expectedAutomatedVerdicts as at, retryTransient as b, listRepeatingSends as bn, createWakeSchedule as bt, classifySignalContent as c, listDefaultNetworkMembers as cn, updateWakeSchedule as cr, addDefaultNetworkMember as ct, parseRepeatTick as d, listEmailRuleResults as dn, whoami as dr, checkDefaultNetworkContactAdmission as dt, inviteAgentConnection as en, testFunction as er, AutomatedFilterUnsupportedError as et, preparePresenceAliveEmail as f, listEmails as fn, __exportAll as fr, checkSendability as ft, WaitDeadlineReached as g, listGroups as gn, createFunction as gt, sendPreparedSignal as h, listFunctions as hn, createEndpoint as ht, REPEAT_EVERY_MAX_MINUTES as i, listAgentContacts as in, updateKey as ir, ensureSearchReportsAutomated as it, sleep as j, putAgentContactPolicy as jn, downloadSentAttachmentByFilename as jt, quoteDslValue as k, pullWebhookEvent as kn, downloadEmailAttachmentPart as kt, parseInteractionEnvelope as l, listDomains as ln, verifyAgentClaim as lr, cancelSentEmail as lt, repeatStopCommand as m, listFunctionLogs as mn, completeWebhookEvent as mt, MAX_PRESENCE_ENVELOPE_BYTES as n, listActivityObjects as nn, updateDefaultNetworkMember as nr, automatedRejectedError as nt, REPEAT_MAX_SENDS_MAX as o, listContacts as on, updateRoute as or, hasAutomatedVerdict as ot, prepareSignalEmail as p, listEndpoints as pn, cliLogout as pt, isEmailReceivedEvent as q, setFunctionSecret as qn, getOutboundStatus as qt, PRESENCE_PROBE_TEXT as r, listAgentConnections as rn, updateFunction as rr, automatedSurfaceForOperation as rt, buildRepeatStopBody as s, listDefaultNetworkAgents as sn, updateWakeAuthorization as sr, isAutomatedRejectedError as st, MAX_INTERACTION_BYTES as t, leaveOrganization as tn, unsetFunctionRoute as tr, assertAutomatedVerdict as tt, parsePresenceEnvelope as u, listEmailAttachmentArchiveMembers as un, verifyAgentSignup as ur, cancelSentEmailByIdempotencyKey as ut, parseRetryAfter as v, listMailboxAccess as vn, createRoute as vt, collectNewAcceptedEmails as w, listSentEmails as wn, deleteRoute as wt, retryingOperation as x, listRoles as xn, deleteAgentContact as xt, pauseForTransientFailure as y, listOrganizationPeople as yn, createWakeAuthorization as yt, formatAwaitingCell as z, rotateKey as zn, getEmail as zt };
25648
+ export { parseFromHeader as $, startAgentClaim as $n, getSendFrom as $t, lateMailReread as A, listWakeSchedules as An, downloadEmailAttachmentArchiveMember as At, ensureSearchReportsReplyState as B, resendAgentSignupVerification as Bn, getCreditBalance as Bt, waitOutRetryAfter as C, listRepeatingSends as Cn, createWakeSchedule as Ct, encodeReceivedAtSearchCursor as D, listSentEmails as Dn, deleteRoute as Dt, cursorFromAcceptedRows as E, listSentAttachmentArchiveMembers as En, deleteMemory as Et, AWAITING_VALUES as F, putContact as Fn, getAccessMode as Ft, queryUsesAwaiting as G, searchEmails as Gn, getFunctionTestRunTrace as Gt, formatRepliesCell as H, rotateKey as Hn, getEmail as Ht, REPLY_STATE_UNSUPPORTED_CODE as I, redeemCreditCode as In, getAccount as It, SENT_EMAIL_EVENT_TYPES as J, sendEmail as Jn, getMemory as Jt, replyStateSurfaceForOperation as K, searchMemories as Kn, getInboxStatus as Kt, ReplyStateUnsupportedError as L, removeDefaultNetworkMember as Ln, getAgentContactPolicy as Lt, sinceFromFlags as M, pullWebhookEvent as Mn, downloadEmailAttachmentPart as Mt, sleep as N, putAgentContact as Nn, downloadSentAttachmentArchiveMember as Nt, fetchEmailSearchPage as O, listWakeAuthorizations as On, deleteWakeAuthorization as Ot, AWAITING_FLAG_DESCRIPTION as P, putAgentContactPolicy as Pn, downloadSentAttachmentByFilename as Pt, parseWebhookEvent as Q, simulateRoute as Qn, getRepeatingSend as Qt, assertAwaitingFilterRows as R, reorderRoutes as Rn, getContact as Rt, transientFailure as S, listOrganizationPeople as Sn, createWakeAuthorization as St, collectNewAcceptedEmails as T, listRoutes as Tn, deleteContact as Tt, hasReplyState as U, runWakeSchedule as Un, getFunction as Ut, formatAwaitingCell as V, revokeCredential as Vn, getDefaultNetworkAgent as Vt, isAwaitingRejectedError as W, sdk_gen_exports as Wn, getFunctionRouting as Wt, isEmailReceivedEvent as X, setFunctionSecret as Xn, getOutboundStatus as Xt, WEBHOOK_EVENT_TYPES as Y, setFunctionRoute as Yn, getOrgRoutingTopology as Yt, isTrustedSender as Z, setMemory as Zn, getOwnGrant as Zt, describeApiFailure as _, listFunctionLogs as _n, completeWebhookEvent as _t, REPEAT_IDLE_MAX_MINUTES as a, listActivityObjects as an, updateDefaultNetworkMember as ar, automatedRejectedError as at, retryTransient as b, listKeys as bn, createKey as bt, classifySignalContent as c, listAgentNetworks as cn, updateRepeatingSend as cr, expectedAutomatedVerdicts as ct, parseRepeatTick as d, listDefaultNetworkMembers as dn, updateWakeSchedule as dr, addDefaultNetworkMember as dt, getSentEmail as en, startAgentSignup as er, AUTOMATED_FILTER_UNSUPPORTED_CODE as et, preparePresenceAliveEmail as f, listDomains as fn, verifyAgentClaim as fr, cancelSentEmail as ft, WaitDeadlineReached as g, listEndpoints as gn, cliLogout as gt, sendPreparedSignal as h, listEmails as hn, __exportAll as hr, checkSendability as ht, REPEAT_EVERY_MAX_MINUTES as i, leaveOrganization as in, unsetFunctionRoute as ir, assertAutomatedVerdict as it, quoteDslValue as j, pollCliLogin as jn, downloadEmailAttachmentByFilename as jt, filtersFromFlags as k, listWakeDispatches as kn, deleteWakeSchedule as kt, parseInteractionEnvelope as l, listContacts as ln, updateRoute as lr, hasAutomatedVerdict as lt, repeatStopCommand as m, listEmailRuleResults as mn, whoami as mr, checkDefaultNetworkContactAdmission as mt, MAX_PRESENCE_ENVELOPE_BYTES as n, getWakeSchedule as nn, stopRepeatFromEmail as nr, AUTOMATED_VALUES as nt, REPEAT_MAX_SENDS_MAX as o, listAgentConnections as on, updateFunction as or, automatedSurfaceForOperation as ot, prepareSignalEmail as p, listEmailAttachmentArchiveMembers as pn, verifyAgentSignup as pr, cancelSentEmailByIdempotencyKey as pt, EMAIL_RULE_REQUEST_EVENT_TYPES as q, semanticSearch as qn, getKey as qt, PRESENCE_PROBE_TEXT as r, inviteAgentConnection as rn, testFunction as rr, AutomatedFilterUnsupportedError as rt, buildRepeatStopBody as s, listAgentContacts as sn, updateKey as sr, ensureSearchReportsAutomated as st, MAX_INTERACTION_BYTES as t, getThread as tn, startCliLogin as tr, AUTOMATED_FLAG_DESCRIPTION as tt, parsePresenceEnvelope as u, listDefaultNetworkAgents as un, updateWakeAuthorization as ur, isAutomatedRejectedError as ut, parseRetryAfter as v, listFunctions as vn, createEndpoint as vt, SINCE_VALUE_HELP as w, listRoles as wn, deleteAgentContact as wt, retryingOperation as x, listMailboxAccess as xn, createRoute as xt, pauseForTransientFailure as y, listGroups as yn, createFunction as yt, awaitingRejectedError as z, replyToEmail as zn, getConversation as zt };
@@ -1,4 +1,4 @@
1
- import { J as isTrustedSender, b as retryTransient, c as classifySignalContent } from "./repeats-Dj_o6c-X-Ix28GRRc.js";
1
+ import { Z as isTrustedSender, b as retryTransient, c as classifySignalContent } from "./repeats-Dj_o6c-X-C6tOKAqk.js";
2
2
  // src/oclif/presence-provenance.ts
3
3
  function readPresenceProjection(detail) {
4
4
  if (!detail || typeof detail !== "object") return null;