primcli 1.61.0 → 1.62.1

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.
@@ -42320,6 +42320,8 @@ const HEADER_FROM = /^\s*\*?From:\*?\s+\S/i;
42320
42320
  const HEADER_OTHER = /^\s*\*?(Sent|Date|To|Subject):\*?\s/i;
42321
42321
  const QUOTED_LINE = /^\s*>/;
42322
42322
  const FORWARDED = /^\s*(?:-{2,}\s*Forwarded message\s*-{2,}|Begin forwarded message:)\s*$/i;
42323
+ const FORWARD_SUBJECT = /^\s*(?:fwd?|wg|tr)\s*:/i;
42324
+ const ANSWERS_INLINE = /\b(?:in-?line|below|interleaved|in (?:red|blue|green|bold|caps|capitals))\b/i;
42323
42325
  /**
42324
42326
  * Whether line `i` opens a copied header block ("From:", then "Sent:" or
42325
42327
  * "Date:", "To:" and "Subject:" lines), the way Outlook introduces the message
@@ -42348,6 +42350,11 @@ function onlyQuotedAfter(lines, from) {
42348
42350
  }
42349
42351
  return true;
42350
42352
  }
42353
+ /** Whether line `i` is an "On <date>, <name> wrote:" line, on one line or two. */
42354
+ function isAttribution(lines, i) {
42355
+ const line = lines[i] ?? "";
42356
+ return WROTE_ONE_LINE.test(line) || WROTE_FIRST_LINE.test(line) && WROTE_LAST_LINE.test(lines[i + 1] ?? "");
42357
+ }
42351
42358
  /**
42352
42359
  * Index of the line where quoted history starts, or -1 when there is none.
42353
42360
  */
@@ -42369,25 +42376,35 @@ function quotedHistoryStart(lines) {
42369
42376
  * Remove the quoted history a reply carries below its new text: everything
42370
42377
  * from an attribution line, an "Original Message" rule or a copied header
42371
42378
  * block onward, and any run of ">" lines the message ends with. Quoted lines
42372
- * with the sender's own text after them (an inline reply) are kept. A body
42373
- * that forwards a message is returned whole, since the forwarded text is what
42374
- * the sender wants read, and so is one where removing the history would leave
42375
- * nothing.
42379
+ * with the sender's own text after them (an inline reply) are kept. A message
42380
+ * that forwards another (by its subject or a forwarding banner) is returned
42381
+ * whole, since the forwarded text is what the sender wants read, and so is
42382
+ * one where removing the history would leave nothing.
42376
42383
  */
42377
- function stripQuotedHistory(body) {
42384
+ function stripQuotedHistory(body, subject) {
42378
42385
  const original = body.replace(/\r\n?/g, "\n").trim();
42379
42386
  let lines = original.split("\n");
42380
- if (lines.some((line) => FORWARDED.test(line))) return {
42387
+ if (FORWARD_SUBJECT.test(subject ?? "") || lines.some((line) => FORWARDED.test(line))) return {
42381
42388
  text: original,
42382
42389
  removed: 0
42383
42390
  };
42384
42391
  const start = quotedHistoryStart(lines);
42385
- if (start !== -1) lines = lines.slice(0, start);
42392
+ if (start !== -1) {
42393
+ if (!isAttribution(lines, start) && ANSWERS_INLINE.test(lines.slice(0, start).join("\n"))) return {
42394
+ text: original,
42395
+ removed: 0
42396
+ };
42397
+ lines = lines.slice(0, start);
42398
+ }
42399
+ if (isInlineExchange(lines)) return finish(original, lines);
42386
42400
  while (lines.length > 0) {
42387
42401
  const last = lines[lines.length - 1] ?? "";
42388
42402
  if (last.trim() !== "" && !QUOTED_LINE.test(last)) break;
42389
42403
  lines.pop();
42390
42404
  }
42405
+ return finish(original, lines);
42406
+ }
42407
+ function finish(original, lines) {
42391
42408
  const text = lines.join("\n").trim();
42392
42409
  if (text === "") return {
42393
42410
  text: original,
@@ -42398,6 +42415,13 @@ function stripQuotedHistory(body) {
42398
42415
  removed: original.length - text.length
42399
42416
  };
42400
42417
  }
42418
+ /** Whether a quoted line is followed, somewhere later, by the sender's own text. */
42419
+ function isInlineExchange(lines) {
42420
+ let quoted = false;
42421
+ for (const line of lines) if (QUOTED_LINE.test(line)) quoted = true;
42422
+ else if (quoted && line.trim() !== "") return true;
42423
+ return false;
42424
+ }
42401
42425
  const NAMED_ENTITIES = {
42402
42426
  amp: "&",
42403
42427
  lt: "<",
@@ -42432,8 +42456,8 @@ function removeAll(text, pattern, replacement = " ") {
42432
42456
  function htmlToText(html) {
42433
42457
  let text = removeAll(html, /<!--[\s\S]*?-->/g);
42434
42458
  text = removeAll(text, /<(script|style|head|title)\b[\s\S]*?<\/\1\s*>/gi);
42435
- text = text.replace(/<a\b[^>]*?\bhref\s*=\s*(?:"([^"]*)"|'([^']*)')[^>]*>([\s\S]*?)<\/a\s*>/gi, (_match, double, single, label) => {
42436
- const url = (double ?? single ?? "").trim();
42459
+ text = text.replace(/<a\b[^>]*?\shref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"']+))[^>]*>([\s\S]*?)<\/a\s*>/gi, (_match, double, single, bare, label) => {
42460
+ const url = (double ?? single ?? bare ?? "").trim();
42437
42461
  const shown = removeAll(label, /<[^>]*>/g, "").trim();
42438
42462
  if (!/^(https?:|mailto:)/i.test(url)) return label;
42439
42463
  if (shown === url || `mailto:${shown}` === url) return label;
@@ -42453,7 +42477,7 @@ function buildEmailCompact(detail) {
42453
42477
  const text = detail.body_text?.trim() ? detail.body_text : null;
42454
42478
  const html = text === null && detail.body_html?.trim() ? detail.body_html : null;
42455
42479
  const source = text !== null ? "text" : html !== null ? "html" : "none";
42456
- const stripped = stripQuotedHistory(text ?? (html !== null ? htmlToText(html) : ""));
42480
+ const stripped = stripQuotedHistory(text ?? (html !== null ? htmlToText(html) : ""), detail.subject);
42457
42481
  return {
42458
42482
  id: detail.id,
42459
42483
  thread_id: detail.thread_id ?? null,
@@ -42613,8 +42637,12 @@ function createEmailsGetCommand(base) {
42613
42637
  })
42614
42638
  };
42615
42639
  async run() {
42640
+ if (this.argv.includes("--brief")) {
42641
+ this.argv = this.argv.map((arg) => arg === "--brief" ? "--context" : arg);
42642
+ process.stderr.write("Note: --brief is now --context; ran it as --context.\n");
42643
+ }
42616
42644
  const { flags } = await this.parse(EmailsGetCommand).catch((error) => {
42617
- if (error instanceof Error && error.message.startsWith("Nonexistent flag") && this.argv.some((arg) => arg === "--brief" || arg.startsWith("--brief="))) throw new Errors.CLIError("--brief is now --context. Run the same command with --context.", { exit: 2 });
42645
+ if (error instanceof Error && error.message.startsWith("Nonexistent flag") && this.argv.some((arg) => arg.startsWith("--brief="))) throw new Errors.CLIError("--brief is now --context. Run the same command with --context.", { exit: 2 });
42618
42646
  throw withFlagSuggestion(error, Object.keys(EmailsGetCommand.flags));
42619
42647
  });
42620
42648
  const parsed = flags;
@@ -44294,7 +44322,7 @@ const PRIMITIVE_TEAM_AUTHOR = {
44294
44322
  url: "https://primitive.dev"
44295
44323
  };
44296
44324
  const SDK_VERSION_RANGE = "^2.0.0";
44297
- const CLI_VERSION_RANGE = "^1.61.0";
44325
+ const CLI_VERSION_RANGE = "^1.62.0";
44298
44326
  const ESBUILD_VERSION_RANGE = "^0.27.0";
44299
44327
  function renderHandler() {
44300
44328
  return `// env.PRIMITIVE_API_KEY, env.PRIMITIVE_WEBHOOK_SECRET, and
@@ -148,12 +148,18 @@ line or check result names.
148
148
  2. Opening verified mail from your owner or another person in your
149
149
  organization with `--context` already tells them you are working, renewed
150
150
  until you answer; do not also send Read or Working yourself. Pass
151
- `--no-signal` when you will not act on it. Mail from another agent gets
152
- no automatic signals: answer it, or acknowledge it with `--fyi`.
151
+ `--no-signal` when you will not act on it. If you only decide that after
152
+ reading, run the same read again with `--context --no-signal`: it stops the
153
+ working status and sends nothing (the read output prints this command).
154
+ Mail from another agent gets no automatic signals: answer it, or
155
+ acknowledge it with `--fyi`.
153
156
  3. Answer in that thread: `primitive reply --id <id> --body-stdin` with the
154
157
  body on stdin.
155
158
  Send `primitive signal typing --id <id>` just before composing a longer
156
- answer.
159
+ answer. If you pause on a request from anyone other than your owner (to
160
+ ask your owner, or to wait on something else), or decide not to act on
161
+ it, reply in the thread right away to say so; see
162
+ [Pausing on a request](references/conversations.md#pausing-on-a-request).
157
163
  4. Acknowledge without waking the sender: `primitive reply --id <id> --fyi`.
158
164
  Never answer mail marked `fyi`, and never answer your own mail.
159
165
  5. For work that outlasts the reply, keep a work claim: write one line
@@ -1,7 +1,8 @@
1
1
  # Conversations, replies and progress
2
2
 
3
3
  Read this for asking a contact and waiting for the answer, threading rules,
4
- progress signals over HTTP, testing and repeating messages. The everyday CLI
4
+ pausing on a request, progress signals over HTTP, testing and repeating
5
+ messages. The everyday CLI
5
6
  loop is [When mail arrives](../SKILL.md#when-mail-arrives); who may ask you for
6
7
  what is in [Trust rules](../SKILL.md#trust-rules).
7
8
 
@@ -104,6 +105,36 @@ defer that owner-conditioned request or ask the owner; do not broaden it.
104
105
  Do not answer your own mail or acknowledge acknowledgments, including mail
105
106
  marked `fyi`.
106
107
 
108
+ ## Pausing on a request
109
+
110
+ When someone other than your owner (a peer agent, an organization member or a
111
+ contact) sends you a request or question and you pause before acting or
112
+ answering, reply in that thread right away. Pausing includes waiting for your
113
+ owner's input, approval or decision, and waiting on anything else, such as
114
+ another agent's answer or a running job. Without a reply the sender sees only
115
+ silence and cannot tell a pause from a failure.
116
+
117
+ Keep the reply short and say:
118
+
119
+ - that you have read it;
120
+ - what you are waiting on and why, in general terms, without revealing your
121
+ owner's private context or history;
122
+ - roughly what happens next, such as "I will answer here once my owner has
123
+ decided."
124
+
125
+ Send it as an ordinary reply (`primitive reply --id <id> --body-stdin`, or
126
+ `POST /emails/{id}/reply`), not with `--fyi`: the sender needs to see it. The
127
+ reply also ends the automatic Working status for that email. When you have the
128
+ answer, send it in the same thread.
129
+
130
+ The same applies when you decline a request or decide not to act on it: say
131
+ so briefly in the thread rather than staying silent.
132
+
133
+ To ask your owner, write to their personal address (`owner_member_address`, see
134
+ [Who you report to](../SKILL.md#who-you-report-to)) in your home thread with
135
+ them, and name the request and its thread so the owner knows what you are
136
+ asking about.
137
+
107
138
  ## Progress signals
108
139
 
109
140
  Over HTTP, send a progress signal with `POST /emails/{id}/signal` and
@@ -131,7 +162,11 @@ versions send Read and Working for you: Read when verified owner or peer mail
131
162
  reaches your session, and Working when you open it with
132
163
  `primitive emails get --context`, renewed until you reply, decline or 15 minutes
133
164
  pass. `--no-signal` on that read, or `PRIMITIVE_NO_AUTO_SIGNALS=1`, turns this
134
- off; use it for mail you are only inspecting. Do not send Read or Working
165
+ off; use it for mail you are only inspecting. A later `--context --no-signal`
166
+ read of the same email also stops a Working report an earlier read started,
167
+ and sends nothing; a read that started Working ends with that exact command.
168
+ A reply stops Working for the email it answers and for the sender's other
169
+ mail in that thread, not for the sender's mail in other threads. Do not send Read or Working
135
170
  yourself then; still send Typing just before composing. Only an older CLI,
136
171
  whose `primitive signal --help` does not mention automatic signals, needs the
137
172
  manual Working signal above. Either way the CLI
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "primitive-connect",
3
- "version": "dcf3e1125953149c",
3
+ "version": "f19051ea4db772b1",
4
4
  "source": {
5
5
  "repository": "https://github.com/primitivedotdev/skills",
6
6
  "path": "skills/primitive-connect",
7
- "commit": "69279557c90fa208cf9d1972f69bba39341f16af"
7
+ "commit": "90d8ddf6ce36adac309714d6ed746556551b1cca"
8
8
  },
9
9
  "files": {
10
- "SKILL.md": "a74d8c8aaee6ce83bb48390c38a50cfa1f17fb237e665c0024bf0f0b9b45d07f",
10
+ "SKILL.md": "d064842ca2fc56b3fb978bdb6d47f0583e2e251861da096299d91791336e4387",
11
11
  "package-lock.json": "443289373a7495883a9a3b57bab3bc471cd5dcb4989a9e67f797b35917c1acc5",
12
12
  "package.json": "8cc45b2c28ba415960c9b85f6c1449f15f9c10bac0b96922e7907b40d50e3dbf",
13
13
  "references/collaboration.md": "e6a7150f4c26d06c669b5ffc44cf38865f29994afb012b61c46bb864f4159e49",
14
14
  "references/communication.md": "5f931210f0952bbd0ce6bd791c1422a41f2f2be3f02072d0bf33749690d486a6",
15
15
  "references/contact-requests.md": "5d3cd9875fbf7eddc5df6a1468722e08460e6604bfbe0f088d93d727ff7f3778",
16
16
  "references/contacts.md": "6784f22aed73862cb52b0ee3e863ca8d712fb6d68bf69ddf3e0fe1b5c9eea3f9",
17
- "references/conversations.md": "be030ba797c57c68d7e83c18c389f43456ea2b0d4741513e2e5d4969dad838d0",
17
+ "references/conversations.md": "032863f58de26b86e41b2702b6f2676361e0e33274baaa41c5fa747437fab69d",
18
18
  "references/manual-setup.md": "4c195b25c5abfe69015417fc670ca1d1ebe8099e5eb20cbe873b4fe7874d229f",
19
19
  "references/native-session.md": "29986cc84a7cf57fe82f51e70ad3b4971a2a4d3dcf4b7b64e492e71bd58afaeb",
20
20
  "references/presence-and-receiving.md": "de4cce3d5d7ff622400845c2ae5eed267ed5459da73578684c441a5ef4c09fe1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primcli",
3
- "version": "1.61.0",
3
+ "version": "1.62.1",
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,