@extrovert.dev/mcp 0.1.0-pre.3
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/LICENSE +21 -0
- package/README.md +313 -0
- package/dist/bin.d.ts +13 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +89 -0
- package/dist/bin.js.map +1 -0
- package/dist/client.d.ts +956 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1354 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +51 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +53 -0
- package/dist/config.js.map +1 -0
- package/dist/contract.d.ts +62 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +78 -0
- package/dist/contract.js.map +1 -0
- package/dist/extract.d.ts +25 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +131 -0
- package/dist/extract.js.map +1 -0
- package/dist/fixtures.d.ts +676 -0
- package/dist/fixtures.d.ts.map +1 -0
- package/dist/fixtures.js +2685 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/http.d.ts +18 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +124 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +36 -0
- package/dist/server.js.map +1 -0
- package/dist/stdio.d.ts +8 -0
- package/dist/stdio.d.ts.map +1 -0
- package/dist/stdio.js +22 -0
- package/dist/stdio.js.map +1 -0
- package/dist/tools.d.ts +27 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +2752 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +1037 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +83 -0
- package/dist/types.js.map +1 -0
- package/package.json +72 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,956 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin, typed Extrovert API client.
|
|
3
|
+
*
|
|
4
|
+
* One method per REST endpoint in spec §8 (`/v1`). The base URL and scoped
|
|
5
|
+
* agent key come from config (env `EXTROVERT_API_BASE_URL` / `EXTROVERT_API_KEY`).
|
|
6
|
+
* This module is the single seam between the MCP tools and the network — the
|
|
7
|
+
* tools never touch `fetch` directly.
|
|
8
|
+
*
|
|
9
|
+
* While `config.mock` is true, each method returns deterministic fixture data
|
|
10
|
+
* via `FixtureStore` instead of issuing HTTP.
|
|
11
|
+
*/
|
|
12
|
+
import type { ExtrovertConfig } from "./config.js";
|
|
13
|
+
import { NotFoundError } from "./fixtures.js";
|
|
14
|
+
import type { Attachment, AttachmentDownload, AttachmentInput, BatchUpdateResult, Category, ContactListDirection, ContactListEntry, ContactListKind, DeleteResult, Domain, DomainOffboard, EnrollmentResult, GraduationStatus, Inbox, Job, KeyTier, MailboxCredentials, Message, Page, Review, RiskDial, ReviewDecisionContext, ReviewerAction, ReviewerDecisionResult, ReviewEventsResult, ReviewFeedback, ReviewIntent, ReviewMode, ReviewState, CategoryPacingState, ReviewTurn, Rule, RuleAuditEntry, ProblemField, ReplyEmailResult, ScanBacklogStatus, SendEmailResult, SignUpResult, SubmitForReviewResult, SuppressionEntry, SuppressionPrecheck, ReputationRollup, ReputationFinding, ListDeliverabilityFindingsInput, Thread, ThreadDetail, VerifyResult, WaitForEmailResult, Webhook, WebhookEvent, WhoAmI } from "./types.js";
|
|
15
|
+
/** Normalized error surfaced from any client call. */
|
|
16
|
+
export declare class ExtrovertApiError extends Error {
|
|
17
|
+
readonly status: number;
|
|
18
|
+
readonly code?: string | undefined;
|
|
19
|
+
readonly details?: unknown | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* The problem's machine-readable field hints (`problem.errors[]`), verbatim.
|
|
22
|
+
*
|
|
23
|
+
* These are NOT decoration. A 422 `intent_required` carries the exact JSON to
|
|
24
|
+
* add under `retry_with`, and a 409 carries `state` / `revision` / `version` /
|
|
25
|
+
* one `allowed_action` per legal verb — the facts that let an agent recover in
|
|
26
|
+
* one turn instead of guessing. They reach the model only because
|
|
27
|
+
* `toErrorResult` renders them: anything left in `structuredContent` is
|
|
28
|
+
* invisible to a text-only agent.
|
|
29
|
+
*/
|
|
30
|
+
readonly problemErrors?: ProblemField[] | undefined;
|
|
31
|
+
constructor(message: string, status: number, code?: string | undefined, details?: unknown | undefined,
|
|
32
|
+
/**
|
|
33
|
+
* The problem's machine-readable field hints (`problem.errors[]`), verbatim.
|
|
34
|
+
*
|
|
35
|
+
* These are NOT decoration. A 422 `intent_required` carries the exact JSON to
|
|
36
|
+
* add under `retry_with`, and a 409 carries `state` / `revision` / `version` /
|
|
37
|
+
* one `allowed_action` per legal verb — the facts that let an agent recover in
|
|
38
|
+
* one turn instead of guessing. They reach the model only because
|
|
39
|
+
* `toErrorResult` renders them: anything left in `structuredContent` is
|
|
40
|
+
* invisible to a text-only agent.
|
|
41
|
+
*/
|
|
42
|
+
problemErrors?: ProblemField[] | undefined);
|
|
43
|
+
}
|
|
44
|
+
export interface RedeemEnrollmentInput {
|
|
45
|
+
enrollment_token: string;
|
|
46
|
+
/** Idempotency handle (à la AgentMail `client_id`); rebinds the same agent. */
|
|
47
|
+
agent_handle?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Optional client-supplied idempotency key sent as the `Idempotency-Key`
|
|
50
|
+
* header: a retry with the same key replays the original enrollment response.
|
|
51
|
+
*/
|
|
52
|
+
client_id?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A metadata patch on create/update. Each value is string | number | boolean to
|
|
56
|
+
* SET a key, or `null` to DELETE that key (merge-null-clear semantics). A
|
|
57
|
+
* top-level `null` on update clears ALL metadata (see {@link UpdateInboxInput}).
|
|
58
|
+
*/
|
|
59
|
+
export type InboxMetadataPatch = Record<string, string | number | boolean | null>;
|
|
60
|
+
export interface CreateInboxInput {
|
|
61
|
+
username?: string;
|
|
62
|
+
domain?: string;
|
|
63
|
+
display_name?: string;
|
|
64
|
+
inbound_webhook_url?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Optional arbitrary key-value metadata to store on the inbox (AgentMail
|
|
67
|
+
* parity). Values may be string, number, or boolean; a key with a `null` value
|
|
68
|
+
* is dropped. Caps: ≤256 keys, ≤256 chars per key, ≤256 chars per string value;
|
|
69
|
+
* nested objects/arrays are rejected. Echoed back (and replayed on idempotent
|
|
70
|
+
* retries) on the create response.
|
|
71
|
+
*/
|
|
72
|
+
metadata?: InboxMetadataPatch;
|
|
73
|
+
/**
|
|
74
|
+
* Optional assertion that must match the key's bound project — NEVER a
|
|
75
|
+
* selector. A mismatch is rejected server-side; the inbox is always created in
|
|
76
|
+
* the key's stored project.
|
|
77
|
+
*/
|
|
78
|
+
project_id?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Optional client-supplied idempotency key sent as the `Idempotency-Key`
|
|
81
|
+
* header: re-creating with the same key returns the existing inbox rather than
|
|
82
|
+
* a duplicate (the same key with a different request is a 409).
|
|
83
|
+
*/
|
|
84
|
+
client_id?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface RegisterWebhookInput {
|
|
87
|
+
url: string;
|
|
88
|
+
events?: WebhookEvent[];
|
|
89
|
+
inbox?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Optional client-supplied idempotency key sent as the `Idempotency-Key`
|
|
92
|
+
* header: a retry with the same key replays the original registration.
|
|
93
|
+
*/
|
|
94
|
+
client_id?: string;
|
|
95
|
+
}
|
|
96
|
+
/** Mutable inbox settings for `PATCH /v1/inboxes/{inbox_id}`. Omitted fields are left unchanged. */
|
|
97
|
+
export interface UpdateInboxInput {
|
|
98
|
+
/** New sender display / "From" name. Empty string falls back to the local-part. */
|
|
99
|
+
display_name?: string;
|
|
100
|
+
/** Replace the inbound webhook target (empty string clears it). */
|
|
101
|
+
inbound_webhook_url?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Set the effective rolling-24-hour recipient cap (integer 1–10,000).
|
|
104
|
+
* Requires the opt-in `mailbox:quota` scope.
|
|
105
|
+
*/
|
|
106
|
+
daily_send_limit?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Patch the inbox's arbitrary metadata (AgentMail parity) with a shallow merge:
|
|
109
|
+
* an object merges into the existing metadata; a key whose value is `null`
|
|
110
|
+
* deletes that key; a top-level `null` clears ALL metadata (the response then
|
|
111
|
+
* carries `{}`). Omit the field entirely to leave metadata unchanged. Values
|
|
112
|
+
* may be string, number, or boolean; nested objects/arrays are rejected; the
|
|
113
|
+
* same ≤256 key/length caps as create apply.
|
|
114
|
+
*/
|
|
115
|
+
metadata?: InboxMetadataPatch | null;
|
|
116
|
+
/**
|
|
117
|
+
* Optional assertion that must match the key's bound project — NEVER a
|
|
118
|
+
* selector. A mismatch is rejected server-side.
|
|
119
|
+
*/
|
|
120
|
+
project_id?: string;
|
|
121
|
+
}
|
|
122
|
+
export interface SendEmailInput {
|
|
123
|
+
inbox: string;
|
|
124
|
+
to: string[];
|
|
125
|
+
subject: string;
|
|
126
|
+
text: string;
|
|
127
|
+
html?: string;
|
|
128
|
+
cc?: string[];
|
|
129
|
+
bcc?: string[];
|
|
130
|
+
/** Override the Reply-To header. */
|
|
131
|
+
reply_to?: string;
|
|
132
|
+
/** Custom headers to attach (reserved/unsafe names are dropped server-side). */
|
|
133
|
+
headers?: Record<string, string>;
|
|
134
|
+
/** Files to attach (base64). */
|
|
135
|
+
attachments?: AttachmentInput[];
|
|
136
|
+
/** Stable retry key, sent as Idempotency-Key and never in the JSON body. */
|
|
137
|
+
client_id?: string;
|
|
138
|
+
}
|
|
139
|
+
export interface ReplyEmailInput {
|
|
140
|
+
inbox: string;
|
|
141
|
+
/** Exactly one of thread_id / message_id selects the parent. */
|
|
142
|
+
thread_id?: string;
|
|
143
|
+
message_id?: string;
|
|
144
|
+
text?: string;
|
|
145
|
+
html?: string;
|
|
146
|
+
cc?: string[];
|
|
147
|
+
bcc?: string[];
|
|
148
|
+
reply_to?: string;
|
|
149
|
+
headers?: Record<string, string>;
|
|
150
|
+
/** Reply to every thread recipient, not just the original sender. */
|
|
151
|
+
reply_all?: boolean;
|
|
152
|
+
/** Files to attach (base64). */
|
|
153
|
+
attachments?: AttachmentInput[];
|
|
154
|
+
/** Stable retry key, sent as Idempotency-Key and never in the JSON body. */
|
|
155
|
+
client_id?: string;
|
|
156
|
+
}
|
|
157
|
+
export interface ForwardEmailInput {
|
|
158
|
+
inbox: string;
|
|
159
|
+
message_id: string;
|
|
160
|
+
to: string[];
|
|
161
|
+
cc?: string[];
|
|
162
|
+
bcc?: string[];
|
|
163
|
+
text?: string;
|
|
164
|
+
/** Accepted for wire compatibility but ignored; the materialized forward is plain text. */
|
|
165
|
+
html?: string;
|
|
166
|
+
/** Stable retry key, sent as Idempotency-Key and never in the JSON body. */
|
|
167
|
+
client_id?: string;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Submit a forward for human review (Review Loop). A forward is an outbound
|
|
171
|
+
* message to arbitrary NEW recipients that quotes an entire received thread, so it
|
|
172
|
+
* is policy-enforced exactly like send and reply — otherwise it would be the
|
|
173
|
+
* documented bypass, and a worse one, because it exfiltrates a conversation.
|
|
174
|
+
*
|
|
175
|
+
* The subject and the quoted body are materialized server-side at SUBMIT time, so
|
|
176
|
+
* the human reviews the exact bytes that go out and an approved forward delivers
|
|
177
|
+
* the reviewer's edit rather than a body re-derived from the live parent.
|
|
178
|
+
*/
|
|
179
|
+
export interface SubmitForwardForReviewInput {
|
|
180
|
+
inbox: string;
|
|
181
|
+
message_id: string;
|
|
182
|
+
to: string[];
|
|
183
|
+
cc?: string[];
|
|
184
|
+
bcc?: string[];
|
|
185
|
+
/** Optional note to prepend; the parent quote is appended server-side. */
|
|
186
|
+
text?: string;
|
|
187
|
+
/** Accepted for wire compatibility but ignored; the materialized forward is plain text. */
|
|
188
|
+
html?: string;
|
|
189
|
+
mode?: ReviewMode;
|
|
190
|
+
/** Required when the resolved mode is review (D3). */
|
|
191
|
+
intent?: ReviewIntent;
|
|
192
|
+
category_id?: string;
|
|
193
|
+
/** See SubmitForReviewInput.category_confidence. */
|
|
194
|
+
category_confidence?: number;
|
|
195
|
+
/** Stable retry key, sent as Idempotency-Key and never in the JSON body. */
|
|
196
|
+
client_id?: string;
|
|
197
|
+
}
|
|
198
|
+
/** Submit a new message for human review (Review Loop, spec §5.1). */
|
|
199
|
+
export interface SubmitForReviewInput {
|
|
200
|
+
inbox: string;
|
|
201
|
+
to: string[];
|
|
202
|
+
subject?: string;
|
|
203
|
+
text: string;
|
|
204
|
+
html?: string;
|
|
205
|
+
cc?: string[];
|
|
206
|
+
bcc?: string[];
|
|
207
|
+
reply_to?: string;
|
|
208
|
+
headers?: Record<string, string>;
|
|
209
|
+
/**
|
|
210
|
+
* Files to attach (base64). Attachments now survive submit -> review row ->
|
|
211
|
+
* approval dispatch, so the human reviews the message WITH its files and the
|
|
212
|
+
* recipient receives the same ones.
|
|
213
|
+
*/
|
|
214
|
+
attachments?: AttachmentInput[];
|
|
215
|
+
/** "review" (default) routes to the human queue; "direct" requests an immediate send. */
|
|
216
|
+
mode?: ReviewMode;
|
|
217
|
+
/** Required when the resolved mode is review (D3). */
|
|
218
|
+
intent?: ReviewIntent;
|
|
219
|
+
/** Opaque category id (cat_…) matched from the registry; never a name. */
|
|
220
|
+
category_id?: string;
|
|
221
|
+
/**
|
|
222
|
+
* Agent-supplied confidence (0..1) in the category match. Feeds the submit-time
|
|
223
|
+
* min_confidence auto-send gate ONLY; the server never scores ($0 LLM). Below the
|
|
224
|
+
* effective threshold (or omitted when a threshold is set) the would-be auto-send
|
|
225
|
+
* routes to needs_review with gate_outcome held:low_confidence.
|
|
226
|
+
*/
|
|
227
|
+
category_confidence?: number;
|
|
228
|
+
/** Stable retry key, sent as Idempotency-Key and never in the JSON body. */
|
|
229
|
+
client_id?: string;
|
|
230
|
+
}
|
|
231
|
+
/** Submit an in-thread reply for human review (Review Loop). */
|
|
232
|
+
export interface SubmitReplyForReviewInput {
|
|
233
|
+
inbox: string;
|
|
234
|
+
thread_id?: string;
|
|
235
|
+
message_id?: string;
|
|
236
|
+
text: string;
|
|
237
|
+
html?: string;
|
|
238
|
+
cc?: string[];
|
|
239
|
+
bcc?: string[];
|
|
240
|
+
reply_to?: string;
|
|
241
|
+
headers?: Record<string, string>;
|
|
242
|
+
/** Reply to every thread recipient, not just the original sender. */
|
|
243
|
+
reply_all?: boolean;
|
|
244
|
+
/** Files to attach (base64); they survive submit -> review row -> dispatch. */
|
|
245
|
+
attachments?: AttachmentInput[];
|
|
246
|
+
mode?: ReviewMode;
|
|
247
|
+
intent?: ReviewIntent;
|
|
248
|
+
category_id?: string;
|
|
249
|
+
/** See SubmitForReviewInput.category_confidence. */
|
|
250
|
+
category_confidence?: number;
|
|
251
|
+
/** Stable retry key, sent as Idempotency-Key and never in the JSON body. */
|
|
252
|
+
client_id?: string;
|
|
253
|
+
}
|
|
254
|
+
/** Filters for listing review requests (Review Loop, spec §5.2). */
|
|
255
|
+
export interface ListReviewsInput {
|
|
256
|
+
state?: ReviewState | ReviewState[];
|
|
257
|
+
category_id?: string;
|
|
258
|
+
inbox?: string;
|
|
259
|
+
limit?: number;
|
|
260
|
+
page?: string;
|
|
261
|
+
}
|
|
262
|
+
/** Post a chat turn on a review's thread (Review Loop M5, spec §5.2). */
|
|
263
|
+
export interface PostReviewChatInput {
|
|
264
|
+
/** Review id (rr_…). */
|
|
265
|
+
id: string;
|
|
266
|
+
/** The agent's question/comment for the human reviewer. */
|
|
267
|
+
text: string;
|
|
268
|
+
/** Optional idempotency key (sent as the `Idempotency-Key` header). */
|
|
269
|
+
client_id?: string;
|
|
270
|
+
}
|
|
271
|
+
/** Post a new agent draft under a parent_revision CAS (Review Loop M5, spec §5.2). */
|
|
272
|
+
export interface SubmitRevisionInput {
|
|
273
|
+
/** Review id (rr_…). */
|
|
274
|
+
id: string;
|
|
275
|
+
/** The revision the agent composed against (PRIMARY CAS; 409 STALE on mismatch). */
|
|
276
|
+
parent_revision: number;
|
|
277
|
+
/** Optional row-version CAS (defense in depth). */
|
|
278
|
+
version?: number;
|
|
279
|
+
subject?: string;
|
|
280
|
+
/** The canonical new plain-text body (matches `text` on send/reply/forward). */
|
|
281
|
+
text?: string;
|
|
282
|
+
/**
|
|
283
|
+
* DEPRECATED alias for {@link text}, accepted indefinitely so already-shipped
|
|
284
|
+
* callers keep working. Sending BOTH with different content is rejected 400
|
|
285
|
+
* `conflicting_alias` — the server never guesses which bytes you meant.
|
|
286
|
+
*/
|
|
287
|
+
body?: string;
|
|
288
|
+
html?: string;
|
|
289
|
+
/**
|
|
290
|
+
* REPLACES the draft's attachments when present; omit to leave them untouched,
|
|
291
|
+
* pass `[]` to clear them. Without this a redraft after reviewer feedback could
|
|
292
|
+
* never restore a file the human reviewed the message WITH.
|
|
293
|
+
*/
|
|
294
|
+
attachments?: AttachmentInput[];
|
|
295
|
+
/** When the agent built this draft (informational). */
|
|
296
|
+
built_at?: string;
|
|
297
|
+
/** Rule high-water this draft was composed against (born-stale basis). */
|
|
298
|
+
rules_version_seen?: number;
|
|
299
|
+
/** Stable retry key, sent as Idempotency-Key and never in the JSON body. */
|
|
300
|
+
client_id?: string;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* The D19/§8 re-stamp-without-redraft escape valve ($0). The agent asserts it reviewed
|
|
304
|
+
* the draft against rules `against_version` and no change is needed; the server advances
|
|
305
|
+
* the draft's composed_* rules-versions WITHOUT a new draft.
|
|
306
|
+
*/
|
|
307
|
+
export interface RestampReviewInput {
|
|
308
|
+
/** Review id (rr_…). */
|
|
309
|
+
id: string;
|
|
310
|
+
/** The category rules-version the agent reviewed against (≤ the current version). */
|
|
311
|
+
against_version: number;
|
|
312
|
+
/** Optional: re-stamp the house-style axis to this version (≤ the current version). */
|
|
313
|
+
house_style_version?: number;
|
|
314
|
+
/** Stable retry key, sent as Idempotency-Key and never in the JSON body. */
|
|
315
|
+
client_id?: string;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* A reviewer decision (BYO review-agent plane; D5/§9). `action` is approve|edit|reject|
|
|
319
|
+
* escalate. `revision`/`version` are the optimistic CAS — a mismatch is a 409 STALE with
|
|
320
|
+
* NO mutation (the human always wins, D17). `subject`/`body` carry the edited content for
|
|
321
|
+
* the edit action; `feedback` is the reviewer's note.
|
|
322
|
+
*/
|
|
323
|
+
export interface ReviewerDecideInput {
|
|
324
|
+
/** Review id (rr_…). */
|
|
325
|
+
id: string;
|
|
326
|
+
/** approve | edit | reject | escalate. */
|
|
327
|
+
action: ReviewerAction;
|
|
328
|
+
/** The revision you decided against (PRIMARY CAS; 409 STALE on mismatch). */
|
|
329
|
+
revision: number;
|
|
330
|
+
/** Optional row-version CAS (defense in depth). */
|
|
331
|
+
version?: number;
|
|
332
|
+
/** Edited subject (edit action). */
|
|
333
|
+
subject?: string;
|
|
334
|
+
/** Edited body text (edit action). */
|
|
335
|
+
body?: string;
|
|
336
|
+
/** Reviewer note (reject: the rule-birth signal; escalate: the human-facing reason). */
|
|
337
|
+
feedback?: string;
|
|
338
|
+
}
|
|
339
|
+
/** Filters for draining/waiting on review events (Review Loop, spec §5.9). */
|
|
340
|
+
export interface ListReviewEventsInput {
|
|
341
|
+
/** Restrict the drain to one review's events (rr_…). */
|
|
342
|
+
review_id?: string;
|
|
343
|
+
/** Max events to return in one drain. */
|
|
344
|
+
limit?: number;
|
|
345
|
+
}
|
|
346
|
+
/** Long-poll input: like {@link ListReviewEventsInput} plus a wait budget. */
|
|
347
|
+
export interface WaitForReviewEventInput extends ListReviewEventsInput {
|
|
348
|
+
/** Long-poll budget in seconds (default ~30, capped ~55). */
|
|
349
|
+
wait_seconds?: number;
|
|
350
|
+
}
|
|
351
|
+
/** One per-(agent, review) cursor advance for ack_review_event. */
|
|
352
|
+
export interface AckReviewEventEntry {
|
|
353
|
+
review_id: string;
|
|
354
|
+
through_seq: number;
|
|
355
|
+
}
|
|
356
|
+
/** Propose a new category (Review Loop registry, D9). */
|
|
357
|
+
export interface ProposeCategoryInput {
|
|
358
|
+
name: string;
|
|
359
|
+
description?: string;
|
|
360
|
+
/** Defaults to org_shared server-side. */
|
|
361
|
+
scope?: "org_shared" | "agent_private";
|
|
362
|
+
}
|
|
363
|
+
/** Rename / re-describe a category — metadata only (D10). */
|
|
364
|
+
export interface UpdateCategoryInput {
|
|
365
|
+
id: string;
|
|
366
|
+
name?: string;
|
|
367
|
+
description?: string;
|
|
368
|
+
}
|
|
369
|
+
/** Get the ordered writing-rule set (Review Loop, §7). */
|
|
370
|
+
export interface GetRulesInput {
|
|
371
|
+
/** Category id (cat_…). Empty returns ONLY the house-style/general layer. */
|
|
372
|
+
category_id?: string;
|
|
373
|
+
/** Narrow to one layer (general | category). Default returns both. */
|
|
374
|
+
scope?: "general" | "category";
|
|
375
|
+
}
|
|
376
|
+
/** Save / edit a writing rule (append-only by supersession, D11). */
|
|
377
|
+
export interface SaveRuleInput {
|
|
378
|
+
/** Defaults from category_id (general iff empty). */
|
|
379
|
+
scope?: "general" | "category";
|
|
380
|
+
/** Category id (cat_…); empty = house-style/general (D2). */
|
|
381
|
+
category_id?: string;
|
|
382
|
+
rule_text: string;
|
|
383
|
+
/** Defaults soft. hard = non-overridable. */
|
|
384
|
+
kind?: "soft" | "hard";
|
|
385
|
+
priority?: number;
|
|
386
|
+
source_review_id?: string;
|
|
387
|
+
source_turn_id?: string;
|
|
388
|
+
/** Set to EDIT the prior version (rule_…). */
|
|
389
|
+
supersedes_id?: string;
|
|
390
|
+
/** Set for a per-agent override; empty = all org agents. */
|
|
391
|
+
scope_agent_id?: string;
|
|
392
|
+
/** D8 retro-propagation HUMAN OPT-IN (default false): propagate a NEW category rule to pending siblings. */
|
|
393
|
+
propagate_to_pending?: boolean;
|
|
394
|
+
/** Override the propagate batch (0 = base 3, bounded by rework_batch_max). */
|
|
395
|
+
suggested_batch?: number;
|
|
396
|
+
}
|
|
397
|
+
/** Read the rule/category change audit log (D11). */
|
|
398
|
+
export interface GetRuleAuditInput {
|
|
399
|
+
entity_kind?: "rule" | "category";
|
|
400
|
+
entity_id?: string;
|
|
401
|
+
}
|
|
402
|
+
/** Ack input: advance per-review cursor(s) and/or mark broadcast nudges done. */
|
|
403
|
+
export interface AckReviewEventInput {
|
|
404
|
+
acks?: AckReviewEventEntry[];
|
|
405
|
+
broadcast_ids?: string[];
|
|
406
|
+
}
|
|
407
|
+
export interface AddContactListInput {
|
|
408
|
+
inbox: string;
|
|
409
|
+
kind: ContactListKind;
|
|
410
|
+
/** Defaults to "send" server-side. */
|
|
411
|
+
direction?: ContactListDirection;
|
|
412
|
+
/** A bare email address or a bare domain. */
|
|
413
|
+
pattern: string;
|
|
414
|
+
}
|
|
415
|
+
/** Filters for listing the caller's own org suppression rows (`GET /v1/suppressions`). */
|
|
416
|
+
export interface ListSuppressionsInput {
|
|
417
|
+
/** Narrow to one scope; the agent plane only ever returns `org` rows. */
|
|
418
|
+
scope?: "org" | "shared_domain" | "global";
|
|
419
|
+
/** Include revoked rows too (default: active rows only). */
|
|
420
|
+
include_revoked?: boolean;
|
|
421
|
+
limit?: number;
|
|
422
|
+
/** Opaque cursor from a previous page's next_cursor. */
|
|
423
|
+
cursor?: string;
|
|
424
|
+
}
|
|
425
|
+
/** Onboarding modes the agent-facing domains API accepts. */
|
|
426
|
+
export type DomainOnboardMode = "shared" | "ns_delegated" | "manual" | "purchased";
|
|
427
|
+
export interface OnboardDomainInput {
|
|
428
|
+
domain: string;
|
|
429
|
+
/**
|
|
430
|
+
* Onboarding path. Defaults to ns_delegated server-side when omitted. `mode:
|
|
431
|
+
* "purchased"` spends money at the registrar and therefore requires BOTH the
|
|
432
|
+
* `domain:manage` scope (the route gate) AND the explicit, default-off
|
|
433
|
+
* `domain:purchase` scope (it is additionally bounded by the org/project
|
|
434
|
+
* purchased-domain cap). `manual` and `ns_delegated` need `domain:manage` only.
|
|
435
|
+
*/
|
|
436
|
+
mode?: DomainOnboardMode;
|
|
437
|
+
/** A-record IP served at a delegated zone's apex (ns_delegated only). */
|
|
438
|
+
mail_host_ip?: string;
|
|
439
|
+
/**
|
|
440
|
+
* Domain visibility. `org` (default) makes it usable by every project in the
|
|
441
|
+
* org; `project` binds it to the key's OWN bound project (never client-selected)
|
|
442
|
+
* so it is only visible/mintable from that project. A legacy/unscoped key falls
|
|
443
|
+
* back to `org`.
|
|
444
|
+
*/
|
|
445
|
+
scope?: "org" | "project";
|
|
446
|
+
/**
|
|
447
|
+
* Optional assertion that must match the key's bound project — NEVER a
|
|
448
|
+
* selector. A mismatch is rejected server-side; the binding is always derived
|
|
449
|
+
* from the key.
|
|
450
|
+
*/
|
|
451
|
+
project_id?: string;
|
|
452
|
+
}
|
|
453
|
+
export interface WaitForEmailInput {
|
|
454
|
+
inbox: string;
|
|
455
|
+
from?: string;
|
|
456
|
+
subject?: string;
|
|
457
|
+
/** Case-sensitive Go RE2 expression over subject+body (maps to the API `match` field); use a leading `(?i)` for case-insensitive matching. */
|
|
458
|
+
regex?: string;
|
|
459
|
+
/** Prefer an extracted link containing this substring. */
|
|
460
|
+
link_hint?: string;
|
|
461
|
+
/** Only match arrivals after the wait begins (default true). */
|
|
462
|
+
since_now?: boolean;
|
|
463
|
+
timeout_ms: number;
|
|
464
|
+
}
|
|
465
|
+
export declare class ExtrovertClient {
|
|
466
|
+
private readonly config;
|
|
467
|
+
private readonly store?;
|
|
468
|
+
private apiKey;
|
|
469
|
+
constructor(config: ExtrovertConfig);
|
|
470
|
+
get isMock(): boolean;
|
|
471
|
+
redeemEnrollment(input: RedeemEnrollmentInput): Promise<EnrollmentResult>;
|
|
472
|
+
/** Grab a free account: `POST /v1/agent/sign-up` (unauthenticated). */
|
|
473
|
+
signUp(input: {
|
|
474
|
+
human_email: string;
|
|
475
|
+
username?: string;
|
|
476
|
+
}): Promise<SignUpResult>;
|
|
477
|
+
/** Confirm the signup OTP and elevate scope: `POST /v1/agent/verify`. */
|
|
478
|
+
verify(input: {
|
|
479
|
+
otp: string;
|
|
480
|
+
}): Promise<VerifyResult>;
|
|
481
|
+
/** Introspect the principal behind the current key: `GET /v1/auth/me`. */
|
|
482
|
+
whoami(): Promise<WhoAmI>;
|
|
483
|
+
createInbox(input: CreateInboxInput): Promise<Inbox>;
|
|
484
|
+
/**
|
|
485
|
+
* List the agent's inboxes (redesign §4.1 bare-vs-wildcard semantics).
|
|
486
|
+
*
|
|
487
|
+
* Scope is in the KEY. By tier:
|
|
488
|
+
* - project/inbox key → that project's inboxes. Addressed via the canonical
|
|
489
|
+
* project-prefixed envelope `GET /v1/projects/{project_id}/inboxes` (the §5.2
|
|
490
|
+
* `{object:"list", data, has_more, next_cursor}` shape) when a project is
|
|
491
|
+
* resolved; otherwise the bare `/v1/inboxes` curl-sugar form (which resolves
|
|
492
|
+
* to the key's default project and returns the legacy `{inboxes, next_page}`).
|
|
493
|
+
* - org key → MUST pick a breadth: pass `project` (a concrete id) or
|
|
494
|
+
* `wildcard:true` (`/v1/projects/-/inboxes`, the org subtree). A bare org-key
|
|
495
|
+
* list is a 400 `breadth_required` (mirrors the server choke-point) — we fail
|
|
496
|
+
* fast client-side with the same code so the agent sees the next call to make.
|
|
497
|
+
*
|
|
498
|
+
* Either wire shape is normalized into the internal {@link Page}.
|
|
499
|
+
*/
|
|
500
|
+
listInboxes(opts?: {
|
|
501
|
+
limit?: number;
|
|
502
|
+
project?: string;
|
|
503
|
+
wildcard?: boolean;
|
|
504
|
+
cursor?: string;
|
|
505
|
+
} | number): Promise<Page<Inbox>>;
|
|
506
|
+
/** The ceiling tier encoded in the current session's agent key (redesign §3.1). */
|
|
507
|
+
keyTier(): KeyTier;
|
|
508
|
+
getInbox(idOrAddress: string): Promise<Inbox>;
|
|
509
|
+
/**
|
|
510
|
+
* Update an inbox's settings in place: `PATCH /v1/inboxes/{inbox_id}` with
|
|
511
|
+
* `{display_name?, webhook_url?, daily_send_limit?, metadata?, project_id?}`. The agent-facing
|
|
512
|
+
* `inbound_webhook_url` maps to the API's `webhook_url`. `metadata` is a shallow
|
|
513
|
+
* merge: omit it to leave metadata unchanged; an object merges (a `null` value
|
|
514
|
+
* deletes that key); a top-level `null` clears ALL metadata. Owner-scoped
|
|
515
|
+
* server-side. Changing `daily_send_limit` requires the opt-in `mailbox:quota`
|
|
516
|
+
* scope. Returns the updated inbox with the effective enforced cap.
|
|
517
|
+
*/
|
|
518
|
+
updateInbox(idOrAddress: string, input: UpdateInboxInput): Promise<Inbox>;
|
|
519
|
+
getCredentials(idOrAddress: string): Promise<MailboxCredentials>;
|
|
520
|
+
/**
|
|
521
|
+
* Permanently delete an inbox and its messages/sender identity. Requires
|
|
522
|
+
* `mailbox:delete`; this cannot be undone.
|
|
523
|
+
*/
|
|
524
|
+
deleteInbox(idOrAddress: string): Promise<{
|
|
525
|
+
id: string;
|
|
526
|
+
deleted: true;
|
|
527
|
+
}>;
|
|
528
|
+
/**
|
|
529
|
+
* Send a new message WITHOUT the review overload.
|
|
530
|
+
*
|
|
531
|
+
* The return type is a union because the endpoint has two outcomes and the
|
|
532
|
+
* account's policy — not the caller — picks between them. This used to be typed
|
|
533
|
+
* `Promise<Message>` and rendered as a message header, which was garbage against
|
|
534
|
+
* every real response: the server has never returned a Message here. It returns
|
|
535
|
+
* `{status:"sent", message_id, review_id}` on the policy's direct path, and the
|
|
536
|
+
* §5.1 `{kind:"queued_for_review", review}` envelope (HTTP 202) when the policy
|
|
537
|
+
* queues it — which, under the `require_review` default, is the normal outcome.
|
|
538
|
+
*
|
|
539
|
+
* A send with no `intent` under `require_review` never reaches either arm: it is
|
|
540
|
+
* refused with 422 `intent_required` and NOTHING is sent or queued.
|
|
541
|
+
*/
|
|
542
|
+
sendEmail(input: SendEmailInput): Promise<SendEmailResult>;
|
|
543
|
+
/**
|
|
544
|
+
* Thread-aware reply. Canonical contract:
|
|
545
|
+
* `POST /v1/inboxes/{inbox_id}/reply` with `{thread_id|message_id, text, html?, cc?,
|
|
546
|
+
* bcc?, reply_to?, reply_all?}`. The server derives To/Subject/In-Reply-To/
|
|
547
|
+
* References and returns `{message_id, thread_id, review_id}`. No `to` is sent.
|
|
548
|
+
*
|
|
549
|
+
* Like {@link sendEmail} the outcome is policy-decided: a bare reply under
|
|
550
|
+
* `require_review` is QUEUED (202 `{kind:"queued_for_review"}`), not sent, and a
|
|
551
|
+
* bare reply with no intent is refused 422 `intent_required`.
|
|
552
|
+
*/
|
|
553
|
+
replyEmail(input: ReplyEmailInput): Promise<ReplyEmailResult>;
|
|
554
|
+
/**
|
|
555
|
+
* Forward an existing message to new recipients, preserving the original.
|
|
556
|
+
* `POST /v1/inboxes/{inbox_id}/messages/{id}/forward` `{to[], cc?, bcc?, text?, html?}`.
|
|
557
|
+
* `html` is accepted but ignored: the server materializes one plain-text body
|
|
558
|
+
* containing both the note and quoted parent, so HTML clients cannot hide the quote.
|
|
559
|
+
*
|
|
560
|
+
* Policy-decided like send and reply: a bare forward under `require_review` is
|
|
561
|
+
* QUEUED, and one with no intent is refused 422 `intent_required`.
|
|
562
|
+
*/
|
|
563
|
+
forwardEmail(input: ForwardEmailInput): Promise<ReplyEmailResult>;
|
|
564
|
+
/**
|
|
565
|
+
* Submit a forward for human review — the SAME endpoint as {@link forwardEmail}
|
|
566
|
+
* with mode/intent/category_id attached, mirroring how send and reply overload.
|
|
567
|
+
* Returns the discriminated §5.1 envelope (queued OR sent).
|
|
568
|
+
*/
|
|
569
|
+
submitForwardForReview(input: SubmitForwardForReviewInput): Promise<SubmitForReviewResult>;
|
|
570
|
+
/**
|
|
571
|
+
* Submit a new message for human review (`POST /v1/inboxes/{inbox_id}/send` with
|
|
572
|
+
* mode/intent/category_id). The server routes per the account/inbox review
|
|
573
|
+
* policy and returns either `{kind:"queued_for_review"}` (202) or
|
|
574
|
+
* `{kind:"sent"}` (200, policy-permitted direct/graduated path).
|
|
575
|
+
*/
|
|
576
|
+
submitForReview(input: SubmitForReviewInput): Promise<SubmitForReviewResult>;
|
|
577
|
+
/**
|
|
578
|
+
* Submit an in-thread reply for human review (`POST /v1/inboxes/{inbox_id}/reply`
|
|
579
|
+
* with mode/intent/category_id). Same routing/return contract as submitForReview.
|
|
580
|
+
*/
|
|
581
|
+
submitReplyForReview(input: SubmitReplyForReviewInput): Promise<SubmitForReviewResult>;
|
|
582
|
+
/** List review requests (`GET /v1/reviews`). Customer-scoped; agent monitors its submissions. */
|
|
583
|
+
listReviews(input?: ListReviewsInput): Promise<Page<Review>>;
|
|
584
|
+
/** Get one review request (`GET /v1/reviews/{id}`) — current draft + intent + state. */
|
|
585
|
+
getReview(id: string): Promise<Review>;
|
|
586
|
+
/** Get a review's append-only thread turns (`GET /v1/reviews/{id}/turns`). */
|
|
587
|
+
getReviewTurns(id: string): Promise<Page<ReviewTurn>>;
|
|
588
|
+
/**
|
|
589
|
+
* Get the human's assembled feedback for a review (`GET /v1/reviews/{id}/feedback`):
|
|
590
|
+
* the unified + structured diff, the human comments, the decision, and the rules born
|
|
591
|
+
* from this review (rule_ ids). Read-only; $0 LLM (pure assembly).
|
|
592
|
+
*/
|
|
593
|
+
getReviewFeedback(id: string): Promise<ReviewFeedback>;
|
|
594
|
+
/**
|
|
595
|
+
* Post a chat turn on a review's thread (`POST /v1/reviews/{id}/chat`): append an
|
|
596
|
+
* agent_question turn, flip in_review -> chatting on the first turn, enqueue a
|
|
597
|
+
* feedback_added nudge to the human reviewer + emit review.chat. Idempotent on the
|
|
598
|
+
* client-supplied key. $0 LLM — YOU compose the question.
|
|
599
|
+
*/
|
|
600
|
+
postReviewChat(input: PostReviewChatInput): Promise<Review>;
|
|
601
|
+
/**
|
|
602
|
+
* Post a new agent draft under a parent_revision CAS (`POST /v1/reviews/{id}/
|
|
603
|
+
* revision`). parent_revision must equal the draft's current revision, else 409
|
|
604
|
+
* STALE with NO mutation (D17). On a clean CAS the draft is re-rendered in place
|
|
605
|
+
* (revision++), returned to needs_review, and the reviewer is nudged. $0 LLM — YOU
|
|
606
|
+
* compose the redraft.
|
|
607
|
+
*/
|
|
608
|
+
submitRevision(input: SubmitRevisionInput): Promise<Review>;
|
|
609
|
+
/**
|
|
610
|
+
* Withdraw a pending review (`POST /v1/reviews/{id}/cancel`): the composing agent
|
|
611
|
+
* cancels its own review to the terminal cancelled state. A foreign id / another
|
|
612
|
+
* agent's draft 404s; a terminal review 409s.
|
|
613
|
+
*/
|
|
614
|
+
cancelReview(input: {
|
|
615
|
+
id: string;
|
|
616
|
+
client_id?: string;
|
|
617
|
+
}): Promise<Review>;
|
|
618
|
+
/**
|
|
619
|
+
* Re-stamp a draft's rules-version WITHOUT redrafting (`POST /v1/reviews/{id}/
|
|
620
|
+
* restamp`; D19/§8 $0 escape valve). Assert "reviewed against vX, no change needed"
|
|
621
|
+
* and the server advances the draft's composed_* versions with no new draft, no
|
|
622
|
+
* revision bump, no nudge. against_version above the category's current rules-version
|
|
623
|
+
* is 400; a terminal/sent draft 409s.
|
|
624
|
+
*/
|
|
625
|
+
restampReview(input: RestampReviewInput): Promise<Review>;
|
|
626
|
+
/**
|
|
627
|
+
* Get the REVIEWER's decision context for a review (`GET /v1/reviews/{id}/
|
|
628
|
+
* decision-context`; BYO review-agent plane, D5/§9). The reviewer's read-only view:
|
|
629
|
+
* the intent + current draft + thread + the two-circuit-breaker budget (hop_count vs
|
|
630
|
+
* max_hops, the hard review_deadline). Requires review:act + a matching active link;
|
|
631
|
+
* a cross-tenant id is 404, a non-reviewer is 403. `force_to_human` is true when a
|
|
632
|
+
* reject would be FORCED to the human regardless of intent (D17).
|
|
633
|
+
*/
|
|
634
|
+
getReviewDecisionContext(id: string): Promise<ReviewDecisionContext>;
|
|
635
|
+
/**
|
|
636
|
+
* Submit a reviewer decision (`POST /v1/reviews/{id}/decision`; reviewer_decide,
|
|
637
|
+
* D5/§9). approve/edit → the PLATFORM ACS-sends with the COMPOSER's creds (the
|
|
638
|
+
* reviewer NEVER holds mailbox:send — the credential boundary); reject → back to the
|
|
639
|
+
* composer (needs_review, hop_count++); escalate → the human queue. revision/version
|
|
640
|
+
* are the CAS (409 STALE on mismatch, NO mutation — the human always wins, D17). The
|
|
641
|
+
* two circuit breakers (hop_count ≥ max_hops, or the hard review_deadline) FORCE a
|
|
642
|
+
* reject to the human regardless of intent — `forced_by_breaker` names it. $0 LLM —
|
|
643
|
+
* you judged; we route, send, and enforce the breakers.
|
|
644
|
+
*/
|
|
645
|
+
reviewerDecide(input: ReviewerDecideInput): Promise<ReviewerDecisionResult>;
|
|
646
|
+
/**
|
|
647
|
+
* Drain the next un-acked review events (`GET /v1/reviews/events`). Non-blocking;
|
|
648
|
+
* returns the FIFO-ordered nudges + per-review cursors. Side-effect free.
|
|
649
|
+
*/
|
|
650
|
+
listReviewEvents(input?: ListReviewEventsInput): Promise<ReviewEventsResult>;
|
|
651
|
+
/**
|
|
652
|
+
* Long-poll for a review event (`GET /v1/reviews/events/wait`). Blocks ~25–55s
|
|
653
|
+
* until a nudge is available OR the deadline, then returns like
|
|
654
|
+
* {@link listReviewEvents} (empty on timeout).
|
|
655
|
+
*/
|
|
656
|
+
waitForReviewEvent(input?: WaitForReviewEventInput): Promise<ReviewEventsResult>;
|
|
657
|
+
/**
|
|
658
|
+
* Ack review events (`POST /v1/reviews/events/ack`): advance per-(agent, review)
|
|
659
|
+
* cursor(s) and/or mark broadcast nudges done. Idempotent + monotonic.
|
|
660
|
+
*/
|
|
661
|
+
ackReviewEvent(input: AckReviewEventInput): Promise<{
|
|
662
|
+
cursors: ReviewEventsResult["cursors"];
|
|
663
|
+
}>;
|
|
664
|
+
/**
|
|
665
|
+
* Browse the category registry (`GET /v1/categories?match=`). Returns id + name +
|
|
666
|
+
* description + scope + state for fuzzy matching. `match` is a pure lexical filter
|
|
667
|
+
* (NO LLM on our side) — the agent does the semantic match. Customer-scoped.
|
|
668
|
+
*/
|
|
669
|
+
listCategories(match?: string): Promise<Page<Category>>;
|
|
670
|
+
/** Get one category (`GET /v1/categories/{id}`). A foreign id is 404. */
|
|
671
|
+
getCategory(id: string): Promise<Category>;
|
|
672
|
+
/**
|
|
673
|
+
* Propose a new category (`POST /v1/categories`). It stands immediately
|
|
674
|
+
* (author_kind=agent) and writes a create audit/undo row. Match the registry
|
|
675
|
+
* first so you do not duplicate an existing bucket.
|
|
676
|
+
*/
|
|
677
|
+
proposeCategory(input: ProposeCategoryInput): Promise<Category>;
|
|
678
|
+
/**
|
|
679
|
+
* Rename / re-describe a category (`PUT /v1/categories/{id}`) — metadata ONLY
|
|
680
|
+
* (D10). Renaming never breaks a reference; a rename/redescribe undo row is
|
|
681
|
+
* written. Any agent in the customer may edit (the shared-registry exception).
|
|
682
|
+
*/
|
|
683
|
+
updateCategory(input: UpdateCategoryInput): Promise<Category>;
|
|
684
|
+
/**
|
|
685
|
+
* Read the effective risk dial (`GET /v1/risk-dial`): the account default + every
|
|
686
|
+
* category's overrides (each with its resolved effective value; null override =
|
|
687
|
+
* inherit). Read-only — agents read but NEVER flip the dial (setting it is a human
|
|
688
|
+
* console action; D16).
|
|
689
|
+
*/
|
|
690
|
+
getRiskDial(): Promise<RiskDial>;
|
|
691
|
+
/**
|
|
692
|
+
* Read a category's graduation gate status (`GET /v1/categories/{id}/graduation-
|
|
693
|
+
* status`): the gates passed / still needed toward the next rung (approvals N/needed,
|
|
694
|
+
* age, maturity gate, drift vs K, can_graduate). Read-only.
|
|
695
|
+
*/
|
|
696
|
+
getGraduationStatus(categoryId: string): Promise<GraduationStatus>;
|
|
697
|
+
/**
|
|
698
|
+
* Propose graduating a category (`POST /v1/categories/{id}/graduation-request`).
|
|
699
|
+
* RECORDS the request (durable evidence) and returns the current gate status; it
|
|
700
|
+
* does NOT change the category state — flipping the bit is a human (console) action
|
|
701
|
+
* (D16/D6). A never_graduate category stays locked.
|
|
702
|
+
*/
|
|
703
|
+
proposeGraduation(categoryId: string, evidence?: Record<string, unknown>): Promise<GraduationStatus>;
|
|
704
|
+
/**
|
|
705
|
+
* Read the D19/§8 backlog-reconciliation status (`GET /v1/categories/{id}/
|
|
706
|
+
* backlog-status`): how many QUEUED drafts are stale vs current-enough against the
|
|
707
|
+
* current rules-version (a pure $0-LLM integer compare). Read-only — agents READ the
|
|
708
|
+
* picture; the human (console scan-backlog) / hooks TRIGGER the actual sweep.
|
|
709
|
+
*/
|
|
710
|
+
getBacklogStatus(categoryId: string): Promise<ScanBacklogStatus>;
|
|
711
|
+
/**
|
|
712
|
+
* Read the demand-driven pacing state (`GET /v1/categories/{id}/pacing-state`;
|
|
713
|
+
* M7 Slice B/§8): the human review cursor, the effective window/ceiling/interval, and
|
|
714
|
+
* each queued draft's in-window/redrafting/behind-cursor classification. Read-only;
|
|
715
|
+
* the cursor advances from the human's console approve/reject/edit actions.
|
|
716
|
+
*/
|
|
717
|
+
getPacingState(categoryId: string): Promise<CategoryPacingState>;
|
|
718
|
+
/**
|
|
719
|
+
* Get the ORDERED active rule set (`GET /v1/rules?category_id=&scope=`). The §7
|
|
720
|
+
* precedence ladder is applied SERVER-SIDE (NO LLM): hard>soft; per-agent>category>
|
|
721
|
+
* general; human>agent; newest rev/created_at; higher priority; plus a soft cap.
|
|
722
|
+
* Includes the general/house-style layer (D2) IN ADDITION to the category's rules.
|
|
723
|
+
*/
|
|
724
|
+
getRules(input?: GetRulesInput): Promise<Page<Rule>>;
|
|
725
|
+
/**
|
|
726
|
+
* Save / edit a writing rule (`PUT /v1/rules`) — append-only by supersession (D11).
|
|
727
|
+
* scope='general' iff category_id is empty (house-style, D2). With supersedes_id
|
|
728
|
+
* the write is an EDIT (rev+1, same lineage). Writes a create/supersede audit row.
|
|
729
|
+
*/
|
|
730
|
+
saveRule(input: SaveRuleInput): Promise<Rule>;
|
|
731
|
+
/**
|
|
732
|
+
* Promote a rule between the category and general/house-style layers
|
|
733
|
+
* (`POST /v1/rules/{id}/promote`) via a supersession.
|
|
734
|
+
*/
|
|
735
|
+
promoteRule(id: string, toScope: "general" | "category"): Promise<Rule>;
|
|
736
|
+
/** Retire a rule (`POST /v1/rules/{id}/retire`) — soft delete; history survives. */
|
|
737
|
+
retireRule(id: string): Promise<Rule>;
|
|
738
|
+
/**
|
|
739
|
+
* Read the rule/category change audit log (`GET /v1/rules/audit`) — read-only,
|
|
740
|
+
* agent-visible (the audit log is the shared safety net, D11).
|
|
741
|
+
*/
|
|
742
|
+
getRuleAudit(input?: GetRuleAuditInput): Promise<Page<RuleAuditEntry>>;
|
|
743
|
+
/**
|
|
744
|
+
* Undo a rule change (`POST /v1/rules/audit/{udo_id}/undo`) — restore the prior
|
|
745
|
+
* version as a forward 'restore' supersession (D11; agents may undo too).
|
|
746
|
+
* Idempotent: a re-undo of an already-undone row is a clean 409.
|
|
747
|
+
*/
|
|
748
|
+
undoRuleChange(udoId: string): Promise<Rule>;
|
|
749
|
+
/**
|
|
750
|
+
* List messages in an inbox, newest-first. Canonical contract:
|
|
751
|
+
* `GET /v1/inboxes/{inbox_id}/messages` with optional exact-field filters
|
|
752
|
+
* (from/to/subject), an `unread=true` filter (native IMAP \Seen), and
|
|
753
|
+
* limit/offset paging. Returns the canonical `Page<Message>` ({items,total}).
|
|
754
|
+
*/
|
|
755
|
+
listMessages(input: {
|
|
756
|
+
inbox: string;
|
|
757
|
+
limit?: number;
|
|
758
|
+
offset?: number;
|
|
759
|
+
unread_only?: boolean;
|
|
760
|
+
from?: string;
|
|
761
|
+
to?: string;
|
|
762
|
+
subject?: string;
|
|
763
|
+
}): Promise<Page<Message>>;
|
|
764
|
+
/** Fetch a single message by its opaque id (`GET /v1/messages/{id}`). */
|
|
765
|
+
getMessage(id: string): Promise<Message>;
|
|
766
|
+
/**
|
|
767
|
+
* List a message's attachment metadata
|
|
768
|
+
* (`GET /v1/inboxes/{inbox_id}/messages/{id}/attachments` → `Page<Attachment>`).
|
|
769
|
+
*/
|
|
770
|
+
listAttachments(input: {
|
|
771
|
+
inbox: string;
|
|
772
|
+
message_id: string;
|
|
773
|
+
}): Promise<Page<Attachment>>;
|
|
774
|
+
/**
|
|
775
|
+
* Download one attachment's bytes (base64) + metadata
|
|
776
|
+
* (`GET /v1/inboxes/{inbox_id}/messages/{id}/attachments/{attId}` → raw bytes with
|
|
777
|
+
* Content-Type + Content-Disposition). The "easy attachment fetch."
|
|
778
|
+
*/
|
|
779
|
+
getAttachment(input: {
|
|
780
|
+
inbox: string;
|
|
781
|
+
message_id: string;
|
|
782
|
+
attachment_id: string;
|
|
783
|
+
}): Promise<AttachmentDownload>;
|
|
784
|
+
/**
|
|
785
|
+
* Mark a message read/unread via the native IMAP \Seen flag
|
|
786
|
+
* (`PATCH /v1/inboxes/{inbox_id}/messages/{id}` {read}). The inbox is resolved
|
|
787
|
+
* from the message id. Returns the updated message.
|
|
788
|
+
*/
|
|
789
|
+
markRead(input: {
|
|
790
|
+
inbox: string;
|
|
791
|
+
id: string;
|
|
792
|
+
read: boolean;
|
|
793
|
+
}): Promise<Message>;
|
|
794
|
+
listThreads(input: {
|
|
795
|
+
inbox: string;
|
|
796
|
+
limit?: number;
|
|
797
|
+
}): Promise<Page<Thread>>;
|
|
798
|
+
/**
|
|
799
|
+
* Fetch one thread (with its messages, oldest-first) by stable id, scoped to
|
|
800
|
+
* the owning inbox: `GET /v1/inboxes/{inbox_id}/threads/{id}`.
|
|
801
|
+
*/
|
|
802
|
+
getThread(input: {
|
|
803
|
+
inbox: string;
|
|
804
|
+
thread_id: string;
|
|
805
|
+
}): Promise<ThreadDetail>;
|
|
806
|
+
/**
|
|
807
|
+
* Delete a message: move it to Trash, or permanently expunge it when
|
|
808
|
+
* `expunge` is set (`DELETE /v1/inboxes/{inbox_id}/messages/{id}?expunge=`). A
|
|
809
|
+
* message already in Trash is always expunged.
|
|
810
|
+
*/
|
|
811
|
+
deleteMessage(input: {
|
|
812
|
+
inbox: string;
|
|
813
|
+
id: string;
|
|
814
|
+
expunge?: boolean;
|
|
815
|
+
}): Promise<DeleteResult>;
|
|
816
|
+
/**
|
|
817
|
+
* Delete an entire thread (every message): move to Trash, or expunge when
|
|
818
|
+
* `expunge` is set (`DELETE /v1/inboxes/{inbox_id}/threads/{id}?expunge=`).
|
|
819
|
+
*/
|
|
820
|
+
deleteThread(input: {
|
|
821
|
+
inbox: string;
|
|
822
|
+
thread_id: string;
|
|
823
|
+
expunge?: boolean;
|
|
824
|
+
}): Promise<DeleteResult>;
|
|
825
|
+
/**
|
|
826
|
+
* Batch mark read/unread and/or move folder for a list of message ids in one
|
|
827
|
+
* inbox (`PATCH /v1/inboxes/{inbox_id}/messages/batch`). At least one of
|
|
828
|
+
* `read` / `folder` must be set; returns the per-id `{updated, failed}` split.
|
|
829
|
+
*/
|
|
830
|
+
batchUpdateMessages(input: {
|
|
831
|
+
inbox: string;
|
|
832
|
+
ids: string[];
|
|
833
|
+
read?: boolean;
|
|
834
|
+
folder?: string;
|
|
835
|
+
}): Promise<BatchUpdateResult>;
|
|
836
|
+
/**
|
|
837
|
+
* Full-text search backed by IMAP SEARCH, scoped to one inbox
|
|
838
|
+
* (`GET /v1/inboxes/{inbox_id}/messages/search?q=...`). When `inbox` is omitted,
|
|
839
|
+
* iterate every inbox the agent owns and merge the results (newest-first).
|
|
840
|
+
*/
|
|
841
|
+
search(input: {
|
|
842
|
+
query: string;
|
|
843
|
+
inbox?: string;
|
|
844
|
+
limit?: number;
|
|
845
|
+
}): Promise<Page<Message>>;
|
|
846
|
+
waitForEmail(input: WaitForEmailInput): Promise<WaitForEmailResult>;
|
|
847
|
+
/**
|
|
848
|
+
* Register an inbound webhook (`POST /v1/webhooks`). The signing `secret` is
|
|
849
|
+
* returned ONCE here; deliveries are HMAC-signed in the canonical
|
|
850
|
+
* `X-Extrovert-Signature: t=<unix>,v1=<hex>` format.
|
|
851
|
+
*/
|
|
852
|
+
registerWebhook(input: RegisterWebhookInput): Promise<Webhook>;
|
|
853
|
+
/** List registered webhooks (`GET /v1/webhooks`); secrets are redacted. */
|
|
854
|
+
listWebhooks(): Promise<Page<Webhook>>;
|
|
855
|
+
/** Get one webhook by id (`GET /v1/webhooks/{id}`); secret redacted. */
|
|
856
|
+
getWebhook(id: string): Promise<Webhook>;
|
|
857
|
+
/**
|
|
858
|
+
* Update a webhook in place (`PATCH /v1/webhooks/{id}`). Every field is
|
|
859
|
+
* optional; an omitted field is left unchanged (PATCH semantics). The signing
|
|
860
|
+
* secret is immutable and stays redacted in the response.
|
|
861
|
+
*/
|
|
862
|
+
updateWebhook(id: string, input: {
|
|
863
|
+
url?: string;
|
|
864
|
+
events?: WebhookEvent[];
|
|
865
|
+
inbox?: string;
|
|
866
|
+
active?: boolean;
|
|
867
|
+
}): Promise<Webhook>;
|
|
868
|
+
/** Delete a webhook by id (`DELETE /v1/webhooks/{id}`). */
|
|
869
|
+
deleteWebhook(id: string): Promise<{
|
|
870
|
+
id: string;
|
|
871
|
+
deleted: true;
|
|
872
|
+
}>;
|
|
873
|
+
/**
|
|
874
|
+
* Add an allow/block entry to an inbox's contact lists
|
|
875
|
+
* (`POST /v1/inboxes/{inbox_id}/lists`). A `block` entry rejects a matching
|
|
876
|
+
* recipient on send; when an `allow` entry exists, sends from this inbox are
|
|
877
|
+
* restricted to recipients that match one (allowlist mode).
|
|
878
|
+
*/
|
|
879
|
+
addContactListEntry(input: AddContactListInput): Promise<ContactListEntry>;
|
|
880
|
+
/** List the contact-list entries governing an inbox (`GET /v1/inboxes/{inbox_id}/lists`). */
|
|
881
|
+
listContactListEntries(inbox: string): Promise<Page<ContactListEntry>>;
|
|
882
|
+
/** Delete a contact-list entry by id (`DELETE /v1/inboxes/{inbox_id}/lists/{id}`). */
|
|
883
|
+
deleteContactListEntry(inbox: string, id: string): Promise<{
|
|
884
|
+
id: string;
|
|
885
|
+
deleted: true;
|
|
886
|
+
}>;
|
|
887
|
+
/** List the customer's onboarded domains (`GET /v1/domains`). Canonical page envelope. */
|
|
888
|
+
listDomains(): Promise<Page<Domain>>;
|
|
889
|
+
/** Get one domain's detail + verification status + the DNS records to set (`GET /v1/domains/{domain}`). */
|
|
890
|
+
getDomain(domain: string): Promise<Domain>;
|
|
891
|
+
/** Onboard/add a domain for the customer (`POST /v1/domains`). */
|
|
892
|
+
onboardDomain(input: OnboardDomainInput): Promise<Domain>;
|
|
893
|
+
/** Trigger/refresh verification for a domain (`POST /v1/domains/{domain}/verify`). */
|
|
894
|
+
verifyDomain(domain: string): Promise<Domain>;
|
|
895
|
+
/**
|
|
896
|
+
* Offboard (remove) a domain from the customer (`DELETE /v1/domains/{domain}`).
|
|
897
|
+
* The API accepts the request (HTTP 202) and runs the teardown — reaping the
|
|
898
|
+
* outbound provider sender identities + routing rows, then scrubbing the DNS
|
|
899
|
+
* zone/records and the domain row — as an async job. This returns the job id and
|
|
900
|
+
* a poll URL (`status_url`, i.e. `GET /v1/jobs/{job_id}`); offboarding is
|
|
901
|
+
* ACCEPTED, not yet complete. Poll with `getJob(job_id)` (the `get_job` tool)
|
|
902
|
+
* until the status is terminal.
|
|
903
|
+
*/
|
|
904
|
+
offboardDomain(domain: string): Promise<DomainOffboard>;
|
|
905
|
+
/**
|
|
906
|
+
* Poll the status of an async job (`GET /v1/jobs/{job_id}`) — currently only
|
|
907
|
+
* the domain-offboard teardown enqueues one. `status` is terminal on
|
|
908
|
+
* succeeded/failed/cancelled; keep polling otherwise.
|
|
909
|
+
*/
|
|
910
|
+
getJob(jobId: string): Promise<Job>;
|
|
911
|
+
/**
|
|
912
|
+
* Pre-check whether the caller's org suppresses a recipient
|
|
913
|
+
* (`GET /v1/suppressions?recipient=…`). Returns `{recipient, suppressed, rows}`
|
|
914
|
+
* over the caller's OWN active org rows — never a global/shared/cross-tenant
|
|
915
|
+
* opt-out. Use it BEFORE composing to skip a would-be-rejected recipient.
|
|
916
|
+
*/
|
|
917
|
+
precheckSuppression(recipient: string): Promise<SuppressionPrecheck>;
|
|
918
|
+
/**
|
|
919
|
+
* List the caller's own org suppression rows (`GET /v1/suppressions`). No
|
|
920
|
+
* `recipient` is sent here — that param switches the server to the pre-check.
|
|
921
|
+
*/
|
|
922
|
+
listSuppressions(input?: ListSuppressionsInput): Promise<Page<SuppressionEntry>>;
|
|
923
|
+
/**
|
|
924
|
+
* Revoke one org-scope suppression row (`POST /v1/suppressions/{id}/revoke`),
|
|
925
|
+
* re-enabling sending to that recipient. A `reason` is REQUIRED (empty is a 400)
|
|
926
|
+
* and is audit-logged. A foreign/global/shared id is an indistinguishable 404.
|
|
927
|
+
*/
|
|
928
|
+
revokeSuppression(id: string, reason: string): Promise<SuppressionEntry>;
|
|
929
|
+
/**
|
|
930
|
+
* The caller's org deliverability rollup (`GET /v1/reputation`): derived status
|
|
931
|
+
* badge, per-provider/tenant sending status, latest Sends/Bounces/Complaints
|
|
932
|
+
* window, and open-finding count. Read-only; strictly org-scoped. Advisor
|
|
933
|
+
* findings show `unavailable_vdm_disabled` when VDM is off.
|
|
934
|
+
*/
|
|
935
|
+
getReputation(): Promise<ReputationRollup>;
|
|
936
|
+
/**
|
|
937
|
+
* List the caller's org deliverability findings (`GET /v1/reputation/findings`),
|
|
938
|
+
* newest-first, with optional status/severity/domain/sender filters. Read-only.
|
|
939
|
+
*/
|
|
940
|
+
listDeliverabilityFindings(input?: ListDeliverabilityFindingsInput): Promise<Page<ReputationFinding>>;
|
|
941
|
+
private get;
|
|
942
|
+
/**
|
|
943
|
+
* Fetch a binary endpoint (the attachment download) and return its bytes as
|
|
944
|
+
* base64 plus the filename + content type pulled from the response headers.
|
|
945
|
+
* Bypasses the JSON `request` path so arbitrary bytes survive intact.
|
|
946
|
+
*/
|
|
947
|
+
private getBinary;
|
|
948
|
+
private post;
|
|
949
|
+
private del;
|
|
950
|
+
private patch;
|
|
951
|
+
private put;
|
|
952
|
+
private request;
|
|
953
|
+
private setSessionKey;
|
|
954
|
+
}
|
|
955
|
+
export { NotFoundError };
|
|
956
|
+
//# sourceMappingURL=client.d.ts.map
|