primcli 1.63.0 → 1.64.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.
@@ -1,12 +1,12 @@
1
- import { a as REPEAT_IDLE_MAX_MINUTES, d as parseRepeatTick, f as preparePresenceAliveEmail, g as isEmailReceivedEvent, i as REPEAT_EVERY_MAX_MINUTES, l as parseInteractionEnvelope$1, m as repeatStopCommand, o as REPEAT_MAX_SENDS_MAX, p as prepareSignalEmail, s as buildRepeatStopBody, u as parsePresenceEnvelope, v as parseWebhookEvent, y as parseFromHeader } from "../repeats-x4QM2yoG-DTpqXyRo.js";
1
+ import { a as REPEAT_IDLE_MAX_MINUTES, b as parseWebhookEvent, d as parseRepeatTick, f as preparePresenceAliveEmail, i as REPEAT_EVERY_MAX_MINUTES, l as parseInteractionEnvelope$1, m as repeatStopCommand, o as REPEAT_MAX_SENDS_MAX, p as prepareSignalEmail, s as buildRepeatStopBody, u as parsePresenceEnvelope, v as isEmailReceivedEvent, x as parseFromHeader } from "../repeats-BL7ZC-_6-Dzangtkf.js";
2
2
  import { A as saveActiveChatState, C as resolveCliAuth, D as deleteChatState, E as chatStatePath, F as agentProfilesDirectory, H as requireDefaultLoginProfile, M as AgentConnectionSetupError, N as agentProfileDirectory, O as loadActiveChatState, P as agentProfileName, R as loadConnectedAgentProfile, T as saveSignupCredentials, W as PrimitiveApiClient, _ as deleteCliCredentials, a as normalizeCliEnvironmentName, b as hasStoredCliLogin, c as resolveConfigEnvironment, g as credentialsPath, h as credentialsLockPath, i as loadCliConfig, j as AGENT_PROFILE_ENV, k as loadChatConversationByLocalId, l as saveCliConfig, m as cliAccessTokenExpiresAt, n as deleteCliConfig, o as redactCliEnvironment, p as acquireCliCredentialsLock, r as emptyCliConfig, s as removeCliEnvironment, u as upsertCliEnvironment, v as deleteCliCredentialsLock, w as saveCliCredentials, x as loadCliCredentials, y as detectPrimitiveKeyEnvMisname } from "../cli-config-DMszFbGn.js";
3
- import { $ as apiResultHttpStatus, $n as replyToEmail, $t as completeWebhookEvent, A as readThreadContext, An as listAgentNetworks, At as formatAlreadySentNotice, B as pendingMailPath, Bn as listRoutes, Bt as expectedAutomatedVerdicts, C as queryUsesAwaiting, Cn as getMemory, Cr as verifyAgentSignup, Ct as cliInvocation, D as displayAddress, Dn as getThread, Dt as identitySuggestions, E as describeWake, En as getSentEmail, Et as generatedAgentName, F as wakeReadCommand, Fn as listEmails, Ft as AUTOMATED_VALUES, G as interactionNextActions, Gn as pollCliLogin, H as recordPendingMail, Hn as listWakeAuthorizations, Ht as isAutomatedRejectedError, I as wakeRecipientField, In as listEndpoints, It as AutomatedFilterUnsupportedError, J as replyInteractionWarning, Jt as refreshStoredCliCredentials, K as readEmailInteraction, Kn as pullWebhookEvent, Kt as createAuthenticatedCliApiClient, L as wakeRelationship, Ln as listFunctionLogs, Lt as assertAutomatedVerdict, M as serverMuted, Mn as listDefaultNetworkAgents, Mt as withFlagSuggestion, N as serverRelationship, Nn as listDefaultNetworkMembers, Nt as AUTOMATED_FILTER_UNSUPPORTED_CODE, O as formatMailWakeLine, On as getWakeSchedule, Ot as loadSkillLine, Pn as listDomains, Pt as AUTOMATED_FLAG_DESCRIPTION, Q as SEND_OUTCOME_HELP, Qn as reorderRoutes, Qt as cliLogout, R as clearConsumedPendingMail, Rn as listFunctions, Rt as automatedRejectedError, S as isAwaitingRejectedError, Sn as getInboxStatus, Sr as verifyAgentClaim, T as bareAddress, Tn as getRepeatingSend, U as removePendingMail, Un as listWakeDispatches, Ut as queryUsesAutomated, V as readPendingMail, Vn as listSentEmails, Vt as hasAutomatedVerdict, W as interactionHumanLine, Wn as listWakeSchedules, Wt as ConnectedAgentKeyRequiredError, X as IDEMPOTENCY_KEY_FLAG_DESCRIPTION, Xn as redeemCreditCode, Xt as addDefaultNetworkMember, Yt as resolveCliApiRequestConfig, Z as MAX_SEND_WAIT_TIMEOUT_MS, Zn as removeDefaultNetworkMember, Zt as checkDefaultNetworkContactAdmission, _ as awaitingRejectedError, _n as getDefaultNetworkAgent, _r as updateFunction, _t as sendWaitClampNotice, a as extractErrorCode, ar as sendEmail, at as deriveSendIdempotencyKey, b as formatRepliesCell, bn as getFunctionRouting, br as updateWakeAuthorization, bt as successfulSendOutcome, c as readTextFileFlag, cn as deleteRoute, cr as setMemory, ct as formatDeletedEarlierSendNotice, d as writeErrorWithHints, dr as startAgentSignup, dt as formatSendFailureSummary, en as createEndpoint, er as resendAgentSignupVerification, et as assertValidIdempotencyKey, f as AWAITING_FLAG_DESCRIPTION, fn as getAccount, fr as startCliLogin, ft as formatSendRecordFailureSummary, g as assertAwaitingFilterRows, gn as getCreditBalance, gr as updateDefaultNetworkMember, gt as sendOutcomeExitCode, h as ReplyStateUnsupportedError, hn as getConversation, hr as unsetFunctionRoute, ht as sendIdentityFields, i as createOperationCommand, in as createWakeSchedule, ir as semanticSearch, it as classifySendError, j as sentInThread, jt as writeIdempotentReplayBannerIfReplay, k as latestOwnOutbound, kn as listAgentContacts, kt as currentMailSessionKey, l as runWithTiming, ln as deleteWakeAuthorization, lr as simulateRoute, lt as formatPriorRepliesCheckSkipped, m as REPLY_STATE_UNSUPPORTED_CODE, mr as testFunction, mt as reportSendCommandResult, n as API_ERROR_CODES, nn as createRoute, nr as searchEmails, nt as buildThrownSendFailureEnvelope, o as extractErrorPayload, or as setFunctionRoute, ot as excludeSignalReplies, p as AWAITING_VALUES, pn as getAgentContactPolicy, pr as stopRepeatFromEmail, pt as priorRepliesThatWentOut, q as replyExpectation, qt as createCliApiClient, r as TIME_FLAG_DESCRIPTION, rn as createWakeAuthorization, rr as searchMemories, rt as checkPriorReplies, s as formatErrorPayload, sn as deleteMemory, sr as setFunctionSecret, st as followUpCommandPrefix, t as API_BASE_URL_FLAG_DESCRIPTION, tn as createFunction, tr as runWakeSchedule, tt as buildFollowUpCommand, u as surfaceUnauthorizedHint, un as deleteWakeSchedule, ur as startAgentClaim, ut as formatPriorRepliesWarning, v as ensureSearchReportsReplyState, vn as getEmail, vr as updateRepeatingSend, vt as sentHistoryWindowStart, w as explainPendingMailNotFound, wn as getOrgRoutingTopology, wt as connectNextSteps, x as hasReplyState, xn as getFunctionTestRunTrace, xr as updateWakeSchedule, xt as thrownErrorExitCode, y as formatAwaitingCell, yn as getFunction, yr as updateRoute, yt as serializeErrorPayload, z as clearReadPendingMail, zn as listRepeatingSends, zt as ensureSearchReportsAutomated } from "../api-command-CDjvGDQS.js";
3
+ import { $ as apiResultHttpStatus, $n as replyToEmail, $t as completeWebhookEvent, A as readThreadContext, An as listAgentNetworks, At as formatAlreadySentNotice, B as pendingMailPath, Bn as listRoutes, Bt as expectedAutomatedVerdicts, C as queryUsesAwaiting, Cn as getMemory, Cr as verifyAgentSignup, Ct as cliInvocation, D as displayAddress, Dn as getThread, Dt as identitySuggestions, E as describeWake, En as getSentEmail, Et as generatedAgentName, F as wakeReadCommand, Fn as listEmails, Ft as AUTOMATED_VALUES, G as interactionNextActions, Gn as pollCliLogin, H as recordPendingMail, Hn as listWakeAuthorizations, Ht as isAutomatedRejectedError, I as wakeRecipientField, In as listEndpoints, It as AutomatedFilterUnsupportedError, J as replyInteractionWarning, Jt as refreshStoredCliCredentials, K as readEmailInteraction, Kn as pullWebhookEvent, Kt as createAuthenticatedCliApiClient, L as wakeRelationship, Ln as listFunctionLogs, Lt as assertAutomatedVerdict, M as serverMuted, Mn as listDefaultNetworkAgents, Mt as withFlagSuggestion, N as serverRelationship, Nn as listDefaultNetworkMembers, Nt as AUTOMATED_FILTER_UNSUPPORTED_CODE, O as formatMailWakeLine, On as getWakeSchedule, Ot as loadSkillLine, Pn as listDomains, Pt as AUTOMATED_FLAG_DESCRIPTION, Q as SEND_OUTCOME_HELP, Qn as reorderRoutes, Qt as cliLogout, R as clearConsumedPendingMail, Rn as listFunctions, Rt as automatedRejectedError, S as isAwaitingRejectedError, Sn as getInboxStatus, Sr as verifyAgentClaim, T as bareAddress, Tn as getRepeatingSend, U as removePendingMail, Un as listWakeDispatches, Ut as queryUsesAutomated, V as readPendingMail, Vn as listSentEmails, Vt as hasAutomatedVerdict, W as interactionHumanLine, Wn as listWakeSchedules, Wt as ConnectedAgentKeyRequiredError, X as IDEMPOTENCY_KEY_FLAG_DESCRIPTION, Xn as redeemCreditCode, Xt as addDefaultNetworkMember, Yt as resolveCliApiRequestConfig, Z as MAX_SEND_WAIT_TIMEOUT_MS, Zn as removeDefaultNetworkMember, Zt as checkDefaultNetworkContactAdmission, _ as awaitingRejectedError, _n as getDefaultNetworkAgent, _r as updateFunction, _t as sendWaitClampNotice, a as extractErrorCode, ar as sendEmail, at as deriveSendIdempotencyKey, b as formatRepliesCell, bn as getFunctionRouting, br as updateWakeAuthorization, bt as successfulSendOutcome, c as readTextFileFlag, cn as deleteRoute, cr as setMemory, ct as formatDeletedEarlierSendNotice, d as writeErrorWithHints, dr as startAgentSignup, dt as formatSendFailureSummary, en as createEndpoint, er as resendAgentSignupVerification, et as assertValidIdempotencyKey, f as AWAITING_FLAG_DESCRIPTION, fn as getAccount, fr as startCliLogin, ft as formatSendRecordFailureSummary, g as assertAwaitingFilterRows, gn as getCreditBalance, gr as updateDefaultNetworkMember, gt as sendOutcomeExitCode, h as ReplyStateUnsupportedError, hn as getConversation, hr as unsetFunctionRoute, ht as sendIdentityFields, i as createOperationCommand, in as createWakeSchedule, ir as semanticSearch, it as classifySendError, j as sentInThread, jt as writeIdempotentReplayBannerIfReplay, k as latestOwnOutbound, kn as listAgentContacts, kt as currentMailSessionKey, l as runWithTiming, ln as deleteWakeAuthorization, lr as simulateRoute, lt as formatPriorRepliesCheckSkipped, m as REPLY_STATE_UNSUPPORTED_CODE, mr as testFunction, mt as reportSendCommandResult, n as API_ERROR_CODES, nn as createRoute, nr as searchEmails, nt as buildThrownSendFailureEnvelope, o as extractErrorPayload, or as setFunctionRoute, ot as excludeSignalReplies, p as AWAITING_VALUES, pn as getAgentContactPolicy, pr as stopRepeatFromEmail, pt as priorRepliesThatWentOut, q as replyExpectation, qt as createCliApiClient, r as TIME_FLAG_DESCRIPTION, rn as createWakeAuthorization, rr as searchMemories, rt as checkPriorReplies, s as formatErrorPayload, sn as deleteMemory, sr as setFunctionSecret, st as followUpCommandPrefix, t as API_BASE_URL_FLAG_DESCRIPTION, tn as createFunction, tr as runWakeSchedule, tt as buildFollowUpCommand, u as surfaceUnauthorizedHint, un as deleteWakeSchedule, ur as startAgentClaim, ut as formatPriorRepliesWarning, v as ensureSearchReportsReplyState, vn as getEmail, vr as updateRepeatingSend, vt as sentHistoryWindowStart, w as explainPendingMailNotFound, wn as getOrgRoutingTopology, wt as connectNextSteps, x as hasReplyState, xn as getFunctionTestRunTrace, xr as updateWakeSchedule, xt as thrownErrorExitCode, y as formatAwaitingCell, yn as getFunction, yr as updateRoute, yt as serializeErrorPayload, z as clearReadPendingMail, zn as listRepeatingSends, zt as ensureSearchReportsAutomated } from "../api-command-C3XihKH7.js";
4
4
  import { S as resolveListenSubscription, _ as acquireListenLock, a as mailLockBusy, c as mailTime, d as readMailJson, f as removeMailFile, g as ListenStateError, h as writeMailJson, i as mailId, l as privateMailDirectory, m as withMailLock, o as mailObject, u as privateMailPermissions, x as normalizeListenOrigin, y as listenIdentity } from "../shared-mail-files-MwlVE90c.js";
5
- import { _ as detectAgentRuntime, a as NotificationRetryError, b as installedVersion, c as readConversationStatusContent, d as defaultSessionSocket, f as NativeSessionDisconnectedError, g as connectSkillTarget, h as NotificationOutcomeUnknownError, i as notificationReceiptPage, l as SESSION_UUID$1, m as NativeSessionNotLoadedError, n as notificationSenders, o as isRoutineNotificationContent, p as NativeSessionError, r as openSessionNotifications, s as notificationPartReader, t as notificationScope, v as installConnectSkill, x as readBundledConnectSkill, y as installedConnectSkillFile } from "../notify-session-7JzG7GNX.js";
6
- import { $ as describeSessionHookItem, A as evaluateContactPolicy, B as agentInvitationHash, C as RECEIVER_MODES, D as NETWORK_ADMISSION_PENDING_RETRY_MS, E as ContactPolicyReadRetryError, F as ContactsApiError, G as saveConnectionName, H as readAgentInvitation, I as contactAddress, J as recordHookMailCheck, K as savedReceiver, L as contactAgentAddress, M as AddressNotesApiError, N as addressNoteTarget, O as NetworkAdmissionPendingError, P as runAddressNotesRequest, Q as describeSessionHookChange, R as runContactRequest, S as runAgentConnect, T as verificationReplySubmitted, U as receiverStatusCommand, V as connectAgent, W as refusalAfterReplacement, X as claudeConfigDir, Y as boundSessionProfiles, Z as currentCliLocation, _ as disconnectAgent, _t as withOwnerMemberAddress, a as endSession, at as readClaudeSettings, b as invitationProfileName, c as pendingSessionDisconnects, ct as writeClaudeSettings, d as registerSession, dt as jsonIndentation, et as ensureHookLauncher, f as retryPendingDisconnects, ft as readManagedFile, g as AgentDisconnectError, gt as refreshOwnerMemberAddressPeriodically, h as enrollmentResumes, ht as readHookLauncherWarning, i as connectedProfilesForSession, it as inspectClaudeHooks, j as canonicalContactSelector, k as createNotificationContactPolicy, l as psProcessInfo, lt as MachineFileError, m as enrollAgent, mt as writeManagedFile, n as OMP_MAIN, nt as findOnPath, o as headlessClaudeRun, ot as repairClaudeHooks, p as runDetached, pt as upsertManagedBlock, q as installClaudeWakeHook, r as agentConnectionState, rt as hasMachineSessionHooks, st as samePath, t as MACHINE_RUNTIMES, tt as ephemeralCliReason, u as readClaudeHookInput, ut as inspectManagedBlock, v as connectWarnings, w as externalReceivingState, x as pollCheckCommand, y as defaultAgentProfileName, z as agentConnectionStatus } from "../machine-session-NjXIXTRX.js";
7
- import { a as scopedChatSenderTrust, i as readBeforeDeadline, n as isPlainChatReply, o as presenceDisposition, r as isScopedChatReply, s as readPresenceProjection, t as isConnectedChatCredential } from "../scoped-chat-BvkUTggT.js";
5
+ import { _ as detectAgentRuntime, a as NotificationRetryError, b as installedVersion, c as readConversationStatusContent, d as defaultSessionSocket, f as NativeSessionDisconnectedError, g as connectSkillTarget, h as NotificationOutcomeUnknownError, i as notificationReceiptPage, l as SESSION_UUID$1, m as NativeSessionNotLoadedError, n as notificationSenders, o as isRoutineNotificationContent, p as NativeSessionError, r as openSessionNotifications, s as notificationPartReader, t as notificationScope, v as installConnectSkill, x as readBundledConnectSkill, y as installedConnectSkillFile } from "../notify-session-Bzcs3VBe.js";
6
+ import { $ as boundSessionProfiles, A as AgentDisconnectError, B as runContactRequest, C as verificationReplySubmitted, D as createNotificationContactPolicy, E as NetworkAdmissionPendingError, F as addressNoteTarget, G as receiverStatusCommand, H as agentInvitationHash, I as runAddressNotesRequest, J as savedReceiver, K as refusalAfterReplacement, L as ContactsApiError, M as clearRevokedAddresses, N as disconnectAgent, O as evaluateContactPolicy, P as AddressNotesApiError, Q as recordHookMailCheck, R as contactAddress, S as externalReceivingState, T as NETWORK_ADMISSION_PENDING_RETRY_MS, U as connectAgent, V as agentConnectionStatus, W as readAgentInvitation, X as releaseRegistrationsForProfile, Y as MACHINE_RUNTIMES, Z as installClaudeWakeHook, _ as defaultAgentProfileName, _t as upsertManagedBlock, a as endSession, at as ephemeralCliReason, b as runAgentConnect, bt as refreshOwnerMemberAddressPeriodically, c as pendingSessionDisconnects, ct as inspectClaudeHooks, d as registerSession, dt as samePath, et as claudeConfigDir, f as retryPendingDisconnects, ft as writeClaudeSettings, g as connectWarnings, gt as readManagedFile, h as enrollmentResumes, ht as jsonIndentation, i as connectedProfilesForSession, it as ensureHookLauncher, j as claimOverRevokedSetup, k as canonicalContactSelector, l as psProcessInfo, lt as readClaudeSettings, m as enrollAgent, mt as inspectManagedBlock, n as OMP_MAIN, nt as describeSessionHookChange, o as headlessClaudeRun, ot as findOnPath, p as runDetached, pt as MachineFileError, q as saveConnectionName, r as agentConnectionState, rt as describeSessionHookItem, st as hasMachineSessionHooks, t as HOOK_END_GRACE_MS, tt as currentCliLocation, u as readClaudeHookInput, ut as repairClaudeHooks, v as invitationProfileName, vt as writeManagedFile, w as ContactPolicyReadRetryError, x as RECEIVER_MODES, xt as withOwnerMemberAddress, y as pollCheckCommand, yt as readHookLauncherWarning, z as contactAgentAddress } from "../machine-session-B3JznlvO.js";
7
+ import { a as scopedChatSenderTrust, i as readBeforeDeadline, n as isPlainChatReply, o as presenceDisposition, r as isScopedChatReply, s as readPresenceProjection, t as isConnectedChatCredential } from "../scoped-chat-BW041zEY.js";
8
8
  import { c as startBackgroundListen, i as backgroundListenToken, l as stopBackgroundListen, o as runBackgroundListen, r as backgroundListenStatus, u as verifyBackgroundListenTarget } from "../listen-background--0peztKE.js";
9
- import { a as ensureSharedMailSubscription, c as isConnectedAgentKey, d as reserveSharedMailSubscription, f as followEmailConversation, g as EventReceiverError, h as EventConnection, i as sharedMailScope, l as createSharedMailWaiter, m as otherParticipants, n as reconcileChatSend, p as readConversationFollow, r as openSharedMailReceiver, s as AGENT_CONNECTION_REQUIRED_MESSAGE, t as sendSignal, u as openSharedMailStore } from "../signal-command-50rw5Sh-.js";
9
+ import { a as ensureSharedMailSubscription, c as isConnectedAgentKey, d as reserveSharedMailSubscription, f as followEmailConversation, g as EventReceiverError, h as EventConnection, i as sharedMailScope, l as createSharedMailWaiter, m as otherParticipants, n as reconcileChatSend, p as readConversationFollow, r as openSharedMailReceiver, s as AGENT_CONNECTION_REQUIRED_MESSAGE, t as sendSignal, u as openSharedMailStore } from "../signal-command-CgNIftzG.js";
10
10
  import { autoSignalEligible, dispatchAutoRead, dispatchAutoWorking, haltAutoWorking, isSentSignal, readWorkingLease, restoreAutoWorking } from "./auto-signals.js";
11
11
  import { t as guardJsonOutputCommands } from "../json-output-CEskSQJi.js";
12
12
  import { Args, Command, Errors, Flags, ux } from "@oclif/core";
@@ -2409,7 +2409,7 @@ const openapiDocument = {
2409
2409
  "/webhooks/deliveries": { "get": {
2410
2410
  "operationId": "listDeliveries",
2411
2411
  "summary": "List webhook deliveries",
2412
- "description": "Returns a paginated list of webhook delivery attempts. Each delivery\nincludes a nested `email` object with sender, recipient, and subject.\n",
2412
+ "description": "Returns a paginated list of webhook delivery attempts, newest first.\nA delivery of an inbound email includes a nested `email` object with\nsender, recipient, and subject. A delivery of an opt-in\n`sent_email.*` event has `email_id` and `email` set to null and\n`sent_email_id` set to the send it is about. Filter by `event_type`\nand `sent_email_id` to find the deliveries of one send.\n",
2413
2413
  "tags": ["Webhook Deliveries"],
2414
2414
  "parameters": [
2415
2415
  { "$ref": "#/components/parameters/Cursor" },
@@ -2423,6 +2423,25 @@ const openapiDocument = {
2423
2423
  },
2424
2424
  "description": "Filter by email ID"
2425
2425
  },
2426
+ {
2427
+ "name": "event_type",
2428
+ "in": "query",
2429
+ "schema": {
2430
+ "type": "string",
2431
+ "minLength": 1,
2432
+ "maxLength": 200
2433
+ },
2434
+ "description": "Only deliveries of this event type, for example `sent_email.failed`. Deliveries recorded before event types existed have none and never match."
2435
+ },
2436
+ {
2437
+ "name": "sent_email_id",
2438
+ "in": "query",
2439
+ "schema": {
2440
+ "type": "string",
2441
+ "format": "uuid"
2442
+ },
2443
+ "description": "Only deliveries of `sent_email.*` events about this sent email."
2444
+ },
2426
2445
  {
2427
2446
  "name": "status",
2428
2447
  "in": "query",
@@ -2432,7 +2451,8 @@ const openapiDocument = {
2432
2451
  "pending",
2433
2452
  "delivered",
2434
2453
  "header_confirmed",
2435
- "failed"
2454
+ "failed",
2455
+ "skipped_by_rules"
2436
2456
  ]
2437
2457
  },
2438
2458
  "description": "Filter by delivery status"
@@ -2478,14 +2498,14 @@ const openapiDocument = {
2478
2498
  "required": true,
2479
2499
  "schema": {
2480
2500
  "type": "string",
2481
- "pattern": "^\\d+$"
2501
+ "pattern": "^(\\d+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
2482
2502
  },
2483
- "description": "Delivery ID (numeric)"
2503
+ "description": "Delivery ID, as `id` in the deliveries list: a numeric string or a UUID."
2484
2504
  }],
2485
2505
  "post": {
2486
2506
  "operationId": "replayDelivery",
2487
2507
  "summary": "Replay a webhook delivery",
2488
- "description": "Re-sends the stored webhook payload from a previous delivery attempt.\nIf the original endpoint is still active, it is targeted. If the\noriginal endpoint was deleted, the oldest active endpoint is used.\nDeactivated endpoints cannot be replayed to. Rate limited per-org,\nsharing an org-wide budget with email replays.\n",
2508
+ "description": "Re-sends a previous delivery to its original endpoint. If that\nendpoint was deleted or deactivated, the replay is rejected.\nSupports inbound email deliveries and `sent_email.*` deliveries.\nAn inbound email delivery is replayed with its original stored\npayload and event id. A `sent_email.*` delivery is replayed with the\nsame event id but a payload rebuilt from the send as it is now; it\nis rejected if the send was deleted or the endpoint is no longer an\nactive http endpoint. Rate limited per-org, sharing an org-wide\nbudget with email replays.\n",
2489
2509
  "tags": ["Webhook Deliveries"],
2490
2510
  "responses": {
2491
2511
  "200": {
@@ -12806,6 +12826,11 @@ const openapiDocument = {
12806
12826
  "type": "string",
12807
12827
  "description": "Bare email address parsed from `to_header`."
12808
12828
  },
12829
+ "recipient_count": {
12830
+ "type": ["integer", "null"],
12831
+ "minimum": 0,
12832
+ "description": "Every recipient of the send, To, Cc and Bcc together, each address counted once: the size of `to_addresses`, `cc` and `bcc` combined without duplicates. On a mail relay send `bcc` lists every hidden recipient. Null when the request uses an address-bound agent connection key whose address is not the sender, because the count would reveal Bcc recipients. The `sent_email` object of the `sent_email.*` webhook events carries the same field."
12833
+ },
12809
12834
  "subject": { "type": "string" },
12810
12835
  "body_size_bytes": {
12811
12836
  "type": "integer",
@@ -14337,7 +14362,8 @@ const openapiDocument = {
14337
14362
  "items": {
14338
14363
  "type": "string",
14339
14364
  "minLength": 1
14340
- }
14365
+ },
14366
+ "description": "Event types this endpoint subscribes to, matched by exact string. Omitted means every event type except the opt-in `sent_email.*` events (`sent_email.accepted`, `sent_email.delivered`, `sent_email.failed`, `sent_email.completed`), which an endpoint receives only when it lists them, and only for sends made after it first listed one. An endpoint that lists `sent_email.*` events and also handles inbound mail must keep its inbound event types (such as `email.received`) in the list. An empty array is rejected; omit the field instead."
14341
14367
  } }
14342
14368
  },
14343
14369
  "created_at": {
@@ -14460,7 +14486,8 @@ const openapiDocument = {
14460
14486
  "items": {
14461
14487
  "type": "string",
14462
14488
  "minLength": 1
14463
- }
14489
+ },
14490
+ "description": "Event types this endpoint subscribes to, matched by exact string. Omitted means every event type except the opt-in `sent_email.*` events (`sent_email.accepted`, `sent_email.delivered`, `sent_email.failed`, `sent_email.completed`), which an endpoint receives only when it lists them, and only for sends made after it first listed one. An endpoint that lists `sent_email.*` events and also handles inbound mail must keep its inbound event types (such as `email.received`) in the list. An empty array is rejected; omit the field instead."
14464
14491
  } }
14465
14492
  },
14466
14493
  "is_route_target": {
@@ -14498,7 +14525,8 @@ const openapiDocument = {
14498
14525
  "items": {
14499
14526
  "type": "string",
14500
14527
  "minLength": 1
14501
- }
14528
+ },
14529
+ "description": "Event types this endpoint subscribes to, matched by exact string. Omitted means every event type except the opt-in `sent_email.*` events (`sent_email.accepted`, `sent_email.delivered`, `sent_email.failed`, `sent_email.completed`), which an endpoint receives only when it lists them, and only for sends made after it first listed one. An endpoint that lists `sent_email.*` events and also handles inbound mail must keep its inbound event types (such as `email.received`) in the list. An empty array is rejected; omit the field instead."
14502
14530
  } }
14503
14531
  }
14504
14532
  },
@@ -15182,11 +15210,21 @@ const openapiDocument = {
15182
15210
  "properties": {
15183
15211
  "id": {
15184
15212
  "type": "string",
15185
- "description": "Delivery ID (numeric string)"
15213
+ "description": "Delivery ID: a numeric string or a UUID. Pass it to the replay operation as is."
15186
15214
  },
15187
15215
  "email_id": {
15188
- "type": "string",
15189
- "format": "uuid"
15216
+ "type": ["string", "null"],
15217
+ "format": "uuid",
15218
+ "description": "The inbound email this delivery is about. Null for deliveries that are not about a received email, such as `sent_email.*` events."
15219
+ },
15220
+ "event_type": {
15221
+ "type": ["string", "null"],
15222
+ "description": "The delivered event type, for example `email.received` or `sent_email.delivered`. Null for deliveries recorded before event types existed."
15223
+ },
15224
+ "sent_email_id": {
15225
+ "type": ["string", "null"],
15226
+ "format": "uuid",
15227
+ "description": "The sent email a `sent_email.*` delivery is about. Null for every other delivery."
15190
15228
  },
15191
15229
  "org_id": {
15192
15230
  "type": "string",
@@ -15196,19 +15234,27 @@ const openapiDocument = {
15196
15234
  "type": "string",
15197
15235
  "format": "uuid"
15198
15236
  },
15199
- "endpoint_url": { "type": "string" },
15237
+ "endpoint_url": {
15238
+ "type": ["string", "null"],
15239
+ "description": "The endpoint's URL. For a function-backed endpoint, an opaque `function://<id>` identifier rather than a callable URL."
15240
+ },
15200
15241
  "status": {
15201
15242
  "type": "string",
15202
15243
  "enum": [
15203
15244
  "pending",
15204
15245
  "delivered",
15205
15246
  "header_confirmed",
15206
- "failed"
15247
+ "failed",
15248
+ "skipped_by_rules"
15207
15249
  ]
15208
15250
  },
15209
15251
  "attempt_count": { "type": "integer" },
15210
15252
  "duration_ms": { "type": ["integer", "null"] },
15211
15253
  "last_error": { "type": ["string", "null"] },
15254
+ "last_error_code": {
15255
+ "type": ["string", "null"],
15256
+ "description": "A stable code for the last failure, for example `http_500`."
15257
+ },
15212
15258
  "created_at": {
15213
15259
  "type": "string",
15214
15260
  "format": "date-time"
@@ -15221,10 +15267,11 @@ const openapiDocument = {
15221
15267
  "type": ["object", "null"],
15222
15268
  "properties": {
15223
15269
  "sender": { "type": "string" },
15224
- "recipient": { "type": "string" },
15270
+ "recipient": { "type": ["string", "null"] },
15225
15271
  "subject": { "type": ["string", "null"] }
15226
15272
  },
15227
- "required": ["sender", "recipient"]
15273
+ "required": ["sender", "recipient"],
15274
+ "description": "Null for deliveries that are not about a received email."
15228
15275
  }
15229
15276
  },
15230
15277
  "required": [
@@ -24736,7 +24783,8 @@ const operationManifest = [
24736
24783
  "items": {
24737
24784
  "type": "string",
24738
24785
  "minLength": 1
24739
- }
24786
+ },
24787
+ "description": "Event types this endpoint subscribes to, matched by exact string. Omitted means every event type except the opt-in `sent_email.*` events (`sent_email.accepted`, `sent_email.delivered`, `sent_email.failed`, `sent_email.completed`), which an endpoint receives only when it lists them, and only for sends made after it first listed one. An endpoint that lists `sent_email.*` events and also handles inbound mail must keep its inbound event types (such as `email.received`) in the list. An empty array is rejected; omit the field instead."
24740
24788
  } }
24741
24789
  },
24742
24790
  "is_route_target": {
@@ -24808,7 +24856,8 @@ const operationManifest = [
24808
24856
  "items": {
24809
24857
  "type": "string",
24810
24858
  "minLength": 1
24811
- }
24859
+ },
24860
+ "description": "Event types this endpoint subscribes to, matched by exact string. Omitted means every event type except the opt-in `sent_email.*` events (`sent_email.accepted`, `sent_email.delivered`, `sent_email.failed`, `sent_email.completed`), which an endpoint receives only when it lists them, and only for sends made after it first listed one. An endpoint that lists `sent_email.*` events and also handles inbound mail must keep its inbound event types (such as `email.received`) in the list. An empty array is rejected; omit the field instead."
24812
24861
  } }
24813
24862
  },
24814
24863
  "created_at": {
@@ -24988,7 +25037,8 @@ const operationManifest = [
24988
25037
  "items": {
24989
25038
  "type": "string",
24990
25039
  "minLength": 1
24991
- }
25040
+ },
25041
+ "description": "Event types this endpoint subscribes to, matched by exact string. Omitted means every event type except the opt-in `sent_email.*` events (`sent_email.accepted`, `sent_email.delivered`, `sent_email.failed`, `sent_email.completed`), which an endpoint receives only when it lists them, and only for sends made after it first listed one. An endpoint that lists `sent_email.*` events and also handles inbound mail must keep its inbound event types (such as `email.received`) in the list. An empty array is rejected; omit the field instead."
24992
25042
  } }
24993
25043
  },
24994
25044
  "created_at": {
@@ -25394,7 +25444,8 @@ const operationManifest = [
25394
25444
  "items": {
25395
25445
  "type": "string",
25396
25446
  "minLength": 1
25397
- }
25447
+ },
25448
+ "description": "Event types this endpoint subscribes to, matched by exact string. Omitted means every event type except the opt-in `sent_email.*` events (`sent_email.accepted`, `sent_email.delivered`, `sent_email.failed`, `sent_email.completed`), which an endpoint receives only when it lists them, and only for sends made after it first listed one. An endpoint that lists `sent_email.*` events and also handles inbound mail must keep its inbound event types (such as `email.received`) in the list. An empty array is rejected; omit the field instead."
25398
25449
  } }
25399
25450
  }
25400
25451
  },
@@ -25458,7 +25509,8 @@ const operationManifest = [
25458
25509
  "items": {
25459
25510
  "type": "string",
25460
25511
  "minLength": 1
25461
- }
25512
+ },
25513
+ "description": "Event types this endpoint subscribes to, matched by exact string. Omitted means every event type except the opt-in `sent_email.*` events (`sent_email.accepted`, `sent_email.delivered`, `sent_email.failed`, `sent_email.completed`), which an endpoint receives only when it lists them, and only for sends made after it first listed one. An endpoint that lists `sent_email.*` events and also handles inbound mail must keep its inbound event types (such as `email.received`) in the list. An empty array is rejected; omit the field instead."
25462
25514
  } }
25463
25515
  },
25464
25516
  "created_at": {
@@ -31368,6 +31420,11 @@ const operationManifest = [
31368
31420
  "type": "string",
31369
31421
  "description": "Bare email address parsed from `to_header`."
31370
31422
  },
31423
+ "recipient_count": {
31424
+ "type": ["integer", "null"],
31425
+ "minimum": 0,
31426
+ "description": "Every recipient of the send, To, Cc and Bcc together, each address counted once: the size of `to_addresses`, `cc` and `bcc` combined without duplicates. On a mail relay send `bcc` lists every hidden recipient. Null when the request uses an address-bound agent connection key whose address is not the sender, because the count would reveal Bcc recipients. The `sent_email` object of the `sent_email.*` webhook events carries the same field."
31427
+ },
31371
31428
  "subject": { "type": "string" },
31372
31429
  "body_size_bytes": {
31373
31430
  "type": "integer",
@@ -32103,6 +32160,11 @@ const operationManifest = [
32103
32160
  "type": "string",
32104
32161
  "description": "Bare email address parsed from `to_header`."
32105
32162
  },
32163
+ "recipient_count": {
32164
+ "type": ["integer", "null"],
32165
+ "minimum": 0,
32166
+ "description": "Every recipient of the send, To, Cc and Bcc together, each address counted once: the size of `to_addresses`, `cc` and `bcc` combined without duplicates. On a mail relay send `bcc` lists every hidden recipient. Null when the request uses an address-bound agent connection key whose address is not the sender, because the count would reveal Bcc recipients. The `sent_email` object of the `sent_email.*` webhook events carries the same field."
32167
+ },
32106
32168
  "subject": { "type": "string" },
32107
32169
  "body_size_bytes": {
32108
32170
  "type": "integer",
@@ -32603,6 +32665,11 @@ const operationManifest = [
32603
32665
  "type": "string",
32604
32666
  "description": "Bare email address parsed from `to_header`."
32605
32667
  },
32668
+ "recipient_count": {
32669
+ "type": ["integer", "null"],
32670
+ "minimum": 0,
32671
+ "description": "Every recipient of the send, To, Cc and Bcc together, each address counted once: the size of `to_addresses`, `cc` and `bcc` combined without duplicates. On a mail relay send `bcc` lists every hidden recipient. Null when the request uses an address-bound agent connection key whose address is not the sender, because the count would reveal Bcc recipients. The `sent_email` object of the `sent_email.*` webhook events carries the same field."
32672
+ },
32606
32673
  "subject": { "type": "string" },
32607
32674
  "body_size_bytes": {
32608
32675
  "type": "integer",
@@ -33122,6 +33189,11 @@ const operationManifest = [
33122
33189
  "type": "string",
33123
33190
  "description": "Bare email address parsed from `to_header`."
33124
33191
  },
33192
+ "recipient_count": {
33193
+ "type": ["integer", "null"],
33194
+ "minimum": 0,
33195
+ "description": "Every recipient of the send, To, Cc and Bcc together, each address counted once: the size of `to_addresses`, `cc` and `bcc` combined without duplicates. On a mail relay send `bcc` lists every hidden recipient. Null when the request uses an address-bound agent connection key whose address is not the sender, because the count would reveal Bcc recipients. The `sent_email` object of the `sent_email.*` webhook events carries the same field."
33196
+ },
33125
33197
  "subject": { "type": "string" },
33126
33198
  "body_size_bytes": {
33127
33199
  "type": "integer",
@@ -35340,7 +35412,7 @@ const operationManifest = [
35340
35412
  "binaryResponse": false,
35341
35413
  "bodyRequired": false,
35342
35414
  "command": "list-deliveries",
35343
- "description": "Returns a paginated list of webhook delivery attempts. Each delivery\nincludes a nested `email` object with sender, recipient, and subject.\n",
35415
+ "description": "Returns a paginated list of webhook delivery attempts, newest first.\nA delivery of an inbound email includes a nested `email` object with\nsender, recipient, and subject. A delivery of an opt-in\n`sent_email.*` event has `email_id` and `email` set to null and\n`sent_email_id` set to the send it is about. Filter by `event_type`\nand `sent_email_id` to find the deliveries of one send.\n",
35344
35416
  "hasJsonBody": false,
35345
35417
  "method": "GET",
35346
35418
  "operationId": "listDeliveries",
@@ -35371,13 +35443,28 @@ const operationManifest = [
35371
35443
  "required": false,
35372
35444
  "type": "string"
35373
35445
  },
35446
+ {
35447
+ "description": "Only deliveries of this event type, for example `sent_email.failed`. Deliveries recorded before event types existed have none and never match.",
35448
+ "enum": null,
35449
+ "name": "event_type",
35450
+ "required": false,
35451
+ "type": "string"
35452
+ },
35453
+ {
35454
+ "description": "Only deliveries of `sent_email.*` events about this sent email.",
35455
+ "enum": null,
35456
+ "name": "sent_email_id",
35457
+ "required": false,
35458
+ "type": "string"
35459
+ },
35374
35460
  {
35375
35461
  "description": "Filter by delivery status",
35376
35462
  "enum": [
35377
35463
  "pending",
35378
35464
  "delivered",
35379
35465
  "header_confirmed",
35380
- "failed"
35466
+ "failed",
35467
+ "skipped_by_rules"
35381
35468
  ],
35382
35469
  "name": "status",
35383
35470
  "required": false,
@@ -35406,11 +35493,21 @@ const operationManifest = [
35406
35493
  "properties": {
35407
35494
  "id": {
35408
35495
  "type": "string",
35409
- "description": "Delivery ID (numeric string)"
35496
+ "description": "Delivery ID: a numeric string or a UUID. Pass it to the replay operation as is."
35410
35497
  },
35411
35498
  "email_id": {
35412
- "type": "string",
35413
- "format": "uuid"
35499
+ "type": ["string", "null"],
35500
+ "format": "uuid",
35501
+ "description": "The inbound email this delivery is about. Null for deliveries that are not about a received email, such as `sent_email.*` events."
35502
+ },
35503
+ "event_type": {
35504
+ "type": ["string", "null"],
35505
+ "description": "The delivered event type, for example `email.received` or `sent_email.delivered`. Null for deliveries recorded before event types existed."
35506
+ },
35507
+ "sent_email_id": {
35508
+ "type": ["string", "null"],
35509
+ "format": "uuid",
35510
+ "description": "The sent email a `sent_email.*` delivery is about. Null for every other delivery."
35414
35511
  },
35415
35512
  "org_id": {
35416
35513
  "type": "string",
@@ -35420,19 +35517,27 @@ const operationManifest = [
35420
35517
  "type": "string",
35421
35518
  "format": "uuid"
35422
35519
  },
35423
- "endpoint_url": { "type": "string" },
35520
+ "endpoint_url": {
35521
+ "type": ["string", "null"],
35522
+ "description": "The endpoint's URL. For a function-backed endpoint, an opaque `function://<id>` identifier rather than a callable URL."
35523
+ },
35424
35524
  "status": {
35425
35525
  "type": "string",
35426
35526
  "enum": [
35427
35527
  "pending",
35428
35528
  "delivered",
35429
35529
  "header_confirmed",
35430
- "failed"
35530
+ "failed",
35531
+ "skipped_by_rules"
35431
35532
  ]
35432
35533
  },
35433
35534
  "attempt_count": { "type": "integer" },
35434
35535
  "duration_ms": { "type": ["integer", "null"] },
35435
35536
  "last_error": { "type": ["string", "null"] },
35537
+ "last_error_code": {
35538
+ "type": ["string", "null"],
35539
+ "description": "A stable code for the last failure, for example `http_500`."
35540
+ },
35436
35541
  "created_at": {
35437
35542
  "type": "string",
35438
35543
  "format": "date-time"
@@ -35445,10 +35550,11 @@ const operationManifest = [
35445
35550
  "type": ["object", "null"],
35446
35551
  "properties": {
35447
35552
  "sender": { "type": "string" },
35448
- "recipient": { "type": "string" },
35553
+ "recipient": { "type": ["string", "null"] },
35449
35554
  "subject": { "type": ["string", "null"] }
35450
35555
  },
35451
- "required": ["sender", "recipient"]
35556
+ "required": ["sender", "recipient"],
35557
+ "description": "Null for deliveries that are not about a received email."
35452
35558
  }
35453
35559
  },
35454
35560
  "required": [
@@ -35473,13 +35579,13 @@ const operationManifest = [
35473
35579
  "binaryResponse": false,
35474
35580
  "bodyRequired": false,
35475
35581
  "command": "replay-delivery",
35476
- "description": "Re-sends the stored webhook payload from a previous delivery attempt.\nIf the original endpoint is still active, it is targeted. If the\noriginal endpoint was deleted, the oldest active endpoint is used.\nDeactivated endpoints cannot be replayed to. Rate limited per-org,\nsharing an org-wide budget with email replays.\n",
35582
+ "description": "Re-sends a previous delivery to its original endpoint. If that\nendpoint was deleted or deactivated, the replay is rejected.\nSupports inbound email deliveries and `sent_email.*` deliveries.\nAn inbound email delivery is replayed with its original stored\npayload and event id. A `sent_email.*` delivery is replayed with the\nsame event id but a payload rebuilt from the send as it is now; it\nis rejected if the send was deleted or the endpoint is no longer an\nactive http endpoint. Rate limited per-org, sharing an org-wide\nbudget with email replays.\n",
35477
35583
  "hasJsonBody": false,
35478
35584
  "method": "POST",
35479
35585
  "operationId": "replayDelivery",
35480
35586
  "path": "/webhooks/deliveries/{id}/replay",
35481
35587
  "pathParams": [{
35482
- "description": "Delivery ID (numeric)",
35588
+ "description": "Delivery ID, as `id` in the deliveries list: a numeric string or a UUID.",
35483
35589
  "enum": null,
35484
35590
  "name": "id",
35485
35591
  "required": true,
@@ -36137,6 +36243,11 @@ async function replaceSessionAddresses(params) {
36137
36243
  const directory = agentProfileDirectory(params.configDir, profile);
36138
36244
  archive(join(directory, "setup.json"), stamp);
36139
36245
  archive(join(directory, "enrollment", "state.json"), stamp);
36246
+ await releaseRegistrationsForProfile({
36247
+ configDir: params.configDir,
36248
+ profileName: profile,
36249
+ now: params.now
36250
+ });
36140
36251
  }
36141
36252
  } catch (error) {
36142
36253
  const done = replaced.length ? ` Already disconnected: ${replaced.map((r) => r.address).join(", ")}.` : "";
@@ -36188,8 +36299,16 @@ function statusProfileMissingDetail(bound) {
36188
36299
  function invocation$1(entry) {
36189
36300
  return entry && /[\\/]_npx[\\/]/.test(entry) ? "npx -y primitive@latest" : "primitive";
36190
36301
  }
36302
+ /**
36303
+ * Names the addresses this run cleared as already revoked, so a later
36304
+ * refusal or failure that says nothing changed is not taken literally.
36305
+ */
36306
+ function withClearedNote(message, cleared) {
36307
+ if (!cleared.length) return message;
36308
+ return `${message} Before that, this run cleared ${cleared.map((row) => `${row.address} (profile ${row.profile})`).join(", ")} on this machine because Primitive confirmed ${cleared.length === 1 ? "its credential was" : "their credentials were"} already revoked; ${cleared.length === 1 ? "it stays" : "they stay"} disconnected.`;
36309
+ }
36191
36310
  var AgentConnectCommand = class AgentConnectCommand extends Command {
36192
- static description = `Connect this coding session to Primitive in one call. With --session, the command checks this CLI's capabilities, installs or refreshes the matching primitive-connect skill for the detected runtime (Claude Code or Codex) from files bundled in this CLI, claims the owner's private setup invitation from piped stdin, answers one authenticated setup challenge, enables owner notifications, starts receiving, seeds a private AGENT_INFO note from --name and --info when absent, and prints one JSON result. The receiver defaults to external hooks in Claude Code and the native background listener elsewhere. When the native default cannot work because this machine has no local session socket (for example Codex older than 0.158.0), the command connects with poll receiving instead and reports receiving.fallbackReason and receiving.fallbackDetail. Without a session (no --session, or an empty one) the receiver is poll: for runtimes with no local session ID or hooks, such as a cloud-hosted conversation whose commands run in a separate sandbox, the invitation is claimed and verified the same way, nothing is installed, and the result's receiving.checkCommand is the command the agent runs to check for new mail at the start of each turn and after it sends. Native receiving starts or reuses a supervised background listener and waits briefly for its first successful mail check; external receiving installs the exact Claude session's fail-open Stop hook and resume SessionStart hook after the verification reply; a real idle mail event must still verify wake. The profile defaults to session-<session>, or to connection-<invitation hash prefix> without a session. --resume continues saved progress without reading stdin or replaying a claim or uncertain verification send. After the reply is submitted it waits up to a minute for the server to confirm the connection and reports verification.state verified, or reply_submitted while confirmation is still pending. Verification is separate from receiver health. Both official production (https://api.primitive.dev/v1) and staging (https://api.primitive-staging-1.com/v1) invitations pin their API origin. Never pass an invitation as a command argument. One address per session: if this session already has a connected Primitive address, including one saved in the profile being connected, the command claims nothing, leaves stdin unread, and exits 3 with status already_connected. Its detail names how to continue that profile's own connection when that is the only one: --resume for a setup with saved progress, or --keep-existing to refresh a claim-only profile from the same invitation. Otherwise ask the user whether to keep the existing address or disconnect it first, then rerun with --keep-existing or --replace-existing. Never choose for the user. Select the saved identity with PRIMITIVE_AGENT_PROFILE. Use --status --json with --profile, with PRIMITIVE_AGENT_PROFILE set, or with --session (the address connected for that session) to inspect saved identity and local receiver health offline; it exits 1 when nothing is configured. A status check before connecting is optional: connect itself claims nothing and exits 3 when the session already has an address. A completed connection's result carries nextSteps, in order: report to the owner in two short sentences, make one offer to rename a generated name and record where the agent runs, and load the primitive-connect skill before handling mail. When the claim reported one, the result also carries the connection's name and nameIsDefault.`;
36311
+ static description = `Connect this coding session to Primitive in one call. With --session, the command checks this CLI's capabilities, installs or refreshes the matching primitive-connect skill for the detected runtime (Claude Code or Codex) from files bundled in this CLI, claims the owner's private setup invitation from piped stdin, answers one authenticated setup challenge, enables owner notifications, starts receiving, seeds a private AGENT_INFO note from --name and --info when absent, and prints one JSON result. The receiver defaults to external hooks in Claude Code and the native background listener elsewhere. When the native default cannot work because this machine has no local session socket (for example Codex older than 0.158.0), the command connects with poll receiving instead and reports receiving.fallbackReason and receiving.fallbackDetail. Without a session (no --session, or an empty one) the receiver is poll: for runtimes with no local session ID or hooks, such as a cloud-hosted conversation whose commands run in a separate sandbox, the invitation is claimed and verified the same way, nothing is installed, and the result's receiving.checkCommand is the command the agent runs to check for new mail at the start of each turn and after it sends. Native receiving starts or reuses a supervised background listener and waits briefly for its first successful mail check; external receiving installs the exact Claude session's fail-open Stop hook and resume SessionStart hook after the verification reply; a real idle mail event must still verify wake. The profile defaults to session-<session>, or to connection-<invitation hash prefix> without a session. --resume continues saved progress without reading stdin or replaying a claim or uncertain verification send. After the reply is submitted it waits up to a minute for the server to confirm the connection and reports verification.state verified, or reply_submitted while confirmation is still pending. Verification is separate from receiver health. Both official production (https://api.primitive.dev/v1) and staging (https://api.primitive-staging-1.com/v1) invitations pin their API origin. Never pass an invitation as a command argument. One address per session: an address whose credential Primitive confirms was already revoked (for example, revoked in the app before the owner reconnected it) no longer counts; it is disconnected locally, reported in clearedRevoked, and its saved setup is moved aside so the new invitation can be claimed into the same profile. Otherwise, if this session already has a connected Primitive address, including one saved in the profile being connected, the command claims nothing, leaves stdin unread, and exits 3 with status already_connected. Its detail names how to continue that profile's own connection when that is the only one: --resume for a setup with saved progress, or --keep-existing to refresh a claim-only profile from the same invitation. Otherwise ask the user whether to keep the existing address or disconnect it first, then rerun with --keep-existing or --replace-existing. Never choose for the user. Select the saved identity with PRIMITIVE_AGENT_PROFILE. Use --status --json with --profile, with PRIMITIVE_AGENT_PROFILE set, or with --session (the address connected for that session) to inspect saved identity and local receiver health offline; it exits 1 when nothing is configured. A status check before connecting is optional: connect itself claims nothing and exits 3 when the session already has an address. A completed connection's result carries nextSteps, in order: report to the owner in two short sentences, make one offer to rename a generated name and record where the agent runs, and load the primitive-connect skill before handling mail. When the claim reported one, the result also carries the connection's name and nameIsDefault.`;
36193
36312
  static summary = "Connect and verify an agent address";
36194
36313
  static examples = [
36195
36314
  "<%= config.bin %> agent connect --session \"$CODEX_THREAD_ID\" --name Research --info \"Reviews pull requests\" --json < private-invitation.txt",
@@ -36250,6 +36369,7 @@ var AgentConnectCommand = class AgentConnectCommand extends Command {
36250
36369
  const { flags } = await this.parse(AgentConnectCommand);
36251
36370
  let pollProfile;
36252
36371
  let replaced = [];
36372
+ let cleared = [];
36253
36373
  try {
36254
36374
  if (flags.status) {
36255
36375
  const statusSession = flags.session?.trim();
@@ -36321,10 +36441,25 @@ var AgentConnectCommand = class AgentConnectCommand extends Command {
36321
36441
  address: check.target.address
36322
36442
  }];
36323
36443
  if (bound.length > 0 && !flags["replace-existing"]) {
36324
- const continuation = check.target && targetContinuation(this.config.configDir, check.target.profile, claimOnly);
36444
+ const result = await clearRevokedAddresses({
36445
+ configDir: this.config.configDir,
36446
+ rows: bound,
36447
+ disconnect: disconnectAgent
36448
+ });
36449
+ bound = result.remaining;
36450
+ cleared = result.cleared;
36451
+ if (!flags.json) for (const row of cleared) this.log(`Cleared ${row.address} (profile ${row.profile}): Primitive confirmed its credential was already revoked.`);
36452
+ }
36453
+ if (bound.length > 0 && !flags["replace-existing"]) {
36454
+ const continuation = check.target && bound.some((row) => row.profile === check.target?.profile) && targetContinuation(this.config.configDir, check.target.profile, claimOnly);
36325
36455
  const refusal = alreadyConnected(guardSession, bound, "connect", continuation || void 0);
36326
- if (flags.json) this.log(JSON.stringify(refusal));
36327
- else this.log(refusal.detail);
36456
+ const detail = withClearedNote(refusal.detail, cleared);
36457
+ if (flags.json) this.log(JSON.stringify(cleared.length ? {
36458
+ ...refusal,
36459
+ detail,
36460
+ clearedRevoked: cleared
36461
+ } : refusal));
36462
+ else this.log(detail);
36328
36463
  process.exitCode = 3;
36329
36464
  return;
36330
36465
  }
@@ -36386,10 +36521,11 @@ var AgentConnectCommand = class AgentConnectCommand extends Command {
36386
36521
  guidance: `${output.guidance} Next: ${nextSteps.join(" ")}`
36387
36522
  } : {}
36388
36523
  };
36389
- if (flags.json) this.log(JSON.stringify(replaced.length ? {
36524
+ if (flags.json) this.log(JSON.stringify({
36390
36525
  ...suggested,
36391
- replacedExisting: replaced
36392
- } : suggested));
36526
+ ...replaced.length ? { replacedExisting: replaced } : {},
36527
+ ...cleared.length ? { clearedRevoked: cleared } : {}
36528
+ }));
36393
36529
  else {
36394
36530
  this.log(`Agent ${output.address}: verification ${output.verification.state}; receiving ${output.receiving.state}; skill ${output.skill.state}.`);
36395
36531
  this.log(`Select it with ${output.selectProfile}.`);
@@ -36411,25 +36547,29 @@ var AgentConnectCommand = class AgentConnectCommand extends Command {
36411
36547
  }
36412
36548
  if (!flags.profile) throw new AgentConnectionSetupError("Pass --profile for claim-only.");
36413
36549
  const invitation = await readInvitationOnce();
36414
- agentInvitationHash(invitation);
36550
+ const invitationHash = agentInvitationHash(invitation);
36415
36551
  await replaceExisting?.();
36416
- const claimed = await connectAgent({
36552
+ const profileName = flags.profile;
36553
+ const claimed = await claimOverRevokedSetup({
36417
36554
  configDir: this.config.configDir,
36418
- profileName: flags.profile,
36419
- invitation
36420
- });
36555
+ profileName,
36556
+ invitationHash
36557
+ }, (claimLockHeld) => connectAgent({
36558
+ configDir: this.config.configDir,
36559
+ profileName,
36560
+ invitation,
36561
+ claimLockHeld
36562
+ }));
36421
36563
  const result = await withOwnerMemberAddress(claimed, {
36422
36564
  configDir: this.config.configDir,
36423
36565
  onlyIfUnknown: claimed.status === "claimed"
36424
36566
  });
36425
36567
  const warnings = connectWarnings(this.config.configDir, result.identity.profileName);
36426
- if (flags.json) this.log(JSON.stringify(replaced.length ? {
36568
+ if (flags.json) this.log(JSON.stringify({
36427
36569
  ...result,
36428
36570
  warnings,
36429
- replacedExisting: replaced
36430
- } : {
36431
- ...result,
36432
- warnings
36571
+ ...replaced.length ? { replacedExisting: replaced } : {},
36572
+ ...cleared.length ? { clearedRevoked: cleared } : {}
36433
36573
  }));
36434
36574
  else {
36435
36575
  this.log(result.status === "claimed" ? "Agent profile saved. Email readiness is not yet verified." : "Agent profile already configured; no claim was sent.");
@@ -36439,7 +36579,7 @@ var AgentConnectCommand = class AgentConnectCommand extends Command {
36439
36579
  }
36440
36580
  } catch (caught) {
36441
36581
  const error = refusalAfterReplacement(caught, replaced);
36442
- throw new Errors.CLIError(error instanceof AgentConnectionSetupError ? error.message : flags.session?.trim() ? `Setup paused. Preserve the private profile and run ${invocation$1(process.argv[1])} agent connect --profile ${flags.profile ?? defaultAgentProfileName(flags.session.trim())} --session ${flags.session.trim()}${flags.receiver ? ` --receiver ${flags.receiver}` : ""} --resume --json. Do not manually resend verification or reclaim the invitation.` : pollProfile ? `Setup paused. Preserve the private profile and run ${invocation$1(process.argv[1])} agent connect --profile ${pollProfile} --receiver poll --resume --json. Do not manually resend verification or reclaim the invitation.` : "Agent setup did not complete. Preserve the private profile and request a fresh owner invitation if a claim may have been submitted.", { exit: 1 });
36582
+ throw new Errors.CLIError(withClearedNote(error instanceof AgentConnectionSetupError ? error.message : flags.session?.trim() ? `Setup paused. Preserve the private profile and run ${invocation$1(process.argv[1])} agent connect --profile ${flags.profile ?? defaultAgentProfileName(flags.session.trim())} --session ${flags.session.trim()}${flags.receiver ? ` --receiver ${flags.receiver}` : ""} --resume --json. Do not manually resend verification or reclaim the invitation.` : pollProfile ? `Setup paused. Preserve the private profile and run ${invocation$1(process.argv[1])} agent connect --profile ${pollProfile} --receiver poll --resume --json. Do not manually resend verification or reclaim the invitation.` : "Agent setup did not complete. Preserve the private profile and request a fresh owner invitation if a claim may have been submitted.", cleared), { exit: 1 });
36443
36583
  }
36444
36584
  }
36445
36585
  };
@@ -36620,7 +36760,7 @@ var AgentContactsUpdateCommand = class AgentContactsUpdateCommand extends Comman
36620
36760
  //#endregion
36621
36761
  //#region src/oclif/commands/agent-disconnect.ts
36622
36762
  var AgentDisconnectCommand = class AgentDisconnectCommand extends Command {
36623
- static description = "Disconnect exactly one saved connected-agent profile. Stop its tracked bound receiver, revoke only that address's bound credential at its pinned Primitive origin, then remove only the local credential after confirmed revocation. Mail, notes, setup evidence and notification receipts remain. This does not permanently remove the connection record; an owner or admin can do that separately.";
36763
+ static description = "Disconnect exactly one saved connected-agent profile. Stop its tracked bound receiver, revoke only that address's bound credential at its pinned Primitive origin, then remove only the local credential after confirmed revocation. When Primitive refuses the credential as unauthorized because it was already revoked (in the app or from another machine), the same credential is checked once more and, only if that confirms it no longer authenticates, the disconnect completes and reports revocation already_revoked; a server error or network failure is never treated as confirmation. Mail, notes, setup evidence and notification receipts remain. This does not permanently remove the connection record; an owner or admin can do that separately.";
36624
36764
  static summary = "Disconnect one connected agent";
36625
36765
  static examples = ["<%= config.bin %> agent disconnect --profile work", "<%= config.bin %> agent disconnect --profile work --json"];
36626
36766
  static flags = {
@@ -37291,7 +37431,7 @@ var AgentRuntimeGetCommand = class AgentRuntimeGetCommand extends Command {
37291
37431
  //#region src/oclif/commands/agent-session-end.ts
37292
37432
  var AgentSessionEndCommand = class AgentSessionEndCommand extends Command {
37293
37433
  static summary = "Disconnect the agent a session registered when it ends";
37294
- static description = "Disconnects the agent that `primitive agent session-register` created for this session, and removes its exact-session receive hooks. Agents connected any other way are left connected. Never blocks or fails a session: every outcome exits 0 with a status. --hook reads Claude's SessionEnd hook input from stdin and disconnects in the background.";
37434
+ static description = "Disconnects the agent that `primitive agent session-register` created for this session, and removes its exact-session receive hooks. Agents connected any other way are left connected, including an agent later connected into the same profile with `primitive agent connect`. Never blocks or fails a session: every outcome exits 0 with a status. --hook reads Claude's SessionEnd hook input from stdin and disconnects in the background after a grace period: Claude reports the same end for a restart, a switch to another session and a real exit, so a start of the same session within the grace period cancels the end and keeps its agent.";
37295
37435
  static examples = ["<%= config.bin %> agent session-end --runtime claude --json", "<%= config.bin %> agent session-end --runtime codex --session 11111111-1111-4111-8111-111111111111"];
37296
37436
  static flags = {
37297
37437
  runtime: Flags.string({
@@ -37300,6 +37440,12 @@ var AgentSessionEndCommand = class AgentSessionEndCommand extends Command {
37300
37440
  description: "The coding agent runtime this session runs in"
37301
37441
  }),
37302
37442
  session: Flags.string({ description: "Exact session UUID; defaults to the runtime's own session ID" }),
37443
+ grace: Flags.integer({
37444
+ min: 0,
37445
+ max: 3600,
37446
+ description: "Seconds to wait before disconnecting; a start of the same session meanwhile cancels the end"
37447
+ }),
37448
+ reason: Flags.string({ description: "The runtime's reason for the end, recorded with it" }),
37303
37449
  hook: Flags.boolean({ description: "Read Claude hook JSON from stdin and disconnect in the background" }),
37304
37450
  json: Flags.boolean({ description: "Print the result as JSON" }),
37305
37451
  quiet: Flags.boolean({ description: "Print nothing" })
@@ -37320,6 +37466,9 @@ var AgentSessionEndCommand = class AgentSessionEndCommand extends Command {
37320
37466
  runtime,
37321
37467
  "--session",
37322
37468
  input.sessionId,
37469
+ "--grace",
37470
+ String(HOOK_END_GRACE_MS / 1e3),
37471
+ ...input.reason ? ["--reason", input.reason] : [],
37323
37472
  "--quiet"
37324
37473
  ],
37325
37474
  env: process.env,
@@ -37330,7 +37479,9 @@ var AgentSessionEndCommand = class AgentSessionEndCommand extends Command {
37330
37479
  const result = await endSession({
37331
37480
  configDir: this.config.configDir,
37332
37481
  runtime,
37333
- session: flags.session
37482
+ session: flags.session,
37483
+ graceMs: (flags.grace ?? 0) * 1e3,
37484
+ reason: flags.reason ?? null
37334
37485
  });
37335
37486
  const { status, ...rest } = result;
37336
37487
  if (flags.json) this.log(JSON.stringify({
@@ -44604,7 +44755,7 @@ const PRIMITIVE_TEAM_AUTHOR = {
44604
44755
  url: "https://primitive.dev"
44605
44756
  };
44606
44757
  const SDK_VERSION_RANGE = "^2.0.0";
44607
- const CLI_VERSION_RANGE = "^1.63.0";
44758
+ const CLI_VERSION_RANGE = "^1.64.0";
44608
44759
  const ESBUILD_VERSION_RANGE = "^0.27.0";
44609
44760
  function renderHandler() {
44610
44761
  return `// env.PRIMITIVE_API_KEY, env.PRIMITIVE_WEBHOOK_SECRET, and