@primitivedotdev/sdk 0.33.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.js +3 -3
- package/dist/{api-Dto6GBP0.js → api-2gC06vxj.js} +127 -13
- package/dist/{index-iU6aiuLg.d.ts → index-CBt3RDtQ.d.ts} +395 -13
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/openapi/index.js +1 -1
- package/dist/{operations.generated-BHoPLMUf.js → operations.generated-CZx0VGSj.js} +714 -2
- package/package.json +1 -1
|
@@ -53,6 +53,10 @@ const openapiDocument = {
|
|
|
53
53
|
"name": "Emails",
|
|
54
54
|
"description": "List, inspect, and manage received emails"
|
|
55
55
|
},
|
|
56
|
+
{
|
|
57
|
+
"name": "Search",
|
|
58
|
+
"description": "Semantic and hybrid search across received and sent mail"
|
|
59
|
+
},
|
|
56
60
|
{
|
|
57
61
|
"name": "Sending",
|
|
58
62
|
"description": "Send outbound emails through the Primitive API"
|
|
@@ -1041,7 +1045,14 @@ const openapiDocument = {
|
|
|
1041
1045
|
"post": {
|
|
1042
1046
|
"operationId": "replyToEmail",
|
|
1043
1047
|
"summary": "Reply to an inbound email",
|
|
1044
|
-
"description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody and optional
|
|
1048
|
+
"description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody, optional From override, optional attachments, and optional\n`wait` flag; passing any header or recipient override is\nrejected by the schema (`additionalProperties: false`).\n\nForwards through the same gates as `/send-mail`: the response\nstatus, error envelope, and `idempotent_replay` flag mirror\nthe send-mail contract verbatim.\n",
|
|
1049
|
+
"servers": [{
|
|
1050
|
+
"url": "https://api.primitive.dev/v1",
|
|
1051
|
+
"description": "Attachments-supporting send host (recommended)"
|
|
1052
|
+
}, {
|
|
1053
|
+
"url": "https://www.primitive.dev/api/v1",
|
|
1054
|
+
"description": "Primary host (attachment-free replies only)"
|
|
1055
|
+
}],
|
|
1045
1056
|
"tags": ["Sending"],
|
|
1046
1057
|
"requestBody": {
|
|
1047
1058
|
"required": true,
|
|
@@ -1126,6 +1137,27 @@ const openapiDocument = {
|
|
|
1126
1137
|
}
|
|
1127
1138
|
}
|
|
1128
1139
|
},
|
|
1140
|
+
"/emails/{id}/conversation": {
|
|
1141
|
+
"parameters": [{ "$ref": "#/components/parameters/ResourceId" }],
|
|
1142
|
+
"get": {
|
|
1143
|
+
"operationId": "getConversation",
|
|
1144
|
+
"summary": "Get the conversation an email belongs to",
|
|
1145
|
+
"description": "Returns the full conversation the given inbound email belongs\nto, as ordered, ready-to-prompt turns WITH bodies. It resolves\nthe thread from the email and returns every message oldest-first,\nso an agent that received an email can pass `messages` straight\nto a chat model in one call instead of walking `/threads/{id}`\nplus `/emails/{id}` and `/sent-emails/{id}` per message.\n\nEach message carries a `direction` (`inbound` | `outbound`) and a\nderived `role`: `inbound` -> `user`, `outbound` -> `assistant`\n(your own prior replies). The role mapping assumes the caller\nowns the outbound side, which is the agent-reply case this exists\nfor. If the email has no thread yet (a brand-new message), the\nconversation is just that one message as a single user turn.\n\nThe message list is capped; check `truncated` to detect when\nolder messages were omitted. Consecutive same-role turns are not\nmerged here; that normalization is model-specific and left to the\ncaller.\n",
|
|
1146
|
+
"tags": ["Emails"],
|
|
1147
|
+
"responses": {
|
|
1148
|
+
"200": {
|
|
1149
|
+
"description": "Conversation",
|
|
1150
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
1151
|
+
"type": "object",
|
|
1152
|
+
"properties": { "data": { "$ref": "#/components/schemas/Conversation" } }
|
|
1153
|
+
}] } } }
|
|
1154
|
+
},
|
|
1155
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
1156
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
1157
|
+
"404": { "$ref": "#/components/responses/NotFound" }
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
},
|
|
1129
1161
|
"/endpoints": {
|
|
1130
1162
|
"get": {
|
|
1131
1163
|
"operationId": "listEndpoints",
|
|
@@ -1470,6 +1502,42 @@ const openapiDocument = {
|
|
|
1470
1502
|
"503": { "$ref": "#/components/responses/ServiceUnavailable" }
|
|
1471
1503
|
}
|
|
1472
1504
|
} },
|
|
1505
|
+
"/semantic-search": { "post": {
|
|
1506
|
+
"operationId": "semanticSearch",
|
|
1507
|
+
"summary": "Semantic search across received and sent mail",
|
|
1508
|
+
"description": "Ranked search across both received and sent mail. The `mode`\nfield selects the ranking strategy:\n\n- `keyword`: lexical full-text matching only (no embeddings).\n- `semantic`: meaning-based matching using vector embeddings.\n- `hybrid` (default): blends the semantic and keyword signals.\n\nResults are ordered by a relevance `score`. Every row reports the\nfields it matched (`matched_fields`), a match-centered excerpt per\nfield (`snippets`), and a `score_breakdown` whose components account\nfor the `score`. Page through results by passing the prior\nresponse's `meta.cursor` back as `cursor`.\n\nRequires the Pro plan and the `semantic_search_enabled`\nentitlement; callers without them receive `403`.\n\nHost routing: this operation is served only by the search host\n(`https://api.primitive.dev/v1`). The typed SDKs route it there\nautomatically.\n",
|
|
1509
|
+
"servers": [{
|
|
1510
|
+
"url": "https://api.primitive.dev/v1",
|
|
1511
|
+
"description": "Search host"
|
|
1512
|
+
}],
|
|
1513
|
+
"tags": ["Search"],
|
|
1514
|
+
"requestBody": {
|
|
1515
|
+
"required": true,
|
|
1516
|
+
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/SemanticSearchInput" } } }
|
|
1517
|
+
},
|
|
1518
|
+
"responses": {
|
|
1519
|
+
"200": {
|
|
1520
|
+
"description": "Ranked search results",
|
|
1521
|
+
"content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
|
|
1522
|
+
"type": "object",
|
|
1523
|
+
"properties": {
|
|
1524
|
+
"data": {
|
|
1525
|
+
"type": "array",
|
|
1526
|
+
"items": { "$ref": "#/components/schemas/SemanticSearchResult" }
|
|
1527
|
+
},
|
|
1528
|
+
"meta": { "$ref": "#/components/schemas/SemanticSearchMeta" }
|
|
1529
|
+
},
|
|
1530
|
+
"required": ["data", "meta"]
|
|
1531
|
+
}] } } }
|
|
1532
|
+
},
|
|
1533
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
1534
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
1535
|
+
"403": { "$ref": "#/components/responses/Forbidden" },
|
|
1536
|
+
"429": { "$ref": "#/components/responses/RateLimited" },
|
|
1537
|
+
"500": { "$ref": "#/components/responses/InternalError" },
|
|
1538
|
+
"503": { "$ref": "#/components/responses/ServiceUnavailable" }
|
|
1539
|
+
}
|
|
1540
|
+
} },
|
|
1473
1541
|
"/sent-emails": { "get": {
|
|
1474
1542
|
"operationId": "listSentEmails",
|
|
1475
1543
|
"summary": "List outbound sent emails",
|
|
@@ -3964,6 +4032,78 @@ const openapiDocument = {
|
|
|
3964
4032
|
},
|
|
3965
4033
|
"required": ["direction", "id"]
|
|
3966
4034
|
},
|
|
4035
|
+
"Conversation": {
|
|
4036
|
+
"type": "object",
|
|
4037
|
+
"description": "The full conversation an inbound email belongs to, as ordered,\nready-to-prompt turns with bodies. Resolves the thread from the\nemail and returns every message oldest-first, so an agent that\nreceived an email can pass `messages` straight to a chat model in\none call.\n",
|
|
4038
|
+
"properties": {
|
|
4039
|
+
"thread_id": {
|
|
4040
|
+
"type": ["string", "null"],
|
|
4041
|
+
"format": "uuid",
|
|
4042
|
+
"description": "The thread this email belongs to, or null when the email\nisn't threaded yet (the conversation is then just this one\nmessage).\n"
|
|
4043
|
+
},
|
|
4044
|
+
"subject": {
|
|
4045
|
+
"type": ["string", "null"],
|
|
4046
|
+
"description": "Normalized thread subject (Re/Fwd prefixes stripped), or the\nemail's own subject when it isn't threaded.\n"
|
|
4047
|
+
},
|
|
4048
|
+
"message_count": {
|
|
4049
|
+
"type": "integer",
|
|
4050
|
+
"description": "Total messages in the thread. `messages` is capped, so\n`truncated` is true (and this can exceed `messages.length`)\nwhen older messages were omitted.\n"
|
|
4051
|
+
},
|
|
4052
|
+
"truncated": {
|
|
4053
|
+
"type": "boolean",
|
|
4054
|
+
"description": "True when `messages` omits part of the conversation because\nthe thread exceeds the per-call cap.\n"
|
|
4055
|
+
},
|
|
4056
|
+
"messages": {
|
|
4057
|
+
"type": "array",
|
|
4058
|
+
"items": { "$ref": "#/components/schemas/ConversationMessage" }
|
|
4059
|
+
}
|
|
4060
|
+
},
|
|
4061
|
+
"required": [
|
|
4062
|
+
"thread_id",
|
|
4063
|
+
"message_count",
|
|
4064
|
+
"truncated",
|
|
4065
|
+
"messages"
|
|
4066
|
+
]
|
|
4067
|
+
},
|
|
4068
|
+
"ConversationMessage": {
|
|
4069
|
+
"type": "object",
|
|
4070
|
+
"description": "One message in the conversation, with its body and a chat role.",
|
|
4071
|
+
"properties": {
|
|
4072
|
+
"role": {
|
|
4073
|
+
"type": "string",
|
|
4074
|
+
"enum": ["user", "assistant"],
|
|
4075
|
+
"description": "Chat role derived from `direction`: `user` for inbound\n(received) messages, `assistant` for outbound (your own prior\nreplies). Lets `messages` be passed directly to a chat model.\n"
|
|
4076
|
+
},
|
|
4077
|
+
"direction": {
|
|
4078
|
+
"type": "string",
|
|
4079
|
+
"enum": ["inbound", "outbound"],
|
|
4080
|
+
"description": "`inbound` for a received email (`/emails/{id}`), `outbound`\nfor a send (`/sent-emails/{id}`).\n"
|
|
4081
|
+
},
|
|
4082
|
+
"id": {
|
|
4083
|
+
"type": "string",
|
|
4084
|
+
"format": "uuid"
|
|
4085
|
+
},
|
|
4086
|
+
"message_id": { "type": ["string", "null"] },
|
|
4087
|
+
"from": { "type": ["string", "null"] },
|
|
4088
|
+
"to": { "type": ["string", "null"] },
|
|
4089
|
+
"subject": { "type": ["string", "null"] },
|
|
4090
|
+
"text": {
|
|
4091
|
+
"type": "string",
|
|
4092
|
+
"description": "Plain-text body. Empty string when the message has no text\npart or its content was discarded by retention.\n"
|
|
4093
|
+
},
|
|
4094
|
+
"timestamp": {
|
|
4095
|
+
"type": ["string", "null"],
|
|
4096
|
+
"format": "date-time",
|
|
4097
|
+
"description": "received_at for inbound, created_at for outbound."
|
|
4098
|
+
}
|
|
4099
|
+
},
|
|
4100
|
+
"required": [
|
|
4101
|
+
"role",
|
|
4102
|
+
"direction",
|
|
4103
|
+
"id",
|
|
4104
|
+
"text"
|
|
4105
|
+
]
|
|
4106
|
+
},
|
|
3967
4107
|
"SendMailAttachment": {
|
|
3968
4108
|
"type": "object",
|
|
3969
4109
|
"additionalProperties": false,
|
|
@@ -4242,6 +4382,236 @@ const openapiDocument = {
|
|
|
4242
4382
|
"body_size_bytes"
|
|
4243
4383
|
]
|
|
4244
4384
|
},
|
|
4385
|
+
"SemanticSearchField": {
|
|
4386
|
+
"type": "string",
|
|
4387
|
+
"enum": [
|
|
4388
|
+
"subject",
|
|
4389
|
+
"headers",
|
|
4390
|
+
"addresses",
|
|
4391
|
+
"body"
|
|
4392
|
+
],
|
|
4393
|
+
"description": "A searchable email field."
|
|
4394
|
+
},
|
|
4395
|
+
"SemanticSearchInput": {
|
|
4396
|
+
"type": "object",
|
|
4397
|
+
"properties": {
|
|
4398
|
+
"query": {
|
|
4399
|
+
"type": "string",
|
|
4400
|
+
"minLength": 1,
|
|
4401
|
+
"maxLength": 2048,
|
|
4402
|
+
"description": "Free-text query. Required for `semantic` and `hybrid` modes;\noptional for `keyword` mode.\n"
|
|
4403
|
+
},
|
|
4404
|
+
"mode": {
|
|
4405
|
+
"type": "string",
|
|
4406
|
+
"enum": [
|
|
4407
|
+
"hybrid",
|
|
4408
|
+
"semantic",
|
|
4409
|
+
"keyword"
|
|
4410
|
+
],
|
|
4411
|
+
"default": "hybrid",
|
|
4412
|
+
"description": "Ranking strategy. `keyword` is lexical only, `semantic` is\nembedding-based, `hybrid` blends both.\n"
|
|
4413
|
+
},
|
|
4414
|
+
"corpus": {
|
|
4415
|
+
"type": "array",
|
|
4416
|
+
"items": {
|
|
4417
|
+
"type": "string",
|
|
4418
|
+
"enum": ["inbound", "outbound"]
|
|
4419
|
+
},
|
|
4420
|
+
"minItems": 1,
|
|
4421
|
+
"maxItems": 2,
|
|
4422
|
+
"description": "Which mail to search. Defaults to both received (`inbound`)\nand sent (`outbound`).\n"
|
|
4423
|
+
},
|
|
4424
|
+
"search_in": {
|
|
4425
|
+
"type": "array",
|
|
4426
|
+
"items": { "$ref": "#/components/schemas/SemanticSearchField" },
|
|
4427
|
+
"description": "Restrict matching to these fields. Defaults to all."
|
|
4428
|
+
},
|
|
4429
|
+
"exclude": {
|
|
4430
|
+
"type": "array",
|
|
4431
|
+
"items": { "$ref": "#/components/schemas/SemanticSearchField" },
|
|
4432
|
+
"description": "Exclude these fields from matching."
|
|
4433
|
+
},
|
|
4434
|
+
"date_from": {
|
|
4435
|
+
"type": "string",
|
|
4436
|
+
"format": "date-time",
|
|
4437
|
+
"description": "Only include mail at or after this timestamp."
|
|
4438
|
+
},
|
|
4439
|
+
"date_to": {
|
|
4440
|
+
"type": "string",
|
|
4441
|
+
"format": "date-time",
|
|
4442
|
+
"description": "Only include mail at or before this timestamp."
|
|
4443
|
+
},
|
|
4444
|
+
"include": {
|
|
4445
|
+
"type": "array",
|
|
4446
|
+
"items": {
|
|
4447
|
+
"type": "string",
|
|
4448
|
+
"enum": ["coverage"]
|
|
4449
|
+
},
|
|
4450
|
+
"description": "Opt-in extras. `coverage` adds an index-coverage snapshot to\n`meta`. Matched fields, snippets, and the score breakdown are\nalways returned regardless of this field.\n"
|
|
4451
|
+
},
|
|
4452
|
+
"limit": {
|
|
4453
|
+
"type": "integer",
|
|
4454
|
+
"minimum": 1,
|
|
4455
|
+
"maximum": 100,
|
|
4456
|
+
"default": 10,
|
|
4457
|
+
"description": "Maximum number of results to return."
|
|
4458
|
+
},
|
|
4459
|
+
"cursor": {
|
|
4460
|
+
"type": "string",
|
|
4461
|
+
"description": "Opaque pagination cursor from a prior response's `meta.cursor`."
|
|
4462
|
+
}
|
|
4463
|
+
}
|
|
4464
|
+
},
|
|
4465
|
+
"SemanticSearchSnippet": {
|
|
4466
|
+
"type": "object",
|
|
4467
|
+
"properties": {
|
|
4468
|
+
"field": {
|
|
4469
|
+
"type": "string",
|
|
4470
|
+
"description": "The field this excerpt came from."
|
|
4471
|
+
},
|
|
4472
|
+
"text": {
|
|
4473
|
+
"type": "string",
|
|
4474
|
+
"description": "Plain-text excerpt centered on the match (no markup)."
|
|
4475
|
+
}
|
|
4476
|
+
},
|
|
4477
|
+
"required": ["field", "text"]
|
|
4478
|
+
},
|
|
4479
|
+
"SemanticSearchScoreBreakdown": {
|
|
4480
|
+
"type": "object",
|
|
4481
|
+
"description": "Additive contributions to `score`. `semantic` and `keyword` are the\nraw signals times the mode's weight (null when not applicable);\nthese plus `field_boost` and `recency` sum to `score` before each\nvalue is independently rounded to 5 decimal places.\n",
|
|
4482
|
+
"properties": {
|
|
4483
|
+
"semantic": { "type": ["number", "null"] },
|
|
4484
|
+
"keyword": { "type": ["number", "null"] },
|
|
4485
|
+
"field_boost": { "type": "number" },
|
|
4486
|
+
"recency": { "type": "number" }
|
|
4487
|
+
},
|
|
4488
|
+
"required": [
|
|
4489
|
+
"semantic",
|
|
4490
|
+
"keyword",
|
|
4491
|
+
"field_boost",
|
|
4492
|
+
"recency"
|
|
4493
|
+
]
|
|
4494
|
+
},
|
|
4495
|
+
"SemanticSearchResult": {
|
|
4496
|
+
"type": "object",
|
|
4497
|
+
"properties": {
|
|
4498
|
+
"source_type": {
|
|
4499
|
+
"type": "string",
|
|
4500
|
+
"enum": ["inbound_email", "sent_email"],
|
|
4501
|
+
"description": "Whether this row is a received or sent message."
|
|
4502
|
+
},
|
|
4503
|
+
"id": {
|
|
4504
|
+
"type": "string",
|
|
4505
|
+
"description": "Message id. Combine with `api_url` to fetch the full record."
|
|
4506
|
+
},
|
|
4507
|
+
"subject": { "type": ["string", "null"] },
|
|
4508
|
+
"from": { "type": ["string", "null"] },
|
|
4509
|
+
"to": { "type": ["string", "null"] },
|
|
4510
|
+
"timestamp": {
|
|
4511
|
+
"type": "string",
|
|
4512
|
+
"description": "Message timestamp (received_at for inbound, created_at for sent)."
|
|
4513
|
+
},
|
|
4514
|
+
"status": {
|
|
4515
|
+
"type": "string",
|
|
4516
|
+
"description": "Lifecycle status of the message."
|
|
4517
|
+
},
|
|
4518
|
+
"score": {
|
|
4519
|
+
"type": "number",
|
|
4520
|
+
"description": "Overall relevance score; the `score_breakdown` components account for it."
|
|
4521
|
+
},
|
|
4522
|
+
"semantic_score": {
|
|
4523
|
+
"type": ["number", "null"],
|
|
4524
|
+
"description": "Raw semantic similarity signal, or null when not applicable."
|
|
4525
|
+
},
|
|
4526
|
+
"keyword_score": {
|
|
4527
|
+
"type": ["number", "null"],
|
|
4528
|
+
"description": "Raw keyword (lexical) signal, or null when not applicable."
|
|
4529
|
+
},
|
|
4530
|
+
"matched_fields": {
|
|
4531
|
+
"type": "array",
|
|
4532
|
+
"items": { "$ref": "#/components/schemas/SemanticSearchField" },
|
|
4533
|
+
"description": "Fields where the query matched."
|
|
4534
|
+
},
|
|
4535
|
+
"snippets": {
|
|
4536
|
+
"type": "array",
|
|
4537
|
+
"items": { "$ref": "#/components/schemas/SemanticSearchSnippet" },
|
|
4538
|
+
"description": "Match-centered excerpts, one per matched field."
|
|
4539
|
+
},
|
|
4540
|
+
"score_breakdown": { "$ref": "#/components/schemas/SemanticSearchScoreBreakdown" },
|
|
4541
|
+
"api_url": {
|
|
4542
|
+
"type": ["string", "null"],
|
|
4543
|
+
"description": "Relative API path to fetch the full message."
|
|
4544
|
+
}
|
|
4545
|
+
},
|
|
4546
|
+
"required": [
|
|
4547
|
+
"source_type",
|
|
4548
|
+
"id",
|
|
4549
|
+
"subject",
|
|
4550
|
+
"from",
|
|
4551
|
+
"to",
|
|
4552
|
+
"timestamp",
|
|
4553
|
+
"status",
|
|
4554
|
+
"score",
|
|
4555
|
+
"semantic_score",
|
|
4556
|
+
"keyword_score",
|
|
4557
|
+
"matched_fields",
|
|
4558
|
+
"snippets",
|
|
4559
|
+
"score_breakdown",
|
|
4560
|
+
"api_url"
|
|
4561
|
+
]
|
|
4562
|
+
},
|
|
4563
|
+
"SemanticSearchCoverage": {
|
|
4564
|
+
"type": "object",
|
|
4565
|
+
"description": "Index-coverage snapshot for the org, returned only when the `coverage` include option is requested.",
|
|
4566
|
+
"properties": {
|
|
4567
|
+
"embedded_chunks": { "type": "integer" },
|
|
4568
|
+
"pending_chunks": { "type": "integer" },
|
|
4569
|
+
"skipped_plan_chunks": { "type": "integer" },
|
|
4570
|
+
"skipped_quota_chunks": { "type": "integer" },
|
|
4571
|
+
"unsupported_attachment_chunks": { "type": "integer" },
|
|
4572
|
+
"failed_chunks": { "type": "integer" }
|
|
4573
|
+
},
|
|
4574
|
+
"required": [
|
|
4575
|
+
"embedded_chunks",
|
|
4576
|
+
"pending_chunks",
|
|
4577
|
+
"skipped_plan_chunks",
|
|
4578
|
+
"skipped_quota_chunks",
|
|
4579
|
+
"unsupported_attachment_chunks",
|
|
4580
|
+
"failed_chunks"
|
|
4581
|
+
]
|
|
4582
|
+
},
|
|
4583
|
+
"SemanticSearchMeta": {
|
|
4584
|
+
"type": "object",
|
|
4585
|
+
"properties": {
|
|
4586
|
+
"limit": {
|
|
4587
|
+
"type": "integer",
|
|
4588
|
+
"description": "Page size used for this request."
|
|
4589
|
+
},
|
|
4590
|
+
"cursor": {
|
|
4591
|
+
"type": ["string", "null"],
|
|
4592
|
+
"description": "Cursor for the next page, or null if there are no more results."
|
|
4593
|
+
},
|
|
4594
|
+
"mode": {
|
|
4595
|
+
"type": "string",
|
|
4596
|
+
"enum": [
|
|
4597
|
+
"hybrid",
|
|
4598
|
+
"semantic",
|
|
4599
|
+
"keyword"
|
|
4600
|
+
],
|
|
4601
|
+
"description": "Ranking mode used for this response."
|
|
4602
|
+
},
|
|
4603
|
+
"coverage": {
|
|
4604
|
+
"oneOf": [{ "$ref": "#/components/schemas/SemanticSearchCoverage" }, { "type": "null" }],
|
|
4605
|
+
"description": "Index-coverage snapshot, present only when requested via\n`include: [coverage]`; otherwise null.\n"
|
|
4606
|
+
}
|
|
4607
|
+
},
|
|
4608
|
+
"required": [
|
|
4609
|
+
"limit",
|
|
4610
|
+
"cursor",
|
|
4611
|
+
"mode",
|
|
4612
|
+
"coverage"
|
|
4613
|
+
]
|
|
4614
|
+
},
|
|
4245
4615
|
"SentEmailDetail": {
|
|
4246
4616
|
"description": "Full sent-email record, including `body_text` and\n`body_html`. Returned by /sent-emails/{id}.\n",
|
|
4247
4617
|
"allOf": [{ "$ref": "#/components/schemas/SentEmailSummary" }, {
|
|
@@ -4280,6 +4650,12 @@ const openapiDocument = {
|
|
|
4280
4650
|
"wait": {
|
|
4281
4651
|
"type": "boolean",
|
|
4282
4652
|
"description": "When true, wait for the first downstream SMTP delivery outcome before returning, mirroring the send-mail `wait` semantics."
|
|
4653
|
+
},
|
|
4654
|
+
"attachments": {
|
|
4655
|
+
"type": "array",
|
|
4656
|
+
"maxItems": 100,
|
|
4657
|
+
"description": "Inline attachments for this reply. Use https://api.primitive.dev/v1 for replies with attachments. Combined raw decoded attachment bytes must be at most 31457280.",
|
|
4658
|
+
"items": { "$ref": "#/components/schemas/SendMailAttachment" }
|
|
4283
4659
|
}
|
|
4284
4660
|
}
|
|
4285
4661
|
},
|
|
@@ -7120,6 +7496,100 @@ const operationManifest = [
|
|
|
7120
7496
|
"tag": "Emails",
|
|
7121
7497
|
"tagCommand": "emails"
|
|
7122
7498
|
},
|
|
7499
|
+
{
|
|
7500
|
+
"binaryResponse": false,
|
|
7501
|
+
"bodyRequired": false,
|
|
7502
|
+
"command": "get-conversation",
|
|
7503
|
+
"description": "Returns the full conversation the given inbound email belongs\nto, as ordered, ready-to-prompt turns WITH bodies. It resolves\nthe thread from the email and returns every message oldest-first,\nso an agent that received an email can pass `messages` straight\nto a chat model in one call instead of walking `/threads/{id}`\nplus `/emails/{id}` and `/sent-emails/{id}` per message.\n\nEach message carries a `direction` (`inbound` | `outbound`) and a\nderived `role`: `inbound` -> `user`, `outbound` -> `assistant`\n(your own prior replies). The role mapping assumes the caller\nowns the outbound side, which is the agent-reply case this exists\nfor. If the email has no thread yet (a brand-new message), the\nconversation is just that one message as a single user turn.\n\nThe message list is capped; check `truncated` to detect when\nolder messages were omitted. Consecutive same-role turns are not\nmerged here; that normalization is model-specific and left to the\ncaller.\n",
|
|
7504
|
+
"hasJsonBody": false,
|
|
7505
|
+
"method": "GET",
|
|
7506
|
+
"operationId": "getConversation",
|
|
7507
|
+
"path": "/emails/{id}/conversation",
|
|
7508
|
+
"pathParams": [{
|
|
7509
|
+
"description": "Resource UUID",
|
|
7510
|
+
"enum": null,
|
|
7511
|
+
"name": "id",
|
|
7512
|
+
"required": true,
|
|
7513
|
+
"type": "string"
|
|
7514
|
+
}],
|
|
7515
|
+
"queryParams": [],
|
|
7516
|
+
"requestSchema": null,
|
|
7517
|
+
"responseSchema": {
|
|
7518
|
+
"type": "object",
|
|
7519
|
+
"description": "The full conversation an inbound email belongs to, as ordered,\nready-to-prompt turns with bodies. Resolves the thread from the\nemail and returns every message oldest-first, so an agent that\nreceived an email can pass `messages` straight to a chat model in\none call.\n",
|
|
7520
|
+
"properties": {
|
|
7521
|
+
"thread_id": {
|
|
7522
|
+
"type": ["string", "null"],
|
|
7523
|
+
"format": "uuid",
|
|
7524
|
+
"description": "The thread this email belongs to, or null when the email\nisn't threaded yet (the conversation is then just this one\nmessage).\n"
|
|
7525
|
+
},
|
|
7526
|
+
"subject": {
|
|
7527
|
+
"type": ["string", "null"],
|
|
7528
|
+
"description": "Normalized thread subject (Re/Fwd prefixes stripped), or the\nemail's own subject when it isn't threaded.\n"
|
|
7529
|
+
},
|
|
7530
|
+
"message_count": {
|
|
7531
|
+
"type": "integer",
|
|
7532
|
+
"description": "Total messages in the thread. `messages` is capped, so\n`truncated` is true (and this can exceed `messages.length`)\nwhen older messages were omitted.\n"
|
|
7533
|
+
},
|
|
7534
|
+
"truncated": {
|
|
7535
|
+
"type": "boolean",
|
|
7536
|
+
"description": "True when `messages` omits part of the conversation because\nthe thread exceeds the per-call cap.\n"
|
|
7537
|
+
},
|
|
7538
|
+
"messages": {
|
|
7539
|
+
"type": "array",
|
|
7540
|
+
"items": {
|
|
7541
|
+
"type": "object",
|
|
7542
|
+
"description": "One message in the conversation, with its body and a chat role.",
|
|
7543
|
+
"properties": {
|
|
7544
|
+
"role": {
|
|
7545
|
+
"type": "string",
|
|
7546
|
+
"enum": ["user", "assistant"],
|
|
7547
|
+
"description": "Chat role derived from `direction`: `user` for inbound\n(received) messages, `assistant` for outbound (your own prior\nreplies). Lets `messages` be passed directly to a chat model.\n"
|
|
7548
|
+
},
|
|
7549
|
+
"direction": {
|
|
7550
|
+
"type": "string",
|
|
7551
|
+
"enum": ["inbound", "outbound"],
|
|
7552
|
+
"description": "`inbound` for a received email (`/emails/{id}`), `outbound`\nfor a send (`/sent-emails/{id}`).\n"
|
|
7553
|
+
},
|
|
7554
|
+
"id": {
|
|
7555
|
+
"type": "string",
|
|
7556
|
+
"format": "uuid"
|
|
7557
|
+
},
|
|
7558
|
+
"message_id": { "type": ["string", "null"] },
|
|
7559
|
+
"from": { "type": ["string", "null"] },
|
|
7560
|
+
"to": { "type": ["string", "null"] },
|
|
7561
|
+
"subject": { "type": ["string", "null"] },
|
|
7562
|
+
"text": {
|
|
7563
|
+
"type": "string",
|
|
7564
|
+
"description": "Plain-text body. Empty string when the message has no text\npart or its content was discarded by retention.\n"
|
|
7565
|
+
},
|
|
7566
|
+
"timestamp": {
|
|
7567
|
+
"type": ["string", "null"],
|
|
7568
|
+
"format": "date-time",
|
|
7569
|
+
"description": "received_at for inbound, created_at for outbound."
|
|
7570
|
+
}
|
|
7571
|
+
},
|
|
7572
|
+
"required": [
|
|
7573
|
+
"role",
|
|
7574
|
+
"direction",
|
|
7575
|
+
"id",
|
|
7576
|
+
"text"
|
|
7577
|
+
]
|
|
7578
|
+
}
|
|
7579
|
+
}
|
|
7580
|
+
},
|
|
7581
|
+
"required": [
|
|
7582
|
+
"thread_id",
|
|
7583
|
+
"message_count",
|
|
7584
|
+
"truncated",
|
|
7585
|
+
"messages"
|
|
7586
|
+
]
|
|
7587
|
+
},
|
|
7588
|
+
"sdkName": "getConversation",
|
|
7589
|
+
"summary": "Get the conversation an email belongs to",
|
|
7590
|
+
"tag": "Emails",
|
|
7591
|
+
"tagCommand": "emails"
|
|
7592
|
+
},
|
|
7123
7593
|
{
|
|
7124
7594
|
"binaryResponse": false,
|
|
7125
7595
|
"bodyRequired": false,
|
|
@@ -9944,6 +10414,218 @@ const operationManifest = [
|
|
|
9944
10414
|
"tag": "Inbox",
|
|
9945
10415
|
"tagCommand": "inbox"
|
|
9946
10416
|
},
|
|
10417
|
+
{
|
|
10418
|
+
"binaryResponse": false,
|
|
10419
|
+
"bodyRequired": true,
|
|
10420
|
+
"command": "semantic-search",
|
|
10421
|
+
"description": "Ranked search across both received and sent mail. The `mode`\nfield selects the ranking strategy:\n\n- `keyword`: lexical full-text matching only (no embeddings).\n- `semantic`: meaning-based matching using vector embeddings.\n- `hybrid` (default): blends the semantic and keyword signals.\n\nResults are ordered by a relevance `score`. Every row reports the\nfields it matched (`matched_fields`), a match-centered excerpt per\nfield (`snippets`), and a `score_breakdown` whose components account\nfor the `score`. Page through results by passing the prior\nresponse's `meta.cursor` back as `cursor`.\n\nRequires the Pro plan and the `semantic_search_enabled`\nentitlement; callers without them receive `403`.\n\nHost routing: this operation is served only by the search host\n(`https://api.primitive.dev/v1`). The typed SDKs route it there\nautomatically.\n",
|
|
10422
|
+
"hasJsonBody": true,
|
|
10423
|
+
"method": "POST",
|
|
10424
|
+
"operationId": "semanticSearch",
|
|
10425
|
+
"path": "/semantic-search",
|
|
10426
|
+
"pathParams": [],
|
|
10427
|
+
"queryParams": [],
|
|
10428
|
+
"requestSchema": {
|
|
10429
|
+
"type": "object",
|
|
10430
|
+
"properties": {
|
|
10431
|
+
"query": {
|
|
10432
|
+
"type": "string",
|
|
10433
|
+
"minLength": 1,
|
|
10434
|
+
"maxLength": 2048,
|
|
10435
|
+
"description": "Free-text query. Required for `semantic` and `hybrid` modes;\noptional for `keyword` mode.\n"
|
|
10436
|
+
},
|
|
10437
|
+
"mode": {
|
|
10438
|
+
"type": "string",
|
|
10439
|
+
"enum": [
|
|
10440
|
+
"hybrid",
|
|
10441
|
+
"semantic",
|
|
10442
|
+
"keyword"
|
|
10443
|
+
],
|
|
10444
|
+
"default": "hybrid",
|
|
10445
|
+
"description": "Ranking strategy. `keyword` is lexical only, `semantic` is\nembedding-based, `hybrid` blends both.\n"
|
|
10446
|
+
},
|
|
10447
|
+
"corpus": {
|
|
10448
|
+
"type": "array",
|
|
10449
|
+
"items": {
|
|
10450
|
+
"type": "string",
|
|
10451
|
+
"enum": ["inbound", "outbound"]
|
|
10452
|
+
},
|
|
10453
|
+
"minItems": 1,
|
|
10454
|
+
"maxItems": 2,
|
|
10455
|
+
"description": "Which mail to search. Defaults to both received (`inbound`)\nand sent (`outbound`).\n"
|
|
10456
|
+
},
|
|
10457
|
+
"search_in": {
|
|
10458
|
+
"type": "array",
|
|
10459
|
+
"items": {
|
|
10460
|
+
"type": "string",
|
|
10461
|
+
"enum": [
|
|
10462
|
+
"subject",
|
|
10463
|
+
"headers",
|
|
10464
|
+
"addresses",
|
|
10465
|
+
"body"
|
|
10466
|
+
],
|
|
10467
|
+
"description": "A searchable email field."
|
|
10468
|
+
},
|
|
10469
|
+
"description": "Restrict matching to these fields. Defaults to all."
|
|
10470
|
+
},
|
|
10471
|
+
"exclude": {
|
|
10472
|
+
"type": "array",
|
|
10473
|
+
"items": {
|
|
10474
|
+
"type": "string",
|
|
10475
|
+
"enum": [
|
|
10476
|
+
"subject",
|
|
10477
|
+
"headers",
|
|
10478
|
+
"addresses",
|
|
10479
|
+
"body"
|
|
10480
|
+
],
|
|
10481
|
+
"description": "A searchable email field."
|
|
10482
|
+
},
|
|
10483
|
+
"description": "Exclude these fields from matching."
|
|
10484
|
+
},
|
|
10485
|
+
"date_from": {
|
|
10486
|
+
"type": "string",
|
|
10487
|
+
"format": "date-time",
|
|
10488
|
+
"description": "Only include mail at or after this timestamp."
|
|
10489
|
+
},
|
|
10490
|
+
"date_to": {
|
|
10491
|
+
"type": "string",
|
|
10492
|
+
"format": "date-time",
|
|
10493
|
+
"description": "Only include mail at or before this timestamp."
|
|
10494
|
+
},
|
|
10495
|
+
"include": {
|
|
10496
|
+
"type": "array",
|
|
10497
|
+
"items": {
|
|
10498
|
+
"type": "string",
|
|
10499
|
+
"enum": ["coverage"]
|
|
10500
|
+
},
|
|
10501
|
+
"description": "Opt-in extras. `coverage` adds an index-coverage snapshot to\n`meta`. Matched fields, snippets, and the score breakdown are\nalways returned regardless of this field.\n"
|
|
10502
|
+
},
|
|
10503
|
+
"limit": {
|
|
10504
|
+
"type": "integer",
|
|
10505
|
+
"minimum": 1,
|
|
10506
|
+
"maximum": 100,
|
|
10507
|
+
"default": 10,
|
|
10508
|
+
"description": "Maximum number of results to return."
|
|
10509
|
+
},
|
|
10510
|
+
"cursor": {
|
|
10511
|
+
"type": "string",
|
|
10512
|
+
"description": "Opaque pagination cursor from a prior response's `meta.cursor`."
|
|
10513
|
+
}
|
|
10514
|
+
}
|
|
10515
|
+
},
|
|
10516
|
+
"responseSchema": {
|
|
10517
|
+
"type": "array",
|
|
10518
|
+
"items": {
|
|
10519
|
+
"type": "object",
|
|
10520
|
+
"properties": {
|
|
10521
|
+
"source_type": {
|
|
10522
|
+
"type": "string",
|
|
10523
|
+
"enum": ["inbound_email", "sent_email"],
|
|
10524
|
+
"description": "Whether this row is a received or sent message."
|
|
10525
|
+
},
|
|
10526
|
+
"id": {
|
|
10527
|
+
"type": "string",
|
|
10528
|
+
"description": "Message id. Combine with `api_url` to fetch the full record."
|
|
10529
|
+
},
|
|
10530
|
+
"subject": { "type": ["string", "null"] },
|
|
10531
|
+
"from": { "type": ["string", "null"] },
|
|
10532
|
+
"to": { "type": ["string", "null"] },
|
|
10533
|
+
"timestamp": {
|
|
10534
|
+
"type": "string",
|
|
10535
|
+
"description": "Message timestamp (received_at for inbound, created_at for sent)."
|
|
10536
|
+
},
|
|
10537
|
+
"status": {
|
|
10538
|
+
"type": "string",
|
|
10539
|
+
"description": "Lifecycle status of the message."
|
|
10540
|
+
},
|
|
10541
|
+
"score": {
|
|
10542
|
+
"type": "number",
|
|
10543
|
+
"description": "Overall relevance score; the `score_breakdown` components account for it."
|
|
10544
|
+
},
|
|
10545
|
+
"semantic_score": {
|
|
10546
|
+
"type": ["number", "null"],
|
|
10547
|
+
"description": "Raw semantic similarity signal, or null when not applicable."
|
|
10548
|
+
},
|
|
10549
|
+
"keyword_score": {
|
|
10550
|
+
"type": ["number", "null"],
|
|
10551
|
+
"description": "Raw keyword (lexical) signal, or null when not applicable."
|
|
10552
|
+
},
|
|
10553
|
+
"matched_fields": {
|
|
10554
|
+
"type": "array",
|
|
10555
|
+
"items": {
|
|
10556
|
+
"type": "string",
|
|
10557
|
+
"enum": [
|
|
10558
|
+
"subject",
|
|
10559
|
+
"headers",
|
|
10560
|
+
"addresses",
|
|
10561
|
+
"body"
|
|
10562
|
+
],
|
|
10563
|
+
"description": "A searchable email field."
|
|
10564
|
+
},
|
|
10565
|
+
"description": "Fields where the query matched."
|
|
10566
|
+
},
|
|
10567
|
+
"snippets": {
|
|
10568
|
+
"type": "array",
|
|
10569
|
+
"items": {
|
|
10570
|
+
"type": "object",
|
|
10571
|
+
"properties": {
|
|
10572
|
+
"field": {
|
|
10573
|
+
"type": "string",
|
|
10574
|
+
"description": "The field this excerpt came from."
|
|
10575
|
+
},
|
|
10576
|
+
"text": {
|
|
10577
|
+
"type": "string",
|
|
10578
|
+
"description": "Plain-text excerpt centered on the match (no markup)."
|
|
10579
|
+
}
|
|
10580
|
+
},
|
|
10581
|
+
"required": ["field", "text"]
|
|
10582
|
+
},
|
|
10583
|
+
"description": "Match-centered excerpts, one per matched field."
|
|
10584
|
+
},
|
|
10585
|
+
"score_breakdown": {
|
|
10586
|
+
"type": "object",
|
|
10587
|
+
"description": "Additive contributions to `score`. `semantic` and `keyword` are the\nraw signals times the mode's weight (null when not applicable);\nthese plus `field_boost` and `recency` sum to `score` before each\nvalue is independently rounded to 5 decimal places.\n",
|
|
10588
|
+
"properties": {
|
|
10589
|
+
"semantic": { "type": ["number", "null"] },
|
|
10590
|
+
"keyword": { "type": ["number", "null"] },
|
|
10591
|
+
"field_boost": { "type": "number" },
|
|
10592
|
+
"recency": { "type": "number" }
|
|
10593
|
+
},
|
|
10594
|
+
"required": [
|
|
10595
|
+
"semantic",
|
|
10596
|
+
"keyword",
|
|
10597
|
+
"field_boost",
|
|
10598
|
+
"recency"
|
|
10599
|
+
]
|
|
10600
|
+
},
|
|
10601
|
+
"api_url": {
|
|
10602
|
+
"type": ["string", "null"],
|
|
10603
|
+
"description": "Relative API path to fetch the full message."
|
|
10604
|
+
}
|
|
10605
|
+
},
|
|
10606
|
+
"required": [
|
|
10607
|
+
"source_type",
|
|
10608
|
+
"id",
|
|
10609
|
+
"subject",
|
|
10610
|
+
"from",
|
|
10611
|
+
"to",
|
|
10612
|
+
"timestamp",
|
|
10613
|
+
"status",
|
|
10614
|
+
"score",
|
|
10615
|
+
"semantic_score",
|
|
10616
|
+
"keyword_score",
|
|
10617
|
+
"matched_fields",
|
|
10618
|
+
"snippets",
|
|
10619
|
+
"score_breakdown",
|
|
10620
|
+
"api_url"
|
|
10621
|
+
]
|
|
10622
|
+
}
|
|
10623
|
+
},
|
|
10624
|
+
"sdkName": "semanticSearch",
|
|
10625
|
+
"summary": "Semantic search across received and sent mail",
|
|
10626
|
+
"tag": "Search",
|
|
10627
|
+
"tagCommand": "search"
|
|
10628
|
+
},
|
|
9947
10629
|
{
|
|
9948
10630
|
"binaryResponse": false,
|
|
9949
10631
|
"bodyRequired": false,
|
|
@@ -10596,7 +11278,7 @@ const operationManifest = [
|
|
|
10596
11278
|
"binaryResponse": false,
|
|
10597
11279
|
"bodyRequired": true,
|
|
10598
11280
|
"command": "reply-to-email",
|
|
10599
|
-
"description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody and optional
|
|
11281
|
+
"description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody, optional From override, optional attachments, and optional\n`wait` flag; passing any header or recipient override is\nrejected by the schema (`additionalProperties: false`).\n\nForwards through the same gates as `/send-mail`: the response\nstatus, error envelope, and `idempotent_replay` flag mirror\nthe send-mail contract verbatim.\n",
|
|
10600
11282
|
"hasJsonBody": true,
|
|
10601
11283
|
"method": "POST",
|
|
10602
11284
|
"operationId": "replyToEmail",
|
|
@@ -10631,6 +11313,36 @@ const operationManifest = [
|
|
|
10631
11313
|
"wait": {
|
|
10632
11314
|
"type": "boolean",
|
|
10633
11315
|
"description": "When true, wait for the first downstream SMTP delivery outcome before returning, mirroring the send-mail `wait` semantics."
|
|
11316
|
+
},
|
|
11317
|
+
"attachments": {
|
|
11318
|
+
"type": "array",
|
|
11319
|
+
"maxItems": 100,
|
|
11320
|
+
"description": "Inline attachments for this reply. Use https://api.primitive.dev/v1 for replies with attachments. Combined raw decoded attachment bytes must be at most 31457280.",
|
|
11321
|
+
"items": {
|
|
11322
|
+
"type": "object",
|
|
11323
|
+
"additionalProperties": false,
|
|
11324
|
+
"properties": {
|
|
11325
|
+
"filename": {
|
|
11326
|
+
"type": "string",
|
|
11327
|
+
"minLength": 1,
|
|
11328
|
+
"maxLength": 255,
|
|
11329
|
+
"description": "Attachment filename. Control characters are rejected."
|
|
11330
|
+
},
|
|
11331
|
+
"content_type": {
|
|
11332
|
+
"type": "string",
|
|
11333
|
+
"minLength": 1,
|
|
11334
|
+
"maxLength": 255,
|
|
11335
|
+
"description": "Optional MIME content type. Control characters are rejected."
|
|
11336
|
+
},
|
|
11337
|
+
"content_base64": {
|
|
11338
|
+
"type": "string",
|
|
11339
|
+
"minLength": 1,
|
|
11340
|
+
"maxLength": 44040192,
|
|
11341
|
+
"description": "Base64-encoded attachment bytes."
|
|
11342
|
+
}
|
|
11343
|
+
},
|
|
11344
|
+
"required": ["filename", "content_base64"]
|
|
11345
|
+
}
|
|
10634
11346
|
}
|
|
10635
11347
|
}
|
|
10636
11348
|
},
|