@pidgeon-ai/sdk 1.11.0 → 1.13.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.
package/CHANGELOG.md CHANGED
@@ -9,6 +9,26 @@ call shapes, the result shape — not to the API behind it.
9
9
 
10
10
  ## Unreleased
11
11
 
12
+ ## 1.13.0 — what the agent reads
13
+
14
+ `firewall.clean_text` on every inbound message: the new text with hidden
15
+ content and invisible characters removed, and lines posing as a chat turn
16
+ marked, under a one-line note saying what changed. `body=clean` on
17
+ `GET /messages/{id}` and `GET /messages/await` returns it as `text` and
18
+ `reply_text`, with `html` and `reply_html` empty. The default is still
19
+ `original`. The MCP server and the AI SDK ask for `clean` unless told
20
+ otherwise.
21
+
22
+ ## 1.12.0 — Pidgeon Firewall
23
+
24
+ Every inbound `Message` carries `firewall`: a `verdict` (`clean` or
25
+ `suspicious`) and the `signals` that produced it — hidden text, instructions
26
+ addressed to an AI, impersonated chat turns, directives buried in quoted
27
+ history, look-alike senders, display-name spoofing, and requests to send
28
+ secrets out — each with where it fired and a sentence quoting it.
29
+ `message.received` carries the verdict and the signal kinds. Observe-only:
30
+ nothing is held or changed. Read it before acting on what a message asks.
31
+
12
32
  ## 1.11.0 — a key for one pod
13
33
 
14
34
  `apiKeysCreate` takes `pod_id` in place of `identity_ids`: the key reaches
package/dist/index.d.cts CHANGED
@@ -528,6 +528,34 @@ type Message = {
528
528
  * The event the calendar made of that invitation, or null. A different fact from `invitation`: that is what the mail said, this is what the calendar now holds — a meeting later moved still reports the time this message invited you to.
529
529
  */
530
530
  calendar_event_id: string | null;
531
+ /**
532
+ * Pidgeon Firewall: does this message try to steer the agent reading it — hidden text, instructions addressed to an AI, impersonated chat turns, look-alike senders, requests to send secrets out. Null on outbound mail. Read it before acting on what the message asks.
533
+ */
534
+ firewall: {
535
+ /**
536
+ * `suspicious` when any signal fired. Observe-only: nothing is held or changed.
537
+ */
538
+ verdict: 'clean' | 'suspicious';
539
+ /**
540
+ * The rules that fired, most specific first. Empty when the verdict is `clean`.
541
+ */
542
+ signals: Array<{
543
+ kind: 'hidden_text' | 'invisible_characters' | 'assistant_directive' | 'role_spoof' | 'quoted_directive' | 'lookalike_sender' | 'display_name_spoof' | 'unauthenticated_with_directive' | 'exfiltration_request';
544
+ /**
545
+ * What was found, with a short quote of it.
546
+ */
547
+ detail: string;
548
+ where: 'subject' | 'text' | 'html' | 'from' | 'quoted';
549
+ }>;
550
+ /**
551
+ * What an agent should read: the new text with hidden content and invisible characters removed and lines posing as a chat turn marked, under a one-line note saying what changed. The new text unchanged when nothing needed it. Ask for `body=clean` to get it in place of the body.
552
+ */
553
+ clean_text: string;
554
+ /**
555
+ * Bumped when the rules change in a way that could change a verdict.
556
+ */
557
+ version: number;
558
+ } | null;
531
559
  /**
532
560
  * Verification codes and links found in the message, most likely first — read from the new text, never the quoted history. Empty lists when nothing was found.
533
561
  */
@@ -681,6 +709,34 @@ type AwaitedMessage = {
681
709
  * The event the calendar made of that invitation, or null. A different fact from `invitation`: that is what the mail said, this is what the calendar now holds — a meeting later moved still reports the time this message invited you to.
682
710
  */
683
711
  calendar_event_id: string | null;
712
+ /**
713
+ * Pidgeon Firewall: does this message try to steer the agent reading it — hidden text, instructions addressed to an AI, impersonated chat turns, look-alike senders, requests to send secrets out. Null on outbound mail. Read it before acting on what the message asks.
714
+ */
715
+ firewall: {
716
+ /**
717
+ * `suspicious` when any signal fired. Observe-only: nothing is held or changed.
718
+ */
719
+ verdict: 'clean' | 'suspicious';
720
+ /**
721
+ * The rules that fired, most specific first. Empty when the verdict is `clean`.
722
+ */
723
+ signals: Array<{
724
+ kind: 'hidden_text' | 'invisible_characters' | 'assistant_directive' | 'role_spoof' | 'quoted_directive' | 'lookalike_sender' | 'display_name_spoof' | 'unauthenticated_with_directive' | 'exfiltration_request';
725
+ /**
726
+ * What was found, with a short quote of it.
727
+ */
728
+ detail: string;
729
+ where: 'subject' | 'text' | 'html' | 'from' | 'quoted';
730
+ }>;
731
+ /**
732
+ * What an agent should read: the new text with hidden content and invisible characters removed and lines posing as a chat turn marked, under a one-line note saying what changed. The new text unchanged when nothing needed it. Ask for `body=clean` to get it in place of the body.
733
+ */
734
+ clean_text: string;
735
+ /**
736
+ * Bumped when the rules change in a way that could change a verdict.
737
+ */
738
+ version: number;
739
+ } | null;
684
740
  /**
685
741
  * Verification codes and links found in the message, most likely first — read from the new text, never the quoted history. Empty lists when nothing was found.
686
742
  */
@@ -2878,6 +2934,7 @@ type MessagesAwaitData = {
2878
2934
  path?: never;
2879
2935
  query: {
2880
2936
  identity_id: string;
2937
+ body?: 'original' | 'clean';
2881
2938
  from?: string;
2882
2939
  subject_contains?: string;
2883
2940
  has_code?: 'true' | 'false';
@@ -2915,7 +2972,9 @@ type MessagesGetData = {
2915
2972
  path: {
2916
2973
  id: string;
2917
2974
  };
2918
- query?: never;
2975
+ query?: {
2976
+ body?: 'original' | 'clean';
2977
+ };
2919
2978
  url: '/messages/{id}';
2920
2979
  };
2921
2980
  type MessagesGetErrors = {
package/dist/index.d.ts CHANGED
@@ -528,6 +528,34 @@ type Message = {
528
528
  * The event the calendar made of that invitation, or null. A different fact from `invitation`: that is what the mail said, this is what the calendar now holds — a meeting later moved still reports the time this message invited you to.
529
529
  */
530
530
  calendar_event_id: string | null;
531
+ /**
532
+ * Pidgeon Firewall: does this message try to steer the agent reading it — hidden text, instructions addressed to an AI, impersonated chat turns, look-alike senders, requests to send secrets out. Null on outbound mail. Read it before acting on what the message asks.
533
+ */
534
+ firewall: {
535
+ /**
536
+ * `suspicious` when any signal fired. Observe-only: nothing is held or changed.
537
+ */
538
+ verdict: 'clean' | 'suspicious';
539
+ /**
540
+ * The rules that fired, most specific first. Empty when the verdict is `clean`.
541
+ */
542
+ signals: Array<{
543
+ kind: 'hidden_text' | 'invisible_characters' | 'assistant_directive' | 'role_spoof' | 'quoted_directive' | 'lookalike_sender' | 'display_name_spoof' | 'unauthenticated_with_directive' | 'exfiltration_request';
544
+ /**
545
+ * What was found, with a short quote of it.
546
+ */
547
+ detail: string;
548
+ where: 'subject' | 'text' | 'html' | 'from' | 'quoted';
549
+ }>;
550
+ /**
551
+ * What an agent should read: the new text with hidden content and invisible characters removed and lines posing as a chat turn marked, under a one-line note saying what changed. The new text unchanged when nothing needed it. Ask for `body=clean` to get it in place of the body.
552
+ */
553
+ clean_text: string;
554
+ /**
555
+ * Bumped when the rules change in a way that could change a verdict.
556
+ */
557
+ version: number;
558
+ } | null;
531
559
  /**
532
560
  * Verification codes and links found in the message, most likely first — read from the new text, never the quoted history. Empty lists when nothing was found.
533
561
  */
@@ -681,6 +709,34 @@ type AwaitedMessage = {
681
709
  * The event the calendar made of that invitation, or null. A different fact from `invitation`: that is what the mail said, this is what the calendar now holds — a meeting later moved still reports the time this message invited you to.
682
710
  */
683
711
  calendar_event_id: string | null;
712
+ /**
713
+ * Pidgeon Firewall: does this message try to steer the agent reading it — hidden text, instructions addressed to an AI, impersonated chat turns, look-alike senders, requests to send secrets out. Null on outbound mail. Read it before acting on what the message asks.
714
+ */
715
+ firewall: {
716
+ /**
717
+ * `suspicious` when any signal fired. Observe-only: nothing is held or changed.
718
+ */
719
+ verdict: 'clean' | 'suspicious';
720
+ /**
721
+ * The rules that fired, most specific first. Empty when the verdict is `clean`.
722
+ */
723
+ signals: Array<{
724
+ kind: 'hidden_text' | 'invisible_characters' | 'assistant_directive' | 'role_spoof' | 'quoted_directive' | 'lookalike_sender' | 'display_name_spoof' | 'unauthenticated_with_directive' | 'exfiltration_request';
725
+ /**
726
+ * What was found, with a short quote of it.
727
+ */
728
+ detail: string;
729
+ where: 'subject' | 'text' | 'html' | 'from' | 'quoted';
730
+ }>;
731
+ /**
732
+ * What an agent should read: the new text with hidden content and invisible characters removed and lines posing as a chat turn marked, under a one-line note saying what changed. The new text unchanged when nothing needed it. Ask for `body=clean` to get it in place of the body.
733
+ */
734
+ clean_text: string;
735
+ /**
736
+ * Bumped when the rules change in a way that could change a verdict.
737
+ */
738
+ version: number;
739
+ } | null;
684
740
  /**
685
741
  * Verification codes and links found in the message, most likely first — read from the new text, never the quoted history. Empty lists when nothing was found.
686
742
  */
@@ -2878,6 +2934,7 @@ type MessagesAwaitData = {
2878
2934
  path?: never;
2879
2935
  query: {
2880
2936
  identity_id: string;
2937
+ body?: 'original' | 'clean';
2881
2938
  from?: string;
2882
2939
  subject_contains?: string;
2883
2940
  has_code?: 'true' | 'false';
@@ -2915,7 +2972,9 @@ type MessagesGetData = {
2915
2972
  path: {
2916
2973
  id: string;
2917
2974
  };
2918
- query?: never;
2975
+ query?: {
2976
+ body?: 'original' | 'clean';
2977
+ };
2919
2978
  url: '/messages/{id}';
2920
2979
  };
2921
2980
  type MessagesGetErrors = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pidgeon-ai/sdk",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "description": "Thin TypeScript client for the Pidgeon email API.",
5
5
  "keywords": [
6
6
  "pidgeon",