primcli 1.71.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 (26) hide show
  1. package/README.md +115 -2
  2. package/dist/{api-command-B8C3jr7A.js → api-command-BrwPbyPP.js} +83 -15
  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-BrTXqxK9.js → machine-session-Be6j29GE.js} +6 -4
  6. package/dist/{notify-session-JbFGcjiM.js → notify-session-Byt5sPWW.js} +1 -1
  7. package/dist/oclif/auto-signal-worker.js +2 -2
  8. package/dist/oclif/index.js +1304 -56
  9. package/dist/oclif/proxy-auto-detect.js +1 -1
  10. package/dist/oclif/receiver-heal.js +2 -2
  11. package/dist/oclif/root-signup-hint.js +1 -1
  12. package/dist/{signal-command-B2TZ8n9c.js → signal-command-DeEEZPbQ.js} +1 -1
  13. package/dist/skills/primitive-connect/SKILL.md +162 -355
  14. package/dist/skills/primitive-connect/references/collaboration.md +39 -2
  15. package/dist/skills/primitive-connect/references/communication.md +2 -2
  16. package/dist/skills/primitive-connect/references/connect.md +234 -0
  17. package/dist/skills/primitive-connect/references/contact-requests.md +3 -3
  18. package/dist/skills/primitive-connect/references/contacts.md +4 -4
  19. package/dist/skills/primitive-connect/references/conversations.md +4 -4
  20. package/dist/skills/primitive-connect/references/external-services.md +86 -0
  21. package/dist/skills/primitive-connect/references/manual-setup.md +2 -2
  22. package/dist/skills/primitive-connect/references/presence-and-receiving.md +5 -5
  23. package/dist/skills/primitive-connect/scripts/check-cli-capabilities.mjs +13 -4
  24. package/dist/skills/primitive-connect.json +13 -11
  25. package/man/primitive.1 +17 -3
  26. package/package.json +1 -1
package/README.md CHANGED
@@ -142,6 +142,49 @@ primitive inbox next
142
142
 
143
143
  Run `primitive --help` for the full command list. Per-command help (`primitive functions deploy --help`) carries enough detail that an agent can compose any operation without leaving the terminal.
144
144
 
145
+ ## Verification codes and sign-in links
146
+
147
+ Your address works for signing up and logging in to other services. After you
148
+ enter it, wait for the email and take what you need from it:
149
+
150
+ ```bash
151
+ # Sign up with your address, then:
152
+ primitive wait --from github.com --code # prints 482913
153
+ primitive wait --from vercel.com --link # prints the sign-in link
154
+ primitive wait --subject "verify" --timeout 90s
155
+ primitive wait --from stripe.com --code --json
156
+ ```
157
+
158
+ `primitive wait` waits for the next email to the identity the CLI resolves (a
159
+ connected agent profile's own address, or any inbound mail for a member login)
160
+ and prints it: sender, subject, time, the start of its text and its ID, ready
161
+ for `primitive reply --id <id>`. Only mail that arrives after the command starts
162
+ matches; `--include-existing` also lets one of the newest 50 emails match, for
163
+ a code that arrived before you started waiting.
164
+
165
+ - `--from` takes an address or a bare domain; `github.com` matches any sender at
166
+ it or its subdomains. It narrows the wait; it does not authenticate the sender.
167
+ - `--subject` matches text in the subject; `--thread <id>` and
168
+ `--reply-to <sent-email-id>` narrow to a conversation.
169
+ - `--timeout` takes `90s`, `5m`, `1h` or plain seconds (default `5m`, `0` waits
170
+ forever).
171
+ - `--code` prints only the one-time code, preferring numbers next to words like
172
+ code, verification or passcode and ignoring years, phone numbers, prices and
173
+ order numbers. A code split as `123 456` prints as `123456`.
174
+ - `--link` prints only the most likely verify, confirm, sign-in, magic or reset
175
+ link, skipping unsubscribe, privacy, help and social links and removing an
176
+ obvious click-tracking wrapper.
177
+ - `--json` prints one object: `id`, `thread_id`, `from`, `to`, `subject`,
178
+ `received_at`, `text` and, when asked, `code` and `link`.
179
+
180
+ | Exit | Meaning |
181
+ |---|---|
182
+ | 0 | A matching email arrived and was printed. |
183
+ | 1 | Error (API failure or authentication). |
184
+ | 2 | Invalid flags or arguments. |
185
+ | 5 | No matching email before `--timeout`. |
186
+ | 6 | The email arrived without a code (`--code`) or link (`--link`); its ID is on stderr. |
187
+
145
188
  ## Waiting with connected credentials
146
189
 
147
190
  After sending, wait for the existing send's reply without sending again:
@@ -157,8 +200,9 @@ default, so fast replies are not missed; use `--since <timestamp>` to narrow the
157
200
  window. They require an authenticated peer and the exact outbound parent.
158
201
  Interaction attachments remain pending with inspection guidance. JSONL includes
159
202
  matching email details, or use `--table` for compact output and `--number N` for
160
- multiple replies. Timeout exits 1; repeat the same wait to recover without
161
- resending. Connected waits share one local address event receiver and recover
203
+ multiple replies. `--json` prints the same JSONL and reports a timeout or error
204
+ as one final JSON line with `error` and `exit_code`. Timeout exits 1; repeat
205
+ the same wait to recover without resending. Connected waits share one local address event receiver and recover
162
206
  through exact-parent search, without scanning inbox history. Additional content
163
207
  filters on this command require organization credentials.
164
208
 
@@ -538,6 +582,31 @@ The sender sees the stop in the thread. `primitive emails get --id <email-id>
538
582
  --context` marks a repeating message with its cadence and, when the recipient may
539
583
  stop it, the exact stop command.
540
584
 
585
+ ## Custom headers and scheduled sends
586
+
587
+ `send` and `reply` take `--header "Name: value"` (or `Name=value`), repeatable
588
+ once per name. The CLI checks only the shape and refuses a duplicate name; the
589
+ server decides which names are allowed and says why in a `validation_error`.
590
+
591
+ ```bash
592
+ primitive send --to alice@example.com --body "Spring sale" --header "X-Campaign-Id: spring-sale" --header "Auto-Submitted=auto-generated"
593
+ primitive reply --id <email-id> --body "Ticket updated." --header "X-Ticket-Id: 4821"
594
+ ```
595
+
596
+ `send --scheduled-at <time>` records the send with status `scheduled` and sends it
597
+ at that time. The time needs `Z` or a numeric UTC offset. It cannot be combined
598
+ with `--wait`, `--attachment`, `--fyi` or `--if-latest-message-id`. The summary
599
+ says the message is scheduled and how to cancel it, and the `--json` envelope
600
+ adds a `cancel_scheduled_send` follow-up command.
601
+
602
+ ```bash
603
+ primitive send --to alice@example.com --body "Reminder: standup" --scheduled-at 2026-10-09T17:00:00Z --idempotency-key standup-2026-10-09
604
+ primitive sent cancel --idempotency-key standup-2026-10-09
605
+ ```
606
+
607
+ Generated operation commands also expose the request headers the spec declares,
608
+ for example `primitive sending send-email --idempotency-key <key>`.
609
+
541
610
  ## Recipient routing
542
611
 
543
612
  Bind a recipient address to a destination so inbound mail resolves to a single
@@ -1061,6 +1130,50 @@ stops running. Claude reports the same SessionEnd for a restart, a switch to
1061
1130
  another session and a real exit, so the hook waits five minutes first, and a
1062
1131
  start of the same session within that time cancels the end.
1063
1132
 
1133
+ #### Session agent identity in Claude Code
1134
+
1135
+ Claude Code gives SessionStart hooks a file named by `CLAUDE_ENV_FILE` and
1136
+ runs it before every later Bash command in the session. Once the session's
1137
+ profile is saved and connected (on the first start, on resume, or for a
1138
+ session whose agent already exists), the SessionStart hook appends two lines
1139
+ to it:
1140
+
1141
+ ```sh
1142
+ export PRIMITIVE_AGENT_PROFILE=session-<session id>
1143
+ export PRIMITIVE_AGENT_ADDRESS=<the agent's email address>
1144
+ ```
1145
+
1146
+ So every `primitive` command in the session, and any tool that runs
1147
+ `primitive`, acts as the session's agent without a prefix, and `send` and
1148
+ `reply` send from the agent's address without `--from`. Registration that
1149
+ finishes after the hook returns still writes the lines, and later commands
1150
+ pick them up. Nothing is written for a session that already sets
1151
+ `PRIMITIVE_AGENT_PROFILE` (including to an empty value), when the file already
1152
+ assigns either variable, while setup is still pending, while another connected
1153
+ profile is bound to or receives for the session, or for a profile that is not
1154
+ saved, so a session is never pointed at a profile that does not exist.
1155
+
1156
+ `PRIMITIVE_AGENT_ADDRESS` is for other tools in the session that need the
1157
+ agent's email address without running the CLI. It is set only together with
1158
+ `PRIMITIVE_AGENT_PROFILE` and always names that profile's address.
1159
+ `primitive whoami` prints the address alone on its first line, offline, and
1160
+ `primitive whoami --json` adds `address`, `profile` and `source`
1161
+ (`session_hook` for the session's own exported agent, `env` for any other
1162
+ `PRIMITIVE_AGENT_PROFILE`).
1163
+
1164
+ Commands that manage the member login (`login`, `logout`, `signup`,
1165
+ `agent enroll`, and the other commands that refuse a selected profile) still
1166
+ refuse. To run any command as the member login from inside such a session,
1167
+ put an empty `PRIMITIVE_AGENT_PROFILE=` in front of it, or run it under
1168
+ `env -u PRIMITIVE_AGENT_PROFILE`:
1169
+
1170
+ ```sh
1171
+ PRIMITIVE_AGENT_PROFILE= primitive whoami
1172
+ ```
1173
+
1174
+ Codex hooks have no equivalent of `CLAUDE_ENV_FILE`, so Codex sessions still
1175
+ select their profile with `PRIMITIVE_AGENT_PROFILE` on each command.
1176
+
1064
1177
  An agent that `session-register` created is disconnected only when its session
1065
1178
  has not started again for 30 days, by `machine doctor --fix` or the next
1066
1179
  `session-register` on the machine, and only while the session's profile still
@@ -1,5 +1,5 @@
1
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, 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";
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";
@@ -4365,6 +4365,16 @@ function describeSentStatus(status) {
4365
4365
  function formatSentSummary(noun, sent) {
4366
4366
  return `${noun} sent (${describeSentStatus(sent.status)}, id ${sent.id}). Do not resend.`;
4367
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
+ }
4368
4378
  function formatSendFailureSummary(noun, outcome, httpStatus) {
4369
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.`;
4370
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.`;
@@ -4582,8 +4592,9 @@ function sendIdentityFields(params) {
4582
4592
  };
4583
4593
  }
4584
4594
  /**
4585
- * Commands that inspect an existing send. None of them send again:
4586
- * 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.
4587
4598
  */
4588
4599
  function buildSendCommandFollowUps(params) {
4589
4600
  const commands = [];
@@ -4594,13 +4605,22 @@ function buildSendCommandFollowUps(params) {
4594
4605
  "--idempotency-key",
4595
4606
  params.idempotencyKey
4596
4607
  ]));
4597
- if (params.sentId !== null) commands.push(buildFollowUpCommand("inspect_sent_email", "Inspect the send and its delivery status", [
4598
- "primitive",
4599
- "sent",
4600
- "get",
4601
- "--id",
4602
- params.sentId
4603
- ]));
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
+ }
4604
4624
  if (params.outcome === "uncertain") commands.push(buildFollowUpCommand("list_recent_sent_emails", "Check sent history for this attempt before retrying", [
4605
4625
  "primitive",
4606
4626
  "sent",
@@ -4639,7 +4659,7 @@ function reportSendCommandResult(params) {
4639
4659
  errorPayload = { message: "The API returned no send record." };
4640
4660
  } else {
4641
4661
  outcome = successfulSendOutcome(sent);
4642
- 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, {
4643
4663
  keyOrigin: params.idempotencyKeyOrigin ?? "caller",
4644
4664
  keyHint: "--idempotency-key with a new key"
4645
4665
  }) : formatSentSummary(params.noun, sent);
@@ -4662,6 +4682,7 @@ function reportSendCommandResult(params) {
4662
4682
  attemptStartedAtIso: params.attemptStartedAtIso,
4663
4683
  idempotencyKey: params.idempotencyKey,
4664
4684
  outcome,
4685
+ scheduled: sent?.status === "scheduled",
4665
4686
  sentId: sent?.id ?? null
4666
4687
  }),
4667
4688
  ...params.extraEnvelopeFields
@@ -5551,7 +5572,7 @@ function savedConnectedProfiles(configDir, exclude) {
5551
5572
  */
5552
5573
  async function otherProfiles(configDir, session, current) {
5553
5574
  if (session) try {
5554
- const { connectedProfilesForSession } = await import("./machine-session-BrTXqxK9.js").then((n) => n.s);
5575
+ const { connectedProfilesForSession } = await import("./machine-session-Be6j29GE.js").then((n) => n.s);
5555
5576
  return {
5556
5577
  inSession: true,
5557
5578
  profiles: connectedProfilesForSession(configDir, session, current)
@@ -5818,6 +5839,42 @@ const API_ERROR_CODES = {
5818
5839
  function flagName(parameterName) {
5819
5840
  return parameterName.replace(/_/g, "-");
5820
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
+ }
5821
5878
  function flagDescription(parameter) {
5822
5879
  return parameter.description ?? parameter.name;
5823
5880
  }
@@ -6166,6 +6223,14 @@ function buildFlags(operation) {
6166
6223
  bodyFieldFlagToProperty.set(name, extra.property);
6167
6224
  }
6168
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
+ }
6169
6234
  if (EVENT_TYPES_FLAG_OPERATIONS.has(operation.sdkName)) flags["event-types"] = Flags.string({
6170
6235
  description: EVENT_TYPES_FLAG_DESCRIPTION,
6171
6236
  multiple: true
@@ -6178,7 +6243,8 @@ function buildFlags(operation) {
6178
6243
  });
6179
6244
  return {
6180
6245
  flags,
6181
- bodyFieldFlagToProperty
6246
+ bodyFieldFlagToProperty,
6247
+ headerFlagToName
6182
6248
  };
6183
6249
  }
6184
6250
  function collectBodyFieldFlags(parsedFlags, bodyFieldFlagToProperty) {
@@ -6273,7 +6339,7 @@ const OPERATION_SUCCESS_HOOKS = { verifyAgentSignup: ({ envelope, configDir, api
6273
6339
  writeStderr("Credentials saved to the CLI config; `primitive whoami` will work on the next call.\n");
6274
6340
  } };
6275
6341
  function createOperationCommand(operation) {
6276
- const { flags, bodyFieldFlagToProperty } = buildFlags(operation);
6342
+ const { flags, bodyFieldFlagToProperty, headerFlagToName } = buildFlags(operation);
6277
6343
  const baseDescription = operation.description !== null && operation.description !== void 0 ? canonicalizeCliReferences(operation.description) : `${operation.method} ${operation.path}`;
6278
6344
  const schemaSummary = operation.hasJsonBody ? renderRequestSchemaSummary(operation.requestSchema) : null;
6279
6345
  const hint = OPERATION_HINTS[operation.sdkName];
@@ -6289,6 +6355,7 @@ function createOperationCommand(operation) {
6289
6355
  throw withFlagSuggestion(error, flagNames);
6290
6356
  });
6291
6357
  const parsedFlags = flags;
6358
+ const headers = collectHeaderFlags(parsedFlags, headerFlagToName);
6292
6359
  if ([
6293
6360
  "startAgentSignup",
6294
6361
  "verifyAgentSignup",
@@ -6336,6 +6403,7 @@ function createOperationCommand(operation) {
6336
6403
  const callOperation = () => operationFn({
6337
6404
  body,
6338
6405
  client: apiClient.client,
6406
+ ...Object.keys(headers).length > 0 ? { headers } : {},
6339
6407
  parseAs: operation.binaryResponse ? "blob" : "auto",
6340
6408
  path: collectValues(operation.pathParams, parsedFlags),
6341
6409
  query,
@@ -6475,4 +6543,4 @@ function canonicalizeCliReferences(description) {
6475
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'`");
6476
6544
  }
6477
6545
  //#endregion
6478
- export { apiResultHttpStatus as $, listWakeAuthorizations as $n, addDefaultNetworkMember as $t, readThreadContext as A, getFunctionTestRunTrace as An, updateRoute as Ar, formatAlreadySentNotice as At, pendingMailPath as B, listContacts as Bn, expectedAutomatedVerdicts as Bt, queryUsesAwaiting as C, getContact as Cn, startCliLogin as Cr, cliInvocation as Ct, displayAddress as D, getEmail as Dn, updateDefaultNetworkMember as Dr, identitySuggestions as Dt, describeWake as E, getDefaultNetworkAgent as En, unsetFunctionRoute as Er, generatedAgentName as Et, wakeReadCommand as F, getSentEmail as Fn, AUTOMATED_VALUES as Ft, interactionNextActions as G, listEmails as Gn, ATTACHMENT_WAIT_MAX_MS as Gt, recordPendingMail as H, listDefaultNetworkMembers as Hn, isAutomatedRejectedError as Ht, wakeRecipientField as I, getThread as In, AutomatedFilterUnsupportedError as It, replyInteractionWarning as J, listFunctions as Jn, SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE as Jt, readEmailInteraction as K, listEndpoints as Kn, withAttachmentWait as Kt, wakeRelationship as L, getWakeSchedule as Ln, assertAutomatedVerdict as Lt, serverMuted as M, getMemory as Mn, updateWakeSchedule as Mr, withFlagSuggestion as Mt, serverRelationship as N, getOrgRoutingTopology as Nn, verifyAgentClaim as Nr, AUTOMATED_FILTER_UNSUPPORTED_CODE as Nt, formatMailWakeLine as O, getFunction as On, updateFunction as Or, loadSkillLine as Ot, skillFirstLine as P, getRepeatingSend as Pn, verifyAgentSignup as Pr, AUTOMATED_FLAG_DESCRIPTION as Pt, SEND_OUTCOME_HELP as Q, listSentEmails as Qn, resolveCliApiRequestConfig as Qt, clearConsumedPendingMail as R, listAgentContacts as Rn, automatedRejectedError as Rt, isAwaitingRejectedError as S, getAgentContactPolicy as Sn, startAgentSignup as Sr, DEFAULT_ENROLL_NAME as St, bareAddress$1 as T, getCreditBalance as Tn, testFunction as Tr, defaultConnectionName as Tt, removePendingMail as U, listDomains as Un, queryUsesAutomated as Ut, readPendingMail as V, listDefaultNetworkAgents as Vn, hasAutomatedVerdict as Vt, interactionHumanLine as W, listEmailAttachmentArchiveMembers as Wn, ATTACHMENT_WAIT_FLAG_DESCRIPTION as Wt, IDEMPOTENCY_KEY_FLAG_DESCRIPTION as X, listRoutes as Xn, createCliApiClient as Xt, wakeInteractionSentence as Y, listRepeatingSends as Yn, createAuthenticatedCliApiClient as Yt, MAX_SEND_WAIT_TIMEOUT_MS as Z, listSentAttachmentArchiveMembers as Zn, refreshStoredCliCredentials as Zt, awaitingRejectedError as _, downloadEmailAttachmentByFilename as _n, setFunctionRoute as _r, sendWaitClampNotice as _t, extractErrorCode as a, createEndpoint as an, putAgentContactPolicy as ar, deriveSendIdempotencyKey as at, formatRepliesCell as b, downloadSentAttachmentByFilename as bn, simulateRoute as br, successfulSendOutcome as bt, readTextFileFlag as c, createWakeAuthorization as cn, removeDefaultNetworkMember as cr, formatDeletedEarlierSendNotice as ct, writeErrorWithHints as d, deleteContact as dn, resendAgentSignupVerification as dr, formatSendFailureSummary as dt, cancelSentEmail as en, listWakeDispatches as er, assertValidIdempotencyKey as et, AWAITING_FLAG_DESCRIPTION as f, deleteMemory as fn, runWakeSchedule as fr, formatSendRecordFailureSummary as ft, assertAwaitingFilterRows as g, downloadEmailAttachmentArchiveMember as gn, sendEmail as gr, sendOutcomeExitCode as gt, ReplyStateUnsupportedError as h, deleteWakeSchedule as hn, semanticSearch as hr, sendIdentityFields as ht, createOperationCommand as i, completeWebhookEvent as in, putAgentContact as ir, classifySendError as it, sentInThread as j, getInboxStatus as jn, updateWakeAuthorization as jr, writeIdempotentReplayBannerIfReplay as jt, latestOwnOutbound as k, getFunctionRouting as kn, updateRepeatingSend as kr, currentMailSessionKey as kt, runWithTiming as l, createWakeSchedule as ln, reorderRoutes as lr, formatPriorRepliesCheckSkipped as lt, REPLY_STATE_UNSUPPORTED_CODE as m, deleteWakeAuthorization as mn, searchMemories as mr, reportSendCommandResult as mt, API_ERROR_CODES as n, checkDefaultNetworkContactAdmission as nn, pollCliLogin as nr, buildThrownSendFailureEnvelope as nt, extractErrorPayload as o, createFunction as on, putContact as or, excludeSignalReplies as ot, AWAITING_VALUES as p, deleteRoute as pn, searchEmails as pr, priorRepliesThatWentOut as pt, replyExpectation as q, listFunctionLogs as qn, ConnectedAgentKeyRequiredError as qt, TIME_FLAG_DESCRIPTION as r, cliLogout as rn, pullWebhookEvent as rr, checkPriorReplies as rt, formatErrorPayload as s, createRoute as sn, redeemCreditCode as sr, followUpCommandPrefix as st, API_BASE_URL_FLAG_DESCRIPTION as t, cancelSentEmailByIdempotencyKey as tn, listWakeSchedules as tr, buildFollowUpCommand as tt, surfaceUnauthorizedHint as u, deleteAgentContact as un, replyToEmail as ur, formatPriorRepliesWarning as ut, ensureSearchReportsReplyState as v, downloadEmailAttachmentPart as vn, setFunctionSecret as vr, sentHistoryWindowStart as vt, explainPendingMailNotFound as w, getConversation as wn, stopRepeatFromEmail as wr, connectNextSteps as wt, hasReplyState as x, getAccount as xn, startAgentClaim as xr, thrownErrorExitCode as xt, formatAwaitingCell as y, downloadSentAttachmentArchiveMember as yn, setMemory as yr, serializeErrorPayload as yt, clearReadPendingMail as z, listAgentNetworks 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 };
@@ -17,7 +17,10 @@ import { format } from "node:util";
17
17
  * - A command whose `--json` output is a bare JSON array keeps that
18
18
  * documented shape on success; its stderr notices are dropped.
19
19
  *
20
- * Commands that stream several documents (`listen`) are not guarded.
20
+ * Commands that stream several documents (`listen`, `emails wait`) are
21
+ * not guarded. `emails wait` uses `runStreamingJson` instead: one JSON
22
+ * line per result on stdout, and on failure one more JSON line carrying
23
+ * `error` and `exit_code`.
21
24
  */
22
25
  const GUARDED = Symbol.for("primitive.cli.jsonOutputGuard");
23
26
  /** True when `--json` appears before any `--` separator. */
@@ -235,7 +238,72 @@ function guardJsonOutput(cls) {
235
238
  };
236
239
  }
237
240
  /** Command ids whose `--json` streams several documents over time. */
238
- const STREAMING_JSON_COMMAND_IDS = /* @__PURE__ */ new Set(["listen"]);
241
+ const STREAMING_JSON_COMMAND_IDS = /* @__PURE__ */ new Set(["emails:wait", "listen"]);
242
+ /**
243
+ * Run the body of a command whose `--json` output is newline-delimited
244
+ * JSON, one line per result, written to stdout as each result is found.
245
+ *
246
+ * stdout stays live. Everything the body writes to stderr is held back,
247
+ * so a caller reading `2>&1` still gets only JSON lines. On success the
248
+ * held lines are dropped. On failure one more line is printed on stdout:
249
+ * an object with `error`, `exit_code` and, when there were any, the held
250
+ * lines as `warnings`, built the same way as a guarded command's error
251
+ * document. `failure` may supply a more specific `error` body and extra
252
+ * top-level fields. The exit code is unchanged.
253
+ */
254
+ async function runStreamingJson(body, failure) {
255
+ const stderr = [];
256
+ const originalStderrWrite = process.stderr.write;
257
+ const originalConsole = {
258
+ debug: console.debug,
259
+ error: console.error,
260
+ warn: console.warn
261
+ };
262
+ const toStderr = (...args) => {
263
+ stderr.push(`${format(...args)}\n`);
264
+ };
265
+ process.stderr.write = capturingWrite(stderr);
266
+ console.debug = toStderr;
267
+ console.error = toStderr;
268
+ console.warn = toStderr;
269
+ let thrown;
270
+ try {
271
+ await body();
272
+ } catch (error) {
273
+ thrown = { error };
274
+ } finally {
275
+ process.stderr.write = originalStderrWrite;
276
+ console.debug = originalConsole.debug;
277
+ console.error = originalConsole.error;
278
+ console.warn = originalConsole.warn;
279
+ }
280
+ const exitCode = thrown ? isExitSignal(thrown.error) ? errorExitCode(thrown.error) ?? 0 : errorExitCode(thrown.error) ?? 1 : typeof process.exitCode === "number" ? process.exitCode : 0;
281
+ if (exitCode !== 0) {
282
+ const document = composeJsonDocument({
283
+ exitCode,
284
+ stderr,
285
+ stdout: "",
286
+ thrown
287
+ });
288
+ const specific = failure?.();
289
+ const line = specific ? {
290
+ ...document,
291
+ ...specific.fields,
292
+ error: specific.error
293
+ } : document;
294
+ const message = line.error?.message;
295
+ if (Array.isArray(line.warnings)) {
296
+ const warnings = line.warnings.filter((warning) => warning !== message);
297
+ if (warnings.length > 0) line.warnings = warnings;
298
+ else delete line.warnings;
299
+ }
300
+ process.stdout.write(`${JSON.stringify(line)}\n`);
301
+ }
302
+ if (thrown) {
303
+ if (thrown.error !== null && typeof thrown.error === "object") thrown.error.skipOclifErrorHandling = true;
304
+ throw thrown.error;
305
+ }
306
+ }
239
307
  /**
240
308
  * Guard every command in `commands` that accepts `--json`, except the
241
309
  * streaming ones. Called once by the command registry.
@@ -251,4 +319,4 @@ function guardJsonOutputCommands(commands) {
251
319
  }
252
320
  }
253
321
  //#endregion
254
- export { jsonOutputRequested as n, guardJsonOutputCommands as t };
322
+ export { jsonOutputRequested as n, runStreamingJson as r, guardJsonOutputCommands as t };
@@ -1,8 +1,8 @@
1
1
  import { S as __exportAll } from "./repeats-BL7ZC-_6-CKMKBlx7.js";
2
- import { B as parseOwnerMemberAddress, F as agentProfilesDirectory, I as connectedAgentIdentity, L as connectedApiBaseUrl, M as AgentConnectionSetupError, N as agentProfileDirectory, P as agentProfileName, R as loadConnectedAgentProfile, U as saveConnectedAgentProfile, V as profileAlreadyConnectedMessage, W as PrimitiveApiClient, j as AGENT_PROFILE_ENV, x as loadCliCredentials, z as parseConnectedAgentProfile } from "./cli-config-DMszFbGn.js";
3
- import { Bn as listContacts, Cn as getContact, Ct as cliInvocation, Dn as getEmail, Qn as listSentEmails, Rn as listAgentContacts, Sn as getAgentContactPolicy, Tt as defaultConnectionName, Un as listDomains, Zt as refreshStoredCliCredentials, ar as putAgentContactPolicy, dn as deleteContact, gr as sendEmail, ir as putAgentContact, or as putContact, pr as searchEmails, un as deleteAgentContact } from "./api-command-B8C3jr7A.js";
2
+ import { B as parseConnectedAgentProfile, F as agentProfileName, G as PrimitiveApiClient, H as profileAlreadyConnectedMessage, I as agentProfilesDirectory, L as connectedAgentIdentity, M as AGENT_PROFILE_ENV, N as AgentConnectionSetupError, P as agentProfileDirectory, R as connectedApiBaseUrl, V as parseOwnerMemberAddress, W as saveConnectedAgentProfile, x as loadCliCredentials, z as loadConnectedAgentProfile } from "./cli-config--YTRdJ3t.js";
3
+ import { $t as refreshStoredCliCredentials, Bn as listAgentContacts, Dt as defaultConnectionName, Gn as listDomains, Hn as listContacts, Tn as getContact, Tt as cliInvocation, cr as putContact, er as listSentEmails, fn as deleteAgentContact, hr as searchEmails, kn as getEmail, or as putAgentContact, pn as deleteContact, sr as putAgentContactPolicy, vr as sendEmail, wn as getAgentContactPolicy } from "./api-command-BrwPbyPP.js";
4
4
  import { _ as acquireListenLock, c as mailTime, d as readMailJson, f as removeMailFile, g as ListenStateError, h as writeMailJson, i as mailId, l as privateMailDirectory, o as mailObject, r as mailAddress, s as mailString } from "./shared-mail-files-MwlVE90c.js";
5
- import { _ as detectAgentRuntime, a as NotificationRetryError, d as defaultSessionSocket, f as NativeSessionDisconnectedError, l as SESSION_UUID, t as notificationScope, u as connectNativeSession, v as installConnectSkill, x as readBundledConnectSkill } from "./notify-session-JbFGcjiM.js";
5
+ import { _ as detectAgentRuntime, a as NotificationRetryError, d as defaultSessionSocket, f as NativeSessionDisconnectedError, l as SESSION_UUID, t as notificationScope, u as connectNativeSession, v as installConnectSkill, x as readBundledConnectSkill } from "./notify-session-Byt5sPWW.js";
6
6
  import { a as scopedChatSenderTrust } from "./scoped-chat-DTFkP360.js";
7
7
  import { l as stopBackgroundListen, r as backgroundListenStatus } from "./listen-background--0peztKE.js";
8
8
  import { t as readSharedMailOwner } from "./shared-mail-watch-DtKpsgg8.js";
@@ -4724,7 +4724,7 @@ async function enrollAgent(params) {
4724
4724
  const receiverMode = params.receiverMode ?? "native";
4725
4725
  const contactRequests = Boolean(params.contactRequests);
4726
4726
  const env = params.env ?? process.env;
4727
- if (env["PRIMITIVE_AGENT_PROFILE"]?.trim() || env.PRIMITIVE_API_KEY?.trim() || env.PRIMITIVE_KEY?.trim()) throw refuse("Enrollment requires the saved member OAuth login. Unset agent-profile and API-key environment overrides.");
4727
+ if (env["PRIMITIVE_AGENT_PROFILE"]?.trim() || env.PRIMITIVE_API_KEY?.trim() || env.PRIMITIVE_KEY?.trim()) throw refuse("Enrollment uses only the saved member login; rerun it under `env -u PRIMITIVE_AGENT_PROFILE -u PRIMITIVE_API_KEY -u PRIMITIVE_KEY` so no agent profile or API key override applies.");
4728
4728
  const saved = loadCliCredentials(params.configDir);
4729
4729
  if (!saved) throw refuse("Sign in with `primitive signin` as a member of this organization first.");
4730
4730
  const apiBaseUrl = connectedApiBaseUrl(saved.api_base_url);
@@ -5588,6 +5588,7 @@ async function registerSession(options) {
5588
5588
  receiving: RECEIVING[runtime],
5589
5589
  status: "already_registered",
5590
5590
  ...resumeNote,
5591
+ ...hooked === "held" ? { receiverHeld: true } : {},
5591
5592
  detail: hooked === "installed" ? "This session is already connected." : hooked === "held" ? HELD_DETAIL : "This session is already connected, but its receive hook could not be installed. Run `primitive machine doctor`."
5592
5593
  };
5593
5594
  }
@@ -5672,6 +5673,7 @@ async function registerSession(options) {
5672
5673
  name,
5673
5674
  nameIsDefault: name === record.name,
5674
5675
  ...resumeNote,
5676
+ ...hooked === "held" ? { receiverHeld: true } : {},
5675
5677
  detail: hooked === "installed" ? `Connected as ${address}.` : hooked === "held" ? `Connected as ${address}. ${HELD_DETAIL}` : `Connected as ${address}, but the receive hook could not be installed. Run \`primitive machine doctor\`.`
5676
5678
  };
5677
5679
  if (status === "revoked" || status === "owner_inactive") return {
@@ -1,5 +1,5 @@
1
1
  import { b as parseWebhookEvent, c as classifySignalContent, v as isEmailReceivedEvent, y as isTrustedSender } from "./repeats-BL7ZC-_6-CKMKBlx7.js";
2
- import { F as wakeReadCommand, P as skillFirstLine, Y as wakeInteractionSentence, vn as downloadEmailAttachmentPart } from "./api-command-B8C3jr7A.js";
2
+ import { I as skillFirstLine, L as wakeReadCommand, Z as wakeInteractionSentence, bn as downloadEmailAttachmentPart } from "./api-command-BrwPbyPP.js";
3
3
  import { _ as acquireListenLock, g as ListenStateError, y as listenIdentity } from "./shared-mail-files-MwlVE90c.js";
4
4
  import { closeSync, copyFileSync, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, opendirSync, readFileSync, readdirSync, readlinkSync, renameSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
5
5
  import { createHash, randomUUID, scryptSync } from "node:crypto";
@@ -1,6 +1,6 @@
1
- import { A as readThreadContext, Fn as getSentEmail, Yt as createAuthenticatedCliApiClient } from "../api-command-B8C3jr7A.js";
1
+ import { Ln as getSentEmail, M as readThreadContext, Zt as createAuthenticatedCliApiClient } from "../api-command-BrwPbyPP.js";
2
2
  import { _ as acquireListenLock } from "../shared-mail-files-MwlVE90c.js";
3
- import { t as sendSignal } from "../signal-command-B2TZ8n9c.js";
3
+ import { t as sendSignal } from "../signal-command-DeEEZPbQ.js";
4
4
  import { AUTO_SIGNAL_KIND_ENV, AUTO_WORKING_RENEW_MS, autoSignalsDisabled, clearWorkingSending, markWorkingSending, readAutoClaim, readWorkingLease, recordRenewer, stopWorkingLease, writeWorkingLease } from "./auto-signals.js";
5
5
  import { join } from "node:path";
6
6
  import { homedir } from "node:os";