primcli 1.42.0 → 1.44.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,6 +1,6 @@
1
- import { N as agentProfileDirectory, P as agentProfileName, R as loadConnectedAgentProfile, j as AGENT_PROFILE_ENV } from "../cli-config-BoZ1lMUQ.js";
1
+ import { N as agentProfileDirectory, P as agentProfileName, R as loadConnectedAgentProfile, j as AGENT_PROFILE_ENV } from "../cli-config-DGrZCUfw.js";
2
2
  import { d as readMailJson } from "../shared-mail-files-SPPcis9g.js";
3
- import { m as SESSION_UUID, n as detectAgentRuntime, o as notificationScope } from "../connect-skill-BHxdjtkK.js";
3
+ import { m as SESSION_UUID, n as detectAgentRuntime, o as notificationScope } from "../connect-skill-BJFxnbwI.js";
4
4
  import { a as claimBackgroundListenRestart, n as backgroundListenRestartable, r as backgroundListenStatus } from "../listen-background-TTBqrO_R.js";
5
5
  import { join } from "node:path";
6
6
  import { spawn } from "node:child_process";
@@ -1,4 +1,4 @@
1
- import { S as normalizeApiBaseUrl, c as resolveConfigEnvironment, i as loadCliConfig } from "../cli-config-BoZ1lMUQ.js";
1
+ import { S as normalizeApiBaseUrl, c as resolveConfigEnvironment, i as loadCliConfig } from "../cli-config-DGrZCUfw.js";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { homedir } from "node:os";
@@ -9676,7 +9676,7 @@ function normalizeOptions(options) {
9676
9676
  };
9677
9677
  }
9678
9678
  //#endregion
9679
- //#region ../sdk-node/dist/repeats-CoK0tpCK.js
9679
+ //#region ../sdk-node/dist/repeats-D2xtLium.js
9680
9680
  const UUID$3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9681
9681
  const ATOM = "[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+";
9682
9682
  const MAILBOX$1 = new RegExp(`^${ATOM}(?:\\.${ATOM})*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$`);
@@ -9869,9 +9869,28 @@ function utcExpiry(value) {
9869
9869
  ];
9870
9870
  return year >= 1970 && month >= 1 && month <= 12 && day >= 1 && day <= (days[month - 1] ?? 0) && Number(match[4]) < 24 && Number(match[5]) < 60 && Number(match[6]) < 60;
9871
9871
  }
9872
+ /** The fixed body of a repeat-stop notice; the stated reason is its only variable text. */
9873
+ function repeatStopNoticeText(reason) {
9874
+ return reason ? `Stopped this repeating message. Reason: ${reason}` : "Stopped this repeating message.";
9875
+ }
9876
+ /**
9877
+ * The notice body for a `repeat.stop/1` envelope sent back to a repeat's sender:
9878
+ * step `stop`, a previous step, no expiry, and a payload of `{}` or `{reason}`.
9879
+ * Unlike a status signal, the notice text is required.
9880
+ */
9881
+ function repeatStopFallback(e) {
9882
+ if (!exactKeys(e, ENVELOPE_KEYS$1) || e.protocol_version !== 1 || e.step !== "stop" || typeof e.prev_step_id !== "string" || e.expires_at !== null || !e.payload || typeof e.payload !== "object" || Array.isArray(e.payload)) return null;
9883
+ const p = e.payload;
9884
+ if (!exactKeys(p, [], ["reason"])) return null;
9885
+ if (!Object.hasOwn(p, "reason")) return repeatStopNoticeText(null);
9886
+ const reason = p.reason;
9887
+ if (typeof reason !== "string" || reason.length === 0 || reason.length > 280 || reason.includes("\0")) return null;
9888
+ return repeatStopNoticeText(reason);
9889
+ }
9872
9890
  function fallback(result) {
9873
9891
  if (result.status !== "valid") return null;
9874
9892
  const e = result.envelope;
9893
+ if (e.protocol === "repeat.stop") return repeatStopFallback(e);
9875
9894
  if (!exactKeys(e, ENVELOPE_KEYS$1) || e.protocol_version !== 1 || ![
9876
9895
  "ack",
9877
9896
  "read",
@@ -9948,7 +9967,7 @@ function classifySignalContent(input) {
9948
9967
  };
9949
9968
  const actual = (input.bodies.text ?? "").replace(/\r\n/g, "\n");
9950
9969
  const expected = text.replace(/\r\n/g, "\n");
9951
- const matches = actual === "" || actual === "\n" || actual === expected || actual === `${expected}\n`;
9970
+ const matches = !(interaction.status === "valid" && interaction.envelope.protocol === "repeat.stop") && (actual === "" || actual === "\n") || actual === expected || actual === `${expected}\n`;
9952
9971
  return {
9953
9972
  classification: matches ? "informational_only" : "mixed_or_unsupported",
9954
9973
  reason: matches ? "informational_signal" : "text_mismatch",
@@ -1,7 +1,7 @@
1
- import { h as sendPreparedSignal, p as prepareSignalEmail } from "./repeats-CoK0tpCK-Bx7nmyRi.js";
2
- import { Bt as getEmail, Dn as sendEmail, I as extractErrorPayload, St as createEndpoint, g as classifySendError, k as successfulSendOutcome, ln as listSentEmails, r as isWakeInteractionLabel, s as wakeInteractionLabel } from "./interaction-actions-D5o_frTT.js";
1
+ import { h as sendPreparedSignal, p as prepareSignalEmail } from "./repeats-D2xtLium-Dv34tqei.js";
2
+ import { En as listSentEmails, T as bareAddress, Wn as sendEmail, mt as successfulSendOutcome, o as extractErrorPayload, rn as getEmail, tt as classifySendError, zt as createEndpoint } from "./api-command-CpW39SQw.js";
3
3
  import { _ as acquireListenLock, a as mailLockBusy, b as listenProcessIdentity, c as mailTime, d as readMailJson, f as removeMailFile, h as writeMailJson, i as mailId, l as privateMailDirectory, m as withMailLock, n as invalidSharedMail, o as mailObject, p as syncMailDirectory, r as mailAddress, s as mailString, t as SharedMailStateError, v as compareListenProcessIdentity, y as listenIdentity } from "./shared-mail-files-SPPcis9g.js";
4
- import { F as readBeforeDeadline, I as scopedChatSenderTrust, N as isPlainChatReply, S as recordSentSignal } from "./auto-signals-D3NqwgYA.js";
4
+ import { F as readBeforeDeadline, I as scopedChatSenderTrust, N as isPlainChatReply, S as recordSentSignal } from "./auto-signals-oSCnNgts.js";
5
5
  import { Errors } from "@oclif/core";
6
6
  import { opendirSync, watch } from "node:fs";
7
7
  import { createHash, randomUUID, scryptSync } from "node:crypto";
@@ -332,7 +332,7 @@ async function pullFile(root, outPath, opts) {
332
332
  return manifest;
333
333
  }
334
334
  //#endregion
335
- //#region ../sdk-node/dist/api-D3QkZNtn.js
335
+ //#region ../sdk-node/dist/api-CQJEoY6H.js
336
336
  const jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
337
337
  function createSseClient({ onRequest, onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url, ...options }) {
338
338
  let lastEventId;
@@ -962,13 +962,13 @@ var EventReceiverError = class extends Error {
962
962
  this.name = "EventReceiverError";
963
963
  }
964
964
  };
965
- function record$2(value) {
965
+ function record$1(value) {
966
966
  return value !== null && typeof value === "object" && !Array.isArray(value);
967
967
  }
968
968
  function validateOffer(value) {
969
- if (!record$2(value) || !Number.isSafeInteger(value.backlog) || Number(value.backlog) < 0 || !Number.isSafeInteger(value.gap_count) || Number(value.gap_count) < 0 || value.last_gap_reason !== null && typeof value.last_gap_reason !== "string" || value.retention_seconds !== 86400 || value.handler_timeout_seconds !== 30) throw new EventReceiverError("Invalid event status response", "invalid_response");
969
+ if (!record$1(value) || !Number.isSafeInteger(value.backlog) || Number(value.backlog) < 0 || !Number.isSafeInteger(value.gap_count) || Number(value.gap_count) < 0 || value.last_gap_reason !== null && typeof value.last_gap_reason !== "string" || value.retention_seconds !== 86400 || value.handler_timeout_seconds !== 30) throw new EventReceiverError("Invalid event status response", "invalid_response");
970
970
  const d = value.delivery;
971
- if (d !== null && (!record$2(d) || ![
971
+ if (d !== null && (!record$1(d) || ![
972
972
  "queue_id",
973
973
  "event_id",
974
974
  "delivery_id",
@@ -976,7 +976,7 @@ function validateOffer(value) {
976
976
  "event_type",
977
977
  "body",
978
978
  "lease_expires_at"
979
- ].every((key) => typeof d[key] === "string") || !Number.isFinite(Date.parse(String(d.lease_expires_at))) || !record$2(d.headers) || !Object.values(d.headers).every((header) => typeof header === "string"))) throw new EventReceiverError("Invalid event delivery response", "invalid_response");
979
+ ].every((key) => typeof d[key] === "string") || !Number.isFinite(Date.parse(String(d.lease_expires_at))) || !record$1(d.headers) || !Object.values(d.headers).every((header) => typeof header === "string"))) throw new EventReceiverError("Invalid event delivery response", "invalid_response");
980
980
  return value;
981
981
  }
982
982
  function retryAfter(value) {
@@ -986,7 +986,7 @@ function retryAfter(value) {
986
986
  }
987
987
  function unwrap(result) {
988
988
  if (result.data !== void 0 && !result.error) return result.data;
989
- const code = record$2(result.error) && record$2(result.error.error) && typeof result.error.error.code === "string" ? result.error.error.code : "request_failed";
989
+ const code = record$1(result.error) && record$1(result.error.error) && typeof result.error.error.code === "string" ? result.error.error.code : "request_failed";
990
990
  throw new EventReceiverError(`Event request failed (${result.response?.status ?? 0}, ${code})`, code, result.response?.status ?? 0, retryAfter(result.response?.headers.get("retry-after") ?? null));
991
991
  }
992
992
  /** Shared by the SDK and CLI. Completion retries preserve the original evidence. */
@@ -1038,7 +1038,7 @@ var EventConnection = class {
1038
1038
  return;
1039
1039
  }
1040
1040
  this.touch?.();
1041
- if (!record$2(frame)) {
1041
+ if (!record$1(frame)) {
1042
1042
  this.fail(new EventReceiverError("Invalid event frame", "invalid_response"));
1043
1043
  return;
1044
1044
  }
@@ -1077,7 +1077,7 @@ var EventConnection = class {
1077
1077
  token
1078
1078
  })), { once: true });
1079
1079
  }, 15e3);
1080
- if (!record$2(ready) || ready.type !== "ready" || ready.protocol !== "primitive.events.v1") {
1080
+ if (!record$1(ready) || ready.type !== "ready" || ready.protocol !== "primitive.events.v1") {
1081
1081
  this.close();
1082
1082
  throw new EventReceiverError("Unsupported event stream protocol", "unsupported");
1083
1083
  }
@@ -1132,7 +1132,7 @@ var EventConnection = class {
1132
1132
  })).data);
1133
1133
  await this.open(signal);
1134
1134
  const frame = await this.exchange(signal, { type: "receive" }, void 0, 9e4);
1135
- if (!record$2(frame) || frame.type !== "event") throw new EventReceiverError("Invalid event frame", "invalid_response");
1135
+ if (!record$1(frame) || frame.type !== "event") throw new EventReceiverError("Invalid event frame", "invalid_response");
1136
1136
  return validateOffer(frame.data);
1137
1137
  }
1138
1138
  async complete(body, signal) {
@@ -1151,10 +1151,10 @@ var EventConnection = class {
1151
1151
  type: "complete",
1152
1152
  body
1153
1153
  }, void 0, 15e3);
1154
- if (!record$2(frame) || frame.type !== "receipt") throw new EventReceiverError("Invalid event receipt", "invalid_response");
1154
+ if (!record$1(frame) || frame.type !== "receipt") throw new EventReceiverError("Invalid event receipt", "invalid_response");
1155
1155
  receipt = frame.data;
1156
1156
  }
1157
- if (!record$2(receipt) || !["completed", "already_completed"].includes(String(receipt.result))) throw new EventReceiverError("Invalid event receipt", "invalid_response");
1157
+ if (!record$1(receipt) || !["completed", "already_completed"].includes(String(receipt.result))) throw new EventReceiverError("Invalid event receipt", "invalid_response");
1158
1158
  }
1159
1159
  };
1160
1160
  //#endregion
@@ -1298,173 +1298,6 @@ function waitForSharedMailChange(store, options) {
1298
1298
  });
1299
1299
  }
1300
1300
  //#endregion
1301
- //#region src/oclif/wake-context.ts
1302
- const security = [{
1303
- scheme: "bearer",
1304
- type: "http"
1305
- }];
1306
- const UUID = /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i;
1307
- const WAKE_ADDRESS = /^[a-z0-9._%+-]{1,64}@[a-z0-9.-]{1,253}$/;
1308
- const afterUnsupported = /* @__PURE__ */ new WeakSet();
1309
- /** The bare lowercase address in `Name <addr>` or `addr` form. */
1310
- function bareAddress(value) {
1311
- if (typeof value !== "string") return null;
1312
- const address = (/<([^<>\s]+@[^<>\s]+)>\s*$/.exec(value)?.[1] ?? value).trim().toLowerCase();
1313
- return /^[^\s<>@]+@[^\s<>@]+$/.test(address) ? address : null;
1314
- }
1315
- function record$1(value) {
1316
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1317
- }
1318
- function newerRows(value) {
1319
- if (!Array.isArray(value)) return void 0;
1320
- const rows = [];
1321
- for (const item of value.slice(-20)) {
1322
- const row = record$1(item);
1323
- const from = bareAddress(row?.from);
1324
- if (!row || typeof row.id !== "string" || !UUID.test(row.id) || !from || typeof row.received_at !== "string" || !Number.isFinite(Date.parse(row.received_at))) return void 0;
1325
- rows.push({
1326
- id: row.id.toLowerCase(),
1327
- from,
1328
- received_at: row.received_at
1329
- });
1330
- }
1331
- return rows;
1332
- }
1333
- /**
1334
- * Read one thread, asking for mail newer than `afterEmailId`. The newer-mail
1335
- * fields are feature-detected: an API that does not return them yields a
1336
- * context without `newerInboundCount`. Returns null when the thread cannot be
1337
- * read; callers treat that as "unknown", never as an error.
1338
- */
1339
- async function readThreadContext(client, threadId, afterEmailId, signal) {
1340
- if (!UUID.test(threadId)) return null;
1341
- const bounded = AbortSignal.any([signal, AbortSignal.timeout(5e3)]);
1342
- const read = (after) => client.get({
1343
- security,
1344
- url: "/threads/{id}",
1345
- path: { id: threadId },
1346
- ...after ? { query: { after } } : {},
1347
- signal: bounded,
1348
- responseStyle: "fields"
1349
- });
1350
- try {
1351
- const askAfter = afterEmailId !== void 0 && UUID.test(afterEmailId) && !afterUnsupported.has(client);
1352
- let result = await read(askAfter ? afterEmailId : void 0);
1353
- if (askAfter && result.response?.status === 400) {
1354
- afterUnsupported.add(client);
1355
- result = await read();
1356
- }
1357
- if (result.error !== void 0) return null;
1358
- const body = record$1(result.data);
1359
- const data = record$1(body?.data);
1360
- if (body?.success !== true || !data || !Array.isArray(data.messages)) return null;
1361
- const messages = data.messages.filter((message) => Boolean(record$1(message)) && typeof message.id === "string" && ["inbound", "outbound"].includes(message.direction));
1362
- const count = data.newer_inbound_count;
1363
- const newerInboundCount = typeof count === "number" && Number.isSafeInteger(count) && count >= 0 ? count : void 0;
1364
- const newerInbound = newerInboundCount === void 0 ? void 0 : newerRows(data.newer_inbound);
1365
- return {
1366
- threadId: threadId.toLowerCase(),
1367
- messages,
1368
- truncated: typeof data.message_count === "number" && data.message_count > messages.length,
1369
- ...newerInboundCount === void 0 ? {} : { newerInboundCount },
1370
- ...newerInbound === void 0 ? {} : { newerInbound }
1371
- };
1372
- } catch {
1373
- signal.throwIfAborted();
1374
- return null;
1375
- }
1376
- }
1377
- /** Whether `self` has an outbound message in the thread; undefined if unknowable. */
1378
- function sentInThread(context, self) {
1379
- if (!context) return void 0;
1380
- const address = self.toLowerCase();
1381
- if (context.messages.some((message) => message.direction === "outbound" && bareAddress(message.from) === address)) return true;
1382
- return context.truncated ? void 0 : false;
1383
- }
1384
- /** The latest outbound message from `self` in the thread, if listed. */
1385
- function latestOwnOutbound(context, self) {
1386
- const address = self.toLowerCase();
1387
- return [...context?.messages ?? []].reverse().find((message) => message.direction === "outbound" && bareAddress(message.from) === address);
1388
- }
1389
- function hasAttachments(detail) {
1390
- return (detail.parsed?.attachments?.length ?? 0) > 0;
1391
- }
1392
- /**
1393
- * Map server-provided sender facts to one relationship label. The owner and
1394
- * member labels come only from server admission; `agent` from the server's
1395
- * connected-agent verification or network admission; `contact` from an
1396
- * explicit contact allowance.
1397
- */
1398
- function wakeRelationship(input) {
1399
- if (input.senderRelation) return input.senderRelation;
1400
- if (input.connectedAgentVerified || input.network) return "agent";
1401
- if (input.contact) return "contact";
1402
- return "other";
1403
- }
1404
- const SERVER_RELATIONSHIPS = {
1405
- owner: "owner",
1406
- org_agent: "agent",
1407
- member: "member",
1408
- contact: "contact",
1409
- other: "other"
1410
- };
1411
- /** The `collaboration` object of an email read, when the server sends one. */
1412
- function collaborationOf(detail) {
1413
- return record$1(record$1(detail)?.collaboration);
1414
- }
1415
- /**
1416
- * The sender relationship the server computed for this email
1417
- * (`collaboration.sender_relationship`), mapped to the CLI's labels:
1418
- * `org_agent` reads as `agent`. When present it is authoritative, `other`
1419
- * included, so a stale local classification cannot override it. Returns
1420
- * undefined only for an older server that sends no such field, or an
1421
- * unrecognized value; the caller then keeps its own derivation.
1422
- */
1423
- function serverRelationship(detail) {
1424
- const value = collaborationOf(detail)?.sender_relationship;
1425
- return typeof value === "string" && Object.hasOwn(SERVER_RELATIONSHIPS, value) ? SERVER_RELATIONSHIPS[value] : void 0;
1426
- }
1427
- /**
1428
- * True when the server reports this email's thread as muted for the
1429
- * receiving address (`collaboration.muted`, or `muted` on the email). An
1430
- * older server sends neither and nothing is muted by it.
1431
- */
1432
- function serverMuted(detail) {
1433
- return collaborationOf(detail)?.muted === true || record$1(detail)?.muted === true;
1434
- }
1435
- /**
1436
- * An address fit to print as trusted metadata, or `unavailable`. The
1437
- * sender's address is parsed from a header the sender wrote, so anything
1438
- * outside a plain charset (quotes, spaces, line breaks) is withheld.
1439
- */
1440
- function displayAddress(value) {
1441
- return WAKE_ADDRESS.test(value) ? value : "unavailable";
1442
- }
1443
- /** The metadata clause of a wake line. Addresses outside a plain charset are withheld. */
1444
- function formatWakeContext(context) {
1445
- const sender = displayAddress(context.sender);
1446
- const thread = context.threadId && UUID.test(context.threadId) ? context.threadId.toLowerCase() : "none";
1447
- const newer = context.newer !== void 0 && Number.isSafeInteger(context.newer) && context.newer >= 0 ? ` newer=${Math.min(context.newer, 9999)}` : "";
1448
- const interaction = isWakeInteractionLabel(context.interaction) ? ` interaction=${context.interaction}` : "";
1449
- return `from=${sender} relationship=${context.relationship} thread=${thread} in_thread=${context.inThread ? "yes" : "no"} attachments=${context.attachments ? "yes" : "no"}${newer}${interaction}`;
1450
- }
1451
- /** Build a wake context, reading the thread once. Never throws for API failures. */
1452
- async function describeWake(input) {
1453
- const { detail } = input;
1454
- const threadId = typeof detail.thread_id === "string" && UUID.test(detail.thread_id) ? detail.thread_id.toLowerCase() : null;
1455
- const thread = threadId ? await readThreadContext(input.client, threadId, detail.id, input.signal) : null;
1456
- const interaction = wakeInteractionLabel(detail);
1457
- return {
1458
- sender: detail.from_email.trim().toLowerCase(),
1459
- relationship: serverRelationship(detail) ?? input.relationship,
1460
- threadId,
1461
- inThread: input.localInThread || sentInThread(thread, input.self) === true,
1462
- attachments: hasAttachments(detail),
1463
- ...thread?.newerInboundCount === void 0 ? {} : { newer: thread.newerInboundCount },
1464
- ...interaction ? { interaction } : {}
1465
- };
1466
- }
1467
- //#endregion
1468
1301
  //#region src/oclif/email-participants.ts
1469
1302
  /**
1470
1303
  * Everyone else an email was addressed to: its parsed To and Cc, as bare
@@ -2953,4 +2786,4 @@ async function sendSignal(context, options) {
2953
2786
  }
2954
2787
  }
2955
2788
  //#endregion
2956
- export { EventConnection as C, pushFile as E, readSharedMailOwner as S, pullFile as T, readThreadContext as _, ensureSharedMailSubscription as a, serverRelationship as b, reserveSharedMailSubscription as c, otherParticipants as d, bareAddress as f, latestOwnOutbound as g, formatWakeContext as h, sharedMailScope as i, followEmailConversation as l, displayAddress as m, reconcileChatSend as n, createSharedMailWaiter as o, describeWake as p, openSharedMailReceiver as r, openSharedMailStore as s, sendSignal as t, readConversationFollow as u, sentInThread as v, EventReceiverError as w, wakeRelationship as x, serverMuted as y };
2789
+ export { ensureSharedMailSubscription as a, reserveSharedMailSubscription as c, otherParticipants as d, readSharedMailOwner as f, pushFile as g, pullFile as h, sharedMailScope as i, followEmailConversation as l, EventReceiverError as m, reconcileChatSend as n, createSharedMailWaiter as o, EventConnection as p, openSharedMailReceiver as r, openSharedMailStore as s, sendSignal as t, readConversationFollow as u };
@@ -13,6 +13,25 @@ later work. An imperative setup instruction pasted as the owner's request
13
13
  authorizes this connection, private credential storage, the verification reply
14
14
  and continued receiving; do not ask for that approval again.
15
15
 
16
+ **One address per session unless the owner says otherwise.** If this session
17
+ already has a Primitive address (you connected it earlier, or a profile is
18
+ already receiving mail here), ask the owner whether to keep that address or
19
+ disconnect that agent first, and do not create a second address without their
20
+ answer. The connect command checks this itself: when the session is already
21
+ connected it claims nothing and exits with status 3 and
22
+ `status: "already_connected"` and names an address already connected here
23
+ (there can be more than one). Tell the owner, relay the same choice, then rerun
24
+ the same command as they chose:
25
+
26
+ - `--replace-existing` disconnects every address connected to this session,
27
+ not just one, then connects. Say so before they choose.
28
+ - `--keep-existing` keeps them all. If the existing address uses this
29
+ session's default profile, also pass a new `--profile <name>` so the second
30
+ address gets its own profile; otherwise the rerun is refused again.
31
+
32
+ Never switch to a separate profile on your own to get around this check; only
33
+ use a new profile as part of the owner's choice to keep both.
34
+
16
35
  The command validates the invitation's API origin, claims it once, answers the
17
36
  verification email, starts receiving for this exact session (or sets up
18
37
  checking for mail when nothing can wake this session), installs or refreshes
@@ -79,6 +98,8 @@ Read the one JSON result:
79
98
  `selectProfile` (`PRIMITIVE_AGENT_PROFILE=<profile>`).
80
99
  - `status: "pending"`: run `resumeCommand` exactly as printed. It never reads
81
100
  or claims the invitation again. `skipped` names each step not done and why.
101
+ - `status: "already_connected"` (exit status 3): ask the owner, then rerun
102
+ with `--replace-existing` or `--keep-existing` as described above.
82
103
  - Exit status 1: follow its message. Never feed the same invitation to the
83
104
  command twice, and never claim it over HTTP after the command may have
84
105
  claimed it. Switch to the [HTTP API path](#connect-with-the-http-api) only
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "primitive-connect",
3
- "version": "a48b2ea39305f258",
3
+ "version": "c744659c2610f3a2",
4
4
  "source": {
5
5
  "repository": "https://github.com/primitivedotdev/skills",
6
6
  "path": "skills/primitive-connect",
7
- "commit": "47e1cb5b6ecef4294c4f4067962c7e6041a625d0"
7
+ "commit": "8f4040ad7b91816efa58c0c175ff860db1e24abe"
8
8
  },
9
9
  "files": {
10
- "SKILL.md": "6631dab8209a823b3790df20856146676deb505a2f7a52de87e953fd75388694",
10
+ "SKILL.md": "e246e732bfede41a5538f8736bf3c6c5cd0b7d3c1ba1b8bb6e2a2d5103e915fb",
11
11
  "package-lock.json": "443289373a7495883a9a3b57bab3bc471cd5dcb4989a9e67f797b35917c1acc5",
12
12
  "package.json": "8cc45b2c28ba415960c9b85f6c1449f15f9c10bac0b96922e7907b40d50e3dbf",
13
13
  "references/communication.md": "c931aada9553a8592088c28de5b272d5e0a15234aa9c9318ea7d1d5f69b39a79",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primcli",
3
- "version": "1.42.0",
3
+ "version": "1.44.0",
4
4
  "description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
5
5
  "type": "module",
6
6
  "sideEffects": false,