@extrovert.dev/sdk 0.1.0-pre.6 → 0.1.0-pre.7
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/README.md +151 -65
- package/dist/index.cjs +493 -114
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +521 -277
- package/dist/index.d.ts +521 -277
- package/dist/index.js +493 -115
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* on 429/5xx, honors `Retry-After`, and surfaces every failure as a typed {@link ApiError}.
|
|
7
7
|
*/
|
|
8
8
|
/** The library version, surfaced in the User-Agent. Kept in sync with package.json by build. */
|
|
9
|
-
declare const SDK_VERSION = "0.1.0-pre.
|
|
9
|
+
declare const SDK_VERSION = "0.1.0-pre.7";
|
|
10
10
|
interface RetryOptions {
|
|
11
11
|
/** Max retry attempts for idempotent requests on 429/5xx/network errors. Default 2. */
|
|
12
12
|
maxRetries: number;
|
|
@@ -33,7 +33,7 @@ type ReviewInclude = "category" | "turns";
|
|
|
33
33
|
declare function serializeInclude(include?: readonly string[]): string | undefined;
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* Extrovert API
|
|
36
|
+
* Extrovert API: typed request/response models.
|
|
37
37
|
*
|
|
38
38
|
* These mirror the Extrovert V1 REST contract (`/v1`, §8 of the build spec). The Go API does not
|
|
39
39
|
* exist yet; field shapes here are the source of truth the client codes against and are validated
|
|
@@ -52,13 +52,13 @@ type IsoTimestamp = string;
|
|
|
52
52
|
* its caveats but cannot exceed them (§5).
|
|
53
53
|
*
|
|
54
54
|
* The `mailbox:*` scope strings are the live wire contract (stored in issued keys'
|
|
55
|
-
* caveats) and are NOT renamed despite the public "inbox" product naming
|
|
56
|
-
* them would invalidate every key already
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* the BYO reviewer decision plane.
|
|
55
|
+
* caveats) and are NOT renamed despite the public "inbox" product naming: renaming
|
|
56
|
+
* them would invalidate every key already issued. `domain:manage` gates onboarding
|
|
57
|
+
* for domains the customer already controls. `commerce:request` permits quotes,
|
|
58
|
+
* requests, and status reads, but never a human approval transition or direct spend.
|
|
59
|
+
* `review:act` gates the BYO reviewer decision plane.
|
|
60
60
|
*/
|
|
61
|
-
type Scope = "mailbox:create" | "mailbox:read" | "mailbox:send" | "mailbox:quota" | "mailbox:credentials" | "mailbox:delete" | "webhook:write" | "domain:manage" | "domain:purchase" | "review:act" | "signup:verify";
|
|
61
|
+
type Scope = "mailbox:create" | "mailbox:read" | "mailbox:send" | "mailbox:quota" | "mailbox:credentials" | "mailbox:delete" | "webhook:write" | "domain:manage" | "domain:read" | "domain:purchase" | "commerce:request" | "review:act" | "signup:verify";
|
|
62
62
|
/** How a Extrovert domain was onboarded (§7). */
|
|
63
63
|
type OnboardingMode = "shared" | "purchased" | "ns_delegated" | "manual";
|
|
64
64
|
/** Lifecycle status of an agent principal. */
|
|
@@ -68,35 +68,35 @@ type InboxStatus = "provisioning" | "live" | "disabled" | "deleted";
|
|
|
68
68
|
/** Direction of a message relative to the inbox that owns it. */
|
|
69
69
|
type MessageDirection = "inbound" | "outbound";
|
|
70
70
|
/**
|
|
71
|
-
* Request body for `POST /v1/enroll`. An agent redeems a `pk_enroll_...` token to
|
|
71
|
+
* Request body for `POST /v1/enroll`. An agent redeems a `pk_enroll_...` token to issue a scoped
|
|
72
72
|
* agent key. Idempotent on `agent_handle` (à la AgentMail's `client_id`).
|
|
73
73
|
*/
|
|
74
74
|
interface EnrollRequest {
|
|
75
75
|
/**
|
|
76
76
|
* The raw enrollment token, format `pk_enroll_<id>_<secret>`. Shown once at issue
|
|
77
|
-
* time. REQUIRED
|
|
77
|
+
* time. REQUIRED: this is the wire field the server reads (`json:"token"`); the
|
|
78
78
|
* request is serialized verbatim, so the field name must match the contract.
|
|
79
79
|
*/
|
|
80
80
|
token: string;
|
|
81
81
|
/**
|
|
82
82
|
* Stable client-chosen handle for this agent. Redeeming twice with the same handle returns the
|
|
83
|
-
* same agent rather than
|
|
83
|
+
* same agent rather than creating a new one.
|
|
84
84
|
*/
|
|
85
85
|
agent_handle: string;
|
|
86
|
-
/** Optional human-readable label for the
|
|
86
|
+
/** Optional human-readable label for the created agent. */
|
|
87
87
|
agent_name?: string;
|
|
88
88
|
/**
|
|
89
89
|
* Optional idempotency key (sent as the `Idempotency-Key` header). A retry with
|
|
90
|
-
* the same key replays the original enrollment response instead of
|
|
90
|
+
* the same key replays the original enrollment response instead of reissuing.
|
|
91
91
|
*/
|
|
92
92
|
client_id?: string;
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
95
|
* Response from `POST /v1/enroll`. The `agent_key` is the short-lived, per-agent scoped key the
|
|
96
|
-
* agent uses for all subsequent calls
|
|
96
|
+
* agent uses for all subsequent calls: never an org-wide key (§5, §14).
|
|
97
97
|
*/
|
|
98
98
|
interface EnrollResponse {
|
|
99
|
-
/** The
|
|
99
|
+
/** The created agent principal id, e.g. `agt_7Hq2...`. */
|
|
100
100
|
agent_id: string;
|
|
101
101
|
/**
|
|
102
102
|
* The scoped agent key, format `pk_agent_<id>_<secret>`. Returned once. Treat as a secret and
|
|
@@ -106,13 +106,13 @@ interface EnrollResponse {
|
|
|
106
106
|
/** Scopes granted to this key (a subset of the enrollment token's scopes). */
|
|
107
107
|
scopes: Scope[];
|
|
108
108
|
/**
|
|
109
|
-
* The fixed org the
|
|
109
|
+
* The fixed org the issued key is bound to (the token's resolved org). The agent
|
|
110
110
|
* cannot change it; it is the canonical org for every subsequent call.
|
|
111
111
|
*/
|
|
112
112
|
org_id?: string;
|
|
113
113
|
/**
|
|
114
|
-
* The fixed project the
|
|
115
|
-
* agent cannot change it
|
|
114
|
+
* The fixed project the issued key is bound to (the token's resolved project). The
|
|
115
|
+
* agent cannot change it: there is no mutable project selector for a scoped key.
|
|
116
116
|
*/
|
|
117
117
|
project_id?: string;
|
|
118
118
|
}
|
|
@@ -128,7 +128,7 @@ interface Agent {
|
|
|
128
128
|
/**
|
|
129
129
|
* One arbitrary metadata value stored on an inbox. The wire allows string, number,
|
|
130
130
|
* or boolean (nested objects and arrays are rejected). In a PATCH (update) body a
|
|
131
|
-
* value of `null` for a key DELETES that key (the merge/null-delete semantics
|
|
131
|
+
* value of `null` for a key DELETES that key (the merge/null-delete semantics :
|
|
132
132
|
* see {@link UpdateInboxRequest.metadata}); a read shape ({@link Inbox.metadata})
|
|
133
133
|
* never contains `null`.
|
|
134
134
|
*/
|
|
@@ -146,25 +146,28 @@ type InboxMetadata = Record<string, InboxMetadataValue>;
|
|
|
146
146
|
*/
|
|
147
147
|
type InboxMetadataPatch = Record<string, InboxMetadataValue | null>;
|
|
148
148
|
/**
|
|
149
|
-
* Request body for `POST /v1/inboxes`. All fields optional
|
|
150
|
-
*
|
|
149
|
+
* Request body for `POST /v1/inboxes`. All fields are optional. The default path
|
|
150
|
+
* creates an address on the account's platform shared domain.
|
|
151
151
|
*/
|
|
152
152
|
interface CreateInboxRequest {
|
|
153
153
|
/**
|
|
154
|
-
* Desired local part (before the `@`).
|
|
155
|
-
*
|
|
154
|
+
* Desired local part (before the `@`). Shared-domain names are normalized,
|
|
155
|
+
* must be at least 5 characters, and cannot use reserved names. If omitted,
|
|
156
|
+
* the server generates a random handle.
|
|
157
|
+
* Example: `agent7` -> `agent7@extrovertmail.com` for paid accounts or
|
|
158
|
+
* `agent7@free.extrovertmail.com` for free accounts.
|
|
156
159
|
*/
|
|
157
160
|
username?: string;
|
|
158
161
|
/**
|
|
159
|
-
* Domain to
|
|
160
|
-
* shared
|
|
162
|
+
* Domain to create the inbox on. Must be an org domain the calling key is
|
|
163
|
+
* scoped to. If omitted, the account's shared domain is used.
|
|
161
164
|
*/
|
|
162
165
|
domain?: string;
|
|
163
166
|
/** Human-readable display name used in the `From:` header on sends. */
|
|
164
167
|
display_name?: string;
|
|
165
168
|
/**
|
|
166
169
|
* Idempotency handle. Re-creating with the same `client_id` returns the existing inbox rather
|
|
167
|
-
* than
|
|
170
|
+
* than creating a duplicate.
|
|
168
171
|
*/
|
|
169
172
|
client_id?: string;
|
|
170
173
|
/**
|
|
@@ -181,14 +184,14 @@ interface CreateInboxRequest {
|
|
|
181
184
|
*/
|
|
182
185
|
metadata?: InboxMetadata;
|
|
183
186
|
/**
|
|
184
|
-
* Optional assertion that must match the key's bound project
|
|
187
|
+
* Optional assertion that must match the key's bound project: NEVER a selector.
|
|
185
188
|
* A mismatch is a 403. The inbox is always created in the key's stored project;
|
|
186
189
|
* the assertion only lets a caller defend against a misrouted key.
|
|
187
190
|
*/
|
|
188
191
|
project_id?: string;
|
|
189
192
|
/**
|
|
190
|
-
* Whether to return
|
|
191
|
-
*
|
|
193
|
+
* Whether to return paid-inbox credentials (IMAP/SMTP password) in the response.
|
|
194
|
+
* Requires the `mailbox:credentials` permission and defaults to false.
|
|
192
195
|
*/
|
|
193
196
|
return_credentials?: boolean;
|
|
194
197
|
}
|
|
@@ -223,15 +226,17 @@ interface UpdateInboxRequest {
|
|
|
223
226
|
*/
|
|
224
227
|
metadata?: InboxMetadataPatch | null;
|
|
225
228
|
/**
|
|
226
|
-
* Optional assertion that must match the key's bound project
|
|
229
|
+
* Optional assertion that must match the key's bound project: NEVER a selector.
|
|
227
230
|
* A mismatch is a 403.
|
|
228
231
|
*/
|
|
229
232
|
project_id?: string;
|
|
230
233
|
}
|
|
231
234
|
/**
|
|
232
|
-
* IMAP/SMTP connection config + login for
|
|
235
|
+
* IMAP/SMTP connection config + login for a paid inbox. Export requires the
|
|
236
|
+
* `mailbox:credentials` permission. On create it is present only when
|
|
233
237
|
* `return_credentials` was requested. (The IMAP/SMTP host/port/password are mail
|
|
234
|
-
* protocol internals
|
|
238
|
+
* protocol internals. Exported credentials do not mean direct SMTP is enabled.
|
|
239
|
+
* Check `direct_smtp_enabled` on the inbox before attempting an SMTP send.)
|
|
235
240
|
*/
|
|
236
241
|
interface InboxCredentials {
|
|
237
242
|
imap_host: string;
|
|
@@ -239,7 +244,7 @@ interface InboxCredentials {
|
|
|
239
244
|
smtp_host: string;
|
|
240
245
|
smtp_port: number;
|
|
241
246
|
username: string;
|
|
242
|
-
/** Plaintext password
|
|
247
|
+
/** Plaintext mailbox password. Credential reads can return it again. Treat every response as a secret. */
|
|
243
248
|
password: string;
|
|
244
249
|
}
|
|
245
250
|
/** A provisioned inbox (read shape). */
|
|
@@ -252,7 +257,7 @@ interface Inbox {
|
|
|
252
257
|
object?: "inbox";
|
|
253
258
|
/**
|
|
254
259
|
* The canonical OPAQUE inbox id and path key (`/v1/inboxes/{inbox_id}` /
|
|
255
|
-
* `/v1/projects/{project_id}/inboxes/{inbox_id}`). Treat it as opaque
|
|
260
|
+
* `/v1/projects/{project_id}/inboxes/{inbox_id}`). Treat it as opaque: do not parse
|
|
256
261
|
* the `pmbx_` prefix.
|
|
257
262
|
*/
|
|
258
263
|
id: string;
|
|
@@ -261,11 +266,11 @@ interface Inbox {
|
|
|
261
266
|
*/
|
|
262
267
|
org_id?: string;
|
|
263
268
|
/**
|
|
264
|
-
* The project this inbox belongs to (RFC D9)
|
|
269
|
+
* The project this inbox belongs to (RFC D9): the partition key. Optional for
|
|
265
270
|
* legacy/mock shapes.
|
|
266
271
|
*/
|
|
267
272
|
project_id?: string;
|
|
268
|
-
/** Full address, e.g. `agent7@
|
|
273
|
+
/** Full address, e.g. `agent7@extrovertmail.com`. A within-project email alias for {@link Inbox.id}. */
|
|
269
274
|
address: string;
|
|
270
275
|
username: string;
|
|
271
276
|
domain: string;
|
|
@@ -273,10 +278,17 @@ interface Inbox {
|
|
|
273
278
|
status: InboxStatus;
|
|
274
279
|
/** Onboarding mode of the domain this inbox lives on. */
|
|
275
280
|
onboarding_mode: OnboardingMode;
|
|
276
|
-
/** Agent that owns this inbox, if
|
|
281
|
+
/** Agent that owns this inbox, if created by an agent key. */
|
|
277
282
|
agent_id: string | null;
|
|
278
283
|
/** Effective enforced rolling-24-hour recipient cap for this inbox. */
|
|
279
284
|
daily_send_limit: number;
|
|
285
|
+
/**
|
|
286
|
+
* Whether raw protocol SMTP is currently allowed. It defaults to false, is
|
|
287
|
+
* controlled by a human per inbox, and is effective only while the inbox has a
|
|
288
|
+
* paid entitlement. Exported credentials do not imply this is true. API, SDK,
|
|
289
|
+
* and MCP sends remain governed by the Review Loop regardless of this value.
|
|
290
|
+
*/
|
|
291
|
+
direct_smtp_enabled: boolean;
|
|
280
292
|
/**
|
|
281
293
|
* Inbound webhook registered for this inbox, if any. The wire field is
|
|
282
294
|
* `webhook_url` (the server returns `webhook_url`, never `inbound_webhook_url`);
|
|
@@ -285,7 +297,7 @@ interface Inbox {
|
|
|
285
297
|
webhook_url?: string | null;
|
|
286
298
|
/**
|
|
287
299
|
* Arbitrary key-value metadata stored on the inbox (AgentMail parity). Always an
|
|
288
|
-
* object
|
|
300
|
+
* object: `{}` when none is set, never null. Values are string, number, or
|
|
289
301
|
* boolean. Project-scoped: an agent key only reads/mutates metadata for inboxes in
|
|
290
302
|
* its bound project.
|
|
291
303
|
*/
|
|
@@ -375,7 +387,7 @@ interface AttachmentInput {
|
|
|
375
387
|
* A stored message in an inbox (read shape). Mirrors the canonical Go wire shape
|
|
376
388
|
* (`messageResponse`): `id` is the opaque, inbox-resolvable id; `inbox` is the
|
|
377
389
|
* owning address; `seen` is the native IMAP \Seen read state (Extrovert has no
|
|
378
|
-
* Gmail-style labels
|
|
390
|
+
* Gmail-style labels: read/unread is the \Seen flag); `folder` is the IMAP
|
|
379
391
|
* mailbox; `date` is the raw `Date` header.
|
|
380
392
|
*/
|
|
381
393
|
interface Message {
|
|
@@ -387,6 +399,8 @@ interface Message {
|
|
|
387
399
|
from: EmailAddress;
|
|
388
400
|
to: EmailAddress[];
|
|
389
401
|
cc?: EmailAddress[];
|
|
402
|
+
/** Reply-To addresses parsed from the source message. */
|
|
403
|
+
reply_to?: EmailAddress[];
|
|
390
404
|
subject: string;
|
|
391
405
|
/** Decoded text/plain MIME alternative; null when absent and never derived from HTML. */
|
|
392
406
|
text: string | null;
|
|
@@ -398,6 +412,10 @@ interface Message {
|
|
|
398
412
|
extracted_html?: string | null;
|
|
399
413
|
/** RFC 5322 `Message-ID` header value. */
|
|
400
414
|
message_id: string;
|
|
415
|
+
/** Source RFC 5322 parent Message-ID, when present. */
|
|
416
|
+
in_reply_to?: string;
|
|
417
|
+
/** Source RFC 5322 References chain, when present. */
|
|
418
|
+
references?: string;
|
|
401
419
|
/** IMAP folder the message lives in (e.g. `INBOX`, `Junk`). */
|
|
402
420
|
folder?: string;
|
|
403
421
|
/** Whether the message has been read (native IMAP \Seen flag). */
|
|
@@ -433,7 +451,7 @@ interface SearchMessagesParams {
|
|
|
433
451
|
offset?: number;
|
|
434
452
|
cursor?: string;
|
|
435
453
|
}
|
|
436
|
-
/** Request body for `PATCH /v1/inboxes/{addr}/messages/{id}
|
|
454
|
+
/** Request body for `PATCH /v1/inboxes/{addr}/messages/{id}`: read-state toggle. */
|
|
437
455
|
interface MarkReadRequest {
|
|
438
456
|
/** true to set the \Seen flag (read), false to clear it (unread). */
|
|
439
457
|
read: boolean;
|
|
@@ -490,7 +508,7 @@ interface SendRequest {
|
|
|
490
508
|
/** Override the `Reply-To` header. */
|
|
491
509
|
reply_to?: string;
|
|
492
510
|
/**
|
|
493
|
-
* Idempotency key
|
|
511
|
+
* Idempotency key: a replay with the same key returns the first response
|
|
494
512
|
* instead of sending a second message.
|
|
495
513
|
*
|
|
496
514
|
* Sent as the `Idempotency-Key` HEADER and STRIPPED from the JSON body: the
|
|
@@ -527,7 +545,7 @@ interface SendRequest {
|
|
|
527
545
|
* Request body for the canonical thread-aware reply,
|
|
528
546
|
* `POST /v1/inboxes/{addr}/reply`. Exactly one of `thread_id` / `message_id`
|
|
529
547
|
* selects the parent; the server derives `to` (original participants), the
|
|
530
|
-
* `Re:`-prefixed subject, and the `In-Reply-To` / `References` headers
|
|
548
|
+
* `Re:`-prefixed subject, and the `In-Reply-To` / `References` headers: you do
|
|
531
549
|
* NOT pass `to`. Set `reply_all` to reply to every thread recipient.
|
|
532
550
|
*/
|
|
533
551
|
interface ReplyRequest {
|
|
@@ -535,6 +553,12 @@ interface ReplyRequest {
|
|
|
535
553
|
thread_id?: string;
|
|
536
554
|
/** Reply to this specific message. One of thread_id / message_id. */
|
|
537
555
|
message_id?: string;
|
|
556
|
+
/**
|
|
557
|
+
* Optional optimistic stale-context guard for a thread reply. Use the
|
|
558
|
+
* `last_message_id` from the thread you read; a 409 means the thread advanced.
|
|
559
|
+
* This detects stale context at submission, but is not an atomic send lock.
|
|
560
|
+
*/
|
|
561
|
+
expected_last_message_id?: string;
|
|
538
562
|
/** At least one of `text` / `html` is required. */
|
|
539
563
|
text?: string;
|
|
540
564
|
html?: string;
|
|
@@ -544,7 +568,7 @@ interface ReplyRequest {
|
|
|
544
568
|
reply_to?: string;
|
|
545
569
|
/** Reply to all thread recipients, not just the original sender. */
|
|
546
570
|
reply_all?: boolean;
|
|
547
|
-
/** See {@link SendRequest.idempotency_key}
|
|
571
|
+
/** See {@link SendRequest.idempotency_key}: sent as a header, never in the body. */
|
|
548
572
|
idempotency_key?: string;
|
|
549
573
|
headers?: Record<string, string>;
|
|
550
574
|
/** Files to attach (base64). Emitted as a multipart/mixed message. */
|
|
@@ -566,7 +590,7 @@ interface ReplyRequest {
|
|
|
566
590
|
* A forward is governed by the SAME review policy as a send, and for a stronger
|
|
567
591
|
* reason: it is an outbound message to arbitrary NEW recipients that quotes an
|
|
568
592
|
* entire inbound thread. Leaving it outside the policy would have made forward
|
|
569
|
-
* the documented bypass
|
|
593
|
+
* the documented bypass: and a worse one than a bare send, because it
|
|
570
594
|
* exfiltrates a received conversation.
|
|
571
595
|
*/
|
|
572
596
|
interface ForwardRequest {
|
|
@@ -593,7 +617,7 @@ interface ForwardRequest {
|
|
|
593
617
|
/** Agent-supplied confidence (0..1); see {@link SendRequest.category_confidence}. */
|
|
594
618
|
category_confidence?: number;
|
|
595
619
|
composition_token?: string;
|
|
596
|
-
/** See {@link SendRequest.idempotency_key}
|
|
620
|
+
/** See {@link SendRequest.idempotency_key}: sent as a header, never in the body. */
|
|
597
621
|
idempotency_key?: string;
|
|
598
622
|
}
|
|
599
623
|
/**
|
|
@@ -603,8 +627,8 @@ interface ForwardRequest {
|
|
|
603
627
|
* Its shape differs per verb, which is why almost every field is optional and
|
|
604
628
|
* this type is NOT the whole story (see {@link SendOutcome}):
|
|
605
629
|
*
|
|
606
|
-
* - `send` → `{status:"sent", message_id, review_id}
|
|
607
|
-
* - `reply`/`forward` → `{message_id, thread_id, review_id}
|
|
630
|
+
* - `send` → `{status:"sent", message_id, review_id}`: **no `thread_id`**.
|
|
631
|
+
* - `reply`/`forward` → `{message_id, thread_id, review_id}`: no `status`.
|
|
608
632
|
*
|
|
609
633
|
* `thread_id` was declared REQUIRED here for a long time while the send path
|
|
610
634
|
* never returned one, so `res.thread_id` typechecked and was `undefined` at
|
|
@@ -619,7 +643,7 @@ interface SendResult {
|
|
|
619
643
|
kind?: undefined;
|
|
620
644
|
/** Extrovert message id of the sent outbound message. */
|
|
621
645
|
message_id: string;
|
|
622
|
-
/** Thread id
|
|
646
|
+
/** Thread id: present on reply/forward; ABSENT on the direct-send response. */
|
|
623
647
|
thread_id?: string;
|
|
624
648
|
/**
|
|
625
649
|
* Opaque review id (rr_…) of the review row that governed this send. Every
|
|
@@ -637,16 +661,16 @@ interface SendResult {
|
|
|
637
661
|
* Every shape `inbox.send()` / `.reply()` / `.forward()` / `.submitForReview()`
|
|
638
662
|
* can return, discriminated by `kind`.
|
|
639
663
|
*
|
|
640
|
-
* There are three, because the resolved review policy
|
|
664
|
+
* There are three, because the resolved review policy: not the caller: decides
|
|
641
665
|
* what happens to an outbound message:
|
|
642
666
|
*
|
|
643
|
-
* - {@link QueuedForReviewResult} (`kind:"queued_for_review"`, 202)
|
|
667
|
+
* - {@link QueuedForReviewResult} (`kind:"queued_for_review"`, 202): parked for
|
|
644
668
|
* a human. **Nothing has been delivered yet.** Monitor
|
|
645
669
|
* `reviewEvents.wait({review_id})` until a `sent` or `send_failed` event
|
|
646
670
|
* arrives.
|
|
647
|
-
* - {@link SentResult} (`kind:"sent"`, 200)
|
|
671
|
+
* - {@link SentResult} (`kind:"sent"`, 200): delivered immediately, returned to
|
|
648
672
|
* callers that opted into the review loop by passing mode/intent/category_id.
|
|
649
|
-
* - {@link SendResult} (no `kind`, 202)
|
|
673
|
+
* - {@link SendResult} (no `kind`, 202): the legacy immediate-send body for a
|
|
650
674
|
* caller that mentioned none of those fields.
|
|
651
675
|
*
|
|
652
676
|
* Under the default `require_review` policy a send WITHOUT an `intent` does not
|
|
@@ -658,15 +682,15 @@ type SendOutcome = SendResult | SentResult | QueuedForReviewResult;
|
|
|
658
682
|
/** Per-send agent assertion (D3/D6). The resolved policy may downgrade `direct`. */
|
|
659
683
|
type ReviewMode = "review" | "direct";
|
|
660
684
|
/**
|
|
661
|
-
* The account/inbox review policy
|
|
685
|
+
* The account/inbox review policy: the AUTHORITY on what happens to an outbound
|
|
662
686
|
* message. There is no way for a caller to opt out of it.
|
|
663
687
|
*
|
|
664
|
-
* - `require_review
|
|
688
|
+
* - `require_review`: the default for every account. A send WITHOUT an `intent`
|
|
665
689
|
* is rejected 422 `intent_required` (nothing sent, nothing queued); a send
|
|
666
690
|
* WITH one is queued for a human (202 `queued_for_review`).
|
|
667
|
-
* - `allow_direct
|
|
691
|
+
* - `allow_direct`: a bare send (no mode/intent/category_id) is delivered
|
|
668
692
|
* immediately. Supplying an intent, or `mode: "review"`, still queues it.
|
|
669
|
-
* - `auto_send_graduated
|
|
693
|
+
* - `auto_send_graduated`: a categorized message that clears the graduation
|
|
670
694
|
* gates auto-sends; everything else is queued.
|
|
671
695
|
*
|
|
672
696
|
* Read {@link Inbox.effective_review_policy} once before your first send rather
|
|
@@ -685,7 +709,7 @@ interface ReviewIntent {
|
|
|
685
709
|
urgency?: string;
|
|
686
710
|
};
|
|
687
711
|
}
|
|
688
|
-
/** A review request (rr_…)
|
|
712
|
+
/** A review request (rr_…): the pre-send record under the Review Loop. */
|
|
689
713
|
interface Review {
|
|
690
714
|
id: string;
|
|
691
715
|
state: ReviewState;
|
|
@@ -718,8 +742,8 @@ interface Review {
|
|
|
718
742
|
* `failed`**.
|
|
719
743
|
*
|
|
720
744
|
* `failed` is included deliberately even though it is not in the formal
|
|
721
|
-
* terminal set: nothing in the product can move a failed review
|
|
722
|
-
* cannot re-approve it
|
|
745
|
+
* terminal set: nothing in the product can move a failed review: the console
|
|
746
|
+
* cannot re-approve it: so a flag that said `false` there would invite an
|
|
723
747
|
* agent to wait forever on a row nobody will ever touch.
|
|
724
748
|
*
|
|
725
749
|
* An agent that lost its event cursor (a crash, a fresh process) reads this
|
|
@@ -733,7 +757,7 @@ interface Review {
|
|
|
733
757
|
send_error?: string;
|
|
734
758
|
/**
|
|
735
759
|
* How the message was released, once sent: `human_reviewed`,
|
|
736
|
-
* `reviewer_approved`, `graduated_auto` or `agent_direct
|
|
760
|
+
* `reviewer_approved`, `graduated_auto` or `agent_direct`: without a turns
|
|
737
761
|
* fetch.
|
|
738
762
|
*/
|
|
739
763
|
send_path?: string;
|
|
@@ -775,7 +799,7 @@ interface ReviewFeedbackComment {
|
|
|
775
799
|
* The human's assembled feedback for a review (spec §11), returned by
|
|
776
800
|
* `reviews.feedback(id)`: the unified + structured diff of the human edit, the human
|
|
777
801
|
* comments / rejection feedback, the decision, and the rules born from this review
|
|
778
|
-
* (rule_ ids whose source_review_id is this review). $0 LLM
|
|
802
|
+
* (rule_ ids whose source_review_id is this review). $0 LLM: pure assembly.
|
|
779
803
|
*/
|
|
780
804
|
interface ReviewFeedback {
|
|
781
805
|
review_id: string;
|
|
@@ -792,7 +816,7 @@ interface PostReviewChatRequest {
|
|
|
792
816
|
}
|
|
793
817
|
/**
|
|
794
818
|
* Body for posting a new agent draft under a parent_revision CAS (spec §5.2; M5,
|
|
795
|
-
* D17). parent_revision is the PRIMARY CAS
|
|
819
|
+
* D17). parent_revision is the PRIMARY CAS: it must equal the draft's current
|
|
796
820
|
* revision, else 409 STALE with NO mutation. version is OPTIONAL belt-and-suspenders.
|
|
797
821
|
*/
|
|
798
822
|
interface SubmitRevisionRequest {
|
|
@@ -801,7 +825,7 @@ interface SubmitRevisionRequest {
|
|
|
801
825
|
subject?: string;
|
|
802
826
|
/**
|
|
803
827
|
* The redrafted plain-text body. Canonical, matching `text` on send / reply /
|
|
804
|
-
* forward
|
|
828
|
+
* forward: the same concept should not have two names in the one flow an
|
|
805
829
|
* agent runs most.
|
|
806
830
|
*/
|
|
807
831
|
text?: string;
|
|
@@ -854,7 +878,7 @@ type ReviewEventReason =
|
|
|
854
878
|
* cancel, so compose and submit a NEW message rather than retrying this one.
|
|
855
879
|
*/
|
|
856
880
|
| "send_failed"
|
|
857
|
-
/** Withdrawn
|
|
881
|
+
/** Withdrawn: by you, by a human, or as the close-out of a failed send. */
|
|
858
882
|
| "cancelled"
|
|
859
883
|
/**
|
|
860
884
|
* You were front-run: the review reached a terminal state while you were
|
|
@@ -862,9 +886,9 @@ type ReviewEventReason =
|
|
|
862
886
|
* `cancel_review` answered 409 `terminal`. STOP retrying that review.
|
|
863
887
|
*/
|
|
864
888
|
| "front_run_next"
|
|
865
|
-
/** RESERVED
|
|
889
|
+
/** RESERVED: never emitted. Terminal success is `sent`. */
|
|
866
890
|
| "approved"
|
|
867
|
-
/** RESERVED
|
|
891
|
+
/** RESERVED: no production producer (the D13 staleness detector is unbuilt). */
|
|
868
892
|
| "staleness";
|
|
869
893
|
/**
|
|
870
894
|
* One durable review nudge (ndg_…) drained from the AUTHORITATIVE liveness queue
|
|
@@ -880,12 +904,12 @@ interface ReviewEvent {
|
|
|
880
904
|
payload?: Record<string, unknown>;
|
|
881
905
|
created_at: IsoTimestamp;
|
|
882
906
|
}
|
|
883
|
-
/** The agent's per-(agent, review) ack frontier
|
|
907
|
+
/** The agent's per-(agent, review) ack frontier: its strict-FIFO position. */
|
|
884
908
|
interface ReviewEventCursor {
|
|
885
909
|
review_id: string;
|
|
886
910
|
last_acked_seq: number;
|
|
887
911
|
}
|
|
888
|
-
/** Drain result for list/wait
|
|
912
|
+
/** Drain result for list/wait: un-acked events in FIFO seq order + cursors. */
|
|
889
913
|
interface ReviewEventsResult {
|
|
890
914
|
events: ReviewEvent[];
|
|
891
915
|
cursors?: ReviewEventCursor[];
|
|
@@ -901,7 +925,7 @@ interface ListReviewEventsParams {
|
|
|
901
925
|
* A category (cat_…) in the Review Loop registry (D9/D10). `name` + `description`
|
|
902
926
|
* are skill-style metadata the agent fuzzy-matches against; nothing keys on the
|
|
903
927
|
* name (renames never break a reference). Categories are CUSTOMER-scoped and
|
|
904
|
-
* agent-attributed
|
|
928
|
+
* agent-attributed: the deliberate cross-agent-404 exception. Opaque ids only.
|
|
905
929
|
*/
|
|
906
930
|
interface Category {
|
|
907
931
|
id: string;
|
|
@@ -930,13 +954,13 @@ interface ProposeCategoryRequest {
|
|
|
930
954
|
/** Defaults to org_shared server-side. */
|
|
931
955
|
scope?: "org_shared" | "agent_private";
|
|
932
956
|
}
|
|
933
|
-
/** Rename / re-describe a category
|
|
957
|
+
/** Rename / re-describe a category: metadata only (spec §5.5; D10). */
|
|
934
958
|
interface UpdateCategoryRequest {
|
|
935
959
|
name?: string;
|
|
936
960
|
description?: string;
|
|
937
961
|
}
|
|
938
962
|
/**
|
|
939
|
-
* The account-wide default risk dial (Review Loop, D4/D12)
|
|
963
|
+
* The account-wide default risk dial (Review Loop, D4/D12): the values a per-
|
|
940
964
|
* category null override inherits. The single user-configurable brand-risk lever.
|
|
941
965
|
*/
|
|
942
966
|
interface AccountRiskDial {
|
|
@@ -974,7 +998,7 @@ interface CategoryRiskDial {
|
|
|
974
998
|
}
|
|
975
999
|
/**
|
|
976
1000
|
* The effective risk dial (Review Loop, agent plane; D4/D12): the account default
|
|
977
|
-
* plus every category's overrides. Read-only for agents
|
|
1001
|
+
* plus every category's overrides. Read-only for agents: flipping the dial is a
|
|
978
1002
|
* console (human) action (D16).
|
|
979
1003
|
*/
|
|
980
1004
|
interface RiskDial {
|
|
@@ -1027,7 +1051,7 @@ type ReviewerAction = "approve" | "edit" | "reject" | "escalate";
|
|
|
1027
1051
|
* The REVIEWER's read-only decision surface for a review (BYO review-agent plane;
|
|
1028
1052
|
* D5/§9), returned by `reviews.decisionContext(id)`: the intent + current draft + the
|
|
1029
1053
|
* append-only thread + the two-circuit-breaker budget. `force_to_human` is true when
|
|
1030
|
-
* EITHER breaker has tripped
|
|
1054
|
+
* EITHER breaker has tripped: the reviewer's next reject would be FORCED to the human
|
|
1031
1055
|
* regardless of intent (the human is the only terminal authority, D17).
|
|
1032
1056
|
*/
|
|
1033
1057
|
interface ReviewDecisionContext {
|
|
@@ -1051,7 +1075,7 @@ interface ReviewDecisionContext {
|
|
|
1051
1075
|
/**
|
|
1052
1076
|
* Body for a reviewer decision (`reviews.decide(id, req)`; reviewer_decide, D5/§9).
|
|
1053
1077
|
* `action` is approve|edit|reject|escalate. `revision`/`version` are the optimistic CAS
|
|
1054
|
-
|
|
1078
|
+
*: a mismatch is a 409 STALE with NO mutation (the human always wins, D17). subject/
|
|
1055
1079
|
* body carry the edited content for the edit action; feedback is the reviewer's note.
|
|
1056
1080
|
*/
|
|
1057
1081
|
interface ReviewerDecisionRequest {
|
|
@@ -1068,8 +1092,8 @@ interface ReviewerDecisionRequest {
|
|
|
1068
1092
|
feedback?: string;
|
|
1069
1093
|
}
|
|
1070
1094
|
/**
|
|
1071
|
-
* The outcome of a reviewer decision (D5/§9). `kind=sent` when the platform
|
|
1072
|
-
* with the COMPOSER's creds (approve/edit
|
|
1095
|
+
* The outcome of a reviewer decision (D5/§9). `kind=sent` when the platform sent
|
|
1096
|
+
* with the COMPOSER's creds (approve/edit: the reviewer NEVER holds mailbox:send);
|
|
1073
1097
|
* `kind=sent_to_human` when the draft returned to the human queue (reject/escalate, or
|
|
1074
1098
|
* a reject FORCED to the human by a circuit breaker, with `forced_by_breaker` naming it).
|
|
1075
1099
|
*/
|
|
@@ -1085,7 +1109,7 @@ interface ReviewerDecisionResult {
|
|
|
1085
1109
|
/**
|
|
1086
1110
|
* The D19/§8 backlog-reconciliation snapshot for a category (agent-readable, $0-LLM).
|
|
1087
1111
|
* Counts the QUEUED drafts that are stale vs current-enough against the current
|
|
1088
|
-
* category rules-version + house-style version (a pure integer compare). Read-only
|
|
1112
|
+
* category rules-version + house-style version (a pure integer compare). Read-only :
|
|
1089
1113
|
* the agent READS the picture; the human / hooks TRIGGER the actual sweep.
|
|
1090
1114
|
*/
|
|
1091
1115
|
interface ScanBacklogStatus {
|
|
@@ -1108,7 +1132,7 @@ interface PacingItem {
|
|
|
1108
1132
|
state: "behind_cursor" | "in_window_fresh" | "in_window_redrafting" | "ahead";
|
|
1109
1133
|
}
|
|
1110
1134
|
/**
|
|
1111
|
-
* The demand-driven pacing snapshot for a category (agent-readable, $0-LLM
|
|
1135
|
+
* The demand-driven pacing snapshot for a category (agent-readable, $0-LLM: M7 Slice
|
|
1112
1136
|
* B/§8): the human review cursor, the effective window/ceiling/interval, the queued
|
|
1113
1137
|
* count, and each queued draft's in-window/redrafting/behind-cursor classification.
|
|
1114
1138
|
* Read-only; the cursor advances from the human's console approve/reject/edit actions.
|
|
@@ -1121,7 +1145,7 @@ interface CategoryPacingState {
|
|
|
1121
1145
|
cursor_advanced_count: number;
|
|
1122
1146
|
/** Effective freshness window (default org_settings.lookahead_window=3). */
|
|
1123
1147
|
lookahead_window: number;
|
|
1124
|
-
/** HARD per-nudge fan-out ceiling (default 10)
|
|
1148
|
+
/** HARD per-nudge fan-out ceiling (default 10): one nudge can never fan to 500. */
|
|
1125
1149
|
rework_batch_max: number;
|
|
1126
1150
|
/** Per-agent token-bucket interval that coalesces feedback storms (default 5000). */
|
|
1127
1151
|
nudge_min_interval_ms: number;
|
|
@@ -1202,11 +1226,11 @@ interface RuleSnapshot extends Page<Rule> {
|
|
|
1202
1226
|
/**
|
|
1203
1227
|
* Save / edit a writing rule (append-only by supersession; spec §5.4; D11).
|
|
1204
1228
|
*
|
|
1205
|
-
* Layering (org/project): an agent-plane save is ALWAYS project-layer
|
|
1229
|
+
* Layering (org/project): an agent-plane save is ALWAYS project-layer: the saved
|
|
1206
1230
|
* rule's `rule_layer` is `project`, bound to the calling key's project. There is no
|
|
1207
1231
|
* settable `rule_layer` here: an agent cannot create org-layer / house-style
|
|
1208
1232
|
* (`rule_layer="org"`) rules in v1; authoring org rules is a console/admin action.
|
|
1209
|
-
* (`scope: "general"` still means a house-style rule WITHIN the project layer
|
|
1233
|
+
* (`scope: "general"` still means a house-style rule WITHIN the project layer :
|
|
1210
1234
|
* `scope` is the category axis, `rule_layer` is the ownership axis.)
|
|
1211
1235
|
*/
|
|
1212
1236
|
interface SaveRuleRequest {
|
|
@@ -1229,7 +1253,7 @@ interface SaveRuleRequest {
|
|
|
1229
1253
|
/**
|
|
1230
1254
|
* D8 retro-propagation HUMAN OPT-IN (default false). When true, a NEW category rule
|
|
1231
1255
|
* that could apply to pending siblings enqueues ONE propagate_general_rule nudge
|
|
1232
|
-
* (siblings + suggested_batch) so the agent redrafts a FEW at a time
|
|
1256
|
+
* (siblings + suggested_batch) so the agent redrafts a FEW at a time: never the
|
|
1233
1257
|
* whole queue. Set only after the human said "apply to N pending?".
|
|
1234
1258
|
*/
|
|
1235
1259
|
propagate_to_pending?: boolean;
|
|
@@ -1286,7 +1310,7 @@ interface SentResult {
|
|
|
1286
1310
|
};
|
|
1287
1311
|
/**
|
|
1288
1312
|
* The review row that governed this send (ADDITIVE). Present on every send the
|
|
1289
|
-
* service routed, i.e. all of them
|
|
1313
|
+
* service routed, i.e. all of them: it is the handle that makes a post-crash
|
|
1290
1314
|
* `reviews.get(id)` possible on the direct path too.
|
|
1291
1315
|
*/
|
|
1292
1316
|
review?: {
|
|
@@ -1306,14 +1330,20 @@ interface Thread {
|
|
|
1306
1330
|
/** Owning inbox address. */
|
|
1307
1331
|
inbox_id: string;
|
|
1308
1332
|
subject: string;
|
|
1309
|
-
/**
|
|
1333
|
+
/** List/search summaries use the latest envelope; thread detail may include the full conversation set. */
|
|
1310
1334
|
participants: string[];
|
|
1311
1335
|
message_count: number;
|
|
1312
1336
|
last_message_at: IsoTimestamp;
|
|
1313
1337
|
/** Most-recent-message preview snippet. */
|
|
1314
1338
|
snippet: string;
|
|
1339
|
+
/** Whether the latest message is unread. */
|
|
1340
|
+
unread?: boolean;
|
|
1341
|
+
/** Whether the newest message has one or more attachments. */
|
|
1342
|
+
last_message_has_attachments?: boolean;
|
|
1343
|
+
/** Opaque message id for optimistic reply freshness checks. */
|
|
1344
|
+
last_message_id?: string;
|
|
1315
1345
|
}
|
|
1316
|
-
/** A thread plus its messages (oldest-first)
|
|
1346
|
+
/** A thread plus its messages (oldest-first): `GET /v1/inboxes/{addr}/threads/{id}`. */
|
|
1317
1347
|
interface ThreadDetail extends Thread {
|
|
1318
1348
|
messages: Message[];
|
|
1319
1349
|
}
|
|
@@ -1485,7 +1515,7 @@ interface SuppressionEntry {
|
|
|
1485
1515
|
/**
|
|
1486
1516
|
* The result of a pre-check (`GET /v1/suppressions?recipient=…`): whether the
|
|
1487
1517
|
* caller's OWN org suppresses the recipient, plus the matching org rows. Reflects
|
|
1488
|
-
* only the caller's org state
|
|
1518
|
+
* only the caller's org state: never a global/shared/cross-tenant opt-out.
|
|
1489
1519
|
*/
|
|
1490
1520
|
interface SuppressionPrecheck {
|
|
1491
1521
|
recipient: string;
|
|
@@ -1504,7 +1534,7 @@ interface ListSuppressionsParams {
|
|
|
1504
1534
|
/** Opaque cursor from a previous page's `next_cursor`. */
|
|
1505
1535
|
cursor?: string;
|
|
1506
1536
|
}
|
|
1507
|
-
/** One
|
|
1537
|
+
/** One nameserver record the customer must publish for delegated setup. */
|
|
1508
1538
|
interface DomainRecord {
|
|
1509
1539
|
name: string;
|
|
1510
1540
|
type: string;
|
|
@@ -1518,40 +1548,43 @@ type DomainScope = "org" | "project";
|
|
|
1518
1548
|
/**
|
|
1519
1549
|
* Request body for `POST /v1/domains`. Onboards/adds a domain for the customer.
|
|
1520
1550
|
*
|
|
1521
|
-
*
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1524
|
-
* purchased-domain plan limit, enforced before any registrar spend). `manual` and
|
|
1525
|
-
* `ns_delegated` need `domain:manage` only.
|
|
1551
|
+
* Requires the `domain:manage` scope. This request only adds a delegated inbox
|
|
1552
|
+
* domain the customer controls; it cannot register one.
|
|
1553
|
+
* New registrations use the separate commerce quote/request workflow.
|
|
1526
1554
|
*/
|
|
1527
1555
|
interface OnboardDomainRequest {
|
|
1528
1556
|
domain: string;
|
|
1529
1557
|
/**
|
|
1530
|
-
* Onboarding path. Defaults to `ns_delegated` server-side when omitted.
|
|
1531
|
-
* additionally requires the `domain:purchase` scope.
|
|
1558
|
+
* Onboarding path. Defaults to `ns_delegated` server-side when omitted.
|
|
1532
1559
|
*/
|
|
1533
|
-
mode?:
|
|
1534
|
-
/** A-record IP served at a delegated zone's apex (ns_delegated only). */
|
|
1535
|
-
mail_host_ip?: string;
|
|
1560
|
+
mode?: "ns_delegated";
|
|
1536
1561
|
/**
|
|
1537
1562
|
* Domain visibility. Defaults to `org` (org-shared, usable by every project in the
|
|
1538
1563
|
* org). `project` binds the domain to the key's OWN bound project (never
|
|
1539
|
-
* client-selected) so it is only visible/
|
|
1564
|
+
* client-selected) so it is only visible/creatable from that project. A
|
|
1540
1565
|
* legacy/unscoped key (no bound project) falls back to `org`.
|
|
1541
1566
|
*/
|
|
1542
1567
|
scope?: DomainScope;
|
|
1543
1568
|
/**
|
|
1544
|
-
* Optional assertion that must match the key's bound project
|
|
1569
|
+
* Optional assertion that must match the key's bound project: NEVER a selector.
|
|
1545
1570
|
* A mismatch is a 403. The binding is always derived from the key.
|
|
1546
1571
|
*/
|
|
1547
1572
|
project_id?: string;
|
|
1548
1573
|
}
|
|
1549
1574
|
/**
|
|
1550
1575
|
* The agent-facing view of one onboarded domain (mirrors the Go `domainResponse`).
|
|
1551
|
-
* `
|
|
1552
|
-
*
|
|
1576
|
+
* `delegation_ns` is present on get / onboard / verify for delegated domains and
|
|
1577
|
+
* empty on list reads. `records` remains for legacy response compatibility.
|
|
1553
1578
|
*/
|
|
1554
1579
|
interface Domain {
|
|
1580
|
+
/** Authoritative outcome. Absent only when talking to an older server; never infer readiness from DKIM. */
|
|
1581
|
+
readiness?: DomainReadiness;
|
|
1582
|
+
/** Customer DNS health, independent of mail provisioning readiness. */
|
|
1583
|
+
delegation?: {
|
|
1584
|
+
status: "pending" | "confirmed" | "rechecking" | "check_delayed" | "action_required";
|
|
1585
|
+
checked_at?: string;
|
|
1586
|
+
confirmed_at?: string;
|
|
1587
|
+
};
|
|
1555
1588
|
id: string;
|
|
1556
1589
|
domain: string;
|
|
1557
1590
|
mode: OnboardingMode;
|
|
@@ -1566,10 +1599,48 @@ interface Domain {
|
|
|
1566
1599
|
/** Human-facing copy for what the customer must do next. */
|
|
1567
1600
|
instruction?: string;
|
|
1568
1601
|
}
|
|
1602
|
+
interface DomainStatusEvent {
|
|
1603
|
+
id: string;
|
|
1604
|
+
type: string;
|
|
1605
|
+
domain: string;
|
|
1606
|
+
summary: string;
|
|
1607
|
+
data: {
|
|
1608
|
+
domain: string;
|
|
1609
|
+
readiness: DomainReadiness;
|
|
1610
|
+
};
|
|
1611
|
+
created_at: string;
|
|
1612
|
+
}
|
|
1613
|
+
interface DomainStatusEventPage {
|
|
1614
|
+
items: DomainStatusEvent[];
|
|
1615
|
+
next_cursor: string;
|
|
1616
|
+
has_more: boolean;
|
|
1617
|
+
poll_after_seconds: number;
|
|
1618
|
+
}
|
|
1619
|
+
interface DomainReadiness {
|
|
1620
|
+
status: "waiting_for_dns" | "checking" | "setting_up" | "ready" | "action_required" | "needs_attention";
|
|
1621
|
+
label: string;
|
|
1622
|
+
summary: string;
|
|
1623
|
+
reason: string;
|
|
1624
|
+
action_required_by: "customer" | "extrovert" | "none";
|
|
1625
|
+
next_action: "check_dns_entries" | "restore_dns" | "wait" | "create_inbox" | "use_inbox" | "ask_owner_to_create_inbox";
|
|
1626
|
+
/** Domain configuration only; creating an inbox still requires permission and available plan capacity. */
|
|
1627
|
+
ready_for_inboxes: boolean;
|
|
1628
|
+
checked_at?: IsoTimestamp;
|
|
1629
|
+
next_check_at?: IsoTimestamp;
|
|
1630
|
+
poll_after_seconds: number;
|
|
1631
|
+
/** Omitted without inbox-read permission. Counts never imply organization-wide visibility for an agent. */
|
|
1632
|
+
inboxes?: {
|
|
1633
|
+
scope: "agent" | "project" | "organization";
|
|
1634
|
+
total: number;
|
|
1635
|
+
ready: number;
|
|
1636
|
+
setting_up: number;
|
|
1637
|
+
needs_attention: number;
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1569
1640
|
/**
|
|
1570
1641
|
* Result of an ACCEPTED domain offboard (`DELETE /v1/domains/{domain}` → HTTP 202).
|
|
1571
|
-
* Teardown
|
|
1572
|
-
* the DNS zone/records and the domain row
|
|
1642
|
+
* Teardown: reaping the outbound provider senders + routing rows, then scrubbing
|
|
1643
|
+
* the DNS zone/records and the domain row: runs as an async job. Poll `status_url`
|
|
1573
1644
|
* (`GET /v1/jobs/{job_id}`, via {@link Job} / `client.getJob(job_id)`) until
|
|
1574
1645
|
* `status` is terminal (succeeded/failed/cancelled); the domain is ACCEPTED for
|
|
1575
1646
|
* offboard, not yet fully torn down when this returns.
|
|
@@ -1594,6 +1665,95 @@ interface Job {
|
|
|
1594
1665
|
updated_at: IsoTimestamp;
|
|
1595
1666
|
finished_at?: IsoTimestamp;
|
|
1596
1667
|
}
|
|
1668
|
+
/** One exact reason a commerce request cannot advance automatically. */
|
|
1669
|
+
interface CommerceBlocker {
|
|
1670
|
+
code: string;
|
|
1671
|
+
message: string;
|
|
1672
|
+
scope?: "org" | "project" | "agent" | string;
|
|
1673
|
+
limit_id?: string;
|
|
1674
|
+
used_cents?: number;
|
|
1675
|
+
reserved_cents?: number;
|
|
1676
|
+
limit_cents?: number;
|
|
1677
|
+
requested_cents?: number;
|
|
1678
|
+
used_count?: number;
|
|
1679
|
+
reserved_count?: number;
|
|
1680
|
+
limit_count?: number;
|
|
1681
|
+
reset_at?: IsoTimestamp;
|
|
1682
|
+
manage_url?: string;
|
|
1683
|
+
}
|
|
1684
|
+
/** Request body for the non-spending domain quote endpoint. */
|
|
1685
|
+
interface QuoteDomainRequest {
|
|
1686
|
+
domain: string;
|
|
1687
|
+
}
|
|
1688
|
+
/** Current, expiring domain registration quote. Quoting never purchases. */
|
|
1689
|
+
interface DomainQuote {
|
|
1690
|
+
object: "domain_quote";
|
|
1691
|
+
domain: string;
|
|
1692
|
+
available: boolean;
|
|
1693
|
+
currency: string;
|
|
1694
|
+
quote_cents: number;
|
|
1695
|
+
renewal_cents: number;
|
|
1696
|
+
premium: boolean;
|
|
1697
|
+
quote_expires_at: IsoTimestamp;
|
|
1698
|
+
required_plan?: string;
|
|
1699
|
+
required_plan_price_cents?: number;
|
|
1700
|
+
blockers: CommerceBlocker[];
|
|
1701
|
+
}
|
|
1702
|
+
type CommerceRequestKind = "domain_purchase" | "plan_change";
|
|
1703
|
+
interface RequestDomainPurchaseRequest {
|
|
1704
|
+
domain: string;
|
|
1705
|
+
/** Stable retry identity; sent as the `Idempotency-Key` header, not in the JSON body. */
|
|
1706
|
+
idempotency_key: string;
|
|
1707
|
+
scope?: DomainScope;
|
|
1708
|
+
rationale?: string;
|
|
1709
|
+
auto_renew?: boolean;
|
|
1710
|
+
}
|
|
1711
|
+
interface RequestPlanChangeRequest {
|
|
1712
|
+
target_plan: "free" | "developer" | "startup";
|
|
1713
|
+
/** Stable retry identity; sent as the `Idempotency-Key` header, not in the JSON body. */
|
|
1714
|
+
idempotency_key: string;
|
|
1715
|
+
rationale?: string;
|
|
1716
|
+
}
|
|
1717
|
+
interface ListCommerceRequestsParams {
|
|
1718
|
+
limit?: number;
|
|
1719
|
+
page?: string;
|
|
1720
|
+
}
|
|
1721
|
+
/** Durable poll shape for an agent-initiated financial request. */
|
|
1722
|
+
interface CommerceRequest {
|
|
1723
|
+
object: "commerce_request";
|
|
1724
|
+
id: string;
|
|
1725
|
+
project_id?: string;
|
|
1726
|
+
agent_id?: string;
|
|
1727
|
+
kind: CommerceRequestKind;
|
|
1728
|
+
state: string;
|
|
1729
|
+
domain?: string;
|
|
1730
|
+
domain_scope?: DomainScope;
|
|
1731
|
+
target_plan?: string;
|
|
1732
|
+
current_plan?: string;
|
|
1733
|
+
rationale?: string;
|
|
1734
|
+
currency: string;
|
|
1735
|
+
quote_cents: number;
|
|
1736
|
+
renewal_cents: number;
|
|
1737
|
+
approved_max_cents?: number;
|
|
1738
|
+
quote_expires_at?: IsoTimestamp;
|
|
1739
|
+
auto_renew: boolean;
|
|
1740
|
+
required_plan?: string;
|
|
1741
|
+
required_plan_price_cents?: number;
|
|
1742
|
+
blocker_code?: string;
|
|
1743
|
+
blockers: CommerceBlocker[];
|
|
1744
|
+
approval_url?: string;
|
|
1745
|
+
payment_action_url?: string;
|
|
1746
|
+
external_job_id?: string;
|
|
1747
|
+
effective_at?: IsoTimestamp;
|
|
1748
|
+
notification_state?: string;
|
|
1749
|
+
notification_last_error?: string;
|
|
1750
|
+
agent_next_action: string;
|
|
1751
|
+
retry_safe: boolean;
|
|
1752
|
+
poll_after_seconds: number;
|
|
1753
|
+
version: number;
|
|
1754
|
+
created_at: IsoTimestamp;
|
|
1755
|
+
updated_at: IsoTimestamp;
|
|
1756
|
+
}
|
|
1597
1757
|
/**
|
|
1598
1758
|
* One event from the SSE stream (`GET /v1/inboxes/{addr}/stream` or `GET
|
|
1599
1759
|
* /v1/events`). It is the SAME envelope a webhook delivers, so a stream consumer
|
|
@@ -1630,12 +1790,12 @@ interface StreamOptions {
|
|
|
1630
1790
|
interface SignUpRequest {
|
|
1631
1791
|
/** Human email that receives the one-time verification code. */
|
|
1632
1792
|
human_email: string;
|
|
1633
|
-
/** Desired local
|
|
1793
|
+
/** Desired local part on `free.extrovertmail.com`. It must normalize to at least 5 characters and cannot use a reserved name. */
|
|
1634
1794
|
username?: string;
|
|
1635
1795
|
}
|
|
1636
1796
|
/**
|
|
1637
1797
|
* Response from `POST /v1/agent/sign-up`. The `agent_key` is a LIMITED-scope key
|
|
1638
|
-
* (
|
|
1798
|
+
* (verification-only, with no inbox read or send permission) that expires with the emailed code. Successful verification revokes
|
|
1639
1799
|
* it and returns a replacement full-scope key. The OTP itself is never returned.
|
|
1640
1800
|
*/
|
|
1641
1801
|
interface SignUpResponse {
|
|
@@ -1645,7 +1805,7 @@ interface SignUpResponse {
|
|
|
1645
1805
|
agent_key: string;
|
|
1646
1806
|
key_prefix: string;
|
|
1647
1807
|
scopes: Scope[];
|
|
1648
|
-
/** The first inbox
|
|
1808
|
+
/** The first inbox created for the agent. */
|
|
1649
1809
|
address: string;
|
|
1650
1810
|
verified: boolean;
|
|
1651
1811
|
/** Where the verification code was sent. */
|
|
@@ -1694,14 +1854,28 @@ interface VerifyResponse {
|
|
|
1694
1854
|
org_claim_token?: string;
|
|
1695
1855
|
}
|
|
1696
1856
|
/**
|
|
1697
|
-
* Response from `GET /v1/auth/me
|
|
1857
|
+
* Response from `GET /v1/auth/me`: the verified principal behind the key.
|
|
1698
1858
|
*
|
|
1699
1859
|
* `org_id`/`project_id` are the FIXED org/project the key is bound to (resolved from
|
|
1700
1860
|
* the stored key, never client input). There is NO mutable project selector for a
|
|
1701
|
-
* scoped key
|
|
1861
|
+
* scoped key: `whoami` is the canonical project-visibility surface; project
|
|
1702
1862
|
* selection happens when the human/admin issues the enrollment token or agent key.
|
|
1703
1863
|
*/
|
|
1704
1864
|
interface WhoAmI {
|
|
1865
|
+
connection_status?: "connected";
|
|
1866
|
+
summary?: string;
|
|
1867
|
+
agent_name?: string;
|
|
1868
|
+
organization_name?: string;
|
|
1869
|
+
project_name?: string;
|
|
1870
|
+
/** Granted permissions, not a guarantee of plan capacity or review approval. */
|
|
1871
|
+
capabilities?: {
|
|
1872
|
+
read_domain_status: boolean;
|
|
1873
|
+
connect_owned_domains: boolean;
|
|
1874
|
+
create_inboxes: boolean;
|
|
1875
|
+
read_inboxes: boolean;
|
|
1876
|
+
submit_mail_for_review: boolean;
|
|
1877
|
+
request_purchases: boolean;
|
|
1878
|
+
};
|
|
1705
1879
|
customer_id: string;
|
|
1706
1880
|
/**
|
|
1707
1881
|
* The fixed org the key is bound to. Optional to match the OpenAPI contract: a
|
|
@@ -1723,7 +1897,7 @@ interface WhoAmI {
|
|
|
1723
1897
|
*
|
|
1724
1898
|
* Every redesign collection endpoint (the canonical `x.projects.inboxes.*` chain
|
|
1725
1899
|
* and beyond) returns {@link List}: `{ object: "list", data, has_more, next_cursor }`.
|
|
1726
|
-
* `next_cursor` is OPAQUE
|
|
1900
|
+
* `next_cursor` is OPAQUE - treat it as a token and pass it back verbatim as
|
|
1727
1901
|
* `?cursor` to fetch the next page. {@link ListPage} wraps a raw {@link List} with
|
|
1728
1902
|
* ergonomic iteration (`for await … of`) and a `nextPage()` cursor walker so callers
|
|
1729
1903
|
* never thread cursors by hand.
|
|
@@ -1773,7 +1947,7 @@ declare class ListPage<T> implements AsyncIterable<T> {
|
|
|
1773
1947
|
readonly object: "list";
|
|
1774
1948
|
constructor(raw: List<T>, fetcher: PageFetcher<T>);
|
|
1775
1949
|
/**
|
|
1776
|
-
* Fetch the next page. Throws if there is none
|
|
1950
|
+
* Fetch the next page. Throws if there is none - guard with {@link hasMore}.
|
|
1777
1951
|
*/
|
|
1778
1952
|
nextPage(signal?: AbortSignal): Promise<ListPage<T>>;
|
|
1779
1953
|
/**
|
|
@@ -1849,12 +2023,25 @@ interface Transport {
|
|
|
1849
2023
|
precheckSuppression(recipient: string, signal?: AbortSignal): Promise<SuppressionPrecheck>;
|
|
1850
2024
|
listSuppressions(params: ListSuppressionsParams, signal?: AbortSignal): Promise<Page<SuppressionEntry>>;
|
|
1851
2025
|
revokeSuppression(id: string, reason: string, signal?: AbortSignal): Promise<SuppressionEntry>;
|
|
1852
|
-
listDomains(signal?: AbortSignal
|
|
2026
|
+
listDomains(signal?: AbortSignal, params?: {
|
|
2027
|
+
page?: string;
|
|
2028
|
+
limit?: number;
|
|
2029
|
+
}): Promise<Page<Domain>>;
|
|
2030
|
+
listDomainEvents(domain: string, params: {
|
|
2031
|
+
after?: string;
|
|
2032
|
+
limit?: number;
|
|
2033
|
+
}, signal?: AbortSignal): Promise<DomainStatusEventPage>;
|
|
1853
2034
|
getDomain(domain: string, signal?: AbortSignal): Promise<Domain>;
|
|
1854
2035
|
onboardDomain(req: OnboardDomainRequest, signal?: AbortSignal): Promise<Domain>;
|
|
1855
2036
|
verifyDomain(domain: string, signal?: AbortSignal): Promise<Domain>;
|
|
1856
2037
|
offboardDomain(domain: string, signal?: AbortSignal): Promise<DomainOffboard>;
|
|
1857
2038
|
getJob(jobId: string, signal?: AbortSignal): Promise<Job>;
|
|
2039
|
+
quoteDomain(req: QuoteDomainRequest, signal?: AbortSignal): Promise<DomainQuote>;
|
|
2040
|
+
requestDomainPurchase(req: RequestDomainPurchaseRequest, signal?: AbortSignal): Promise<CommerceRequest>;
|
|
2041
|
+
requestPlanChange(req: RequestPlanChangeRequest, signal?: AbortSignal): Promise<CommerceRequest>;
|
|
2042
|
+
getCommerceRequest(requestId: string, signal?: AbortSignal): Promise<CommerceRequest>;
|
|
2043
|
+
cancelCommerceRequest(requestId: string, signal?: AbortSignal): Promise<CommerceRequest>;
|
|
2044
|
+
listCommerceRequests(params: ListCommerceRequestsParams, signal?: AbortSignal): Promise<Page<CommerceRequest>>;
|
|
1858
2045
|
submitForReview(address: string, req: SendRequest, signal?: AbortSignal): Promise<SendOutcome>;
|
|
1859
2046
|
submitReplyForReview(address: string, req: ReplyRequest, signal?: AbortSignal): Promise<SendOutcome>;
|
|
1860
2047
|
listReviews(params: ListReviewsParams, signal?: AbortSignal): Promise<Page<Review>>;
|
|
@@ -1903,7 +2090,7 @@ interface Transport {
|
|
|
1903
2090
|
*
|
|
1904
2091
|
* The mock honors the same request/response models as the real API and reproduces the few behaviors
|
|
1905
2092
|
* the SDK ergonomics depend on (enrollment cap, idempotency on `client_id`, wait_for_email returning
|
|
1906
|
-
* an OTP). It is intentionally simple
|
|
2093
|
+
* an OTP). It is intentionally simple - not a full server - and never reaches the network.
|
|
1907
2094
|
*/
|
|
1908
2095
|
|
|
1909
2096
|
/**
|
|
@@ -1931,7 +2118,7 @@ declare class MockBackend {
|
|
|
1931
2118
|
* Normalize an inbox ref (opaque id OR address alias) to the canonical address the
|
|
1932
2119
|
* mock keys its message/thread/contact maps on. The SDK now routes inbox ops by the
|
|
1933
2120
|
* canonical opaque `id` when it holds a full record (matching the contract's
|
|
1934
|
-
* canonical-key semantics), so the mock must resolve an id back to its address
|
|
2121
|
+
* canonical-key semantics), so the mock must resolve an id back to its address -
|
|
1935
2122
|
* both key `state.inboxes` (same object), `state.messages` keys by address only.
|
|
1936
2123
|
* Unknown refs pass through unchanged so the existing not-found paths still fire.
|
|
1937
2124
|
*/
|
|
@@ -1961,8 +2148,8 @@ declare class MockBackend {
|
|
|
1961
2148
|
forward(address: string, messageId: string, req: ForwardRequest): SendOutcome;
|
|
1962
2149
|
/**
|
|
1963
2150
|
* Submit a new message for review (mock). Rides the SAME endpoint as `send` on
|
|
1964
|
-
* the real server, so it is literally the same call here: the resolved policy
|
|
1965
|
-
* not which SDK method you picked
|
|
2151
|
+
* the real server, so it is literally the same call here: the resolved policy -
|
|
2152
|
+
* not which SDK method you picked - decides whether the message is queued
|
|
1966
2153
|
* (`kind:"queued_for_review"`) or delivered.
|
|
1967
2154
|
*/
|
|
1968
2155
|
submitForReview(address: string, req: SendRequest): SendOutcome;
|
|
@@ -1983,9 +2170,9 @@ declare class MockBackend {
|
|
|
1983
2170
|
private setReviewState;
|
|
1984
2171
|
/** Mark a review delivered on an auto-send path and emit its terminal `sent` nudge. */
|
|
1985
2172
|
private markReviewAutoSent;
|
|
1986
|
-
/** Raw delivery for a send
|
|
2173
|
+
/** Raw delivery for a send - no policy, only reachable from submitOutbound. */
|
|
1987
2174
|
private deliverSend;
|
|
1988
|
-
/** Raw delivery for a reply
|
|
2175
|
+
/** Raw delivery for a reply - no policy, only reachable from submitOutbound. */
|
|
1989
2176
|
private deliverReply;
|
|
1990
2177
|
/** Append the outbound message and shape the legacy send result. */
|
|
1991
2178
|
private deliverRaw;
|
|
@@ -2049,7 +2236,7 @@ declare class MockBackend {
|
|
|
2049
2236
|
reviewerDecide(reviewId: string, req: ReviewerDecisionRequest): ReviewerDecisionResult | undefined;
|
|
2050
2237
|
/**
|
|
2051
2238
|
* Browse the registry (mock), newest-first, excluding merged/soft-deleted. `match`
|
|
2052
|
-
* is a pure lexical filter (every token must appear in name+description)
|
|
2239
|
+
* is a pure lexical filter (every token must appear in name+description) - NO LLM,
|
|
2053
2240
|
* mirroring the server.
|
|
2054
2241
|
*/
|
|
2055
2242
|
listCategories(params?: ListCategoriesParams): Page<Category>;
|
|
@@ -2057,14 +2244,14 @@ declare class MockBackend {
|
|
|
2057
2244
|
getCategory(categoryId: string): Category | undefined;
|
|
2058
2245
|
/** Propose a category (mock): stands immediately, author_kind=agent (D9). */
|
|
2059
2246
|
proposeCategory(req: ProposeCategoryRequest): Category;
|
|
2060
|
-
/** Rename / re-describe a category (mock)
|
|
2247
|
+
/** Rename / re-describe a category (mock) - metadata only (D10). */
|
|
2061
2248
|
updateCategory(categoryId: string, req: UpdateCategoryRequest): Category | undefined;
|
|
2062
2249
|
/** The mock account-default risk dial (mirrors the server defaults). */
|
|
2063
2250
|
private accountDial;
|
|
2064
2251
|
/**
|
|
2065
2252
|
* Read the effective risk dial (mock): the account default + every category with an
|
|
2066
2253
|
* inherited (null override) effective dial. The mock category carries no overrides,
|
|
2067
|
-
* so every category inherits
|
|
2254
|
+
* so every category inherits - effective == account.
|
|
2068
2255
|
*/
|
|
2069
2256
|
getRiskDial(): RiskDial;
|
|
2070
2257
|
private nextGraduationState;
|
|
@@ -2076,19 +2263,19 @@ declare class MockBackend {
|
|
|
2076
2263
|
getGraduationStatus(categoryId: string): GraduationStatus | undefined;
|
|
2077
2264
|
/**
|
|
2078
2265
|
* Propose graduating a category (mock): returns the current gate status without
|
|
2079
|
-
* changing the category state (D16
|
|
2266
|
+
* changing the category state (D16 - an agent can never flip the bit).
|
|
2080
2267
|
*/
|
|
2081
2268
|
proposeGraduation(categoryId: string, _req: ProposeGraduationRequest): GraduationStatus | undefined;
|
|
2082
2269
|
/**
|
|
2083
2270
|
* Read the D19/§8 backlog-reconciliation status (mock): counts the QUEUED drafts in a
|
|
2084
2271
|
* category that are stale vs current-enough against the current rules-version. The
|
|
2085
2272
|
* mock has no per-draft composed_* stamps on its Review fixtures, so every queued
|
|
2086
|
-
* draft reads as current-enough (composed 0 vs current 0)
|
|
2273
|
+
* draft reads as current-enough (composed 0 vs current 0) - the contract shape is
|
|
2087
2274
|
* exercised; the integer-compare logic is covered by the Go tests.
|
|
2088
2275
|
*/
|
|
2089
2276
|
getScanBacklogStatus(categoryId: string): ScanBacklogStatus | undefined;
|
|
2090
2277
|
/**
|
|
2091
|
-
* Read the demand-driven pacing state (mock
|
|
2278
|
+
* Read the demand-driven pacing state (mock - M7 Slice B/§8): the cursor + effective
|
|
2092
2279
|
* window/ceiling/interval + each queued draft's classification. The mock has no cursor
|
|
2093
2280
|
* (nothing reviewed) and no composed_* stamps, so every queued draft reads in-window-
|
|
2094
2281
|
* fresh until the window fills, then ahead; the contract shape is exercised (the
|
|
@@ -2097,17 +2284,17 @@ declare class MockBackend {
|
|
|
2097
2284
|
getCategoryPacingState(categoryId: string): CategoryPacingState | undefined;
|
|
2098
2285
|
/** rank a rule for the §7 ladder (mock mirror of the server's deterministic order). */
|
|
2099
2286
|
private ruleRank;
|
|
2100
|
-
/** Get the ORDERED active rule set (mock)
|
|
2287
|
+
/** Get the ORDERED active rule set (mock) - §7 ladder + category-before-general. */
|
|
2101
2288
|
getRules(params?: GetRulesParams): RuleSnapshot;
|
|
2102
|
-
/** Save / edit a rule (mock)
|
|
2289
|
+
/** Save / edit a rule (mock) - append-only by supersession (D11). */
|
|
2103
2290
|
saveRule(req: SaveRuleRequest): Rule;
|
|
2104
2291
|
/** Promote a rule between layers (mock, via supersession), or undefined when unknown. */
|
|
2105
2292
|
promoteRule(ruleId: string, toScope: "general" | "category"): Rule | undefined;
|
|
2106
|
-
/** Retire a rule (mock)
|
|
2293
|
+
/** Retire a rule (mock) - soft delete, or undefined when unknown. */
|
|
2107
2294
|
retireRule(ruleId: string): Rule | undefined;
|
|
2108
2295
|
/** Read the rule/category change audit log (mock). */
|
|
2109
2296
|
getRuleAudit(params?: GetRuleAuditParams): Page<RuleAuditEntry>;
|
|
2110
|
-
/** Undo a rule change (mock)
|
|
2297
|
+
/** Undo a rule change (mock) - restore the prior version; idempotent (re-undo 409). */
|
|
2111
2298
|
undoRuleChange(udoId: string): Rule;
|
|
2112
2299
|
/** recordRuleAudit appends one change/undo audit row (mock). */
|
|
2113
2300
|
private recordRuleAudit;
|
|
@@ -2124,7 +2311,7 @@ declare class MockBackend {
|
|
|
2124
2311
|
*/
|
|
2125
2312
|
private enqueueTerminalNudge;
|
|
2126
2313
|
/**
|
|
2127
|
-
* Enqueue `front_run_next`
|
|
2314
|
+
* Enqueue `front_run_next` - the signal that the review reached a terminal state
|
|
2128
2315
|
* while the agent was still trying to act on it.
|
|
2129
2316
|
*
|
|
2130
2317
|
* Deduped on (review, terminal state, parent revision) so a retry loop hitting
|
|
@@ -2142,8 +2329,8 @@ declare class MockBackend {
|
|
|
2142
2329
|
}): Review | undefined;
|
|
2143
2330
|
/**
|
|
2144
2331
|
* Mock-only: mirror an approved draft whose delivery then FAILED at the provider.
|
|
2145
|
-
* This is the case the composing agent was previously never told about
|
|
2146
|
-
* console showed the error and the agent's queue stayed silent
|
|
2332
|
+
* This is the case the composing agent was previously never told about - the
|
|
2333
|
+
* console showed the error and the agent's queue stayed silent - so the loop test
|
|
2147
2334
|
* that matters most drives this path.
|
|
2148
2335
|
*/
|
|
2149
2336
|
simulateSendFailed(reviewId: string, error?: string): Review | undefined;
|
|
@@ -2171,7 +2358,7 @@ declare class MockBackend {
|
|
|
2171
2358
|
listReviewEvents(params?: ListReviewEventsParams): ReviewEventsResult;
|
|
2172
2359
|
/**
|
|
2173
2360
|
* Long-poll for a review event (mock). Offline there is nothing to wait FOR, so it
|
|
2174
|
-
* returns the immediate drain (empty when caught up)
|
|
2361
|
+
* returns the immediate drain (empty when caught up) - the server's "empty on
|
|
2175
2362
|
* timeout" contract.
|
|
2176
2363
|
*/
|
|
2177
2364
|
waitForReviewEvent(params?: WaitForReviewEventParams): ReviewEventsResult;
|
|
@@ -2194,9 +2381,10 @@ declare class MockBackend {
|
|
|
2194
2381
|
getMessageRaw(messageId: string): string;
|
|
2195
2382
|
/** Full-text search scoped to one inbox. */
|
|
2196
2383
|
searchMessages(address: string, params: SearchMessagesParams): Page<Message>;
|
|
2197
|
-
listThreads(address: string): Page<Thread>;
|
|
2384
|
+
listThreads(address: string, params?: ListThreadsParams): Page<Thread>;
|
|
2198
2385
|
/** Thread-level search (subject / snippet / participant substring). */
|
|
2199
2386
|
searchThreads(address: string, params: SearchMessagesParams): Page<Thread>;
|
|
2387
|
+
private paginateThreads;
|
|
2200
2388
|
/** Fetch one thread (with messages, oldest-first) by id under an inbox. */
|
|
2201
2389
|
getThread(address: string, threadId: string): ThreadDetail;
|
|
2202
2390
|
/**
|
|
@@ -2251,7 +2439,7 @@ declare class MockBackend {
|
|
|
2251
2439
|
listContactLists(address: string): Page<ContactListEntry> | undefined;
|
|
2252
2440
|
/** Delete a contact-list entry by id; returns false when it was not found. */
|
|
2253
2441
|
deleteContactListEntry(_address: string, entryId: string): boolean;
|
|
2254
|
-
/**
|
|
2442
|
+
/** Add a delegated domain and return only the customer-published nameservers. */
|
|
2255
2443
|
onboardDomain(req: OnboardDomainRequest): Domain;
|
|
2256
2444
|
/** List onboarded domains (records omitted on the summary, mirroring the server). */
|
|
2257
2445
|
listDomains(): Page<Domain>;
|
|
@@ -2268,6 +2456,12 @@ declare class MockBackend {
|
|
|
2268
2456
|
offboardDomain(domain: string): boolean;
|
|
2269
2457
|
/** Get one async job's poll status; undefined when the id is unknown. */
|
|
2270
2458
|
getJob(jobId: string): Job | undefined;
|
|
2459
|
+
quoteDomain(req: QuoteDomainRequest): DomainQuote;
|
|
2460
|
+
requestDomainPurchase(req: RequestDomainPurchaseRequest): CommerceRequest;
|
|
2461
|
+
requestPlanChange(req: RequestPlanChangeRequest): CommerceRequest;
|
|
2462
|
+
getCommerceRequest(requestId: string): CommerceRequest | undefined;
|
|
2463
|
+
cancelCommerceRequest(requestId: string): CommerceRequest | undefined;
|
|
2464
|
+
listCommerceRequests(params?: ListCommerceRequestsParams): Page<CommerceRequest>;
|
|
2271
2465
|
/**
|
|
2272
2466
|
* Pre-check whether the caller's org suppresses a recipient (mirrors
|
|
2273
2467
|
* `GET /v1/suppressions?recipient=…`). Returns `{recipient, suppressed, rows}`
|
|
@@ -2285,7 +2479,7 @@ declare class MockBackend {
|
|
|
2285
2479
|
/**
|
|
2286
2480
|
* Reject the WHOLE send if ANY recipient has an active org-scope suppression,
|
|
2287
2481
|
* naming exactly the suppressed addresses (never the scope/origin) so the caller
|
|
2288
|
-
* can drop them and retry
|
|
2482
|
+
* can drop them and retry - mirroring the live `recipient_suppressed` (422) path.
|
|
2289
2483
|
*/
|
|
2290
2484
|
private enforceSuppression;
|
|
2291
2485
|
/**
|
|
@@ -2296,19 +2490,25 @@ declare class MockBackend {
|
|
|
2296
2490
|
private enforceSendPolicy;
|
|
2297
2491
|
}
|
|
2298
2492
|
|
|
2493
|
+
interface DomainWaitResult {
|
|
2494
|
+
domain: Domain;
|
|
2495
|
+
outcome: "ready" | "action_required" | "needs_attention" | "timed_out" | "status_unavailable";
|
|
2496
|
+
resume_after_seconds: number;
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2299
2499
|
/**
|
|
2300
2500
|
* Key-tier awareness (redesign §3.1).
|
|
2301
2501
|
*
|
|
2302
2502
|
* An agent key encodes its CEILING tier in its raw prefix. The SDK never trusts
|
|
2303
|
-
* client input for scope
|
|
2503
|
+
* client input for scope - the tier is derived from the key the caller already
|
|
2304
2504
|
* holds, purely as a client-side hint so an app can branch (e.g. an org-tier key
|
|
2305
2505
|
* MUST pick a project breadth on a list; a project/inbox key may use the bare
|
|
2306
2506
|
* sugar). The server remains the source of truth; this is advisory only.
|
|
2307
2507
|
*
|
|
2308
2508
|
* Prefix scheme (the secret tail is unchanged across tiers):
|
|
2309
|
-
* - `pk_agent_org_…` → {@link KeyTier.Org} (admin/console
|
|
2509
|
+
* - `pk_agent_org_…` → {@link KeyTier.Org} (admin/console issuance only)
|
|
2310
2510
|
* - `pk_agent_proj_…` → {@link KeyTier.Project} (enrollment redeem + console)
|
|
2311
|
-
* - `pk_agent_inbox_…` → {@link KeyTier.Inbox} (admin/console
|
|
2511
|
+
* - `pk_agent_inbox_…` → {@link KeyTier.Inbox} (admin/console issuance only)
|
|
2312
2512
|
* - legacy `pk_agent_…` (no tier segment) → {@link KeyTier.Project}
|
|
2313
2513
|
*/
|
|
2314
2514
|
/** The ceiling tier encoded in an agent key's prefix. */
|
|
@@ -2316,7 +2516,7 @@ type KeyTier = "org" | "project" | "inbox" | "unknown";
|
|
|
2316
2516
|
/**
|
|
2317
2517
|
* Derive the {@link KeyTier} from a raw agent key by peeking the segment after the
|
|
2318
2518
|
* `pk_agent_` head. A legacy bare `pk_agent_…` key (no tier segment) maps to
|
|
2319
|
-
* `"project"`
|
|
2519
|
+
* `"project"` - exactly today's behavior. A non-agent credential (enrollment
|
|
2320
2520
|
* token, Clerk session, empty) returns `"unknown"`.
|
|
2321
2521
|
*/
|
|
2322
2522
|
declare function parseKeyTier(apiKey: string | undefined): KeyTier;
|
|
@@ -2334,7 +2534,7 @@ declare function tierAllowsOrgWildcard(tier: KeyTier): boolean;
|
|
|
2334
2534
|
declare function tierNeedsExplicitBreadth(tier: KeyTier): boolean;
|
|
2335
2535
|
|
|
2336
2536
|
/**
|
|
2337
|
-
* InboxHandle
|
|
2537
|
+
* InboxHandle: an ergonomic, bound handle to a single inbox.
|
|
2338
2538
|
*
|
|
2339
2539
|
* Returned by `extrovert.inboxes.create(...)` and `extrovert.inbox(address)`, it scopes every operation
|
|
2340
2540
|
* to one address so agent code reads naturally: `inbox.send(...)`, `inbox.waitForEmail(...)`. This
|
|
@@ -2348,7 +2548,7 @@ interface InboxHandleOptions {
|
|
|
2348
2548
|
declare class InboxHandle {
|
|
2349
2549
|
private readonly transport;
|
|
2350
2550
|
private readonly options;
|
|
2351
|
-
/** The canonical address, e.g. `agent7@
|
|
2551
|
+
/** The canonical address, e.g. `agent7@extrovertmail.com`. */
|
|
2352
2552
|
readonly address: string;
|
|
2353
2553
|
/** The full inbox record this handle was created from (absent when constructed by address). */
|
|
2354
2554
|
readonly record: Inbox | undefined;
|
|
@@ -2394,8 +2594,8 @@ declare class InboxHandle {
|
|
|
2394
2594
|
* Returns a three-way {@link SendOutcome}: `kind:"queued_for_review"` means a
|
|
2395
2595
|
* human has to approve it and NOTHING has been delivered yet; anything else was
|
|
2396
2596
|
* delivered. Under the default `require_review` policy a call WITHOUT an
|
|
2397
|
-
* `intent` raises `IntentRequiredError` (422) instead
|
|
2398
|
-
* queued
|
|
2597
|
+
* `intent` raises `IntentRequiredError` (422) instead: nothing sent, nothing
|
|
2598
|
+
* queued: so pass one, or read `inbox.record.effective_review_policy` first.
|
|
2399
2599
|
*/
|
|
2400
2600
|
send(req: SendRequest, signal?: AbortSignal): Promise<SendOutcome>;
|
|
2401
2601
|
/**
|
|
@@ -2403,14 +2603,14 @@ declare class InboxHandle {
|
|
|
2403
2603
|
* the latest message) or `message_id` (reply to that message); the server
|
|
2404
2604
|
* derives To / Subject / In-Reply-To / References. Set `reply_all` to reply to
|
|
2405
2605
|
* every thread recipient. Returns the same three-way {@link SendOutcome} as
|
|
2406
|
-
* {@link send}
|
|
2606
|
+
* {@link send}: a reply is governed by the review policy too.
|
|
2407
2607
|
*/
|
|
2408
2608
|
reply(req: ReplyRequest, signal?: AbortSignal): Promise<SendOutcome>;
|
|
2409
2609
|
/**
|
|
2410
2610
|
* Forward a message in this inbox to new recipients, preserving the original.
|
|
2411
2611
|
*
|
|
2412
2612
|
* A forward is an outbound message to arbitrary NEW recipients that quotes an
|
|
2413
|
-
* inbound thread, so it is governed by the review policy exactly like a send
|
|
2613
|
+
* inbound thread, so it is governed by the review policy exactly like a send :
|
|
2414
2614
|
* same {@link SendOutcome} union, same `intent` requirement.
|
|
2415
2615
|
*/
|
|
2416
2616
|
forward(messageId: string, req: ForwardRequest, signal?: AbortSignal): Promise<SendOutcome>;
|
|
@@ -2511,7 +2711,7 @@ declare class InboxHandle {
|
|
|
2511
2711
|
}
|
|
2512
2712
|
|
|
2513
2713
|
/**
|
|
2514
|
-
* `extrovert.projects
|
|
2714
|
+
* `extrovert.projects`: the CANONICAL project-scoped resource chain (redesign §4).
|
|
2515
2715
|
*
|
|
2516
2716
|
* Scope lives in the KEY; a broad (org-tier) key narrows to one project by PATH.
|
|
2517
2717
|
* The headline chain is `x.projects.inboxes.*`, mirroring
|
|
@@ -2526,7 +2726,7 @@ declare class InboxHandle {
|
|
|
2526
2726
|
*
|
|
2527
2727
|
* Operations are keyed by the OPAQUE `inbox_id` (the inbox's email address is also
|
|
2528
2728
|
* accepted as a within-project alias). `projectId` may be `"-"` for the org-wide
|
|
2529
|
-
* wildcard
|
|
2729
|
+
* wildcard: only an org-tier key may use it (others get 403 `forbidden_scope`).
|
|
2530
2730
|
*
|
|
2531
2731
|
* The bare `x.inboxes.*` / `x.inbox(address)` surface is curl-style sugar that
|
|
2532
2732
|
* resolves to the key's default project; this chain is the contract-canonical one.
|
|
@@ -2538,7 +2738,7 @@ interface ProjectsContext {
|
|
|
2538
2738
|
handleOptions: InboxHandleOptions;
|
|
2539
2739
|
}
|
|
2540
2740
|
/**
|
|
2541
|
-
* `x.projects.inboxes
|
|
2741
|
+
* `x.projects.inboxes`: create / list / get / update / delete inboxes, plus the
|
|
2542
2742
|
* send / reply / message / thread / wait operations, all scoped to one project (or
|
|
2543
2743
|
* the `-` org wildcard for an org-tier key). List returns a {@link ListPage} that
|
|
2544
2744
|
* auto-paginates over the opaque-cursor {@link import("../pagination.js").List} envelope.
|
|
@@ -2574,8 +2774,8 @@ declare class ProjectInboxes {
|
|
|
2574
2774
|
* Returns a three-way {@link SendOutcome}: `kind:"queued_for_review"` means a
|
|
2575
2775
|
* human has to approve it and NOTHING has been delivered yet; anything else was
|
|
2576
2776
|
* delivered. Under the default `require_review` policy a call WITHOUT an
|
|
2577
|
-
* `intent` raises `IntentRequiredError` (422) instead
|
|
2578
|
-
* queued
|
|
2777
|
+
* `intent` raises `IntentRequiredError` (422) instead: nothing sent, nothing
|
|
2778
|
+
* queued: so pass one, or read `inbox.record.effective_review_policy` first.
|
|
2579
2779
|
*/
|
|
2580
2780
|
send(projectId: string, inboxId: string, req: SendRequest, signal?: AbortSignal): Promise<SendOutcome>;
|
|
2581
2781
|
/** Reply within a thread from an inbox in `projectId`. See {@link send} on the return union. */
|
|
@@ -2610,14 +2810,14 @@ declare class ProjectInboxes {
|
|
|
2610
2810
|
*
|
|
2611
2811
|
* The frozen contract project-prefixes ONLY the inbox collection/item/credentials
|
|
2612
2812
|
* routes (`/v1/projects/{project_id}/inboxes[/{inbox_id}][/credentials]`); the
|
|
2613
|
-
* send/reply/forward/message/thread/wait sub-ops have NO project-prefixed path
|
|
2813
|
+
* send/reply/forward/message/thread/wait sub-ops have NO project-prefixed path :
|
|
2614
2814
|
* they address the inbox by its opaque id directly (`/v1/inboxes/{inbox_id}/…`),
|
|
2615
2815
|
* where the project is implicit in (and enforced by) the inbox id server-side.
|
|
2616
2816
|
*
|
|
2617
2817
|
* So for these sub-ops `projectId` cannot be carried on the URL and is NOT a URL
|
|
2618
2818
|
* selector. The adversarial review flagged that silently discarding it makes the
|
|
2619
2819
|
* signature misleading. CHOICE: keep the arg (dropping it would break the chain's
|
|
2620
|
-
* symmetry with create/list/get/update/delete
|
|
2820
|
+
* symmetry with create/list/get/update/delete: the more disruptive option) but
|
|
2621
2821
|
* VALIDATE it rather than ignore it. We reject the two client mistakes we can catch
|
|
2622
2822
|
* without a round-trip:
|
|
2623
2823
|
* - a blank / whitespace-only `projectId` (a required selector everywhere else in
|
|
@@ -2629,12 +2829,12 @@ declare class ProjectInboxes {
|
|
|
2629
2829
|
private ref;
|
|
2630
2830
|
}
|
|
2631
2831
|
/**
|
|
2632
|
-
* `extrovert.projects
|
|
2832
|
+
* `extrovert.projects`: the canonical project-scoped resource namespace. Today it
|
|
2633
2833
|
* exposes the `inboxes` chain (`x.projects.inboxes.*`); future project-scoped
|
|
2634
2834
|
* resources (domains, agents) hang off the same namespace.
|
|
2635
2835
|
*/
|
|
2636
2836
|
declare class Projects {
|
|
2637
|
-
/** `x.projects.inboxes
|
|
2837
|
+
/** `x.projects.inboxes.*`: the canonical inbox chain. */
|
|
2638
2838
|
readonly inboxes: ProjectInboxes;
|
|
2639
2839
|
constructor(ctx: ProjectsContext);
|
|
2640
2840
|
}
|
|
@@ -2655,25 +2855,26 @@ interface ResourceContext {
|
|
|
2655
2855
|
*/
|
|
2656
2856
|
keyTier: KeyTier;
|
|
2657
2857
|
}
|
|
2658
|
-
/** `extrovert.inboxes
|
|
2858
|
+
/** `extrovert.inboxes`: create, list, get, update, delete inboxes. */
|
|
2659
2859
|
declare class Inboxes {
|
|
2660
2860
|
private readonly ctx;
|
|
2661
2861
|
constructor(ctx: ResourceContext);
|
|
2662
2862
|
/**
|
|
2663
|
-
* Create an inbox. The default path
|
|
2664
|
-
* `
|
|
2863
|
+
* Create an inbox. The default path creates an address on `extrovertmail.com`
|
|
2864
|
+
* for paid accounts or `free.extrovertmail.com` for free signups, so it returns
|
|
2865
|
+
* a live inbox in one call.
|
|
2665
2866
|
*
|
|
2666
2867
|
* Pass `metadata` to attach arbitrary key-value data, and `client_id` for idempotent creation
|
|
2667
2868
|
* (re-calling with the same id returns the same inbox, with its metadata replayed verbatim).
|
|
2668
2869
|
*/
|
|
2669
2870
|
create(req?: CreateInboxRequest, signal?: AbortSignal): Promise<InboxHandle>;
|
|
2670
2871
|
/**
|
|
2671
|
-
* List inboxes visible to the calling key (the bare curl-sugar surface
|
|
2872
|
+
* List inboxes visible to the calling key (the bare curl-sugar surface: resolves
|
|
2672
2873
|
* to the key's default project). An org-tier key has no single default project, so
|
|
2673
2874
|
* the bare list is ambiguous: fail fast client-side with a BreadthRequiredError that
|
|
2674
2875
|
* names the next call, matching the MCP surface, instead of round-tripping to a 400.
|
|
2675
2876
|
* Use `extrovert.projects.inboxes.list("<project_id>")` or `"-"` (org subtree) for
|
|
2676
|
-
* an org key. The check is advisory
|
|
2877
|
+
* an org key. The check is advisory: the server stays authoritative.
|
|
2677
2878
|
*/
|
|
2678
2879
|
list(params?: ListInboxesParams, signal?: AbortSignal): Promise<Page<Inbox>>;
|
|
2679
2880
|
/** Fetch a single inbox and return an ergonomic handle bound to it. */
|
|
@@ -2694,7 +2895,7 @@ declare class Inboxes {
|
|
|
2694
2895
|
delete(address: string, signal?: AbortSignal): Promise<void>;
|
|
2695
2896
|
}
|
|
2696
2897
|
/**
|
|
2697
|
-
* `extrovert.messages
|
|
2898
|
+
* `extrovert.messages`: read a message, fetch its raw bytes, mark it read.
|
|
2698
2899
|
*
|
|
2699
2900
|
* Reply and forward are inbox-scoped (the server resolves the parent and derives
|
|
2700
2901
|
* recipients), so they live on the {@link InboxHandle} (`inbox.reply(...)`,
|
|
@@ -2739,21 +2940,27 @@ declare class Messages {
|
|
|
2739
2940
|
getAttachment(inbox: string, messageId: string, attachmentId: string, signal?: AbortSignal): Promise<AttachmentDownload>;
|
|
2740
2941
|
}
|
|
2741
2942
|
/**
|
|
2742
|
-
* `extrovert.threads
|
|
2743
|
-
* scoped to
|
|
2943
|
+
* `extrovert.threads`: list, search, read, reply to, and delete conversations,
|
|
2944
|
+
* scoped to their owning inbox.
|
|
2744
2945
|
*/
|
|
2745
2946
|
declare class Threads {
|
|
2746
2947
|
private readonly ctx;
|
|
2747
2948
|
constructor(ctx: ResourceContext);
|
|
2949
|
+
/** List conversations newest-active first. Pass `next_cursor` back as `cursor` for the next page. */
|
|
2950
|
+
list(inbox: string, params?: ListThreadsParams, signal?: AbortSignal): Promise<Page<Thread>>;
|
|
2951
|
+
/** Search thread subjects, snippets, and participants. Cursor pagination matches {@link list}. */
|
|
2952
|
+
search(inbox: string, params: SearchMessagesParams, signal?: AbortSignal): Promise<Page<Thread>>;
|
|
2748
2953
|
/** Fetch one thread (+ its messages, oldest-first) by id under its owning inbox address. */
|
|
2749
2954
|
get(inbox: string, threadId: string, signal?: AbortSignal): Promise<ThreadDetail>;
|
|
2955
|
+
/** Reply in a thread; recipients and RFC reply headers are derived server-side. */
|
|
2956
|
+
reply(inbox: string, req: ReplyRequest, signal?: AbortSignal): Promise<SendOutcome>;
|
|
2750
2957
|
/**
|
|
2751
2958
|
* Delete an entire thread (every message): move to Trash (default) or
|
|
2752
2959
|
* permanently remove when `expunge` is true. `inbox` is the owning address.
|
|
2753
2960
|
*/
|
|
2754
2961
|
delete(inbox: string, threadId: string, expunge?: boolean, signal?: AbortSignal): Promise<DeleteResult>;
|
|
2755
2962
|
}
|
|
2756
|
-
/** `extrovert.webhooks
|
|
2963
|
+
/** `extrovert.webhooks`: register / list / get / update / delete HMAC-signed inbound webhooks. */
|
|
2757
2964
|
declare class Webhooks {
|
|
2758
2965
|
private readonly ctx;
|
|
2759
2966
|
constructor(ctx: ResourceContext);
|
|
@@ -2774,7 +2981,7 @@ declare class Webhooks {
|
|
|
2774
2981
|
delete(webhookId: string, signal?: AbortSignal): Promise<void>;
|
|
2775
2982
|
}
|
|
2776
2983
|
/**
|
|
2777
|
-
* `extrovert.contactLists
|
|
2984
|
+
* `extrovert.contactLists`: per-inbox allow/block lists of addresses/domains.
|
|
2778
2985
|
* A `block` entry rejects a send to a matching recipient; once an `allow` entry
|
|
2779
2986
|
* exists for an inbox, sends from it are restricted to matching recipients
|
|
2780
2987
|
* (allowlist mode). Entries are addressable by their opaque id (`lst_…`).
|
|
@@ -2790,12 +2997,12 @@ declare class ContactLists {
|
|
|
2790
2997
|
delete(inbox: string, entryId: string, signal?: AbortSignal): Promise<void>;
|
|
2791
2998
|
}
|
|
2792
2999
|
/**
|
|
2793
|
-
* `extrovert.suppressions
|
|
3000
|
+
* `extrovert.suppressions`: recipient opt-outs (list-unsubscribe). A recipient
|
|
2794
3001
|
* that has unsubscribed cannot be mailed by this org: a send to them is rejected
|
|
2795
3002
|
* with `recipient_suppressed` ({@link RecipientSuppressedError}). Use `precheck`
|
|
2796
3003
|
* before composing to skip a would-be-rejected recipient, `list` to browse the
|
|
2797
3004
|
* org's opt-outs, and `revoke` (reason required, audit-logged) to re-enable a
|
|
2798
|
-
* recipient. All reads/writes are scoped to the caller's OWN org
|
|
3005
|
+
* recipient. All reads/writes are scoped to the caller's OWN org: a
|
|
2799
3006
|
* platform-global or shared-domain opt-out is never surfaced here.
|
|
2800
3007
|
*/
|
|
2801
3008
|
declare class Suppressions {
|
|
@@ -2803,7 +3010,7 @@ declare class Suppressions {
|
|
|
2803
3010
|
constructor(ctx: ResourceContext);
|
|
2804
3011
|
/**
|
|
2805
3012
|
* Pre-check whether the caller's org already suppresses a recipient, BEFORE
|
|
2806
|
-
* composing. `suppressed: true` means a send to them would be rejected
|
|
3013
|
+
* composing. `suppressed: true` means a send to them would be rejected: skip
|
|
2807
3014
|
* that recipient. Returns the matching org rows too (never a global/shared row).
|
|
2808
3015
|
*/
|
|
2809
3016
|
precheck(recipient: string, signal?: AbortSignal): Promise<SuppressionPrecheck>;
|
|
@@ -2817,25 +3024,36 @@ declare class Suppressions {
|
|
|
2817
3024
|
revoke(id: string, reason: string, signal?: AbortSignal): Promise<SuppressionEntry>;
|
|
2818
3025
|
}
|
|
2819
3026
|
/**
|
|
2820
|
-
* `extrovert.domains
|
|
2821
|
-
*
|
|
2822
|
-
*
|
|
2823
|
-
* verification, and offboard.
|
|
2824
|
-
*
|
|
2825
|
-
*
|
|
2826
|
-
* bind the domain to the key's project; it defaults to `org` (org-shared).
|
|
3027
|
+
* `extrovert.domains`: read with domain:read or domain:manage; changes require
|
|
3028
|
+
* domain:manage. Add delegated inbox domains the customer
|
|
3029
|
+
* controls, read status + nameserver records inline, trigger/refresh
|
|
3030
|
+
* verification, and offboard. New registrations use `extrovert.commerce`: quote
|
|
3031
|
+
* first, create a request, then poll its status. Set `scope: "project"` to bind a
|
|
3032
|
+
* customer-controlled domain to the key's project; it defaults to `org`.
|
|
2827
3033
|
*/
|
|
2828
3034
|
declare class Domains {
|
|
2829
3035
|
private readonly ctx;
|
|
2830
3036
|
constructor(ctx: ResourceContext);
|
|
2831
3037
|
/** List the customer's onboarded domains and their status. */
|
|
2832
|
-
list(
|
|
2833
|
-
|
|
3038
|
+
list(paramsOrSignal?: {
|
|
3039
|
+
page?: string;
|
|
3040
|
+
limit?: number;
|
|
3041
|
+
} | AbortSignal, signal?: AbortSignal): Promise<Page<Domain>>;
|
|
3042
|
+
/** Get one domain's detail, verification status, and nameserver records. */
|
|
2834
3043
|
get(domain: string, signal?: AbortSignal): Promise<Domain>;
|
|
2835
|
-
/**
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
3044
|
+
/** Wait up to 50 seconds, then return an explicit resumable outcome. No DNS writes. */
|
|
3045
|
+
wait(domain: string, options?: {
|
|
3046
|
+
timeout_seconds?: number;
|
|
3047
|
+
signal?: AbortSignal;
|
|
3048
|
+
}): Promise<DomainWaitResult>;
|
|
3049
|
+
/** Resume durable updates for this domain using the previous next_cursor as after. */
|
|
3050
|
+
events(domain: string, params?: {
|
|
3051
|
+
after?: string;
|
|
3052
|
+
limit?: number;
|
|
3053
|
+
}, signal?: AbortSignal): Promise<DomainStatusEventPage>;
|
|
3054
|
+
/**
|
|
3055
|
+
* Add a delegated inbox domain the customer controls. Returns the nameserver
|
|
3056
|
+
* records to publish and never spends money.
|
|
2839
3057
|
*/
|
|
2840
3058
|
onboard(req: OnboardDomainRequest, signal?: AbortSignal): Promise<Domain>;
|
|
2841
3059
|
/** Trigger or refresh verification for a domain; returns its (possibly advanced) status. */
|
|
@@ -2849,7 +3067,29 @@ declare class Domains {
|
|
|
2849
3067
|
offboard(domain: string, signal?: AbortSignal): Promise<DomainOffboard>;
|
|
2850
3068
|
}
|
|
2851
3069
|
/**
|
|
2852
|
-
* `extrovert.
|
|
3070
|
+
* `extrovert.commerce`: quote, request, cancel, and poll financial operations. Agents
|
|
3071
|
+
* can never approve a request through this resource; approval is a human console
|
|
3072
|
+
* action. Every create requires a stable idempotency key.
|
|
3073
|
+
*/
|
|
3074
|
+
declare class Commerce {
|
|
3075
|
+
private readonly ctx;
|
|
3076
|
+
constructor(ctx: ResourceContext);
|
|
3077
|
+
private requireIdempotencyKey;
|
|
3078
|
+
/** Quote a domain without purchasing, reserving, or approving it. */
|
|
3079
|
+
quoteDomain(req: QuoteDomainRequest, signal?: AbortSignal): Promise<DomainQuote>;
|
|
3080
|
+
/** Create a durable domain-purchase request for human approval. */
|
|
3081
|
+
requestDomainPurchase(req: RequestDomainPurchaseRequest, signal?: AbortSignal): Promise<CommerceRequest>;
|
|
3082
|
+
/** Create a durable plan-upgrade or downgrade request for human approval. */
|
|
3083
|
+
requestPlanChange(req: RequestPlanChangeRequest, signal?: AbortSignal): Promise<CommerceRequest>;
|
|
3084
|
+
/** Poll one request's exact blockers, approval URL, and next-action guidance. */
|
|
3085
|
+
get(requestId: string, signal?: AbortSignal): Promise<CommerceRequest>;
|
|
3086
|
+
/** Withdraw this agent's request while its durable state still permits cancellation. */
|
|
3087
|
+
cancel(requestId: string, signal?: AbortSignal): Promise<CommerceRequest>;
|
|
3088
|
+
/** List visible commerce requests using the API's opaque page token. */
|
|
3089
|
+
list(params?: ListCommerceRequestsParams, signal?: AbortSignal): Promise<Page<CommerceRequest>>;
|
|
3090
|
+
}
|
|
3091
|
+
/**
|
|
3092
|
+
* `extrovert.reviews`: the Review Loop (HITL) agent-plane reads. A sending agent
|
|
2853
3093
|
* monitors its submissions in the human-review queue: list/get a review request and
|
|
2854
3094
|
* read its append-only thread of turns (intent, drafts, human comments/edits/
|
|
2855
3095
|
* decisions, captured diffs). Submitting FOR review rides `inbox.send` /
|
|
@@ -2859,7 +3099,7 @@ declare class Domains {
|
|
|
2859
3099
|
declare class Reviews {
|
|
2860
3100
|
private readonly ctx;
|
|
2861
3101
|
/**
|
|
2862
|
-
* `extrovert.reviews.events
|
|
3102
|
+
* `extrovert.reviews.events`: the Review Loop (HITL) realtime plane: drain,
|
|
2863
3103
|
* long-poll, and ack the durable nudge queue (the AUTHORITATIVE liveness source;
|
|
2864
3104
|
* SSE/webhook are best-effort fast paths on top of it).
|
|
2865
3105
|
*/
|
|
@@ -2874,20 +3114,20 @@ declare class Reviews {
|
|
|
2874
3114
|
/**
|
|
2875
3115
|
* Get the human's assembled feedback (M5): the diff + comments + decision + the
|
|
2876
3116
|
* rules born from this review. Read it after a rejected/edited nudge to learn what
|
|
2877
|
-
* the human wanted. $0 LLM
|
|
3117
|
+
* the human wanted. $0 LLM: pure assembly on our side.
|
|
2878
3118
|
*/
|
|
2879
3119
|
feedback(reviewId: string, signal?: AbortSignal): Promise<ReviewFeedback>;
|
|
2880
3120
|
/**
|
|
2881
3121
|
* Post a chat turn on a review's thread (M5): an agent question to the human
|
|
2882
3122
|
* reviewer; flips in_review -> chatting on the first turn. Idempotent on the
|
|
2883
|
-
* optional `idempotencyKey` (the `Idempotency-Key` header). $0 LLM
|
|
3123
|
+
* optional `idempotencyKey` (the `Idempotency-Key` header). $0 LLM: you compose it.
|
|
2884
3124
|
*/
|
|
2885
3125
|
chat(reviewId: string, req: PostReviewChatRequest, idempotencyKey?: string, signal?: AbortSignal): Promise<Review>;
|
|
2886
3126
|
/**
|
|
2887
3127
|
* Post a new agent draft under a parent_revision CAS (M5; D17). parent_revision
|
|
2888
3128
|
* must equal the draft's current revision, else a 409 STALE with NO mutation (the
|
|
2889
|
-
* human always wins
|
|
2890
|
-
* in place (revision++) and returns to needs_review. $0 LLM
|
|
3129
|
+
* human always wins: re-read, re-apply, retry). On success the draft is re-rendered
|
|
3130
|
+
* in place (revision++) and returns to needs_review. $0 LLM: you compose the redraft.
|
|
2891
3131
|
*/
|
|
2892
3132
|
revise(reviewId: string, req: SubmitRevisionRequest, signal?: AbortSignal): Promise<Review>;
|
|
2893
3133
|
/**
|
|
@@ -2900,9 +3140,9 @@ declare class Reviews {
|
|
|
2900
3140
|
* assert "I reviewed this against rules vX and no change is needed", advancing the
|
|
2901
3141
|
* draft's composed_* versions with no new draft, no revision bump, no nudge. A
|
|
2902
3142
|
* born-stale draft re-stamped to the current version becomes current-enough and
|
|
2903
|
-
* releasable on the next reconciliation sweep
|
|
3143
|
+
* releasable on the next reconciliation sweep: the cheap counterpart to revise().
|
|
2904
3144
|
* against_version above the category's current rules-version is 400; a terminal draft
|
|
2905
|
-
* 409s. $0 LLM
|
|
3145
|
+
* 409s. $0 LLM: you judged.
|
|
2906
3146
|
*/
|
|
2907
3147
|
restamp(reviewId: string, req: RestampReviewRequest, signal?: AbortSignal): Promise<Review>;
|
|
2908
3148
|
/**
|
|
@@ -2917,22 +3157,22 @@ declare class Reviews {
|
|
|
2917
3157
|
decisionContext(reviewId: string, signal?: AbortSignal): Promise<ReviewDecisionContext>;
|
|
2918
3158
|
/**
|
|
2919
3159
|
* Submit a reviewer decision (M8 Slice B; reviewer_decide, D5/§9). approve/edit → the
|
|
2920
|
-
* PLATFORM
|
|
2921
|
-
* mailbox:send on an inbox it doesn't own
|
|
3160
|
+
* PLATFORM sends with the COMPOSER's credentials (the reviewer NEVER holds
|
|
3161
|
+
* mailbox:send on an inbox it doesn't own: the credential boundary); reject → back to
|
|
2922
3162
|
* the composer (needs_review, hop_count++); escalate → the human queue. revision/
|
|
2923
|
-
* version are the CAS (409 STALE on mismatch, NO mutation
|
|
3163
|
+
* version are the CAS (409 STALE on mismatch, NO mutation: the human always wins,
|
|
2924
3164
|
* D17). The two circuit breakers (hop_count ≥ max_hops, or the hard review_deadline)
|
|
2925
|
-
* FORCE a reject to the human regardless of intent
|
|
2926
|
-
* LLM
|
|
3165
|
+
* FORCE a reject to the human regardless of intent: `forced_by_breaker` names it. $0
|
|
3166
|
+
* LLM: you judged; we route, send, and enforce the breakers.
|
|
2927
3167
|
*/
|
|
2928
3168
|
decide(reviewId: string, req: ReviewerDecisionRequest, signal?: AbortSignal): Promise<ReviewerDecisionResult>;
|
|
2929
3169
|
}
|
|
2930
3170
|
/**
|
|
2931
|
-
* `extrovert.reviews.events
|
|
3171
|
+
* `extrovert.reviews.events`: drain / long-poll / ack the durable review nudge
|
|
2932
3172
|
* queue (spec §5.9). `list` is a non-blocking, side-effect-free drain of the next
|
|
2933
3173
|
* un-acked nudges in FIFO seq order (strict per review); `wait` long-polls
|
|
2934
3174
|
* (~25–55s) for the next one; `ack` advances the per-(agent, review) cursor
|
|
2935
|
-
* monotonically (idempotent
|
|
3175
|
+
* monotonically (idempotent: re-acking an older seq is a no-op).
|
|
2936
3176
|
*/
|
|
2937
3177
|
declare class ReviewEvents {
|
|
2938
3178
|
private readonly ctx;
|
|
@@ -2945,10 +3185,10 @@ declare class ReviewEvents {
|
|
|
2945
3185
|
ack(req: AckReviewEventRequest, signal?: AbortSignal): Promise<AckReviewEventResult>;
|
|
2946
3186
|
}
|
|
2947
3187
|
/**
|
|
2948
|
-
* `extrovert.categories
|
|
3188
|
+
* `extrovert.categories`: the Review Loop category registry (D9/D10). Browse and
|
|
2949
3189
|
* MATCH an existing category before composing (like a skills registry), or propose
|
|
2950
3190
|
* a new one. Categories are CUSTOMER-scoped and agent-attributed (the deliberate
|
|
2951
|
-
* cross-agent-404 exception); identity is opaque cat_ ids
|
|
3191
|
+
* cross-agent-404 exception); identity is opaque cat_ ids: nothing keys on the
|
|
2952
3192
|
* name, so renames never break a reference. `match` is a pure lexical filter (NO
|
|
2953
3193
|
* LLM on our side); the agent does the semantic matching. Merging / deleting a
|
|
2954
3194
|
* category is a human (console) action, not exposed here (D17).
|
|
@@ -2962,12 +3202,12 @@ declare class Categories {
|
|
|
2962
3202
|
get(categoryId: string, signal?: AbortSignal): Promise<Category>;
|
|
2963
3203
|
/** Propose a new category; it stands immediately and writes a create audit row. */
|
|
2964
3204
|
propose(req: ProposeCategoryRequest, signal?: AbortSignal): Promise<Category>;
|
|
2965
|
-
/** Rename / re-describe a category
|
|
3205
|
+
/** Rename / re-describe a category: metadata only (D10). */
|
|
2966
3206
|
update(categoryId: string, req: UpdateCategoryRequest, signal?: AbortSignal): Promise<Category>;
|
|
2967
3207
|
/**
|
|
2968
3208
|
* Read the effective risk dial (D4/D12): the account default + every category's
|
|
2969
3209
|
* overrides (each with its resolved effective value; null override = inherit).
|
|
2970
|
-
* Read-only
|
|
3210
|
+
* Read-only: agents read but NEVER flip the dial; setting it is a human (console)
|
|
2971
3211
|
* action (D16).
|
|
2972
3212
|
*/
|
|
2973
3213
|
riskDial(signal?: AbortSignal): Promise<RiskDial>;
|
|
@@ -2979,14 +3219,14 @@ declare class Categories {
|
|
|
2979
3219
|
graduationStatus(categoryId: string, signal?: AbortSignal): Promise<GraduationStatus>;
|
|
2980
3220
|
/**
|
|
2981
3221
|
* Propose graduating a category (D16/D6): RECORDS the request (durable evidence) and
|
|
2982
|
-
* returns the current gate status. It does NOT change the category state
|
|
3222
|
+
* returns the current gate status. It does NOT change the category state: flipping
|
|
2983
3223
|
* the bit is a human (console) action; an agent only proposes.
|
|
2984
3224
|
*/
|
|
2985
3225
|
proposeGraduation(categoryId: string, req?: ProposeGraduationRequest, signal?: AbortSignal): Promise<GraduationStatus>;
|
|
2986
3226
|
/**
|
|
2987
3227
|
* Read the D19/§8 backlog-reconciliation status: how many of the category's QUEUED
|
|
2988
3228
|
* drafts are stale vs current-enough against the current rules-version (a pure
|
|
2989
|
-
* integer compare, $0 LLM). Read-only
|
|
3229
|
+
* integer compare, $0 LLM). Read-only: you READ the picture; the human (console
|
|
2990
3230
|
* scan-backlog) or the graduate/rule-change hooks TRIGGER the actual reconciliation
|
|
2991
3231
|
* sweep that releases current-enough drafts and nudges stale ones to redraft.
|
|
2992
3232
|
*/
|
|
@@ -3002,14 +3242,14 @@ declare class Categories {
|
|
|
3002
3242
|
pacingState(categoryId: string, signal?: AbortSignal): Promise<CategoryPacingState>;
|
|
3003
3243
|
}
|
|
3004
3244
|
/**
|
|
3005
|
-
* `extrovert.rules
|
|
3245
|
+
* `extrovert.rules`: the Review Loop writing-rule store + house-style + the §7
|
|
3006
3246
|
* precedence ladder + audit/undo (D2/D11). ANY agent in the customer may write,
|
|
3007
|
-
* edit, promote, retire, and undo rules (the deliberate cross-agent exception
|
|
3247
|
+
* edit, promote, retire, and undo rules (the deliberate cross-agent exception: the
|
|
3008
3248
|
* shared house-style is the whole pitch). `get()` returns the ORDERED active rule
|
|
3009
3249
|
* set with the precedence ladder applied SERVER-SIDE (NO LLM on our side); the agent
|
|
3010
3250
|
* reconciles the list semantically. Rules are append-only by supersession; undo
|
|
3011
3251
|
* restores the prior version as a forward 'restore' supersession. Identity is opaque
|
|
3012
|
-
* rule_/rln_/udo_ ids
|
|
3252
|
+
* rule_/rln_/udo_ ids: nothing keys on a name.
|
|
3013
3253
|
*/
|
|
3014
3254
|
declare class Rules {
|
|
3015
3255
|
private readonly ctx;
|
|
@@ -3020,21 +3260,21 @@ declare class Rules {
|
|
|
3020
3260
|
* Save / edit a rule (append-only by supersession; D11). An agent-plane save is
|
|
3021
3261
|
* ALWAYS project-layer: the saved rule's `rule_layer` is `project`, bound to the
|
|
3022
3262
|
* key's project. Agents cannot author org-layer / house-style (`rule_layer:"org"`)
|
|
3023
|
-
* rules in v1
|
|
3263
|
+
* rules in v1: that is a console/admin action.
|
|
3024
3264
|
*/
|
|
3025
3265
|
save(req: SaveRuleRequest, signal?: AbortSignal): Promise<Rule>;
|
|
3026
3266
|
/** Promote a rule between the category and general/house-style layers. */
|
|
3027
3267
|
promote(ruleId: string, toScope: "general" | "category", signal?: AbortSignal): Promise<Rule>;
|
|
3028
|
-
/** Retire a rule
|
|
3268
|
+
/** Retire a rule: soft delete; the history survives as training data. */
|
|
3029
3269
|
retire(ruleId: string, signal?: AbortSignal): Promise<Rule>;
|
|
3030
3270
|
/** Read the rule/category change audit log (the safety net, D11). */
|
|
3031
3271
|
audit(params?: GetRuleAuditParams, signal?: AbortSignal): Promise<Page<RuleAuditEntry>>;
|
|
3032
|
-
/** Undo a rule change by its audit-row id (udo_…)
|
|
3272
|
+
/** Undo a rule change by its audit-row id (udo_…): restore the prior version. */
|
|
3033
3273
|
undo(udoId: string, signal?: AbortSignal): Promise<Rule>;
|
|
3034
3274
|
}
|
|
3035
3275
|
|
|
3036
3276
|
/**
|
|
3037
|
-
* ExtrovertClient
|
|
3277
|
+
* ExtrovertClient - the entry point.
|
|
3038
3278
|
*
|
|
3039
3279
|
* ```ts
|
|
3040
3280
|
* import { Extrovert } from "@extrovert.dev/sdk";
|
|
@@ -3085,28 +3325,30 @@ interface ExtrovertClientOptions {
|
|
|
3085
3325
|
mockBackend?: MockBackend;
|
|
3086
3326
|
}
|
|
3087
3327
|
declare class ExtrovertClient {
|
|
3088
|
-
/** `extrovert.inboxes`
|
|
3328
|
+
/** `extrovert.inboxes` - create / list / get / update / delete inboxes. */
|
|
3089
3329
|
readonly inboxes: Inboxes;
|
|
3090
|
-
/** `extrovert.messages`
|
|
3330
|
+
/** `extrovert.messages` - read a message, reply to it (threaded). */
|
|
3091
3331
|
readonly messages: Messages;
|
|
3092
|
-
/** `extrovert.threads`
|
|
3332
|
+
/** `extrovert.threads` - fetch a conversation thread. */
|
|
3093
3333
|
readonly threads: Threads;
|
|
3094
|
-
/** `extrovert.webhooks`
|
|
3334
|
+
/** `extrovert.webhooks` - register HMAC-signed inbound webhooks. */
|
|
3095
3335
|
readonly webhooks: Webhooks;
|
|
3096
|
-
/** `extrovert.contactLists`
|
|
3336
|
+
/** `extrovert.contactLists` - per-inbox allow/block lists of addresses/domains. */
|
|
3097
3337
|
readonly contactLists: ContactLists;
|
|
3098
|
-
/** `extrovert.suppressions`
|
|
3338
|
+
/** `extrovert.suppressions` - recipient opt-outs (list-unsubscribe); precheck/list/revoke. */
|
|
3099
3339
|
readonly suppressions: Suppressions;
|
|
3100
|
-
/** `extrovert.domains`
|
|
3340
|
+
/** `extrovert.domains` - domain readiness and setup (domain:read or domain:manage to read; domain:manage to change). */
|
|
3101
3341
|
readonly domains: Domains;
|
|
3102
|
-
/** `extrovert.
|
|
3342
|
+
/** `extrovert.commerce` - quote/request/cancel/poll financial actions; no agent approval methods. */
|
|
3343
|
+
readonly commerce: Commerce;
|
|
3344
|
+
/** `extrovert.reviews` - the Review Loop (HITL) agent-plane reads. */
|
|
3103
3345
|
readonly reviews: Reviews;
|
|
3104
|
-
/** `extrovert.categories`
|
|
3346
|
+
/** `extrovert.categories` - the Review Loop category registry (browse/propose/curate). */
|
|
3105
3347
|
readonly categories: Categories;
|
|
3106
|
-
/** `extrovert.rules`
|
|
3348
|
+
/** `extrovert.rules` - the Review Loop writing-rule store + house-style + audit/undo. */
|
|
3107
3349
|
readonly rules: Rules;
|
|
3108
3350
|
/**
|
|
3109
|
-
* `extrovert.projects`
|
|
3351
|
+
* `extrovert.projects` - the CANONICAL project-scoped chain. The headline is
|
|
3110
3352
|
* `extrovert.projects.inboxes.*` (create/list/get/update/delete/send/...), keyed by
|
|
3111
3353
|
* the opaque `inbox_id` and scoped to a `{project_id}` path (or `-` for the org
|
|
3112
3354
|
* wildcard on an org-tier key). The bare `extrovert.inboxes` surface is curl sugar
|
|
@@ -3122,7 +3364,7 @@ declare class ExtrovertClient {
|
|
|
3122
3364
|
readonly apiVersion: string;
|
|
3123
3365
|
/**
|
|
3124
3366
|
* The CEILING tier derived from the configured agent key prefix (`org` | `project`
|
|
3125
|
-
* | `inbox` | `unknown`). Advisory client-side hint only
|
|
3367
|
+
* | `inbox` | `unknown`). Advisory client-side hint only - the server is the source
|
|
3126
3368
|
* of truth. Lets an app branch (e.g. require a project pick for an org-tier key).
|
|
3127
3369
|
*/
|
|
3128
3370
|
readonly keyTier: KeyTier;
|
|
@@ -3130,18 +3372,20 @@ declare class ExtrovertClient {
|
|
|
3130
3372
|
private readonly handleOptions;
|
|
3131
3373
|
constructor(options?: ExtrovertClientOptions);
|
|
3132
3374
|
/**
|
|
3133
|
-
* Redeem an enrollment token (`pk_enroll_...`) and
|
|
3375
|
+
* Redeem an enrollment token (`pk_enroll_...`) and issue a scoped agent key.
|
|
3134
3376
|
*
|
|
3135
3377
|
* Idempotent on `agent_handle`: redeeming twice with the same handle returns the same agent.
|
|
3136
|
-
* Returns the raw `EnrollResponse`
|
|
3378
|
+
* Returns the raw `EnrollResponse` - to immediately use the issued key, prefer
|
|
3137
3379
|
* {@link ExtrovertClient.enrolled}.
|
|
3138
3380
|
*/
|
|
3139
3381
|
enroll(req: EnrollRequest, signal?: AbortSignal): Promise<EnrollResponse>;
|
|
3140
3382
|
/**
|
|
3141
|
-
*
|
|
3142
|
-
*
|
|
3143
|
-
*
|
|
3144
|
-
*
|
|
3383
|
+
* Request a free account in one unauthenticated call. When free signup is
|
|
3384
|
+
* enabled, this provisions a tenant plus a first inbox and returns a
|
|
3385
|
+
* verification-only agent key. That key can only call {@link verify}; it cannot
|
|
3386
|
+
* read or send mail. A one-time code is emailed to `human_email`. Call
|
|
3387
|
+
* {@link verify} with the code to activate the account and receive full scopes.
|
|
3388
|
+
* Idempotent on `human_email`: re-calling rotates the key and resends the code.
|
|
3145
3389
|
* When free signup is paused, this throws an `ApiError` with status 403 and
|
|
3146
3390
|
* code `signup_disabled` without creating account state.
|
|
3147
3391
|
*/
|
|
@@ -3158,15 +3402,15 @@ declare class ExtrovertClient {
|
|
|
3158
3402
|
/** Introspect the principal behind the current key (`GET /v1/auth/me`). */
|
|
3159
3403
|
whoami(signal?: AbortSignal): Promise<WhoAmI>;
|
|
3160
3404
|
/**
|
|
3161
|
-
* Poll the status of an async job (`GET /v1/jobs/{job_id}`)
|
|
3405
|
+
* Poll the status of an async job (`GET /v1/jobs/{job_id}`) - currently only
|
|
3162
3406
|
* the domain-offboard teardown started by {@link Domains.offboard} enqueues
|
|
3163
3407
|
* one. `status` is terminal on succeeded/failed/cancelled; keep polling
|
|
3164
3408
|
* otherwise. An unknown or foreign job id is a {@link NotFoundError}.
|
|
3165
3409
|
*/
|
|
3166
3410
|
getJob(jobId: string, signal?: AbortSignal): Promise<Job>;
|
|
3167
3411
|
/**
|
|
3168
|
-
* Redeem an enrollment token and return a *new* client already authenticated with the
|
|
3169
|
-
* agent key
|
|
3412
|
+
* Redeem an enrollment token and return a *new* client already authenticated with the issued
|
|
3413
|
+
* agent key - the natural "redeem then act" flow for an agent.
|
|
3170
3414
|
*
|
|
3171
3415
|
* ```ts
|
|
3172
3416
|
* const bootstrap = new Extrovert({ apiKey: enrollmentToken });
|
|
@@ -3182,7 +3426,7 @@ declare class ExtrovertClient {
|
|
|
3182
3426
|
enrollment: EnrollResponse;
|
|
3183
3427
|
}>;
|
|
3184
3428
|
/**
|
|
3185
|
-
* Get an ergonomic handle to an existing inbox by address
|
|
3429
|
+
* Get an ergonomic handle to an existing inbox by address - without an extra round-trip. Use this
|
|
3186
3430
|
* when you already know the address (e.g. from a previous create) and want to send/wait/reply.
|
|
3187
3431
|
* Call {@link InboxHandle.refresh} to load the full record.
|
|
3188
3432
|
*/
|
|
@@ -3225,7 +3469,7 @@ declare class ExtrovertClient {
|
|
|
3225
3469
|
*/
|
|
3226
3470
|
/**
|
|
3227
3471
|
* The CLOSED problem code enum (mirrors `components.schemas.Problem.code` in the
|
|
3228
|
-
* frozen OpenAPI). Adding a member is a contract change
|
|
3472
|
+
* frozen OpenAPI). Adding a member is a contract change - keep it in lockstep with
|
|
3229
3473
|
* the Go `ProblemCode` enum.
|
|
3230
3474
|
*/
|
|
3231
3475
|
type ProblemCode = "bad_request" | "unauthorized" | "forbidden_scope" | "not_found" | "conflict" | "idempotency_conflict" | "breadth_required" | "quota_exceeded" | "rate_limited" | "domain_not_allowed" | "recipient_blocked" | "recipient_suppressed" | "not_configured" | "domain_unavailable" | "internal" | "intent_required" | "wrong_state" | "terminal" | "stale" | "born_stale" | "send_needs_reconciliation" | "graduation_locked" | "maturity_gate_unmet" | "scope_taken" | "unavailable";
|
|
@@ -3238,11 +3482,11 @@ declare const PROBLEM_CODES: readonly ProblemCode[];
|
|
|
3238
3482
|
* compare-and-set (`stale`) and a redraft built against an older rule high-water
|
|
3239
3483
|
* (`born_stale`) describe a situation a retry can fix, and each only a bounded
|
|
3240
3484
|
* number of times (re-read, re-apply on top of the other party's change,
|
|
3241
|
-
* resubmit). `wrong_state` means the verb is wrong, not the timing
|
|
3485
|
+
* resubmit). `wrong_state` means the verb is wrong, not the timing - read the
|
|
3242
3486
|
* `allowed_action` hints and pick another one. `terminal` means the review is
|
|
3243
3487
|
* finished forever; a `front_run_next` nudge is already waiting on the queue
|
|
3244
3488
|
* with the outcome. `send_needs_reconciliation` means a delivery attempt is
|
|
3245
|
-
* unconfirmed
|
|
3489
|
+
* unconfirmed - resending is precisely how a message goes out twice.
|
|
3246
3490
|
*
|
|
3247
3491
|
* `intent_required` is listed false because retrying the SAME bytes fails
|
|
3248
3492
|
* identically: the fix is to ADD an `intent` and send a different request. The
|
|
@@ -3347,38 +3591,38 @@ declare class ApiError extends Error {
|
|
|
3347
3591
|
/** True for 5xx responses (server errors that may succeed on retry). */
|
|
3348
3592
|
get isServerError(): boolean;
|
|
3349
3593
|
}
|
|
3350
|
-
/** 401
|
|
3594
|
+
/** 401 - the agent key / enrollment token was missing, malformed, expired, or revoked. */
|
|
3351
3595
|
declare class AuthenticationError extends ApiError {
|
|
3352
3596
|
}
|
|
3353
|
-
/** 403
|
|
3597
|
+
/** 403 - authenticated, but the key's scopes don't permit this action (capability denied). */
|
|
3354
3598
|
declare class PermissionError extends ApiError {
|
|
3355
3599
|
}
|
|
3356
3600
|
/**
|
|
3357
|
-
* 403 `forbidden_scope`
|
|
3358
|
-
* on the org-wide wildcard, or
|
|
3601
|
+
* 403 `forbidden_scope` - the call is outside the key's CEILING (e.g. a non-org key
|
|
3602
|
+
* on the org-wide wildcard, or an issuance that would escalate). A redesign-specific
|
|
3359
3603
|
* subclass of {@link PermissionError} so existing `instanceof PermissionError`
|
|
3360
3604
|
* branches keep working.
|
|
3361
3605
|
*/
|
|
3362
3606
|
declare class ForbiddenScopeError extends PermissionError {
|
|
3363
3607
|
}
|
|
3364
3608
|
/**
|
|
3365
|
-
* 400 `breadth_required`
|
|
3609
|
+
* 400 `breadth_required` - an org-tier key/operator issued a bare list that needs a
|
|
3366
3610
|
* breadth pick; the problem `errors`/`detail` name the next call
|
|
3367
3611
|
* (`/v1/projects/{id}/inboxes` or `/v1/projects/-/inboxes`).
|
|
3368
3612
|
*/
|
|
3369
3613
|
declare class BreadthRequiredError extends ApiError {
|
|
3370
3614
|
}
|
|
3371
|
-
/** 404
|
|
3615
|
+
/** 404 - the inbox, message, thread, or webhook does not exist (or isn't visible to this tenant). */
|
|
3372
3616
|
declare class NotFoundError extends ApiError {
|
|
3373
3617
|
}
|
|
3374
|
-
/** 409
|
|
3618
|
+
/** 409 - a conflicting state, e.g. an enrollment token that already created its maximum number of inboxes. */
|
|
3375
3619
|
declare class ConflictError extends ApiError {
|
|
3376
3620
|
}
|
|
3377
|
-
/** 422
|
|
3621
|
+
/** 422 - the request body failed validation; see `body.error.details`. */
|
|
3378
3622
|
declare class ValidationError extends ApiError {
|
|
3379
3623
|
}
|
|
3380
3624
|
/**
|
|
3381
|
-
* 422 `recipient_suppressed`
|
|
3625
|
+
* 422 `recipient_suppressed` - a send/reply/forward was rejected because one or
|
|
3382
3626
|
* more recipients have opted out (list-unsubscribe / suppression). The whole send
|
|
3383
3627
|
* is rejected (never a silent partial drop). {@link suppressedRecipients} lists the
|
|
3384
3628
|
* exact addresses to drop; retry the send without them. The scope/origin of the
|
|
@@ -3386,12 +3630,12 @@ declare class ValidationError extends ApiError {
|
|
|
3386
3630
|
* existing `instanceof ValidationError` branches keep working.
|
|
3387
3631
|
*/
|
|
3388
3632
|
declare class RecipientSuppressedError extends ValidationError {
|
|
3389
|
-
/** The recipient addresses that are suppressed
|
|
3633
|
+
/** The recipient addresses that are suppressed - drop these and retry. */
|
|
3390
3634
|
readonly suppressedRecipients: string[];
|
|
3391
3635
|
constructor(args: ConstructorParameters<typeof ApiError>[0]);
|
|
3392
3636
|
}
|
|
3393
3637
|
/**
|
|
3394
|
-
* 422 `intent_required`
|
|
3638
|
+
* 422 `intent_required` - the inbox's resolved review policy requires a human to
|
|
3395
3639
|
* see this message before it goes out, and the request carried no `intent`.
|
|
3396
3640
|
*
|
|
3397
3641
|
* **Nothing was sent and nothing was queued.** The server checks this before it
|
|
@@ -3400,7 +3644,7 @@ declare class RecipientSuppressedError extends ValidationError {
|
|
|
3400
3644
|
* splice in, and the human-readable remediation (the full recipe, including how
|
|
3401
3645
|
* to monitor the resulting review) is on `.message` / `.problem.detail`.
|
|
3402
3646
|
*
|
|
3403
|
-
* Under `require_review`
|
|
3647
|
+
* Under `require_review` - the default for every account - this is the FIRST
|
|
3404
3648
|
* thing most agents hit. Read `effective_review_policy` on
|
|
3405
3649
|
* `GET /v1/inboxes/{id}` once at start-up and compose an intent up front instead
|
|
3406
3650
|
* of learning the policy by being refused. A subclass of {@link ValidationError}
|
|
@@ -3409,7 +3653,7 @@ declare class RecipientSuppressedError extends ValidationError {
|
|
|
3409
3653
|
declare class IntentRequiredError extends ValidationError {
|
|
3410
3654
|
/** The resolved review policy, e.g. `require_review`. */
|
|
3411
3655
|
readonly policy: string | undefined;
|
|
3412
|
-
/** Where the policy came from
|
|
3656
|
+
/** Where the policy came from - a per-inbox override or the account default. */
|
|
3413
3657
|
readonly policySource: string | undefined;
|
|
3414
3658
|
/** Literal JSON to merge into the original request body, then retry once. */
|
|
3415
3659
|
readonly retryWith: string | undefined;
|
|
@@ -3427,7 +3671,7 @@ declare class IntentRequiredError extends ValidationError {
|
|
|
3427
3671
|
declare class ReviewConflictError extends ConflictError {
|
|
3428
3672
|
/** The review's CURRENT state (`needs_review`, `approved`, `sent`, …). */
|
|
3429
3673
|
readonly currentState: string | undefined;
|
|
3430
|
-
/** The current revision
|
|
3674
|
+
/** The current revision - pass it as `parent_revision` on a legal retry. */
|
|
3431
3675
|
readonly currentRevision: number | undefined;
|
|
3432
3676
|
/** The current row version (the optional belt-and-braces CAS). */
|
|
3433
3677
|
readonly currentVersion: number | undefined;
|
|
@@ -3436,13 +3680,13 @@ declare class ReviewConflictError extends ConflictError {
|
|
|
3436
3680
|
constructor(args: ConstructorParameters<typeof ApiError>[0]);
|
|
3437
3681
|
/**
|
|
3438
3682
|
* Whether retrying the same call could ever succeed. False for every subclass
|
|
3439
|
-
* except {@link StaleError} and {@link BornStaleError}
|
|
3683
|
+
* except {@link StaleError} and {@link BornStaleError} - and true there only
|
|
3440
3684
|
* after re-reading and re-applying on top of the other party's change.
|
|
3441
3685
|
*/
|
|
3442
3686
|
get isRetryable(): boolean;
|
|
3443
3687
|
}
|
|
3444
3688
|
/**
|
|
3445
|
-
* 409 `stale`
|
|
3689
|
+
* 409 `stale` - the `(revision[, version])` you named is no longer current
|
|
3446
3690
|
* because a human or reviewer moved the draft. **Nothing was mutated.**
|
|
3447
3691
|
*
|
|
3448
3692
|
* The one genuinely retryable conflict, and bounded (≤3): re-read the draft and
|
|
@@ -3455,7 +3699,7 @@ declare class StaleError extends ReviewConflictError {
|
|
|
3455
3699
|
get isRetryable(): boolean;
|
|
3456
3700
|
}
|
|
3457
3701
|
/**
|
|
3458
|
-
* 409 `wrong_state`
|
|
3702
|
+
* 409 `wrong_state` - this VERB is illegal from the review's current state, but
|
|
3459
3703
|
* the draft is still live.
|
|
3460
3704
|
*
|
|
3461
3705
|
* **Never retry the same verb**; the timing is not the problem, the choice of
|
|
@@ -3464,7 +3708,7 @@ declare class StaleError extends ReviewConflictError {
|
|
|
3464
3708
|
declare class WrongStateError extends ReviewConflictError {
|
|
3465
3709
|
}
|
|
3466
3710
|
/**
|
|
3467
|
-
* 409 `terminal`
|
|
3711
|
+
* 409 `terminal` - the review has already finished (sent / auto_sent /
|
|
3468
3712
|
* cancelled). Nothing will EVER succeed on it.
|
|
3469
3713
|
*
|
|
3470
3714
|
* **Stop.** A `front_run_next` review event is waiting on the durable queue with
|
|
@@ -3478,12 +3722,12 @@ declare class TerminalError extends ReviewConflictError {
|
|
|
3478
3722
|
constructor(args: ConstructorParameters<typeof ApiError>[0]);
|
|
3479
3723
|
}
|
|
3480
3724
|
/**
|
|
3481
|
-
* 409 `born_stale`
|
|
3725
|
+
* 409 `born_stale` - the redraft was composed against an OLDER writing-rule
|
|
3482
3726
|
* high-water than the one now in force. **Nothing was mutated** and the composer
|
|
3483
3727
|
* has been re-nudged.
|
|
3484
3728
|
*
|
|
3485
3729
|
* Retryable at most once per rule high-water: re-read the rules, re-apply them,
|
|
3486
|
-
* resubmit
|
|
3730
|
+
* resubmit - or `restamp_review` when re-reading shows nothing genuinely needed
|
|
3487
3731
|
* to change. Restamping when the body DID need to change makes the draft lie to
|
|
3488
3732
|
* the born-stale accounting, so do it only for a true no-op.
|
|
3489
3733
|
*/
|
|
@@ -3491,7 +3735,7 @@ declare class BornStaleError extends ReviewConflictError {
|
|
|
3491
3735
|
get isRetryable(): boolean;
|
|
3492
3736
|
}
|
|
3493
3737
|
/**
|
|
3494
|
-
* 409 `send_needs_reconciliation`
|
|
3738
|
+
* 409 `send_needs_reconciliation` - a delivery attempt reached (or may have
|
|
3495
3739
|
* reached) the mail provider and the process died before recording the outcome,
|
|
3496
3740
|
* so the review is parked for recover-by-Message-ID.
|
|
3497
3741
|
*
|
|
@@ -3502,17 +3746,17 @@ declare class BornStaleError extends ReviewConflictError {
|
|
|
3502
3746
|
declare class SendNeedsReconciliationError extends ReviewConflictError {
|
|
3503
3747
|
}
|
|
3504
3748
|
/**
|
|
3505
|
-
* 409 `idempotency_conflict`
|
|
3749
|
+
* 409 `idempotency_conflict` - the same `Idempotency-Key` was replayed with a
|
|
3506
3750
|
* DIFFERENT request body within the same scope. The replay key is a hash of the
|
|
3507
3751
|
* raw bytes, so "same message, different spelling" counts as different.
|
|
3508
3752
|
*
|
|
3509
3753
|
* A caller bug, not a race: do not retry under that key. Either send the byte-
|
|
3510
|
-
* identical body, or
|
|
3754
|
+
* identical body, or use a new key for the genuinely new message.
|
|
3511
3755
|
*/
|
|
3512
3756
|
declare class IdempotencyConflictError extends ConflictError {
|
|
3513
3757
|
}
|
|
3514
3758
|
/**
|
|
3515
|
-
* 503 `unavailable`
|
|
3759
|
+
* 503 `unavailable` - a dependency could not be read, so the request was failed
|
|
3516
3760
|
* CLOSED rather than served on a guess. On the send path this specifically means
|
|
3517
3761
|
* the account's review policy was unreadable: relaying unsupervised mail for a
|
|
3518
3762
|
* customer whose stated policy we could not see is the failure that would be
|
|
@@ -3528,7 +3772,7 @@ declare class UnavailableError extends ApiError {
|
|
|
3528
3772
|
retryAfter?: number;
|
|
3529
3773
|
});
|
|
3530
3774
|
}
|
|
3531
|
-
/** 402
|
|
3775
|
+
/** 402 - payment required (x402 test-mode). `paymentRequired` holds the raw challenge header. */
|
|
3532
3776
|
declare class PaymentRequiredError extends ApiError {
|
|
3533
3777
|
/** The raw `PAYMENT-REQUIRED` header challenge to sign + retry (EIP-3009, Base Sepolia). */
|
|
3534
3778
|
readonly paymentRequired: string | undefined;
|
|
@@ -3536,7 +3780,7 @@ declare class PaymentRequiredError extends ApiError {
|
|
|
3536
3780
|
paymentRequired?: string;
|
|
3537
3781
|
});
|
|
3538
3782
|
}
|
|
3539
|
-
/** 429
|
|
3783
|
+
/** 429 - rate limited. `retryAfter` is the server's hint in seconds, when provided. */
|
|
3540
3784
|
declare class RateLimitError extends ApiError {
|
|
3541
3785
|
/** Seconds to wait before retrying, parsed from the `Retry-After` header. */
|
|
3542
3786
|
readonly retryAfter: number | undefined;
|
|
@@ -3554,7 +3798,7 @@ declare class TimeoutError extends ApiError {
|
|
|
3554
3798
|
}
|
|
3555
3799
|
|
|
3556
3800
|
/**
|
|
3557
|
-
* Narrowing helpers for {@link SendOutcome}
|
|
3801
|
+
* Narrowing helpers for {@link SendOutcome} - the three shapes a send can answer.
|
|
3558
3802
|
*
|
|
3559
3803
|
* `inbox.send()` used to be typed as one struct with a REQUIRED `thread_id`, which
|
|
3560
3804
|
* the direct-send response has never carried. The type checked; the value was
|
|
@@ -3565,7 +3809,7 @@ declare class TimeoutError extends ApiError {
|
|
|
3565
3809
|
* has been delivered**. A human has to approve it first, and the delivery outcome
|
|
3566
3810
|
* arrives later as a `sent` / `send_failed` review event. Code that treats every
|
|
3567
3811
|
* 2xx from `send()` as "the mail went out" is wrong under the default
|
|
3568
|
-
* `require_review` policy
|
|
3812
|
+
* `require_review` policy - which is every account that has not changed it.
|
|
3569
3813
|
*/
|
|
3570
3814
|
|
|
3571
3815
|
/**
|
|
@@ -3575,14 +3819,14 @@ declare class TimeoutError extends ApiError {
|
|
|
3575
3819
|
*/
|
|
3576
3820
|
declare function isQueuedForReview(res: SendOutcome): res is QueuedForReviewResult;
|
|
3577
3821
|
/**
|
|
3578
|
-
* True when the message was delivered immediately
|
|
3822
|
+
* True when the message was delivered immediately - either the review-loop
|
|
3579
3823
|
* `{kind:"sent"}` body or the legacy body a bare send gets under `allow_direct`.
|
|
3580
3824
|
*/
|
|
3581
3825
|
declare function isSentImmediately(res: SendOutcome): res is SendResult | SentResult;
|
|
3582
3826
|
/**
|
|
3583
3827
|
* The delivered message id, or `undefined` when the message was queued instead.
|
|
3584
3828
|
*
|
|
3585
|
-
* `undefined` here is NOT an error
|
|
3829
|
+
* `undefined` here is NOT an error - it is the normal answer under
|
|
3586
3830
|
* `require_review`. Pair it with {@link reviewIdOf} to follow the message to its
|
|
3587
3831
|
* outcome.
|
|
3588
3832
|
*/
|
|
@@ -3690,7 +3934,7 @@ declare function verifyWebhookSignature(options: VerifyWebhookOptions): Promise<
|
|
|
3690
3934
|
*/
|
|
3691
3935
|
declare function parseWebhook(options: VerifyWebhookOptions): Promise<WebhookPayload | null>;
|
|
3692
3936
|
/**
|
|
3693
|
-
* Produce the canonical `X-Extrovert-Signature` header value for a body
|
|
3937
|
+
* Produce the canonical `X-Extrovert-Signature` header value for a body - the exact format the Go
|
|
3694
3938
|
* delivery engine emits: `t=<unix>,v1=<hex hmac-sha256("<t>.<rawbody>")>`. Mainly useful for tests
|
|
3695
3939
|
* and self-hosted senders; the platform signs deliveries server-side. The Go `SignWebhook` and this
|
|
3696
3940
|
* helper are pinned to the same fixed conformance vector across languages.
|
|
@@ -3701,7 +3945,7 @@ declare function signWebhook(secret: string, body: string, timestampSeconds: num
|
|
|
3701
3945
|
* The Extrovert Review-Loop **open contract** (HITL D14, spec §11).
|
|
3702
3946
|
*
|
|
3703
3947
|
* This module is the single, documented, *versioned* publication of the stable
|
|
3704
|
-
* agent-facing JSON shapes that the Review Loop exposes
|
|
3948
|
+
* agent-facing JSON shapes that the Review Loop exposes - the shapes agents and
|
|
3705
3949
|
* third-party harnesses code against. It does **not** redesign any types: it
|
|
3706
3950
|
* re-exports the canonical models built across M1–M8 (see `./models`) under one
|
|
3707
3951
|
* named contract surface, stamps a {@link CONTRACT_VERSION}, and publishes a
|
|
@@ -3711,7 +3955,7 @@ declare function signWebhook(secret: string, body: string, timestampSeconds: num
|
|
|
3711
3955
|
* ## This is a contract, NOT a protocol (D14)
|
|
3712
3956
|
*
|
|
3713
3957
|
* Per resolved decision **D14**, the open surface is published **now** as an open,
|
|
3714
|
-
* documented **skill + SDK contract**
|
|
3958
|
+
* documented **skill + SDK contract** - explicitly **not** a wire protocol and
|
|
3715
3959
|
* **not** a standalone `/v1/contract` endpoint. The contract is exactly: these SDK
|
|
3716
3960
|
* types + the agent skills (`extrovert-send-email`, `extrovert-writing-rules`) + the
|
|
3717
3961
|
* docs, **versioned with the SDK** (this package). Formal protocol
|
|
@@ -3719,7 +3963,7 @@ declare function signWebhook(secret: string, body: string, timestampSeconds: num
|
|
|
3719
3963
|
*
|
|
3720
3964
|
* ## Provisional, pre-1.0 (0.x)
|
|
3721
3965
|
*
|
|
3722
|
-
* {@link CONTRACT_VERSION} is **`0.1.0-pre.
|
|
3966
|
+
* {@link CONTRACT_VERSION} is **`0.1.0-pre.7`** - a deliberately **provisional**, pre-1.0
|
|
3723
3967
|
* contract. It is open and documented, but it MAY still evolve before 1.0: there
|
|
3724
3968
|
* are no external users yet, and the **D20 shared-pool auto-send governor** is a
|
|
3725
3969
|
* hard prerequisite before onboarding external users. Pin the version; expect
|
|
@@ -3729,11 +3973,11 @@ declare function signWebhook(secret: string, body: string, timestampSeconds: num
|
|
|
3729
3973
|
*
|
|
3730
3974
|
* Every shape keys on **opaque, typed ids** (`rr_`, `turn_`, `cat_`, `rule_`,
|
|
3731
3975
|
* `rln_`, `ndg_`, …) and never on names. Names/descriptions are mutable display
|
|
3732
|
-
* metadata; renaming never breaks a reference. $0-LLM on our side
|
|
3976
|
+
* metadata; renaming never breaks a reference. $0-LLM on our side - the contract
|
|
3733
3977
|
* is pure deterministic JSON; all judgment lives in the agent skills.
|
|
3734
3978
|
*
|
|
3735
3979
|
* The canonical example payloads for the §11 core shapes (Intent, ReviewFeedback,
|
|
3736
|
-
* DiffJson, Rule, Nudge) are the conformance golden fixtures
|
|
3980
|
+
* DiffJson, Rule, Nudge) are the conformance golden fixtures - see
|
|
3737
3981
|
* `golang/internal/extrovertapi/testdata/contract/` and the SDK
|
|
3738
3982
|
* `contract.test.ts` (both assert these examples parse/validate without loss).
|
|
3739
3983
|
*
|
|
@@ -3776,24 +4020,24 @@ interface DiffJson {
|
|
|
3776
4020
|
/**
|
|
3777
4021
|
* The published version of the Extrovert Review-Loop open contract (D14).
|
|
3778
4022
|
*
|
|
3779
|
-
* **`0.1.0-pre.
|
|
4023
|
+
* **`0.1.0-pre.7` - PROVISIONAL, pre-1.0.** Versioned *with the SDK* (this package's
|
|
3780
4024
|
* `package.json` version) and aligned to the openapi `info.version`. Open and
|
|
3781
4025
|
* documented, but MAY still evolve before 1.0 (no external users yet; the D20
|
|
3782
4026
|
* shared-pool governor is required before external users). Pin it.
|
|
3783
4027
|
*/
|
|
3784
|
-
declare const CONTRACT_VERSION: "0.1.0-pre.
|
|
4028
|
+
declare const CONTRACT_VERSION: "0.1.0-pre.7";
|
|
3785
4029
|
/** The stability posture of a published contract version. */
|
|
3786
4030
|
type ContractStability = "provisional" | "stable";
|
|
3787
4031
|
/**
|
|
3788
|
-
* The machine-readable manifest of the open contract (D14)
|
|
4032
|
+
* The machine-readable manifest of the open contract (D14) - what a harness pins.
|
|
3789
4033
|
*
|
|
3790
4034
|
* It enumerates the canonical §11 **core** shapes and the **full** M1–M8 surface
|
|
3791
4035
|
* by name, stamps {@link CONTRACT_VERSION}, and marks the {@link ContractStability}
|
|
3792
4036
|
* posture so a consumer can reason about evolution risk. It carries no runtime
|
|
3793
|
-
* behavior (M9 adds none
|
|
4037
|
+
* behavior (M9 adds none - types + a version + a test + docs) and no LLM.
|
|
3794
4038
|
*/
|
|
3795
4039
|
interface ContractManifest {
|
|
3796
|
-
/** Stable contract name (NOT a protocol name
|
|
4040
|
+
/** Stable contract name (NOT a protocol name - D14). */
|
|
3797
4041
|
readonly name: "extrovert.review-loop";
|
|
3798
4042
|
/** The published contract version (== {@link CONTRACT_VERSION}). */
|
|
3799
4043
|
readonly version: string;
|
|
@@ -3803,7 +4047,7 @@ interface ContractManifest {
|
|
|
3803
4047
|
*/
|
|
3804
4048
|
readonly stability: ContractStability;
|
|
3805
4049
|
/**
|
|
3806
|
-
* D14: this is an SDK + skill contract, versioned WITH the SDK
|
|
4050
|
+
* D14: this is an SDK + skill contract, versioned WITH the SDK - never a wire
|
|
3807
4051
|
* protocol or a standalone protocol endpoint.
|
|
3808
4052
|
*/
|
|
3809
4053
|
readonly kind: "sdk+skill-contract";
|
|
@@ -3813,15 +4057,15 @@ interface ContractManifest {
|
|
|
3813
4057
|
readonly core_shapes: readonly string[];
|
|
3814
4058
|
/** The full published M1–M8 agent-facing contract surface (one 0.x contract; no tiering). */
|
|
3815
4059
|
readonly shapes: readonly string[];
|
|
3816
|
-
/** The agent skills that are part of the contract (D14
|
|
4060
|
+
/** The agent skills that are part of the contract (D14 - "skill + SDK"). */
|
|
3817
4061
|
readonly skills: readonly string[];
|
|
3818
4062
|
}
|
|
3819
4063
|
/**
|
|
3820
4064
|
* The published manifest instance. Frozen so a harness can compare it
|
|
3821
4065
|
* structurally. The `core_shapes` are the five §11 canonical shapes; `shapes` is
|
|
3822
4066
|
* the full provisional-0.x surface. Keep this list in sync with the re-exports
|
|
3823
|
-
* above
|
|
4067
|
+
* above - the `contract.test.ts` drift test asserts every named shape resolves.
|
|
3824
4068
|
*/
|
|
3825
4069
|
declare const CONTRACT_MANIFEST: ContractManifest;
|
|
3826
4070
|
|
|
3827
|
-
export { API_VERSION_HEADER, type AccountRiskDial, type AckReviewEventEntry, type AckReviewEventRequest, type AckReviewEventResult, type AddContactListRequest, type Agent, type AgentStatus, ApiError, type ApiErrorBody, type Attachment, type AttachmentDownload, type AttachmentInput, AuthenticationError, type BatchUpdateMessagesRequest, type BatchUpdateResult, BornStaleError, BreadthRequiredError, CONTRACT_MANIFEST, CONTRACT_VERSION, CURRENT_API_VERSION, Categories, type Category, type CategoryPacingState, type CategoryRiskDial, ConflictError, ConnectionError, type ContactListDirection, type ContactListEntry, type ContactListKind, ContactLists, type ContractManifest, type ContractStability, type CreateInboxRequest, type Cursor, DEFAULT_BASE_URL, type DeleteResult, type DiffHunk, type DiffJson, type Domain, type DomainOffboard, type DomainRecord, type DomainScope, Domains, type EffectiveRiskDial, type EmailAddress, type EnrollRequest, type EnrollResponse, type ExtractedCredentials, ExtrovertClient as Extrovert, ExtrovertClient, type ExtrovertClientOptions, ForbiddenScopeError, type ForwardRequest, type GetInboxParams, type GetRuleAuditParams, type GetRulesParams, type GraduationStatus, IdempotencyConflictError, type Inbox, type InboxCredentials, InboxHandle, type InboxInclude, type InboxMetadata, type InboxMetadataPatch, type InboxMetadataValue, type InboxStatus, Inboxes, IntentRequiredError, type IsoTimestamp, type Job, type KeyTier, type List, type ListCategoriesParams, type ListInboxesParams, type ListMessagesParams, ListPage, type ListParams, type ListReviewEventsParams, type ListReviewsParams, type ListSuppressionsParams, type ListThreadsParams, MOCK_BASE_URL, type MailFolder, type MailboxQuickstart, type MailboxQuickstartCall, type MarkReadRequest, type Message, type MessageDirection, Messages, MockBackend, NotFoundError, type OnboardDomainRequest, type OnboardingMode, PROBLEM_CODES, type PacingItem, type Page, type PageFetcher, PaymentRequiredError, PermissionError, type PostReviewChatRequest, type Problem, type ProblemCode, type ProblemField, type ProjectInboxListParams, ProjectInboxes, Projects, type ProposeCategoryRequest, type ProposeGraduationRequest, type QueuedForReviewResult, REVIEW_PROBLEM_RETRYABLE, RateLimitError, RecipientSuppressedError, type RegisterWebhookRequest, type ReplyRequest, type RestampReviewRequest, type Review, ReviewConflictError, type ReviewDecisionContext, type ReviewEvent, type ReviewEventCursor, type ReviewEventReason, ReviewEvents, type ReviewEventsResult, type ReviewFeedback, type ReviewFeedbackComment, type ReviewInclude, type ReviewIntent, type ReviewMode, type ReviewPolicy, type ReviewState, type ReviewTurn, type ReviewerAction, type ReviewerDecisionRequest, type ReviewerDecisionResult, Reviews, type RiskDial, type Rule, type RuleAuditEntry, type RuleLayer, type RuleSnapshot, Rules, SDK_VERSION, type SaveRuleRequest, type ScanBacklogStatus, type Scope, type SearchMessagesParams, SendNeedsReconciliationError, type SendOutcome, type SendRequest, type SendResult, type SentResult, type SignUpRequest, type SignUpResponse, StaleError, type StreamEvent, type StreamOptions, type SubmitForReviewResult, type SubmitRevisionRequest, type SuppressionEntry, type SuppressionPrecheck, type SuppressionScope, type SuppressionSource, Suppressions, TerminalError, type Thread, type ThreadDetail, Threads, TimeoutError, UnavailableError, type UpdateCategoryRequest, type UpdateInboxRequest, type UpdateWebhookRequest, ValidationError, type VerifyRequest, type VerifyResponse, type VerifyWebhookOptions, type WaitForEmailRequest, type WaitForEmailResult, type WaitForReviewEventParams, type Webhook, type WebhookEvent, type WebhookPayload, Webhooks, type WhoAmI, WrongStateError, extractCredentials, extractLink, extractOtp, isProblemCode, isQueuedForReview, isSentImmediately, listPage, parseKeyTier, parseProblem, parseWebhook, reviewIdOf, sentMessageIdOf, serializeInclude, signWebhook, threadIdOf, tierAllowsOrgWildcard, tierNeedsExplicitBreadth, verifyWebhookSignature };
|
|
4071
|
+
export { API_VERSION_HEADER, type AccountRiskDial, type AckReviewEventEntry, type AckReviewEventRequest, type AckReviewEventResult, type AddContactListRequest, type Agent, type AgentStatus, ApiError, type ApiErrorBody, type Attachment, type AttachmentDownload, type AttachmentInput, AuthenticationError, type BatchUpdateMessagesRequest, type BatchUpdateResult, BornStaleError, BreadthRequiredError, CONTRACT_MANIFEST, CONTRACT_VERSION, CURRENT_API_VERSION, Categories, type Category, type CategoryPacingState, type CategoryRiskDial, Commerce, type CommerceBlocker, type CommerceRequest, type CommerceRequestKind, ConflictError, ConnectionError, type ContactListDirection, type ContactListEntry, type ContactListKind, ContactLists, type ContractManifest, type ContractStability, type CreateInboxRequest, type Cursor, DEFAULT_BASE_URL, type DeleteResult, type DiffHunk, type DiffJson, type Domain, type DomainOffboard, type DomainQuote, type DomainReadiness, type DomainRecord, type DomainScope, type DomainStatusEvent, type DomainStatusEventPage, type DomainWaitResult, Domains, type EffectiveRiskDial, type EmailAddress, type EnrollRequest, type EnrollResponse, type ExtractedCredentials, ExtrovertClient as Extrovert, ExtrovertClient, type ExtrovertClientOptions, ForbiddenScopeError, type ForwardRequest, type GetInboxParams, type GetRuleAuditParams, type GetRulesParams, type GraduationStatus, IdempotencyConflictError, type Inbox, type InboxCredentials, InboxHandle, type InboxInclude, type InboxMetadata, type InboxMetadataPatch, type InboxMetadataValue, type InboxStatus, Inboxes, IntentRequiredError, type IsoTimestamp, type Job, type KeyTier, type List, type ListCategoriesParams, type ListCommerceRequestsParams, type ListInboxesParams, type ListMessagesParams, ListPage, type ListParams, type ListReviewEventsParams, type ListReviewsParams, type ListSuppressionsParams, type ListThreadsParams, MOCK_BASE_URL, type MailFolder, type MailboxQuickstart, type MailboxQuickstartCall, type MarkReadRequest, type Message, type MessageDirection, Messages, MockBackend, NotFoundError, type OnboardDomainRequest, type OnboardingMode, PROBLEM_CODES, type PacingItem, type Page, type PageFetcher, PaymentRequiredError, PermissionError, type PostReviewChatRequest, type Problem, type ProblemCode, type ProblemField, type ProjectInboxListParams, ProjectInboxes, Projects, type ProposeCategoryRequest, type ProposeGraduationRequest, type QueuedForReviewResult, type QuoteDomainRequest, REVIEW_PROBLEM_RETRYABLE, RateLimitError, RecipientSuppressedError, type RegisterWebhookRequest, type ReplyRequest, type RequestDomainPurchaseRequest, type RequestPlanChangeRequest, type RestampReviewRequest, type Review, ReviewConflictError, type ReviewDecisionContext, type ReviewEvent, type ReviewEventCursor, type ReviewEventReason, ReviewEvents, type ReviewEventsResult, type ReviewFeedback, type ReviewFeedbackComment, type ReviewInclude, type ReviewIntent, type ReviewMode, type ReviewPolicy, type ReviewState, type ReviewTurn, type ReviewerAction, type ReviewerDecisionRequest, type ReviewerDecisionResult, Reviews, type RiskDial, type Rule, type RuleAuditEntry, type RuleLayer, type RuleSnapshot, Rules, SDK_VERSION, type SaveRuleRequest, type ScanBacklogStatus, type Scope, type SearchMessagesParams, SendNeedsReconciliationError, type SendOutcome, type SendRequest, type SendResult, type SentResult, type SignUpRequest, type SignUpResponse, StaleError, type StreamEvent, type StreamOptions, type SubmitForReviewResult, type SubmitRevisionRequest, type SuppressionEntry, type SuppressionPrecheck, type SuppressionScope, type SuppressionSource, Suppressions, TerminalError, type Thread, type ThreadDetail, Threads, TimeoutError, UnavailableError, type UpdateCategoryRequest, type UpdateInboxRequest, type UpdateWebhookRequest, ValidationError, type VerifyRequest, type VerifyResponse, type VerifyWebhookOptions, type WaitForEmailRequest, type WaitForEmailResult, type WaitForReviewEventParams, type Webhook, type WebhookEvent, type WebhookPayload, Webhooks, type WhoAmI, WrongStateError, extractCredentials, extractLink, extractOtp, isProblemCode, isQueuedForReview, isSentImmediately, listPage, parseKeyTier, parseProblem, parseWebhook, reviewIdOf, sentMessageIdOf, serializeInclude, signWebhook, threadIdOf, tierAllowsOrgWildcard, tierNeedsExplicitBreadth, verifyWebhookSignature };
|