primcli 1.70.0 → 1.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +115 -2
  2. package/dist/{api-command-C58Oh38I.js → api-command-BrwPbyPP.js} +286 -19
  3. package/dist/{cli-config-DMszFbGn.js → cli-config--YTRdJ3t.js} +15 -4
  4. package/dist/{json-output-CEskSQJi.js → json-output-Ce10AsSb.js} +71 -3
  5. package/dist/{machine-session-CKmn5bvB.js → machine-session-Be6j29GE.js} +8 -6
  6. package/dist/{notify-session-CVZtEboh.js → notify-session-Byt5sPWW.js} +2 -2
  7. package/dist/oclif/auto-signal-worker.js +2 -2
  8. package/dist/oclif/auto-signals.js +1 -1
  9. package/dist/oclif/index.js +5266 -112
  10. package/dist/oclif/listen-supervisor.js +1 -2
  11. package/dist/oclif/proxy-auto-detect.js +1 -1
  12. package/dist/oclif/receiver-heal.js +2 -2
  13. package/dist/oclif/root-signup-hint.js +1 -1
  14. package/dist/{repeats-BL7ZC-_6-BZ-MphTV.js → repeats-BL7ZC-_6-CKMKBlx7.js} +1 -1
  15. package/dist/{scoped-chat-Dsark9hm.js → scoped-chat-DTFkP360.js} +1 -1
  16. package/dist/{signal-command-Dy_oub7_.js → signal-command-DeEEZPbQ.js} +4 -4
  17. package/dist/skills/primitive-connect/SKILL.md +162 -355
  18. package/dist/skills/primitive-connect/references/collaboration.md +39 -2
  19. package/dist/skills/primitive-connect/references/communication.md +2 -2
  20. package/dist/skills/primitive-connect/references/connect.md +234 -0
  21. package/dist/skills/primitive-connect/references/contact-requests.md +3 -3
  22. package/dist/skills/primitive-connect/references/contacts.md +4 -4
  23. package/dist/skills/primitive-connect/references/conversations.md +4 -4
  24. package/dist/skills/primitive-connect/references/external-services.md +86 -0
  25. package/dist/skills/primitive-connect/references/manual-setup.md +2 -2
  26. package/dist/skills/primitive-connect/references/presence-and-receiving.md +5 -5
  27. package/dist/skills/primitive-connect/scripts/check-cli-capabilities.mjs +13 -4
  28. package/dist/skills/primitive-connect.json +13 -11
  29. package/man/primitive.1 +17 -3
  30. package/package.json +11 -8
@@ -1,5 +1,5 @@
1
- import { S as __exportAll, _ as WEBHOOK_EVENT_TYPES, g as SENT_EMAIL_EVENT_TYPES } from "./repeats-BL7ZC-_6-BZ-MphTV.js";
2
- import { C as resolveCliAuth, F as agentProfilesDirectory, G as createClient, H as requireDefaultLoginProfile, K as createConfig, N as agentProfileDirectory, R as loadConnectedAgentProfile, S as normalizeApiBaseUrl, T as saveSignupCredentials, W as PrimitiveApiClient, _ as deleteCliCredentials, c as resolveConfigEnvironment, d as validateCliHeaderName, f as validateCliHeaderValue, i as loadCliConfig, j as AGENT_PROFILE_ENV, m as cliAccessTokenExpiresAt, p as acquireCliCredentialsLock, w as saveCliCredentials, x as loadCliCredentials, y as detectPrimitiveKeyEnvMisname } from "./cli-config-DMszFbGn.js";
1
+ import { S as __exportAll, _ as WEBHOOK_EVENT_TYPES, g as SENT_EMAIL_EVENT_TYPES } from "./repeats-BL7ZC-_6-CKMKBlx7.js";
2
+ import { C as resolveCliAuth, G as PrimitiveApiClient, I as agentProfilesDirectory, K as createClient, M as AGENT_PROFILE_ENV, P as agentProfileDirectory, S as normalizeApiBaseUrl, T as saveSignupCredentials, U as requireDefaultLoginProfile, _ as deleteCliCredentials, c as resolveConfigEnvironment, d as validateCliHeaderName, f as validateCliHeaderValue, i as loadCliConfig, m as cliAccessTokenExpiresAt, p as acquireCliCredentialsLock, q as createConfig, w as saveCliCredentials, x as loadCliCredentials, y as detectPrimitiveKeyEnvMisname, z as loadConnectedAgentProfile } from "./cli-config--YTRdJ3t.js";
3
3
  import { h as writeMailJson, m as withMailLock, p as syncMailDirectory, u as privateMailPermissions } from "./shared-mail-files-MwlVE90c.js";
4
4
  import { Command, Errors, Flags } from "@oclif/core";
5
5
  import { existsSync, lstatSync, readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
@@ -15,6 +15,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
15
15
  agentConnectionSetup: () => agentConnectionSetup,
16
16
  awaitReply: () => awaitReply,
17
17
  cancelSentEmail: () => cancelSentEmail,
18
+ cancelSentEmailByIdempotencyKey: () => cancelSentEmailByIdempotencyKey,
18
19
  checkDefaultNetworkContactAdmission: () => checkDefaultNetworkContactAdmission,
19
20
  checkDomainDns: () => checkDomainDns,
20
21
  claimAgentConnection: () => claimAgentConnection,
@@ -55,8 +56,12 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
55
56
  discardEmailContent: () => discardEmailContent,
56
57
  downloadAttachments: () => downloadAttachments,
57
58
  downloadDomainZoneFile: () => downloadDomainZoneFile,
59
+ downloadEmailAttachmentArchiveMember: () => downloadEmailAttachmentArchiveMember,
60
+ downloadEmailAttachmentByFilename: () => downloadEmailAttachmentByFilename,
58
61
  downloadEmailAttachmentPart: () => downloadEmailAttachmentPart,
59
62
  downloadRawEmail: () => downloadRawEmail,
63
+ downloadSentAttachmentArchiveMember: () => downloadSentAttachmentArchiveMember,
64
+ downloadSentAttachmentByFilename: () => downloadSentAttachmentByFilename,
60
65
  downloadSentAttachmentPart: () => downloadSentAttachmentPart,
61
66
  getAccount: () => getAccount,
62
67
  getAgent: () => getAgent,
@@ -91,12 +96,14 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
91
96
  listAgentConnections: () => listAgentConnections,
92
97
  listAgentContacts: () => listAgentContacts,
93
98
  listAgentNetworks: () => listAgentNetworks,
99
+ listChanges: () => listChanges,
94
100
  listContacts: () => listContacts,
95
101
  listDeclinedPayments: () => listDeclinedPayments,
96
102
  listDefaultNetworkAgents: () => listDefaultNetworkAgents,
97
103
  listDefaultNetworkMembers: () => listDefaultNetworkMembers,
98
104
  listDeliveries: () => listDeliveries,
99
105
  listDomains: () => listDomains,
106
+ listEmailAttachmentArchiveMembers: () => listEmailAttachmentArchiveMembers,
100
107
  listEmails: () => listEmails,
101
108
  listEndpoints: () => listEndpoints,
102
109
  listFilters: () => listFilters,
@@ -110,6 +117,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
110
117
  listRegistryRequests: () => listRegistryRequests,
111
118
  listRepeatingSends: () => listRepeatingSends,
112
119
  listRoutes: () => listRoutes,
120
+ listSentAttachmentArchiveMembers: () => listSentAttachmentArchiveMembers,
113
121
  listSentEmails: () => listSentEmails,
114
122
  listTemplates: () => listTemplates,
115
123
  listWakeAuthorizations: () => listWakeAuthorizations,
@@ -887,6 +895,45 @@ const downloadEmailAttachmentPart = (options) => (options.client ?? client).get(
887
895
  ...options
888
896
  });
889
897
  /**
898
+ * Download one received email attachment by filename
899
+ *
900
+ * Returns the same bytes as downloadEmailAttachmentPart, selecting the attachment by its exact filename. The path form `/emails/{id}/attachments/{filename}` also works for any name that is not digits only, which that form reads as a part_index. When several attachments share the filename the response is 409 attachment_name_ambiguous with every matching part_index, and nothing is returned. Authenticate with an organization API key, an authorized organization OAuth token, or an address-bound agent connection key. A connected agent reads only mail received at its own address. Function credentials are not supported. Discarded content is unavailable.
901
+ */
902
+ const downloadEmailAttachmentByFilename = (options) => (options.client ?? client).get({
903
+ security: [{
904
+ scheme: "bearer",
905
+ type: "http"
906
+ }],
907
+ url: "/emails/{id}/attachments",
908
+ ...options
909
+ });
910
+ /**
911
+ * List the files inside a received zip or tar attachment
912
+ *
913
+ * Lists the regular files inside a zip, tar or tar.gz attachment with each one's path, decoded size and SHA-256. The format is detected from the content. Unsafe paths refuse the whole archive, and resource limits bound the work (see the 413 and 422 responses). Authenticate with an organization API key, an authorized organization OAuth token, or an address-bound agent connection key. A connected agent reads only mail received at its own address. Function credentials are not supported. Discarded content is unavailable.
914
+ */
915
+ const listEmailAttachmentArchiveMembers = (options) => (options.client ?? client).get({
916
+ security: [{
917
+ scheme: "bearer",
918
+ type: "http"
919
+ }],
920
+ url: "/emails/{id}/attachments/{attachment}/members",
921
+ ...options
922
+ });
923
+ /**
924
+ * Download one file from inside a received zip or tar attachment
925
+ *
926
+ * Returns the decoded bytes of one regular file inside a zip, tar or tar.gz attachment, by its listed path. The archive's structure, every member path and every limit are checked as for the listing, but only the requested file is decoded and verified (its zip CRC-32, and X-Content-SHA256 of the bytes returned); list the archive to have every file decoded. Authenticate with an organization API key, an authorized organization OAuth token, or an address-bound agent connection key. A connected agent reads only mail received at its own address. Function credentials are not supported. Discarded content is unavailable.
927
+ */
928
+ const downloadEmailAttachmentArchiveMember = (options) => (options.client ?? client).get({
929
+ security: [{
930
+ scheme: "bearer",
931
+ type: "http"
932
+ }],
933
+ url: "/emails/{id}/attachments/{attachment}/members/{path}",
934
+ ...options
935
+ });
936
+ /**
890
937
  * Download one sent email attachment
891
938
  *
892
939
  * Pending service release. This contract does not establish live availability.
@@ -909,6 +956,45 @@ const downloadSentAttachmentPart = (options) => (options.client ?? client).get({
909
956
  ...options
910
957
  });
911
958
  /**
959
+ * Download one sent email attachment by filename
960
+ *
961
+ * Returns the same bytes as downloadSentAttachmentPart, selecting the attachment by its exact filename. The path form `/sent-emails/{id}/attachments/{filename}` also works for any name that is not digits only, which that form reads as a part_index. When several attachments share the filename the response is 409 attachment_name_ambiguous with every matching part_index, and nothing is returned. Authenticate with an organization API key, an authorized organization OAuth token, or an address-bound agent connection key. A connected agent reads only mail sent from its own address. Function credentials are not supported. Discarded content is unavailable.
962
+ */
963
+ const downloadSentAttachmentByFilename = (options) => (options.client ?? client).get({
964
+ security: [{
965
+ scheme: "bearer",
966
+ type: "http"
967
+ }],
968
+ url: "/sent-emails/{id}/attachments",
969
+ ...options
970
+ });
971
+ /**
972
+ * List the files inside a sent zip or tar attachment
973
+ *
974
+ * Lists the regular files inside a zip, tar or tar.gz attachment with each one's path, decoded size and SHA-256. The format is detected from the content. Unsafe paths refuse the whole archive, and resource limits bound the work (see the 413 and 422 responses). Authenticate with an organization API key, an authorized organization OAuth token, or an address-bound agent connection key. A connected agent reads only mail sent from its own address. Function credentials are not supported. Discarded content is unavailable.
975
+ */
976
+ const listSentAttachmentArchiveMembers = (options) => (options.client ?? client).get({
977
+ security: [{
978
+ scheme: "bearer",
979
+ type: "http"
980
+ }],
981
+ url: "/sent-emails/{id}/attachments/{attachment}/members",
982
+ ...options
983
+ });
984
+ /**
985
+ * Download one file from inside a sent zip or tar attachment
986
+ *
987
+ * Returns the decoded bytes of one regular file inside a zip, tar or tar.gz attachment, by its listed path. The archive's structure, every member path and every limit are checked as for the listing, but only the requested file is decoded and verified (its zip CRC-32, and X-Content-SHA256 of the bytes returned); list the archive to have every file decoded. Authenticate with an organization API key, an authorized organization OAuth token, or an address-bound agent connection key. A connected agent reads only mail sent from its own address. Function credentials are not supported. Discarded content is unavailable.
988
+ */
989
+ const downloadSentAttachmentArchiveMember = (options) => (options.client ?? client).get({
990
+ security: [{
991
+ scheme: "bearer",
992
+ type: "http"
993
+ }],
994
+ url: "/sent-emails/{id}/attachments/{attachment}/members/{path}",
995
+ ...options
996
+ });
997
+ /**
912
998
  * Stop the repeat behind a received message
913
999
  *
914
1000
  * Called by the recipient of a repeating send: the connected agent's own
@@ -1990,6 +2076,42 @@ const agentConnectionSetup = (options) => (options?.client ?? client).get({
1990
2076
  ...options
1991
2077
  });
1992
2078
  /**
2079
+ * Long-poll what changed
2080
+ *
2081
+ * One feed of small invalidations (ids and kinds) for everything an app keeps a snapshot of: inbound mail, sent mail, the member's conversation read state, the agent directory and presence, and the credential's own access. Non-consumptive and replayable: any number of devices can read the same cursor independently.
2082
+ *
2083
+ * Start with `since=start` (or no `since`): it returns an empty page whose `next_cursor` is a baseline. Take it BEFORE the initial list reads; every change that commits after it is delivered, including ones those reads already reflect. Then call with `since=<next_cursor>&wait=20` in a loop. Changes come oldest first in commit order, at least once: a write that commits late is never skipped, because positions are assigned at commit.
2084
+ *
2085
+ * Every change is scoped to what this credential's full reads would show: a connected agent sees only its own mail, its own sends and sends it provably received; mail held for sender authentication is announced only when released; read state reaches only the member it belongs to; agent changes reach members and agents allowed to view the network; organization API keys receive no agent changes. Function credentials cannot call this.
2086
+ *
2087
+ * Changes are kept 7 days. A cursor answers 410 `cursor_expired` only when changes after it were pruned (an idle cursor stays valid); rebuild the snapshots from `since=start`.
2088
+ */
2089
+ const listChanges = (options) => (options?.client ?? client).get({
2090
+ security: [{
2091
+ scheme: "bearer",
2092
+ type: "http"
2093
+ }],
2094
+ url: "/changes",
2095
+ ...options
2096
+ });
2097
+ /**
2098
+ * Cancel a scheduled send by idempotency key
2099
+ *
2100
+ * Cancels the still-scheduled send created with this `Idempotency-Key` (matched exactly), as `POST /sent-emails/{id}/cancel` does, and releases the key. 404 `not_found`: no send this credential can act on was created with the key. 409 `not_scheduled`: the send holding the key is no longer scheduled; `error.details` names its `sent_email_id` and `status` (`canceled` if already canceled). Pass `created_before` on a retry so it cannot reach a newer send that reused the released key. A connected agent can cancel any scheduled send from its own address, whoever created it, and no other.
2101
+ */
2102
+ const cancelSentEmailByIdempotencyKey = (options) => (options.client ?? client).post({
2103
+ security: [{
2104
+ scheme: "bearer",
2105
+ type: "http"
2106
+ }],
2107
+ url: "/sent-emails/cancel",
2108
+ ...options,
2109
+ headers: {
2110
+ ...options.body !== void 0 && { "Content-Type": "application/json" },
2111
+ ...options.headers
2112
+ }
2113
+ });
2114
+ /**
1993
2115
  * Cancel a scheduled send
1994
2116
  *
1995
2117
  * Cancels a STILL-SCHEDULED send (status `scheduled`), moving it
@@ -3517,7 +3639,13 @@ async function createAuthenticatedCliApiClient(params) {
3517
3639
  const ATTACHMENT_WAIT_OPERATIONS = /* @__PURE__ */ new Set([
3518
3640
  "downloadAttachments",
3519
3641
  "downloadEmailAttachmentPart",
3520
- "downloadSentAttachmentPart"
3642
+ "downloadSentAttachmentPart",
3643
+ "downloadEmailAttachmentByFilename",
3644
+ "downloadSentAttachmentByFilename",
3645
+ "downloadEmailAttachmentArchiveMember",
3646
+ "downloadSentAttachmentArchiveMember",
3647
+ "listEmailAttachmentArchiveMembers",
3648
+ "listSentAttachmentArchiveMembers"
3521
3649
  ]);
3522
3650
  /** Longest a download command waits for attachment content, in total. */
3523
3651
  const ATTACHMENT_WAIT_MAX_MS = 6e4;
@@ -3891,6 +4019,63 @@ function withFlagSuggestion(error, valid) {
3891
4019
  return error;
3892
4020
  }
3893
4021
  //#endregion
4022
+ //#region src/oclif/from-verified-filter.ts
4023
+ /**
4024
+ * The `from_verified` filter on GET /emails and GET /emails/search: the
4025
+ * `from_verified=true|false` parameter (`--from-verified`) and the
4026
+ * `from_verified:` search term.
4027
+ *
4028
+ * `from_verified` says whether the From domain was authenticated when the
4029
+ * email arrived. A filter on it is a trust decision, so a server that does
4030
+ * not apply it must fail loudly: rows returned for `--from-verified true`
4031
+ * that do not all carry `from_verified: true` are refused instead of being
4032
+ * printed as if they were authenticated mail.
4033
+ */
4034
+ const FROM_VERIFIED_FILTER_UNSUPPORTED_CODE = "from_verified_filter_unsupported";
4035
+ var FromVerifiedFilterUnsupportedError = class extends Error {
4036
+ code = FROM_VERIFIED_FILTER_UNSUPPORTED_CODE;
4037
+ constructor(detail) {
4038
+ super(`The server did not apply the \`from_verified\` filter: ${detail} Nothing was printed. Upgrade to a server that returns \`from_verified\`, or drop the filter.`);
4039
+ this.name = "FromVerifiedFilterUnsupportedError";
4040
+ }
4041
+ };
4042
+ const FROM_VERIFIED_SURFACES = {
4043
+ listEmails: "GET /emails",
4044
+ searchEmails: "GET /emails/search"
4045
+ };
4046
+ const TERM = /(?:^|\s)from_verified:("?)(true|false)\1(?=\s|$)/gi;
4047
+ const PHRASE = /(^|\s)(?:(?!from_verified:)[A-Za-z_][\w.-]*:)?"(?:[^"\\]|\\.)*"/gi;
4048
+ /** The `from_verified:` values a search query asks for, in order. */
4049
+ function fromVerifiedTermsInQuery(q) {
4050
+ if (typeof q !== "string") return [];
4051
+ return [...q.replace(PHRASE, "$1 ").matchAll(TERM)].map((match) => match[2]?.toLowerCase() === "true");
4052
+ }
4053
+ /**
4054
+ * For the generated `emails list` / `emails search` commands: the surface
4055
+ * name and the values every row must have when this call filtered on
4056
+ * `from_verified`, else null.
4057
+ */
4058
+ function fromVerifiedExpectation(sdkName, query) {
4059
+ const surface = FROM_VERIFIED_SURFACES[sdkName];
4060
+ if (!surface || !query) return null;
4061
+ const expected = fromVerifiedTermsInQuery(typeof query.q === "string" ? query.q : void 0);
4062
+ if (query.from_verified === "true") expected.push(true);
4063
+ if (query.from_verified === "false") expected.push(false);
4064
+ return expected.length > 0 ? {
4065
+ surface,
4066
+ expected
4067
+ } : null;
4068
+ }
4069
+ /** Throw unless every row carries `from_verified` with every expected value. */
4070
+ function assertFromVerifiedRows(rows, expectation) {
4071
+ const wrong = rows.filter((row) => {
4072
+ if (row === null || typeof row !== "object") return true;
4073
+ const value = row.from_verified;
4074
+ return typeof value !== "boolean" || expectation.expected.some((expected) => expected !== value);
4075
+ }).length;
4076
+ if (wrong > 0) throw new FromVerifiedFilterUnsupportedError(`${expectation.surface} returned ${wrong} of ${rows.length} email${rows.length === 1 ? "" : "s"} without the requested \`from_verified\` value.`);
4077
+ }
4078
+ //#endregion
3894
4079
  //#region src/oclif/idempotent-replay-banner.ts
3895
4080
  /**
3896
4081
  * If `data` carries `idempotent_replay: true`, write a stderr notice
@@ -4107,7 +4292,7 @@ const SEND_OUTCOME_HELP = `Outcomes and exit codes, shared by chat, chat reply,
4107
4292
  - exit 0 replied: chat only. The message was sent and a reply arrived.
4108
4293
  - exit 0 sent: accepted for delivery. A queued status counts as sent.
4109
4294
  - exit 0 already_sent: an identical earlier send exists (or was deleted: HTTP 410 sent_email_deleted). Nothing new went out. Do not resend.
4110
- - exit 1 not_sent: the API rejected the request (HTTP 400, 401, 402, 403, 404, 413, 422 or 429), the command failed before sending, or the send record has status agent_failed, gate_denied or canceled. Nothing went out.
4295
+ - exit 1 not_sent: the API rejected the request (HTTP 400, 401, 402, 403, 404, 413, 422 or 429, or, from --if-latest-message-id, 409 latest_message_mismatch, 422 latest_message_thread_unresolved or 503 thread_busy), the command failed before sending, or the send record has status agent_failed, gate_denied or canceled. Nothing went out.
4111
4296
  - exit 2: invalid flags or arguments. Nothing went out.
4112
4297
  - exit 3 sent_awaiting_reply: chat only. Sent, but no reply before the timeout. Wait; do not resend.
4113
4298
  - exit 4 uncertain: transport error, conflict, server error, or a send record with status unknown. It may or may not have gone out. Reconcile with primitive sent get --idempotency-key <key> (the key is in the --json envelope) before retrying.`;
@@ -4118,6 +4303,8 @@ function sendFailureOutcome(httpStatus) {
4118
4303
  return httpStatus !== void 0 && DEFINITIVE_SEND_REJECTION_STATUSES.includes(httpStatus) ? "not_sent" : "uncertain";
4119
4304
  }
4120
4305
  const SENT_EMAIL_DELETED_CODE = "sent_email_deleted";
4306
+ const LATEST_MESSAGE_MISMATCH_CODE = "latest_message_mismatch";
4307
+ const THREAD_BUSY_CODE = "thread_busy";
4121
4308
  function errorPayloadCode(payload) {
4122
4309
  if (payload === null || typeof payload !== "object") return void 0;
4123
4310
  const code = payload.code;
@@ -4128,7 +4315,10 @@ function isDeletedEarlierSend(httpStatus, errorPayload) {
4128
4315
  }
4129
4316
  /** Classify an API error from a send request. */
4130
4317
  function classifySendError(httpStatus, errorPayload) {
4131
- return isDeletedEarlierSend(httpStatus, errorPayload) ? "already_sent" : sendFailureOutcome(httpStatus);
4318
+ if (isDeletedEarlierSend(httpStatus, errorPayload)) return "already_sent";
4319
+ if (httpStatus === 409 && errorPayloadCode(errorPayload) === LATEST_MESSAGE_MISMATCH_CODE) return "not_sent";
4320
+ if (httpStatus === 503 && errorPayloadCode(errorPayload) === THREAD_BUSY_CODE) return "not_sent";
4321
+ return sendFailureOutcome(httpStatus);
4132
4322
  }
4133
4323
  function formatDeletedEarlierSendNotice() {
4134
4324
  return "Already sent: an earlier send matching this request went out and its record was later deleted, so the API refused this one (HTTP 410 sent_email_deleted). Nothing new was sent. Do not resend or change the idempotency key to get around this.";
@@ -4175,6 +4365,16 @@ function describeSentStatus(status) {
4175
4365
  function formatSentSummary(noun, sent) {
4176
4366
  return `${noun} sent (${describeSentStatus(sent.status)}, id ${sent.id}). Do not resend.`;
4177
4367
  }
4368
+ /**
4369
+ * Summary for a send the API accepted with status `scheduled`: nothing
4370
+ * has gone out yet, and it can still be canceled.
4371
+ */
4372
+ function formatScheduledSummary(noun, sent, idempotencyKey) {
4373
+ const when = sent.scheduled_at ? ` for ${sent.scheduled_at}` : "";
4374
+ const verb = sent.idempotent_replay === true ? "already scheduled" : "scheduled";
4375
+ const byKey = idempotencyKey ? ` or \`primitive sent cancel --idempotency-key ${shellQuote(idempotencyKey)}\`` : "";
4376
+ return `${noun} ${verb}${when} (id ${sent.id}). Nothing has gone out yet. Do not resend. To cancel it before then, run \`primitive sent cancel --id ${sent.id}\`${byKey}.`;
4377
+ }
4178
4378
  function formatSendFailureSummary(noun, outcome, httpStatus) {
4179
4379
  if (outcome === "not_sent") return `${noun} not sent: ${httpStatus === void 0 ? "the request failed before sending" : `the API rejected the request (HTTP ${httpStatus})`}. Nothing went out; fix the problem before retrying.`;
4180
4380
  return `${noun} send outcome uncertain (${httpStatus === void 0 ? "no response from the API" : `HTTP ${httpStatus}`}): it may or may not have gone out. Do not resend blindly; check sent history first.`;
@@ -4392,8 +4592,9 @@ function sendIdentityFields(params) {
4392
4592
  };
4393
4593
  }
4394
4594
  /**
4395
- * Commands that inspect an existing send. None of them send again:
4396
- * a caller that follows them after a failure cannot double-send.
4595
+ * Commands that inspect an existing send, or cancel one still
4596
+ * scheduled. None of them send again: a caller that follows them after
4597
+ * a failure cannot double-send.
4397
4598
  */
4398
4599
  function buildSendCommandFollowUps(params) {
4399
4600
  const commands = [];
@@ -4404,13 +4605,22 @@ function buildSendCommandFollowUps(params) {
4404
4605
  "--idempotency-key",
4405
4606
  params.idempotencyKey
4406
4607
  ]));
4407
- if (params.sentId !== null) commands.push(buildFollowUpCommand("inspect_sent_email", "Inspect the send and its delivery status", [
4408
- "primitive",
4409
- "sent",
4410
- "get",
4411
- "--id",
4412
- params.sentId
4413
- ]));
4608
+ if (params.sentId !== null) {
4609
+ commands.push(buildFollowUpCommand("inspect_sent_email", "Inspect the send and its delivery status", [
4610
+ "primitive",
4611
+ "sent",
4612
+ "get",
4613
+ "--id",
4614
+ params.sentId
4615
+ ]));
4616
+ if (params.scheduled === true) commands.push(buildFollowUpCommand("cancel_scheduled_send", "Cancel this scheduled send before it goes out", [
4617
+ "primitive",
4618
+ "sent",
4619
+ "cancel",
4620
+ "--id",
4621
+ params.sentId
4622
+ ]));
4623
+ }
4414
4624
  if (params.outcome === "uncertain") commands.push(buildFollowUpCommand("list_recent_sent_emails", "Check sent history for this attempt before retrying", [
4415
4625
  "primitive",
4416
4626
  "sent",
@@ -4449,7 +4659,7 @@ function reportSendCommandResult(params) {
4449
4659
  errorPayload = { message: "The API returned no send record." };
4450
4660
  } else {
4451
4661
  outcome = successfulSendOutcome(sent);
4452
- outcomeMessage = outcome === "not_sent" || outcome === "uncertain" ? formatSendRecordFailureSummary(params.noun, outcome, sent) : outcome === "already_sent" ? formatAlreadySentNotice(sent, {
4662
+ outcomeMessage = outcome === "not_sent" || outcome === "uncertain" ? formatSendRecordFailureSummary(params.noun, outcome, sent) : sent.status === "scheduled" ? formatScheduledSummary(params.noun, sent, params.idempotencyKey ?? sent.client_idempotency_key) : outcome === "already_sent" ? formatAlreadySentNotice(sent, {
4453
4663
  keyOrigin: params.idempotencyKeyOrigin ?? "caller",
4454
4664
  keyHint: "--idempotency-key with a new key"
4455
4665
  }) : formatSentSummary(params.noun, sent);
@@ -4472,6 +4682,7 @@ function reportSendCommandResult(params) {
4472
4682
  attemptStartedAtIso: params.attemptStartedAtIso,
4473
4683
  idempotencyKey: params.idempotencyKey,
4474
4684
  outcome,
4685
+ scheduled: sent?.status === "scheduled",
4475
4686
  sentId: sent?.id ?? null
4476
4687
  }),
4477
4688
  ...params.extraEnvelopeFields
@@ -5361,7 +5572,7 @@ function savedConnectedProfiles(configDir, exclude) {
5361
5572
  */
5362
5573
  async function otherProfiles(configDir, session, current) {
5363
5574
  if (session) try {
5364
- const { connectedProfilesForSession } = await import("./machine-session-CKmn5bvB.js").then((n) => n.s);
5575
+ const { connectedProfilesForSession } = await import("./machine-session-Be6j29GE.js").then((n) => n.s);
5365
5576
  return {
5366
5577
  inSession: true,
5367
5578
  profiles: connectedProfilesForSession(configDir, session, current)
@@ -5628,6 +5839,42 @@ const API_ERROR_CODES = {
5628
5839
  function flagName(parameterName) {
5629
5840
  return parameterName.replace(/_/g, "-");
5630
5841
  }
5842
+ /**
5843
+ * Flag name for a request header an operation declares, such as
5844
+ * `--idempotency-key` for `Idempotency-Key`.
5845
+ */
5846
+ function headerFlagName(headerName) {
5847
+ return headerName.toLowerCase().replace(/_/g, "-");
5848
+ }
5849
+ /**
5850
+ * True when `text` holds an ASCII control character. Header values
5851
+ * travel on the wire as given, so one (a line break above all) could
5852
+ * never be sent and is refused before the request.
5853
+ */
5854
+ function hasControlCharacter(text) {
5855
+ for (let index = 0; index < text.length; index += 1) {
5856
+ const code = text.charCodeAt(index);
5857
+ if (code < 32 || code === 127) return true;
5858
+ }
5859
+ return false;
5860
+ }
5861
+ /**
5862
+ * Read the declared-header flags the caller passed into a header map
5863
+ * keyed by the header name the spec declares. Only flags `buildFlags`
5864
+ * registered for a header are read.
5865
+ */
5866
+ function collectHeaderFlags(parsedFlags, headerFlagToName) {
5867
+ const headers = {};
5868
+ for (const [flag, header] of headerFlagToName) {
5869
+ const value = parsedFlags[flag];
5870
+ if (value === void 0) continue;
5871
+ const text = String(value);
5872
+ if (text.trim() === "") throw new Errors.CLIError(`--${flag} must not be empty.`, { exit: 2 });
5873
+ if (hasControlCharacter(text)) throw new Errors.CLIError(`--${flag} must not contain control characters such as line breaks.`, { exit: 2 });
5874
+ headers[header] = text;
5875
+ }
5876
+ return headers;
5877
+ }
5631
5878
  function flagDescription(parameter) {
5632
5879
  return parameter.description ?? parameter.name;
5633
5880
  }
@@ -5976,6 +6223,14 @@ function buildFlags(operation) {
5976
6223
  bodyFieldFlagToProperty.set(name, extra.property);
5977
6224
  }
5978
6225
  }
6226
+ const headerFlagToName = /* @__PURE__ */ new Map();
6227
+ for (const parameter of operation.headerParams) {
6228
+ const name = headerFlagName(parameter.name);
6229
+ if (RESERVED_FLAG_NAMES.has(name)) continue;
6230
+ if (flags[name] !== void 0) continue;
6231
+ flags[name] = flagForParameter(parameter);
6232
+ headerFlagToName.set(name, parameter.name);
6233
+ }
5979
6234
  if (EVENT_TYPES_FLAG_OPERATIONS.has(operation.sdkName)) flags["event-types"] = Flags.string({
5980
6235
  description: EVENT_TYPES_FLAG_DESCRIPTION,
5981
6236
  multiple: true
@@ -5988,7 +6243,8 @@ function buildFlags(operation) {
5988
6243
  });
5989
6244
  return {
5990
6245
  flags,
5991
- bodyFieldFlagToProperty
6246
+ bodyFieldFlagToProperty,
6247
+ headerFlagToName
5992
6248
  };
5993
6249
  }
5994
6250
  function collectBodyFieldFlags(parsedFlags, bodyFieldFlagToProperty) {
@@ -6083,7 +6339,7 @@ const OPERATION_SUCCESS_HOOKS = { verifyAgentSignup: ({ envelope, configDir, api
6083
6339
  writeStderr("Credentials saved to the CLI config; `primitive whoami` will work on the next call.\n");
6084
6340
  } };
6085
6341
  function createOperationCommand(operation) {
6086
- const { flags, bodyFieldFlagToProperty } = buildFlags(operation);
6342
+ const { flags, bodyFieldFlagToProperty, headerFlagToName } = buildFlags(operation);
6087
6343
  const baseDescription = operation.description !== null && operation.description !== void 0 ? canonicalizeCliReferences(operation.description) : `${operation.method} ${operation.path}`;
6088
6344
  const schemaSummary = operation.hasJsonBody ? renderRequestSchemaSummary(operation.requestSchema) : null;
6089
6345
  const hint = OPERATION_HINTS[operation.sdkName];
@@ -6099,6 +6355,7 @@ function createOperationCommand(operation) {
6099
6355
  throw withFlagSuggestion(error, flagNames);
6100
6356
  });
6101
6357
  const parsedFlags = flags;
6358
+ const headers = collectHeaderFlags(parsedFlags, headerFlagToName);
6102
6359
  if ([
6103
6360
  "startAgentSignup",
6104
6361
  "verifyAgentSignup",
@@ -6142,9 +6399,11 @@ function createOperationCommand(operation) {
6142
6399
  const query = collectValues(operation.queryParams, parsedFlags);
6143
6400
  const replyStateSurface = replyStateSurfaceForOperation(operation.sdkName, query);
6144
6401
  const automatedSurface = automatedSurfaceForOperation(operation.sdkName, query);
6402
+ const fromVerified = fromVerifiedExpectation(operation.sdkName, query);
6145
6403
  const callOperation = () => operationFn({
6146
6404
  body,
6147
6405
  client: apiClient.client,
6406
+ ...Object.keys(headers).length > 0 ? { headers } : {},
6148
6407
  parseAs: operation.binaryResponse ? "blob" : "auto",
6149
6408
  path: collectValues(operation.pathParams, parsedFlags),
6150
6409
  query,
@@ -6220,6 +6479,14 @@ function createOperationCommand(operation) {
6220
6479
  process.exitCode = 1;
6221
6480
  return;
6222
6481
  }
6482
+ if (fromVerified) try {
6483
+ assertFromVerifiedRows(Array.isArray(envelope?.data) ? envelope.data : [], fromVerified);
6484
+ } catch (error) {
6485
+ if (!(error instanceof FromVerifiedFilterUnsupportedError)) throw error;
6486
+ process.stderr.write(`${error.message}\n`);
6487
+ process.exitCode = 1;
6488
+ return;
6489
+ }
6223
6490
  const jsonOutput = parsedFlags.json === true;
6224
6491
  const withEnvelope = parsedFlags.envelope === true;
6225
6492
  const cursor = envelope?.meta?.cursor;
@@ -6276,4 +6543,4 @@ function canonicalizeCliReferences(description) {
6276
6543
  return description.replaceAll("`primitive emails:latest`", "`primitive emails latest`").replaceAll("`primitive describe emails:get-email | jq '.responseSchema.properties'`", "`primitive describe emails:get | jq '.responseSchema.properties'`");
6277
6544
  }
6278
6545
  //#endregion
6279
- export { apiResultHttpStatus as $, replyToEmail as $n, completeWebhookEvent as $t, readThreadContext as A, listAgentNetworks as An, formatAlreadySentNotice as At, pendingMailPath as B, listRoutes as Bn, expectedAutomatedVerdicts as Bt, queryUsesAwaiting as C, getMemory as Cn, verifyAgentSignup as Cr, cliInvocation as Ct, displayAddress as D, getThread as Dn, identitySuggestions as Dt, describeWake as E, getSentEmail as En, generatedAgentName as Et, wakeReadCommand as F, listEmails as Fn, AUTOMATED_VALUES as Ft, interactionNextActions as G, pollCliLogin as Gn, SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE as Gt, recordPendingMail as H, listWakeAuthorizations as Hn, isAutomatedRejectedError as Ht, wakeRecipientField as I, listEndpoints as In, AutomatedFilterUnsupportedError as It, replyInteractionWarning as J, putAgentContactPolicy as Jn, refreshStoredCliCredentials as Jt, readEmailInteraction as K, pullWebhookEvent as Kn, createAuthenticatedCliApiClient as Kt, wakeRelationship as L, listFunctionLogs as Ln, assertAutomatedVerdict as Lt, serverMuted as M, listDefaultNetworkAgents as Mn, withFlagSuggestion as Mt, serverRelationship as N, listDefaultNetworkMembers as Nn, AUTOMATED_FILTER_UNSUPPORTED_CODE as Nt, formatMailWakeLine as O, getWakeSchedule as On, loadSkillLine as Ot, skillFirstLine as P, listDomains as Pn, AUTOMATED_FLAG_DESCRIPTION as Pt, SEND_OUTCOME_HELP as Q, reorderRoutes as Qn, cliLogout as Qt, clearConsumedPendingMail as R, listFunctions as Rn, automatedRejectedError as Rt, isAwaitingRejectedError as S, getInboxStatus as Sn, verifyAgentClaim as Sr, DEFAULT_ENROLL_NAME as St, bareAddress$1 as T, getRepeatingSend as Tn, defaultConnectionName as Tt, removePendingMail as U, listWakeDispatches as Un, queryUsesAutomated as Ut, readPendingMail as V, listSentEmails as Vn, hasAutomatedVerdict as Vt, interactionHumanLine as W, listWakeSchedules as Wn, ConnectedAgentKeyRequiredError as Wt, IDEMPOTENCY_KEY_FLAG_DESCRIPTION as X, redeemCreditCode as Xn, addDefaultNetworkMember as Xt, wakeInteractionSentence as Y, putContact as Yn, resolveCliApiRequestConfig as Yt, MAX_SEND_WAIT_TIMEOUT_MS as Z, removeDefaultNetworkMember as Zn, checkDefaultNetworkContactAdmission as Zt, awaitingRejectedError as _, getDefaultNetworkAgent as _n, updateFunction as _r, sendWaitClampNotice as _t, extractErrorCode as a, deleteAgentContact as an, sendEmail as ar, deriveSendIdempotencyKey as at, formatRepliesCell as b, getFunctionRouting as bn, updateWakeAuthorization as br, successfulSendOutcome as bt, readTextFileFlag as c, deleteRoute as cn, setMemory as cr, formatDeletedEarlierSendNotice as ct, writeErrorWithHints as d, downloadEmailAttachmentPart as dn, startAgentSignup as dr, formatSendFailureSummary as dt, createEndpoint as en, resendAgentSignupVerification as er, assertValidIdempotencyKey as et, AWAITING_FLAG_DESCRIPTION as f, getAccount as fn, startCliLogin as fr, formatSendRecordFailureSummary as ft, assertAwaitingFilterRows as g, getCreditBalance as gn, updateDefaultNetworkMember as gr, sendOutcomeExitCode as gt, ReplyStateUnsupportedError as h, getConversation as hn, unsetFunctionRoute as hr, sendIdentityFields as ht, createOperationCommand as i, createWakeSchedule as in, semanticSearch as ir, classifySendError as it, sentInThread as j, listContacts as jn, writeIdempotentReplayBannerIfReplay as jt, latestOwnOutbound as k, listAgentContacts as kn, currentMailSessionKey as kt, runWithTiming as l, deleteWakeAuthorization as ln, simulateRoute as lr, formatPriorRepliesCheckSkipped as lt, REPLY_STATE_UNSUPPORTED_CODE as m, getContact as mn, testFunction as mr, reportSendCommandResult as mt, API_ERROR_CODES as n, createRoute as nn, searchEmails as nr, buildThrownSendFailureEnvelope as nt, extractErrorPayload as o, deleteContact as on, setFunctionRoute as or, excludeSignalReplies as ot, AWAITING_VALUES as p, getAgentContactPolicy as pn, stopRepeatFromEmail as pr, priorRepliesThatWentOut as pt, replyExpectation as q, putAgentContact as qn, createCliApiClient as qt, TIME_FLAG_DESCRIPTION as r, createWakeAuthorization as rn, searchMemories as rr, checkPriorReplies as rt, formatErrorPayload as s, deleteMemory as sn, setFunctionSecret as sr, followUpCommandPrefix as st, API_BASE_URL_FLAG_DESCRIPTION as t, createFunction as tn, runWakeSchedule as tr, buildFollowUpCommand as tt, surfaceUnauthorizedHint as u, deleteWakeSchedule as un, startAgentClaim as ur, formatPriorRepliesWarning as ut, ensureSearchReportsReplyState as v, getEmail as vn, updateRepeatingSend as vr, sentHistoryWindowStart as vt, explainPendingMailNotFound as w, getOrgRoutingTopology as wn, connectNextSteps as wt, hasReplyState as x, getFunctionTestRunTrace as xn, updateWakeSchedule as xr, thrownErrorExitCode as xt, formatAwaitingCell as y, getFunction as yn, updateRoute as yr, serializeErrorPayload as yt, clearReadPendingMail as z, listRepeatingSends as zn, ensureSearchReportsAutomated as zt };
6546
+ export { MAX_SEND_WAIT_TIMEOUT_MS as $, listSentAttachmentArchiveMembers as $n, refreshStoredCliCredentials as $t, formatMailWakeLine as A, getFunction as An, updateFunction as Ar, loadSkillLine as At, clearConsumedPendingMail as B, listAgentContacts as Bn, automatedRejectedError as Bt, hasReplyState as C, getAccount as Cn, startAgentClaim as Cr, thrownErrorExitCode as Ct, bareAddress$1 as D, getCreditBalance as Dn, testFunction as Dr, defaultConnectionName as Dt, explainPendingMailNotFound as E, getConversation as En, stopRepeatFromEmail as Er, connectNextSteps as Et, serverRelationship as F, getOrgRoutingTopology as Fn, verifyAgentClaim as Fr, AUTOMATED_FILTER_UNSUPPORTED_CODE as Ft, removePendingMail as G, listDomains as Gn, queryUsesAutomated as Gt, pendingMailPath as H, listContacts as Hn, expectedAutomatedVerdicts as Ht, skillFirstLine as I, getRepeatingSend as In, verifyAgentSignup as Ir, AUTOMATED_FLAG_DESCRIPTION as It, readEmailInteraction as J, listEndpoints as Jn, withAttachmentWait as Jt, interactionHumanLine as K, listEmailAttachmentArchiveMembers as Kn, ATTACHMENT_WAIT_FLAG_DESCRIPTION as Kt, wakeReadCommand as L, getSentEmail as Ln, AUTOMATED_VALUES as Lt, readThreadContext as M, getFunctionTestRunTrace as Mn, updateRoute as Mr, formatAlreadySentNotice as Mt, sentInThread as N, getInboxStatus as Nn, updateWakeAuthorization as Nr, writeIdempotentReplayBannerIfReplay as Nt, describeWake as O, getDefaultNetworkAgent as On, unsetFunctionRoute as Or, generatedAgentName as Ot, serverMuted as P, getMemory as Pn, updateWakeSchedule as Pr, withFlagSuggestion as Pt, IDEMPOTENCY_KEY_FLAG_DESCRIPTION as Q, listRoutes as Qn, createCliApiClient as Qt, wakeRecipientField as R, getThread as Rn, AutomatedFilterUnsupportedError as Rt, formatRepliesCell as S, downloadSentAttachmentByFilename as Sn, simulateRoute as Sr, successfulSendOutcome as St, queryUsesAwaiting as T, getContact as Tn, startCliLogin as Tr, cliInvocation as Tt, readPendingMail as U, listDefaultNetworkAgents as Un, hasAutomatedVerdict as Ut, clearReadPendingMail as V, listAgentNetworks as Vn, ensureSearchReportsAutomated as Vt, recordPendingMail as W, listDefaultNetworkMembers as Wn, isAutomatedRejectedError as Wt, replyInteractionWarning as X, listFunctions as Xn, SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE as Xt, replyExpectation as Y, listFunctionLogs as Yn, ConnectedAgentKeyRequiredError as Yt, wakeInteractionSentence as Z, listRepeatingSends as Zn, createAuthenticatedCliApiClient as Zt, ReplyStateUnsupportedError as _, deleteWakeSchedule as _n, semanticSearch as _r, sendIdentityFields as _t, extractErrorCode as a, cliLogout as an, pullWebhookEvent as ar, checkPriorReplies as at, ensureSearchReportsReplyState as b, downloadEmailAttachmentPart as bn, setFunctionSecret as br, sentHistoryWindowStart as bt, hasControlCharacter as c, createFunction as cn, putContact as cr, excludeSignalReplies as ct, runWithTiming as d, createWakeSchedule as dn, reorderRoutes as dr, formatPriorRepliesCheckSkipped as dt, resolveCliApiRequestConfig as en, listSentEmails as er, SEND_OUTCOME_HELP as et, surfaceUnauthorizedHint as f, deleteAgentContact as fn, replyToEmail as fr, formatPriorRepliesWarning as ft, REPLY_STATE_UNSUPPORTED_CODE as g, deleteWakeAuthorization as gn, searchMemories as gr, reportSendCommandResult as gt, AWAITING_VALUES as h, deleteRoute as hn, searchEmails as hr, priorRepliesThatWentOut as ht, createOperationCommand as i, checkDefaultNetworkContactAdmission as in, pollCliLogin as ir, buildThrownSendFailureEnvelope as it, latestOwnOutbound as j, getFunctionRouting as jn, updateRepeatingSend as jr, currentMailSessionKey as jt, displayAddress as k, getEmail as kn, updateDefaultNetworkMember as kr, identitySuggestions as kt, headerFlagName as l, createRoute as ln, redeemCreditCode as lr, followUpCommandPrefix as lt, AWAITING_FLAG_DESCRIPTION as m, deleteMemory as mn, runWakeSchedule as mr, formatSendRecordFailureSummary as mt, API_ERROR_CODES as n, cancelSentEmail as nn, listWakeDispatches as nr, assertValidIdempotencyKey as nt, extractErrorPayload as o, completeWebhookEvent as on, putAgentContact as or, classifySendError as ot, writeErrorWithHints as p, deleteContact as pn, resendAgentSignupVerification as pr, formatSendFailureSummary as pt, interactionNextActions as q, listEmails as qn, ATTACHMENT_WAIT_MAX_MS as qt, TIME_FLAG_DESCRIPTION as r, cancelSentEmailByIdempotencyKey as rn, listWakeSchedules as rr, buildFollowUpCommand as rt, formatErrorPayload as s, createEndpoint as sn, putAgentContactPolicy as sr, deriveSendIdempotencyKey as st, API_BASE_URL_FLAG_DESCRIPTION as t, addDefaultNetworkMember as tn, listWakeAuthorizations as tr, apiResultHttpStatus as tt, readTextFileFlag as u, createWakeAuthorization as un, removeDefaultNetworkMember as ur, formatDeletedEarlierSendNotice as ut, assertAwaitingFilterRows as v, downloadEmailAttachmentArchiveMember as vn, sendEmail as vr, sendOutcomeExitCode as vt, isAwaitingRejectedError as w, getAgentContactPolicy as wn, startAgentSignup as wr, DEFAULT_ENROLL_NAME as wt, formatAwaitingCell as x, downloadSentAttachmentArchiveMember as xn, setMemory as xr, serializeErrorPayload as xt, awaitingRejectedError as y, downloadEmailAttachmentByFilename as yn, setFunctionRoute as yr, sendWaitClampNotice as yt, wakeRelationship as z, getWakeSchedule as zn, assertAutomatedVerdict as zt };
@@ -636,6 +636,17 @@ var PrimitiveApiClient = class {
636
636
  //#endregion
637
637
  //#region src/oclif/connected-agent-profile.ts
638
638
  const AGENT_PROFILE_ENV = "PRIMITIVE_AGENT_PROFILE";
639
+ /**
640
+ * The selected agent's email address, exported next to AGENT_PROFILE_ENV for
641
+ * a registered session so other tools can read it without running the CLI.
642
+ */
643
+ const AGENT_ADDRESS_ENV = "PRIMITIVE_AGENT_ADDRESS";
644
+ /**
645
+ * One sentence telling a session whose agent is selected how to run a command
646
+ * as the member login instead. An empty PRIMITIVE_AGENT_PROFILE selects no
647
+ * profile everywhere in the CLI.
648
+ */
649
+ const MEMBER_LOGIN_OPT_OUT = "rerun the same command with `PRIMITIVE_AGENT_PROFILE=` in front of it (or under `env -u PRIMITIVE_AGENT_PROFILE`) to run it as the member login";
639
650
  function parsePresenceProfile(value, owner) {
640
651
  const row = mailObject(value, [
641
652
  "protocol",
@@ -661,7 +672,7 @@ function supportedPresenceProfile(value, owner) {
661
672
  }
662
673
  var AgentConnectionSetupError = class extends Error {};
663
674
  function requireDefaultLoginProfile() {
664
- if (process.env["PRIMITIVE_AGENT_PROFILE"]?.trim()) throw new AgentConnectionSetupError("This command manages the default OAuth login. Unset PRIMITIVE_AGENT_PROFILE before using it; the connected-agent profile is unchanged.");
675
+ if (process.env["PRIMITIVE_AGENT_PROFILE"]?.trim()) throw new AgentConnectionSetupError(`This command manages the member login, so it does not run as the agent selected by PRIMITIVE_AGENT_PROFILE; ${MEMBER_LOGIN_OPT_OUT}, and the agent profile is unchanged.`);
665
676
  }
666
677
  function agentProfileName(value) {
667
678
  if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,62}$/.test(value)) throw new AgentConnectionSetupError("Agent profile must start with a letter or number and contain only letters, numbers, dots, underscores or hyphens (at most 63 characters).");
@@ -1282,8 +1293,8 @@ function resolveCliAuth(params) {
1282
1293
  const profileName = (params.env ?? process.env)["PRIMITIVE_AGENT_PROFILE"]?.trim() || void 0;
1283
1294
  if (profileName !== void 0) {
1284
1295
  const profile = loadConnectedAgentProfile(params.configDir, profileName);
1285
- if (!profile) throw new AgentConnectionSetupError("Selected agent profile is not configured. No fallback login will be used.");
1286
- if (apiKey && apiKey !== profile.api_key || params.apiBaseUrl !== void 0 && apiBaseUrl !== profile.api_base_url) throw new AgentConnectionSetupError("Explicit credentials or API origin conflict with the selected agent profile.");
1296
+ if (!profile) throw new AgentConnectionSetupError(`Agent profile ${profileName} selected by PRIMITIVE_AGENT_PROFILE is not saved on this machine, so no login is used; run \`primitive agent status --profile ${profileName}\` to see what happened to it, or ${MEMBER_LOGIN_OPT_OUT}.`);
1297
+ if (apiKey && apiKey !== profile.api_key || params.apiBaseUrl !== void 0 && apiBaseUrl !== profile.api_base_url) throw new AgentConnectionSetupError(`An explicit API key or API origin conflicts with agent profile ${profileName} selected by PRIMITIVE_AGENT_PROFILE; drop the override to act as that agent, or rerun the same command with \`PRIMITIVE_AGENT_PROFILE=\` in front of it to use the override.`);
1287
1298
  return {
1288
1299
  apiKey: profile.api_key,
1289
1300
  apiBaseUrl: profile.api_base_url,
@@ -1492,4 +1503,4 @@ function redactCliEnvironment(environment) {
1492
1503
  };
1493
1504
  }
1494
1505
  //#endregion
1495
- export { saveActiveChatState as A, parseOwnerMemberAddress as B, resolveCliAuth as C, deleteChatState as D, chatStatePath as E, agentProfilesDirectory as F, createClient as G, requireDefaultLoginProfile as H, connectedAgentIdentity as I, createConfig as K, connectedApiBaseUrl as L, AgentConnectionSetupError as M, agentProfileDirectory as N, loadActiveChatState as O, agentProfileName as P, loadConnectedAgentProfile as R, normalizeApiBaseUrl as S, saveSignupCredentials as T, saveConnectedAgentProfile as U, profileAlreadyConnectedMessage as V, PrimitiveApiClient as W, deleteCliCredentials as _, normalizeCliEnvironmentName as a, hasStoredCliLogin as b, resolveConfigEnvironment as c, validateCliHeaderName as d, validateCliHeaderValue as f, credentialsPath as g, credentialsLockPath as h, loadCliConfig as i, AGENT_PROFILE_ENV as j, loadChatConversationByLocalId as k, saveCliConfig as l, cliAccessTokenExpiresAt as m, deleteCliConfig as n, redactCliEnvironment as o, acquireCliCredentialsLock as p, emptyCliConfig as r, removeCliEnvironment as s, DEFAULT_ENVIRONMENT as t, upsertCliEnvironment as u, deleteCliCredentialsLock as v, saveCliCredentials as w, loadCliCredentials as x, detectPrimitiveKeyEnvMisname as y, parseConnectedAgentProfile as z };
1506
+ export { saveActiveChatState as A, parseConnectedAgentProfile as B, resolveCliAuth as C, deleteChatState as D, chatStatePath as E, agentProfileName as F, PrimitiveApiClient as G, profileAlreadyConnectedMessage as H, agentProfilesDirectory as I, createClient as K, connectedAgentIdentity as L, AGENT_PROFILE_ENV as M, AgentConnectionSetupError as N, loadActiveChatState as O, agentProfileDirectory as P, connectedApiBaseUrl as R, normalizeApiBaseUrl as S, saveSignupCredentials as T, requireDefaultLoginProfile as U, parseOwnerMemberAddress as V, saveConnectedAgentProfile as W, deleteCliCredentials as _, normalizeCliEnvironmentName as a, hasStoredCliLogin as b, resolveConfigEnvironment as c, validateCliHeaderName as d, validateCliHeaderValue as f, credentialsPath as g, credentialsLockPath as h, loadCliConfig as i, AGENT_ADDRESS_ENV as j, loadChatConversationByLocalId as k, saveCliConfig as l, cliAccessTokenExpiresAt as m, deleteCliConfig as n, redactCliEnvironment as o, acquireCliCredentialsLock as p, createConfig as q, emptyCliConfig as r, removeCliEnvironment as s, DEFAULT_ENVIRONMENT as t, upsertCliEnvironment as u, deleteCliCredentialsLock as v, saveCliCredentials as w, loadCliCredentials as x, detectPrimitiveKeyEnvMisname as y, loadConnectedAgentProfile as z };