@equationalapplications/mcp-server 0.0.0-stage → 7.15.2
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 +159 -2
- package/contract/synapsetree-openapi.subset.json +3842 -0
- package/dist/cli.js +4771 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +4769 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +113 -0
- package/dist/index.d.ts +113 -0
- package/dist/index.js +4406 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4391 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -4
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4391 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'crypto';
|
|
2
|
+
import { z, ZodError } from 'zod';
|
|
3
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
+
|
|
5
|
+
// src/client.ts
|
|
6
|
+
|
|
7
|
+
// contract/synapsetree-openapi.subset.json
|
|
8
|
+
var synapsetree_openapi_subset_default = {
|
|
9
|
+
info: {
|
|
10
|
+
version: "1.0.0-alpha.1",
|
|
11
|
+
"x-operations": [
|
|
12
|
+
"createEvent",
|
|
13
|
+
"ingestDocument",
|
|
14
|
+
"listNamespaces",
|
|
15
|
+
"oauthRevoke",
|
|
16
|
+
"oauthToken",
|
|
17
|
+
"queryMemory",
|
|
18
|
+
"registerAgentIdentity",
|
|
19
|
+
"rememberFact",
|
|
20
|
+
"supersedeFact",
|
|
21
|
+
"traverseGraph",
|
|
22
|
+
"whoami"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
paths: {
|
|
26
|
+
"/v1/memory/query": {
|
|
27
|
+
post: {
|
|
28
|
+
operationId: "queryMemory",
|
|
29
|
+
tags: [
|
|
30
|
+
"memory"
|
|
31
|
+
],
|
|
32
|
+
summary: "Search memory",
|
|
33
|
+
description: "Ranked top-k hybrid search (semantic + keyword) across one or more namespaces. Returns\nthe highest-scoring facts plus pending tasks and recent events. **Not paginated**: the\nranking is not a stable order; raise `limit` (max 100) for more results.\n\nSemantic scoring needs embeddings. In namespaces under server extraction the query is\nembedded with the organization's embeddings registration (BYOK); an organization without\none serves keyword-only search. When the embeddings path is unavailable \u2014 no\nregistration, a key or provider fault, the tier cap exhausted, or a maintenance run\nre-embedding the namespace \u2014 the search degrades to keyword-only and reports why via\n`diagnostics`. That degradation is normal operation, not an error. Alternatively pass\n`queryEmbedding` (same dimension as the stored fact vectors) to supply the vector\nyourself.\n",
|
|
34
|
+
"x-synapsetree-scope": "read",
|
|
35
|
+
"x-synapsetree-engine": "read",
|
|
36
|
+
requestBody: {
|
|
37
|
+
required: true,
|
|
38
|
+
content: {
|
|
39
|
+
"application/json": {
|
|
40
|
+
schema: {
|
|
41
|
+
$ref: "#/components/schemas/QueryRequest"
|
|
42
|
+
},
|
|
43
|
+
examples: {
|
|
44
|
+
single: {
|
|
45
|
+
summary: "One namespace",
|
|
46
|
+
value: {
|
|
47
|
+
namespaces: [
|
|
48
|
+
"repo:synapsetree"
|
|
49
|
+
],
|
|
50
|
+
query: "how are API keys hashed",
|
|
51
|
+
limit: 5
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
weighted: {
|
|
55
|
+
summary: "Two namespaces, weighted, point in time",
|
|
56
|
+
value: {
|
|
57
|
+
namespaces: [
|
|
58
|
+
"repo:synapsetree",
|
|
59
|
+
"team:platform"
|
|
60
|
+
],
|
|
61
|
+
query: "deployment region",
|
|
62
|
+
weights: {
|
|
63
|
+
"repo:synapsetree": 2,
|
|
64
|
+
"team:platform": 1
|
|
65
|
+
},
|
|
66
|
+
floors: {
|
|
67
|
+
"team:platform": 1
|
|
68
|
+
},
|
|
69
|
+
asOf: "2026-09-01T00:00:00Z",
|
|
70
|
+
excludeDrafts: true
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
responses: {
|
|
78
|
+
"200": {
|
|
79
|
+
description: "Ranked facts with pending tasks and recent events.",
|
|
80
|
+
headers: {
|
|
81
|
+
"Request-Id": {
|
|
82
|
+
$ref: "#/components/headers/Request-Id"
|
|
83
|
+
},
|
|
84
|
+
"RateLimit-Policy": {
|
|
85
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
86
|
+
},
|
|
87
|
+
RateLimit: {
|
|
88
|
+
$ref: "#/components/headers/RateLimit"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
content: {
|
|
92
|
+
"application/json": {
|
|
93
|
+
schema: {
|
|
94
|
+
$ref: "#/components/schemas/QueryResponse"
|
|
95
|
+
},
|
|
96
|
+
example: {
|
|
97
|
+
facts: [
|
|
98
|
+
{
|
|
99
|
+
id: "fact_01j9x7k2m3",
|
|
100
|
+
namespace: "repo:synapsetree",
|
|
101
|
+
sourceType: "immutable_document",
|
|
102
|
+
mutable: false,
|
|
103
|
+
sourceRef: "infra__stack.ts",
|
|
104
|
+
sourceHash: "9f2c4b8e1a7d3f6c5b0e2d4a8c1f3e5b7d9a0c2e4f6b8d0a1c3e5f7b9d1a3c5e",
|
|
105
|
+
title: "SynapseTree",
|
|
106
|
+
body: "Hosted LLM memory API. status active.",
|
|
107
|
+
tags: [],
|
|
108
|
+
confidence: "certain",
|
|
109
|
+
okfType: "software_application",
|
|
110
|
+
lifecycleStatus: "stable",
|
|
111
|
+
trustTier: "unverified",
|
|
112
|
+
isStale: false,
|
|
113
|
+
generatedBy: null,
|
|
114
|
+
lastVerifiedAt: null,
|
|
115
|
+
lastVerifiedBy: null,
|
|
116
|
+
validFrom: null,
|
|
117
|
+
validTo: null,
|
|
118
|
+
supersededBy: null,
|
|
119
|
+
supersededAt: null,
|
|
120
|
+
accessCount: 3,
|
|
121
|
+
lastAccessedAt: "2026-09-30T08:00:00Z",
|
|
122
|
+
createdAt: "2026-09-29T10:00:00Z",
|
|
123
|
+
updatedAt: "2026-09-29T10:00:00Z"
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
scores: {
|
|
127
|
+
fact_01j9x7k2m3: 0.82
|
|
128
|
+
},
|
|
129
|
+
tasks: [
|
|
130
|
+
{
|
|
131
|
+
id: "task_01j9x8a1b2",
|
|
132
|
+
namespace: "repo:synapsetree",
|
|
133
|
+
description: "Register the stree_ prefix with GitHub secret scanning",
|
|
134
|
+
status: "pending",
|
|
135
|
+
priority: 5,
|
|
136
|
+
okfType: null,
|
|
137
|
+
createdAt: "2026-09-29T10:00:00Z",
|
|
138
|
+
updatedAt: "2026-09-29T10:00:00Z",
|
|
139
|
+
resolvedAt: null
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
events: [
|
|
143
|
+
{
|
|
144
|
+
id: "evt_01j9x8c3d4",
|
|
145
|
+
namespace: "repo:synapsetree",
|
|
146
|
+
eventType: "decision",
|
|
147
|
+
summary: "Chose DynamoDB for the control plane",
|
|
148
|
+
relatedFactId: null,
|
|
149
|
+
occurredAt: "2026-09-29T09:00:00Z",
|
|
150
|
+
createdAt: "2026-09-29T09:05:00Z"
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
"400": {
|
|
158
|
+
$ref: "#/components/responses/BadRequest"
|
|
159
|
+
},
|
|
160
|
+
"401": {
|
|
161
|
+
$ref: "#/components/responses/Unauthorized"
|
|
162
|
+
},
|
|
163
|
+
"403": {
|
|
164
|
+
$ref: "#/components/responses/Forbidden"
|
|
165
|
+
},
|
|
166
|
+
"429": {
|
|
167
|
+
$ref: "#/components/responses/TooManyRequests"
|
|
168
|
+
},
|
|
169
|
+
"500": {
|
|
170
|
+
$ref: "#/components/responses/InternalError"
|
|
171
|
+
},
|
|
172
|
+
"501": {
|
|
173
|
+
$ref: "#/components/responses/NotImplemented"
|
|
174
|
+
},
|
|
175
|
+
"503": {
|
|
176
|
+
description: "Temporarily unavailable: `unavailable` (tenant cold start or writer handoff)\nor `fenced` (the writer lost its lease). Upstream inference failure never\nsurfaces on the query path \u2014 spec \xA75.2 degrade-never-fail: provider trouble\ndegrades to keyword search with `diagnostics` instead of failing.\n",
|
|
177
|
+
headers: {
|
|
178
|
+
"Request-Id": {
|
|
179
|
+
$ref: "#/components/headers/Request-Id"
|
|
180
|
+
},
|
|
181
|
+
"Retry-After": {
|
|
182
|
+
$ref: "#/components/headers/Retry-After"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
content: {
|
|
186
|
+
"application/problem+json": {
|
|
187
|
+
schema: {
|
|
188
|
+
$ref: "#/components/schemas/Problem"
|
|
189
|
+
},
|
|
190
|
+
examples: {
|
|
191
|
+
fenced: {
|
|
192
|
+
value: {
|
|
193
|
+
type: "urn:synapsetree:problem:fenced",
|
|
194
|
+
title: "Writer fenced",
|
|
195
|
+
status: 503,
|
|
196
|
+
code: "fenced",
|
|
197
|
+
detail: "The write did not commit; retry.",
|
|
198
|
+
requestId: "req_01j9xb7c8d9e",
|
|
199
|
+
retryable: true,
|
|
200
|
+
retryAfterSeconds: 1
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
"/v1/memory/facts": {
|
|
211
|
+
post: {
|
|
212
|
+
operationId: "rememberFact",
|
|
213
|
+
tags: [
|
|
214
|
+
"facts"
|
|
215
|
+
],
|
|
216
|
+
summary: "Store a fact directly",
|
|
217
|
+
description: "Stores one mutable fact (`user_stated` by default) without an LLM step. To replace an\nexisting fact, use `supersedeFact` instead so history is kept.\n",
|
|
218
|
+
"x-synapsetree-scope": "read_write",
|
|
219
|
+
"x-synapsetree-engine": "remember",
|
|
220
|
+
parameters: [
|
|
221
|
+
{
|
|
222
|
+
$ref: "#/components/parameters/IdempotencyKey"
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
requestBody: {
|
|
226
|
+
required: true,
|
|
227
|
+
content: {
|
|
228
|
+
"application/json": {
|
|
229
|
+
schema: {
|
|
230
|
+
$ref: "#/components/schemas/RememberRequest"
|
|
231
|
+
},
|
|
232
|
+
examples: {
|
|
233
|
+
preference: {
|
|
234
|
+
value: {
|
|
235
|
+
namespace: "user:kurt",
|
|
236
|
+
title: "Prefers merge commits",
|
|
237
|
+
body: "Kurt wants PRs merged with merge commits, never squashed.",
|
|
238
|
+
tags: [
|
|
239
|
+
"git"
|
|
240
|
+
],
|
|
241
|
+
confidence: "certain"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
responses: {
|
|
249
|
+
"201": {
|
|
250
|
+
description: "The stored fact.",
|
|
251
|
+
headers: {
|
|
252
|
+
"Request-Id": {
|
|
253
|
+
$ref: "#/components/headers/Request-Id"
|
|
254
|
+
},
|
|
255
|
+
"RateLimit-Policy": {
|
|
256
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
257
|
+
},
|
|
258
|
+
RateLimit: {
|
|
259
|
+
$ref: "#/components/headers/RateLimit"
|
|
260
|
+
},
|
|
261
|
+
"Idempotent-Replayed": {
|
|
262
|
+
$ref: "#/components/headers/Idempotent-Replayed"
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
content: {
|
|
266
|
+
"application/json": {
|
|
267
|
+
schema: {
|
|
268
|
+
$ref: "#/components/schemas/Fact"
|
|
269
|
+
},
|
|
270
|
+
example: {
|
|
271
|
+
id: "fact_01j9xa0000",
|
|
272
|
+
namespace: "user:kurt",
|
|
273
|
+
sourceType: "user_stated",
|
|
274
|
+
mutable: true,
|
|
275
|
+
sourceRef: null,
|
|
276
|
+
sourceHash: null,
|
|
277
|
+
title: "Lives in San Francisco",
|
|
278
|
+
body: "Moved in March.",
|
|
279
|
+
tags: [],
|
|
280
|
+
confidence: "certain",
|
|
281
|
+
okfType: "place",
|
|
282
|
+
lifecycleStatus: "stable",
|
|
283
|
+
trustTier: "unverified",
|
|
284
|
+
isStale: false,
|
|
285
|
+
generatedBy: null,
|
|
286
|
+
lastVerifiedAt: null,
|
|
287
|
+
lastVerifiedBy: null,
|
|
288
|
+
validFrom: "2026-03-01T00:00:00Z",
|
|
289
|
+
validTo: null,
|
|
290
|
+
supersededBy: null,
|
|
291
|
+
supersededAt: null,
|
|
292
|
+
accessCount: 0,
|
|
293
|
+
lastAccessedAt: null,
|
|
294
|
+
createdAt: "2026-09-30T09:00:00Z",
|
|
295
|
+
updatedAt: "2026-09-30T09:00:00Z"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"400": {
|
|
301
|
+
$ref: "#/components/responses/BadRequest"
|
|
302
|
+
},
|
|
303
|
+
"401": {
|
|
304
|
+
$ref: "#/components/responses/Unauthorized"
|
|
305
|
+
},
|
|
306
|
+
"402": {
|
|
307
|
+
$ref: "#/components/responses/PaymentRequired"
|
|
308
|
+
},
|
|
309
|
+
"403": {
|
|
310
|
+
$ref: "#/components/responses/Forbidden"
|
|
311
|
+
},
|
|
312
|
+
"409": {
|
|
313
|
+
$ref: "#/components/responses/Conflict"
|
|
314
|
+
},
|
|
315
|
+
"413": {
|
|
316
|
+
$ref: "#/components/responses/PayloadTooLarge"
|
|
317
|
+
},
|
|
318
|
+
"422": {
|
|
319
|
+
$ref: "#/components/responses/UnprocessableContent"
|
|
320
|
+
},
|
|
321
|
+
"429": {
|
|
322
|
+
$ref: "#/components/responses/TooManyRequests"
|
|
323
|
+
},
|
|
324
|
+
"500": {
|
|
325
|
+
$ref: "#/components/responses/InternalError"
|
|
326
|
+
},
|
|
327
|
+
"503": {
|
|
328
|
+
$ref: "#/components/responses/ServiceUnavailable"
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
"/v1/memory/facts/{factId}/supersede": {
|
|
334
|
+
post: {
|
|
335
|
+
operationId: "supersedeFact",
|
|
336
|
+
tags: [
|
|
337
|
+
"facts"
|
|
338
|
+
],
|
|
339
|
+
summary: "Replace a fact, keeping its history",
|
|
340
|
+
description: "Ends the fact's validity at `validFrom` (default: now) and makes the replacement current\nfrom that instant. The replacement is a new mutable fact or an existing fact id.\n\nRefused with `409 invalid_state` for `immutable_document` facts (re-ingest the document\ninstead), and with `409 conflict` for a fact already superseded or a replacement that\nwould form a cycle.\n",
|
|
341
|
+
"x-synapsetree-scope": "read_write",
|
|
342
|
+
"x-synapsetree-engine": "supersede",
|
|
343
|
+
parameters: [
|
|
344
|
+
{
|
|
345
|
+
$ref: "#/components/parameters/FactId"
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
$ref: "#/components/parameters/IdempotencyKey"
|
|
349
|
+
}
|
|
350
|
+
],
|
|
351
|
+
requestBody: {
|
|
352
|
+
required: true,
|
|
353
|
+
content: {
|
|
354
|
+
"application/json": {
|
|
355
|
+
schema: {
|
|
356
|
+
$ref: "#/components/schemas/SupersedeRequest"
|
|
357
|
+
},
|
|
358
|
+
examples: {
|
|
359
|
+
newFact: {
|
|
360
|
+
summary: "Replace with a new fact, backdated",
|
|
361
|
+
value: {
|
|
362
|
+
namespace: "user:kurt",
|
|
363
|
+
validFrom: "2026-03-01T00:00:00Z",
|
|
364
|
+
replacement: {
|
|
365
|
+
kind: "new",
|
|
366
|
+
title: "Lives in San Francisco",
|
|
367
|
+
body: "Moved in March."
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
existingFact: {
|
|
372
|
+
summary: "Replace with a fact that already exists",
|
|
373
|
+
value: {
|
|
374
|
+
namespace: "user:kurt",
|
|
375
|
+
replacement: {
|
|
376
|
+
kind: "existing",
|
|
377
|
+
factId: "fact_01j9xa0000"
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
responses: {
|
|
386
|
+
"200": {
|
|
387
|
+
description: "The superseded fact and its replacement.",
|
|
388
|
+
headers: {
|
|
389
|
+
"Request-Id": {
|
|
390
|
+
$ref: "#/components/headers/Request-Id"
|
|
391
|
+
},
|
|
392
|
+
"RateLimit-Policy": {
|
|
393
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
394
|
+
},
|
|
395
|
+
RateLimit: {
|
|
396
|
+
$ref: "#/components/headers/RateLimit"
|
|
397
|
+
},
|
|
398
|
+
"Idempotent-Replayed": {
|
|
399
|
+
$ref: "#/components/headers/Idempotent-Replayed"
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
content: {
|
|
403
|
+
"application/json": {
|
|
404
|
+
schema: {
|
|
405
|
+
$ref: "#/components/schemas/SupersedeResponse"
|
|
406
|
+
},
|
|
407
|
+
example: {
|
|
408
|
+
superseded: {
|
|
409
|
+
id: "fact_01j8z9y8x7",
|
|
410
|
+
namespace: "user:kurt",
|
|
411
|
+
sourceType: "user_stated",
|
|
412
|
+
mutable: true,
|
|
413
|
+
sourceRef: null,
|
|
414
|
+
sourceHash: null,
|
|
415
|
+
title: "Lives in Seattle",
|
|
416
|
+
body: "Rents in Capitol Hill.",
|
|
417
|
+
tags: [],
|
|
418
|
+
confidence: "certain",
|
|
419
|
+
okfType: "place",
|
|
420
|
+
lifecycleStatus: "stable",
|
|
421
|
+
trustTier: "unverified",
|
|
422
|
+
isStale: false,
|
|
423
|
+
generatedBy: null,
|
|
424
|
+
lastVerifiedAt: null,
|
|
425
|
+
lastVerifiedBy: null,
|
|
426
|
+
validFrom: null,
|
|
427
|
+
validTo: "2026-03-01T00:00:00Z",
|
|
428
|
+
supersededBy: "fact_01j9xa0000",
|
|
429
|
+
supersededAt: "2026-09-30T09:00:00Z",
|
|
430
|
+
accessCount: 5,
|
|
431
|
+
lastAccessedAt: "2026-09-28T12:00:00Z",
|
|
432
|
+
createdAt: "2026-01-10T12:00:00Z",
|
|
433
|
+
updatedAt: "2026-01-10T12:00:00Z"
|
|
434
|
+
},
|
|
435
|
+
replacement: {
|
|
436
|
+
id: "fact_01j9xa0000",
|
|
437
|
+
namespace: "user:kurt",
|
|
438
|
+
sourceType: "user_stated",
|
|
439
|
+
mutable: true,
|
|
440
|
+
sourceRef: null,
|
|
441
|
+
sourceHash: null,
|
|
442
|
+
title: "Lives in San Francisco",
|
|
443
|
+
body: "Moved in March.",
|
|
444
|
+
tags: [],
|
|
445
|
+
confidence: "certain",
|
|
446
|
+
okfType: "place",
|
|
447
|
+
lifecycleStatus: "stable",
|
|
448
|
+
trustTier: "unverified",
|
|
449
|
+
isStale: false,
|
|
450
|
+
generatedBy: null,
|
|
451
|
+
lastVerifiedAt: null,
|
|
452
|
+
lastVerifiedBy: null,
|
|
453
|
+
validFrom: "2026-03-01T00:00:00Z",
|
|
454
|
+
validTo: null,
|
|
455
|
+
supersededBy: null,
|
|
456
|
+
supersededAt: null,
|
|
457
|
+
accessCount: 0,
|
|
458
|
+
lastAccessedAt: null,
|
|
459
|
+
createdAt: "2026-09-30T09:00:00Z",
|
|
460
|
+
updatedAt: "2026-09-30T09:00:00Z"
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
"400": {
|
|
467
|
+
$ref: "#/components/responses/BadRequest"
|
|
468
|
+
},
|
|
469
|
+
"401": {
|
|
470
|
+
$ref: "#/components/responses/Unauthorized"
|
|
471
|
+
},
|
|
472
|
+
"402": {
|
|
473
|
+
$ref: "#/components/responses/PaymentRequired"
|
|
474
|
+
},
|
|
475
|
+
"403": {
|
|
476
|
+
$ref: "#/components/responses/Forbidden"
|
|
477
|
+
},
|
|
478
|
+
"404": {
|
|
479
|
+
$ref: "#/components/responses/NotFound"
|
|
480
|
+
},
|
|
481
|
+
"409": {
|
|
482
|
+
$ref: "#/components/responses/Conflict"
|
|
483
|
+
},
|
|
484
|
+
"413": {
|
|
485
|
+
$ref: "#/components/responses/PayloadTooLarge"
|
|
486
|
+
},
|
|
487
|
+
"422": {
|
|
488
|
+
$ref: "#/components/responses/UnprocessableContent"
|
|
489
|
+
},
|
|
490
|
+
"429": {
|
|
491
|
+
$ref: "#/components/responses/TooManyRequests"
|
|
492
|
+
},
|
|
493
|
+
"500": {
|
|
494
|
+
$ref: "#/components/responses/InternalError"
|
|
495
|
+
},
|
|
496
|
+
"503": {
|
|
497
|
+
$ref: "#/components/responses/ServiceUnavailable"
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
},
|
|
502
|
+
"/v1/memory/ingest": {
|
|
503
|
+
post: {
|
|
504
|
+
operationId: "ingestDocument",
|
|
505
|
+
tags: [
|
|
506
|
+
"memory"
|
|
507
|
+
],
|
|
508
|
+
summary: "Ingest a document",
|
|
509
|
+
description: "Extracts facts from a document and stores them as `immutable_document` facts under\n`sourceRef`, replacing any earlier version.\n\n- `server_extraction`: SynapseTree runs extraction with the organization's registered\n provider key (BYOK; envelope-encrypted, managed in the dashboard by owner/admin).\n `409 inference_not_configured` when the organization has no extraction registration.\n- `client_extraction`: the client ran the extraction itself against an\n [extraction plan](#operation/createExtractionPlan) and posts each chunk's model\n output. A plan whose fingerprint no longer matches is refused with\n `409 extraction_plan_stale`.\n",
|
|
510
|
+
"x-synapsetree-scope": "read_write",
|
|
511
|
+
"x-synapsetree-engine": "ingestDocument (server_extraction); upstream:ingestExtracted (client_extraction)",
|
|
512
|
+
parameters: [
|
|
513
|
+
{
|
|
514
|
+
$ref: "#/components/parameters/IdempotencyKey"
|
|
515
|
+
}
|
|
516
|
+
],
|
|
517
|
+
requestBody: {
|
|
518
|
+
required: true,
|
|
519
|
+
content: {
|
|
520
|
+
"application/json": {
|
|
521
|
+
schema: {
|
|
522
|
+
$ref: "#/components/schemas/IngestRequest"
|
|
523
|
+
},
|
|
524
|
+
examples: {
|
|
525
|
+
clientExtraction: {
|
|
526
|
+
summary: "Client-side extraction (BYOI)",
|
|
527
|
+
value: {
|
|
528
|
+
mode: "client_extraction",
|
|
529
|
+
namespace: "repo:synapsetree",
|
|
530
|
+
sourceRef: "docs__runbook.md",
|
|
531
|
+
sourceHash: "1b3d5f7a9c0e2b4d6f8a0c2e4b6d8f0a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d",
|
|
532
|
+
planFingerprint: "sha256:4e6a8c0b2d4f6a8c0e2b4d6f8a0c2e4b6d8f0a2c4e6b8d0f2a4c6e8b0d2f4a6c",
|
|
533
|
+
chunks: [
|
|
534
|
+
{
|
|
535
|
+
index: 0,
|
|
536
|
+
response: {
|
|
537
|
+
facts: [
|
|
538
|
+
{
|
|
539
|
+
title: "Deploys go to us-east-1",
|
|
540
|
+
body: "The test stage deploys to us-east-1.",
|
|
541
|
+
tags: [
|
|
542
|
+
"deploy"
|
|
543
|
+
],
|
|
544
|
+
confidence: "certain",
|
|
545
|
+
okfType: "procedure",
|
|
546
|
+
evidence: [
|
|
547
|
+
"Region: us-east-1 (Kurt, 2026-09-29)."
|
|
548
|
+
],
|
|
549
|
+
edges: [
|
|
550
|
+
{
|
|
551
|
+
edgeType: "documents",
|
|
552
|
+
targetTitle: "SynapseTree"
|
|
553
|
+
}
|
|
554
|
+
]
|
|
555
|
+
}
|
|
556
|
+
],
|
|
557
|
+
tasks: []
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
]
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
serverExtraction: {
|
|
564
|
+
summary: "Server-side extraction (BYOK)",
|
|
565
|
+
value: {
|
|
566
|
+
mode: "server_extraction",
|
|
567
|
+
namespace: "repo:synapsetree",
|
|
568
|
+
sourceRef: "docs__runbook.md",
|
|
569
|
+
sourceHash: "1b3d5f7a9c0e2b4d6f8a0c2e4b6d8f0a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d",
|
|
570
|
+
content: "# Deploy the test stage ...",
|
|
571
|
+
onDuplicateHash: "skip"
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
responses: {
|
|
579
|
+
"200": {
|
|
580
|
+
description: "Ingest summary.",
|
|
581
|
+
headers: {
|
|
582
|
+
"Request-Id": {
|
|
583
|
+
$ref: "#/components/headers/Request-Id"
|
|
584
|
+
},
|
|
585
|
+
"RateLimit-Policy": {
|
|
586
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
587
|
+
},
|
|
588
|
+
RateLimit: {
|
|
589
|
+
$ref: "#/components/headers/RateLimit"
|
|
590
|
+
},
|
|
591
|
+
"Idempotent-Replayed": {
|
|
592
|
+
$ref: "#/components/headers/Idempotent-Replayed"
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
content: {
|
|
596
|
+
"application/json": {
|
|
597
|
+
schema: {
|
|
598
|
+
$ref: "#/components/schemas/IngestResponse"
|
|
599
|
+
},
|
|
600
|
+
example: {
|
|
601
|
+
chunks: 1,
|
|
602
|
+
ingestedChunks: 1,
|
|
603
|
+
failedChunks: 0,
|
|
604
|
+
truncated: false,
|
|
605
|
+
duplicateOf: null,
|
|
606
|
+
parseFailures: []
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
},
|
|
611
|
+
"400": {
|
|
612
|
+
$ref: "#/components/responses/BadRequest"
|
|
613
|
+
},
|
|
614
|
+
"401": {
|
|
615
|
+
$ref: "#/components/responses/Unauthorized"
|
|
616
|
+
},
|
|
617
|
+
"402": {
|
|
618
|
+
$ref: "#/components/responses/PaymentRequired"
|
|
619
|
+
},
|
|
620
|
+
"403": {
|
|
621
|
+
$ref: "#/components/responses/Forbidden"
|
|
622
|
+
},
|
|
623
|
+
"409": {
|
|
624
|
+
description: "The write conflicts with current state: `conflict`, `extraction_plan_stale`,\n`source_hash_conflict` (another sourceRef already holds this content hash),\n`namespace_busy` (the namespace is under another write; retry),\n`inference_not_configured` (server extraction requested but the organization has\nno extraction registration), or `inference_config_invalid` (the provider rejected\nthe organization's key as configuration-invalid \u2014 auth or bad option \u2014 on every\nextraction call; nothing was written and the response is not retried).\n",
|
|
625
|
+
headers: {
|
|
626
|
+
"Request-Id": {
|
|
627
|
+
$ref: "#/components/headers/Request-Id"
|
|
628
|
+
},
|
|
629
|
+
"Retry-After": {
|
|
630
|
+
$ref: "#/components/headers/Retry-After"
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
content: {
|
|
634
|
+
"application/problem+json": {
|
|
635
|
+
schema: {
|
|
636
|
+
$ref: "#/components/schemas/Problem"
|
|
637
|
+
},
|
|
638
|
+
examples: {
|
|
639
|
+
sourceHashConflict: {
|
|
640
|
+
value: {
|
|
641
|
+
type: "urn:synapsetree:problem:source_hash_conflict",
|
|
642
|
+
title: "Source hash already stored",
|
|
643
|
+
status: 409,
|
|
644
|
+
code: "source_hash_conflict",
|
|
645
|
+
detail: "Another sourceRef in this namespace already holds this content.",
|
|
646
|
+
requestId: "req_01j9xb7c8d9e",
|
|
647
|
+
retryable: false,
|
|
648
|
+
duplicateOf: "docs__runbook-old.md"
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
inferenceConfigInvalid: {
|
|
652
|
+
value: {
|
|
653
|
+
type: "urn:synapsetree:problem:inference_config_invalid",
|
|
654
|
+
title: "Inference configuration invalid",
|
|
655
|
+
status: 409,
|
|
656
|
+
code: "inference_config_invalid",
|
|
657
|
+
detail: "The provider rejected the tenant's model key as configuration-invalid on every extraction call; nothing was written.",
|
|
658
|
+
requestId: "req_01j9xb7c8d9e",
|
|
659
|
+
retryable: false
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
"413": {
|
|
667
|
+
$ref: "#/components/responses/PayloadTooLarge"
|
|
668
|
+
},
|
|
669
|
+
"422": {
|
|
670
|
+
description: "Well-formed but refused: `ontology_violation`, `ingest_failed`,\n`idempotency_key_reused`, `embedding_dimension_mismatch` (client vector with a\ndifferent dimension), or `embedding_model_mismatch` (the tenant's configured\nembedding model differs from the namespace's stored-vector fingerprint; the\nrefusal precedes any write and points at the re-embed maintenance path).\n",
|
|
671
|
+
headers: {
|
|
672
|
+
"Request-Id": {
|
|
673
|
+
$ref: "#/components/headers/Request-Id"
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
content: {
|
|
677
|
+
"application/problem+json": {
|
|
678
|
+
schema: {
|
|
679
|
+
$ref: "#/components/schemas/Problem"
|
|
680
|
+
},
|
|
681
|
+
examples: {
|
|
682
|
+
ontologyViolation: {
|
|
683
|
+
value: {
|
|
684
|
+
type: "urn:synapsetree:problem:ontology_violation",
|
|
685
|
+
title: "Ontology violation",
|
|
686
|
+
status: 422,
|
|
687
|
+
code: "ontology_violation",
|
|
688
|
+
detail: `Node type "microservice" is not in this namespace's strict manifest.`,
|
|
689
|
+
requestId: "req_01j9xb7c8d9e",
|
|
690
|
+
retryable: false,
|
|
691
|
+
kind: "node",
|
|
692
|
+
ontologyType: "microservice"
|
|
693
|
+
}
|
|
694
|
+
},
|
|
695
|
+
embeddingModelMismatch: {
|
|
696
|
+
value: {
|
|
697
|
+
type: "urn:synapsetree:problem:embedding_model_mismatch",
|
|
698
|
+
title: "Embedding model mismatch",
|
|
699
|
+
status: 422,
|
|
700
|
+
code: "embedding_model_mismatch",
|
|
701
|
+
detail: "The configured embedding model differs from the namespace's stored-vector fingerprint; run maintenance to re-embed.",
|
|
702
|
+
requestId: "req_01j9xb7c8d9e",
|
|
703
|
+
retryable: false
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
},
|
|
710
|
+
"429": {
|
|
711
|
+
$ref: "#/components/responses/TooManyRequests"
|
|
712
|
+
},
|
|
713
|
+
"500": {
|
|
714
|
+
$ref: "#/components/responses/InternalError"
|
|
715
|
+
},
|
|
716
|
+
"501": {
|
|
717
|
+
$ref: "#/components/responses/NotImplemented"
|
|
718
|
+
},
|
|
719
|
+
"503": {
|
|
720
|
+
description: "Temporarily unavailable: `unavailable` (tenant cold start or writer handoff),\n`fenced` (the writer lost its lease; the write did not commit), or\n`upstream_inference_unavailable` (the tenant's inference provider failed on\nevery extraction call, or either BYOK rate cap (extraction or embeddings)\nis exhausted for the window (429/5xx/timeout; nothing was written; safe\nto retry)). When the embeddings rate cap is exhausted by an active\nmaintenance run, the problem `detail` names the run (`mrun_\u2026`) as the\nconsumer.\n",
|
|
721
|
+
headers: {
|
|
722
|
+
"Request-Id": {
|
|
723
|
+
$ref: "#/components/headers/Request-Id"
|
|
724
|
+
},
|
|
725
|
+
"Retry-After": {
|
|
726
|
+
$ref: "#/components/headers/Retry-After"
|
|
727
|
+
}
|
|
728
|
+
},
|
|
729
|
+
content: {
|
|
730
|
+
"application/problem+json": {
|
|
731
|
+
schema: {
|
|
732
|
+
$ref: "#/components/schemas/Problem"
|
|
733
|
+
},
|
|
734
|
+
examples: {
|
|
735
|
+
fenced: {
|
|
736
|
+
value: {
|
|
737
|
+
type: "urn:synapsetree:problem:fenced",
|
|
738
|
+
title: "Writer fenced",
|
|
739
|
+
status: 503,
|
|
740
|
+
code: "fenced",
|
|
741
|
+
detail: "The write did not commit; retry.",
|
|
742
|
+
requestId: "req_01j9xb7c8d9e",
|
|
743
|
+
retryable: true,
|
|
744
|
+
retryAfterSeconds: 1
|
|
745
|
+
}
|
|
746
|
+
},
|
|
747
|
+
upstreamInferenceUnavailable: {
|
|
748
|
+
value: {
|
|
749
|
+
type: "urn:synapsetree:problem:upstream_inference_unavailable",
|
|
750
|
+
title: "Upstream inference unavailable",
|
|
751
|
+
status: 503,
|
|
752
|
+
code: "upstream_inference_unavailable",
|
|
753
|
+
detail: "The tenant's inference provider failed on every extraction call (429/5xx/timeout); nothing was written.",
|
|
754
|
+
requestId: "req_01j9xb7c8d9e",
|
|
755
|
+
retryable: true,
|
|
756
|
+
retryAfterSeconds: 30
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
},
|
|
766
|
+
"/v1/memory/events": {
|
|
767
|
+
post: {
|
|
768
|
+
operationId: "createEvent",
|
|
769
|
+
tags: [
|
|
770
|
+
"memory"
|
|
771
|
+
],
|
|
772
|
+
summary: "Record an event",
|
|
773
|
+
description: "Appends an observation, decision, action, or outcome to a namespace's event log. Events\nare the input to later consolidation into facts; recording one never runs inference.\nA relatedFactId that does not exist in the namespace (superseded facts count as existing)\nis refused with 404.\n",
|
|
774
|
+
"x-synapsetree-scope": "read_write",
|
|
775
|
+
"x-synapsetree-engine": "write",
|
|
776
|
+
parameters: [
|
|
777
|
+
{
|
|
778
|
+
$ref: "#/components/parameters/IdempotencyKey"
|
|
779
|
+
}
|
|
780
|
+
],
|
|
781
|
+
requestBody: {
|
|
782
|
+
required: true,
|
|
783
|
+
content: {
|
|
784
|
+
"application/json": {
|
|
785
|
+
schema: {
|
|
786
|
+
$ref: "#/components/schemas/CreateEventRequest"
|
|
787
|
+
},
|
|
788
|
+
examples: {
|
|
789
|
+
decision: {
|
|
790
|
+
value: {
|
|
791
|
+
namespace: "repo:synapsetree",
|
|
792
|
+
eventType: "decision",
|
|
793
|
+
summary: "Chose DynamoDB for the control plane",
|
|
794
|
+
occurredAt: "2026-09-29T09:00:00Z"
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
responses: {
|
|
802
|
+
"201": {
|
|
803
|
+
description: "The recorded event.",
|
|
804
|
+
headers: {
|
|
805
|
+
"Request-Id": {
|
|
806
|
+
$ref: "#/components/headers/Request-Id"
|
|
807
|
+
},
|
|
808
|
+
"RateLimit-Policy": {
|
|
809
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
810
|
+
},
|
|
811
|
+
RateLimit: {
|
|
812
|
+
$ref: "#/components/headers/RateLimit"
|
|
813
|
+
},
|
|
814
|
+
"Idempotent-Replayed": {
|
|
815
|
+
$ref: "#/components/headers/Idempotent-Replayed"
|
|
816
|
+
}
|
|
817
|
+
},
|
|
818
|
+
content: {
|
|
819
|
+
"application/json": {
|
|
820
|
+
schema: {
|
|
821
|
+
$ref: "#/components/schemas/Event"
|
|
822
|
+
},
|
|
823
|
+
example: {
|
|
824
|
+
id: "evt_01j9x8c3d4",
|
|
825
|
+
namespace: "repo:synapsetree",
|
|
826
|
+
eventType: "decision",
|
|
827
|
+
summary: "Chose DynamoDB for the control plane",
|
|
828
|
+
relatedFactId: null,
|
|
829
|
+
occurredAt: "2026-09-29T09:00:00Z",
|
|
830
|
+
createdAt: "2026-09-29T09:05:00Z"
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
},
|
|
835
|
+
"400": {
|
|
836
|
+
$ref: "#/components/responses/BadRequest"
|
|
837
|
+
},
|
|
838
|
+
"401": {
|
|
839
|
+
$ref: "#/components/responses/Unauthorized"
|
|
840
|
+
},
|
|
841
|
+
"402": {
|
|
842
|
+
$ref: "#/components/responses/PaymentRequired"
|
|
843
|
+
},
|
|
844
|
+
"403": {
|
|
845
|
+
$ref: "#/components/responses/Forbidden"
|
|
846
|
+
},
|
|
847
|
+
"404": {
|
|
848
|
+
$ref: "#/components/responses/NotFound"
|
|
849
|
+
},
|
|
850
|
+
"409": {
|
|
851
|
+
$ref: "#/components/responses/Conflict"
|
|
852
|
+
},
|
|
853
|
+
"413": {
|
|
854
|
+
$ref: "#/components/responses/PayloadTooLarge"
|
|
855
|
+
},
|
|
856
|
+
"422": {
|
|
857
|
+
$ref: "#/components/responses/UnprocessableContent"
|
|
858
|
+
},
|
|
859
|
+
"429": {
|
|
860
|
+
$ref: "#/components/responses/TooManyRequests"
|
|
861
|
+
},
|
|
862
|
+
"500": {
|
|
863
|
+
$ref: "#/components/responses/InternalError"
|
|
864
|
+
},
|
|
865
|
+
"503": {
|
|
866
|
+
$ref: "#/components/responses/ServiceUnavailable"
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
},
|
|
871
|
+
"/v1/graph/traverse": {
|
|
872
|
+
post: {
|
|
873
|
+
operationId: "traverseGraph",
|
|
874
|
+
tags: [
|
|
875
|
+
"graph"
|
|
876
|
+
],
|
|
877
|
+
summary: "Traverse the graph from an anchor fact",
|
|
878
|
+
description: "Walks edges from `sourceId` up to `maxDepth` hops (1\u20133). The anchor is always returned\nfirst; discovered nodes follow in depth order. Only edges whose both endpoints are\nreturned are included. With `asOf`, only facts live at that instant are walked.\nBounded by `maxNodes`; not paginated.\n",
|
|
879
|
+
"x-synapsetree-scope": "read",
|
|
880
|
+
"x-synapsetree-engine": "traverseGraph",
|
|
881
|
+
requestBody: {
|
|
882
|
+
required: true,
|
|
883
|
+
content: {
|
|
884
|
+
"application/json": {
|
|
885
|
+
schema: {
|
|
886
|
+
$ref: "#/components/schemas/TraverseRequest"
|
|
887
|
+
},
|
|
888
|
+
examples: {
|
|
889
|
+
twoHops: {
|
|
890
|
+
summary: "Two hops, outbound, dependency edges only",
|
|
891
|
+
value: {
|
|
892
|
+
namespace: "repo:synapsetree",
|
|
893
|
+
sourceId: "app_synapsetree",
|
|
894
|
+
maxDepth: 2,
|
|
895
|
+
direction: "outbound",
|
|
896
|
+
edgeTypes: [
|
|
897
|
+
"dependsOn"
|
|
898
|
+
],
|
|
899
|
+
maxNodes: 50
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
responses: {
|
|
907
|
+
"200": {
|
|
908
|
+
description: "The anchor's neighbourhood.",
|
|
909
|
+
headers: {
|
|
910
|
+
"Request-Id": {
|
|
911
|
+
$ref: "#/components/headers/Request-Id"
|
|
912
|
+
},
|
|
913
|
+
"RateLimit-Policy": {
|
|
914
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
915
|
+
},
|
|
916
|
+
RateLimit: {
|
|
917
|
+
$ref: "#/components/headers/RateLimit"
|
|
918
|
+
}
|
|
919
|
+
},
|
|
920
|
+
content: {
|
|
921
|
+
"application/json": {
|
|
922
|
+
schema: {
|
|
923
|
+
$ref: "#/components/schemas/TraverseResponse"
|
|
924
|
+
},
|
|
925
|
+
example: {
|
|
926
|
+
nodes: [
|
|
927
|
+
{
|
|
928
|
+
id: "fact_01j9x7k2m3",
|
|
929
|
+
namespace: "repo:synapsetree",
|
|
930
|
+
sourceType: "immutable_document",
|
|
931
|
+
mutable: false,
|
|
932
|
+
sourceRef: "infra__stack.ts",
|
|
933
|
+
sourceHash: "9f2c4b8e1a7d3f6c5b0e2d4a8c1f3e5b7d9a0c2e4f6b8d0a1c3e5f7b9d1a3c5e",
|
|
934
|
+
title: "SynapseTree",
|
|
935
|
+
body: "Hosted LLM memory API. status active.",
|
|
936
|
+
tags: [],
|
|
937
|
+
confidence: "certain",
|
|
938
|
+
okfType: "software_application",
|
|
939
|
+
lifecycleStatus: "stable",
|
|
940
|
+
trustTier: "unverified",
|
|
941
|
+
isStale: false,
|
|
942
|
+
generatedBy: null,
|
|
943
|
+
lastVerifiedAt: null,
|
|
944
|
+
lastVerifiedBy: null,
|
|
945
|
+
validFrom: null,
|
|
946
|
+
validTo: null,
|
|
947
|
+
supersededBy: null,
|
|
948
|
+
supersededAt: null,
|
|
949
|
+
accessCount: 3,
|
|
950
|
+
lastAccessedAt: "2026-09-30T08:00:00Z",
|
|
951
|
+
createdAt: "2026-09-29T10:00:00Z",
|
|
952
|
+
updatedAt: "2026-09-29T10:00:00Z"
|
|
953
|
+
}
|
|
954
|
+
],
|
|
955
|
+
edges: [
|
|
956
|
+
{
|
|
957
|
+
id: "edge_01j9x9e5f6",
|
|
958
|
+
namespace: "repo:synapsetree",
|
|
959
|
+
sourceId: "app_synapsetree",
|
|
960
|
+
targetId: "svc_dynamodb",
|
|
961
|
+
edgeType: "dependsOn",
|
|
962
|
+
createdAt: "2026-09-29T10:00:00Z"
|
|
963
|
+
}
|
|
964
|
+
]
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
},
|
|
969
|
+
"400": {
|
|
970
|
+
$ref: "#/components/responses/BadRequest"
|
|
971
|
+
},
|
|
972
|
+
"401": {
|
|
973
|
+
$ref: "#/components/responses/Unauthorized"
|
|
974
|
+
},
|
|
975
|
+
"403": {
|
|
976
|
+
$ref: "#/components/responses/Forbidden"
|
|
977
|
+
},
|
|
978
|
+
"404": {
|
|
979
|
+
$ref: "#/components/responses/NotFound"
|
|
980
|
+
},
|
|
981
|
+
"409": {
|
|
982
|
+
$ref: "#/components/responses/Conflict"
|
|
983
|
+
},
|
|
984
|
+
"429": {
|
|
985
|
+
$ref: "#/components/responses/TooManyRequests"
|
|
986
|
+
},
|
|
987
|
+
"500": {
|
|
988
|
+
$ref: "#/components/responses/InternalError"
|
|
989
|
+
},
|
|
990
|
+
"503": {
|
|
991
|
+
$ref: "#/components/responses/ServiceUnavailable"
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
},
|
|
996
|
+
"/v1/namespaces": {
|
|
997
|
+
get: {
|
|
998
|
+
operationId: "listNamespaces",
|
|
999
|
+
tags: [
|
|
1000
|
+
"namespaces"
|
|
1001
|
+
],
|
|
1002
|
+
summary: "List namespaces",
|
|
1003
|
+
description: "Namespaces with at least one row, ordered by name (binary ascending). Includes namespaces\nwhose rows are all deleted, until they are pruned.\n",
|
|
1004
|
+
"x-synapsetree-scope": "read",
|
|
1005
|
+
"x-synapsetree-engine": "listEntityIds",
|
|
1006
|
+
parameters: [
|
|
1007
|
+
{
|
|
1008
|
+
name: "prefix",
|
|
1009
|
+
in: "query",
|
|
1010
|
+
required: false,
|
|
1011
|
+
description: "Only namespaces starting with this string.",
|
|
1012
|
+
schema: {
|
|
1013
|
+
type: "string",
|
|
1014
|
+
maxLength: 128
|
|
1015
|
+
},
|
|
1016
|
+
example: "repo:"
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
$ref: "#/components/parameters/After"
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
$ref: "#/components/parameters/Limit"
|
|
1023
|
+
}
|
|
1024
|
+
],
|
|
1025
|
+
responses: {
|
|
1026
|
+
"200": {
|
|
1027
|
+
description: "One page of namespaces.",
|
|
1028
|
+
headers: {
|
|
1029
|
+
"Request-Id": {
|
|
1030
|
+
$ref: "#/components/headers/Request-Id"
|
|
1031
|
+
},
|
|
1032
|
+
"RateLimit-Policy": {
|
|
1033
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
1034
|
+
},
|
|
1035
|
+
RateLimit: {
|
|
1036
|
+
$ref: "#/components/headers/RateLimit"
|
|
1037
|
+
}
|
|
1038
|
+
},
|
|
1039
|
+
content: {
|
|
1040
|
+
"application/json": {
|
|
1041
|
+
schema: {
|
|
1042
|
+
$ref: "#/components/schemas/NamespaceList"
|
|
1043
|
+
},
|
|
1044
|
+
example: {
|
|
1045
|
+
data: [
|
|
1046
|
+
{
|
|
1047
|
+
namespace: "repo:synapsetree"
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
namespace: "user:kurt"
|
|
1051
|
+
}
|
|
1052
|
+
],
|
|
1053
|
+
hasMore: false,
|
|
1054
|
+
nextCursor: null
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
},
|
|
1059
|
+
"400": {
|
|
1060
|
+
$ref: "#/components/responses/BadRequest"
|
|
1061
|
+
},
|
|
1062
|
+
"401": {
|
|
1063
|
+
$ref: "#/components/responses/Unauthorized"
|
|
1064
|
+
},
|
|
1065
|
+
"403": {
|
|
1066
|
+
$ref: "#/components/responses/Forbidden"
|
|
1067
|
+
},
|
|
1068
|
+
"429": {
|
|
1069
|
+
$ref: "#/components/responses/TooManyRequests"
|
|
1070
|
+
},
|
|
1071
|
+
"500": {
|
|
1072
|
+
$ref: "#/components/responses/InternalError"
|
|
1073
|
+
},
|
|
1074
|
+
"503": {
|
|
1075
|
+
$ref: "#/components/responses/ServiceUnavailable"
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
"/v1/whoami": {
|
|
1081
|
+
get: {
|
|
1082
|
+
operationId: "whoami",
|
|
1083
|
+
tags: [
|
|
1084
|
+
"account"
|
|
1085
|
+
],
|
|
1086
|
+
summary: "Describe the calling key",
|
|
1087
|
+
description: "The routing context the authorizer resolved for this key.",
|
|
1088
|
+
"x-synapsetree-scope": "read",
|
|
1089
|
+
"x-synapsetree-engine": "none (control plane)",
|
|
1090
|
+
responses: {
|
|
1091
|
+
"200": {
|
|
1092
|
+
description: "The key's routing context.",
|
|
1093
|
+
headers: {
|
|
1094
|
+
"Request-Id": {
|
|
1095
|
+
$ref: "#/components/headers/Request-Id"
|
|
1096
|
+
},
|
|
1097
|
+
"RateLimit-Policy": {
|
|
1098
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
1099
|
+
},
|
|
1100
|
+
RateLimit: {
|
|
1101
|
+
$ref: "#/components/headers/RateLimit"
|
|
1102
|
+
}
|
|
1103
|
+
},
|
|
1104
|
+
content: {
|
|
1105
|
+
"application/json": {
|
|
1106
|
+
schema: {
|
|
1107
|
+
$ref: "#/components/schemas/Whoami"
|
|
1108
|
+
},
|
|
1109
|
+
example: {
|
|
1110
|
+
apiKeyId: "key_01j9x5v7w8",
|
|
1111
|
+
organizationId: "org_01j9x5t3u4",
|
|
1112
|
+
tenantDatabaseId: "db_01j9x5r1s2",
|
|
1113
|
+
scope: "read_write",
|
|
1114
|
+
planCode: "hobby",
|
|
1115
|
+
subscriptionStatus: "inactive"
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
},
|
|
1120
|
+
"401": {
|
|
1121
|
+
$ref: "#/components/responses/Unauthorized"
|
|
1122
|
+
},
|
|
1123
|
+
"403": {
|
|
1124
|
+
$ref: "#/components/responses/Forbidden"
|
|
1125
|
+
},
|
|
1126
|
+
"429": {
|
|
1127
|
+
$ref: "#/components/responses/TooManyRequests"
|
|
1128
|
+
},
|
|
1129
|
+
"500": {
|
|
1130
|
+
$ref: "#/components/responses/InternalError"
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
},
|
|
1135
|
+
"/agent/identity": {
|
|
1136
|
+
post: {
|
|
1137
|
+
operationId: "registerAgentIdentity",
|
|
1138
|
+
tags: [
|
|
1139
|
+
"agent"
|
|
1140
|
+
],
|
|
1141
|
+
summary: "Start agent registration for an email",
|
|
1142
|
+
description: "First step of auth.md agent registration: an agent without an API key\nasks SynapseTree to email the human a claim link. The endpoint is\nunauthenticated; the response is byte-equal for known and unknown\nemails (anti-enumeration). At most 5 claim tokens may be outstanding\nfor one email \u2014 the 6th answers `quota_exceeded` (an existing\nProblemCode; errors here are problem+json only). Success returns the\n`stclaim_\u2026` claim token the agent polls with, a short `user_code` the\nhuman confirms on the consent interstitial, and the poll parameters. The\noutstanding-token cap responds `quota_exceeded`.\n",
|
|
1143
|
+
security: [],
|
|
1144
|
+
"x-synapsetree-engine": "registerAgentIdentity (control plane)",
|
|
1145
|
+
requestBody: {
|
|
1146
|
+
required: true,
|
|
1147
|
+
content: {
|
|
1148
|
+
"application/json": {
|
|
1149
|
+
schema: {
|
|
1150
|
+
$ref: "#/components/schemas/AgentIdentityRequest"
|
|
1151
|
+
},
|
|
1152
|
+
example: {
|
|
1153
|
+
email: "ada@example.com"
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
},
|
|
1158
|
+
responses: {
|
|
1159
|
+
"200": {
|
|
1160
|
+
description: "The claim is pending; a confirmation email is on its way to the\nhuman. Byte-equal whether or not the email is known to SynapseTree.\n",
|
|
1161
|
+
headers: {
|
|
1162
|
+
"Request-Id": {
|
|
1163
|
+
$ref: "#/components/headers/Request-Id"
|
|
1164
|
+
},
|
|
1165
|
+
"RateLimit-Policy": {
|
|
1166
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
1167
|
+
},
|
|
1168
|
+
RateLimit: {
|
|
1169
|
+
$ref: "#/components/headers/RateLimit"
|
|
1170
|
+
}
|
|
1171
|
+
},
|
|
1172
|
+
content: {
|
|
1173
|
+
"application/json": {
|
|
1174
|
+
schema: {
|
|
1175
|
+
$ref: "#/components/schemas/AgentIdentityResponse"
|
|
1176
|
+
},
|
|
1177
|
+
example: {
|
|
1178
|
+
claim_token: "stclaim_exampleclaimtoken01",
|
|
1179
|
+
user_code: "482913",
|
|
1180
|
+
poll: {
|
|
1181
|
+
token_endpoint: "https://api.synapsetree.dev/oauth2/token",
|
|
1182
|
+
grant: "urn:synapsetree:claim",
|
|
1183
|
+
interval: 5
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
},
|
|
1189
|
+
"400": {
|
|
1190
|
+
$ref: "#/components/responses/BadRequest"
|
|
1191
|
+
},
|
|
1192
|
+
"403": {
|
|
1193
|
+
$ref: "#/components/responses/QuotaExceeded"
|
|
1194
|
+
},
|
|
1195
|
+
"500": {
|
|
1196
|
+
$ref: "#/components/responses/InternalError"
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
},
|
|
1201
|
+
"/oauth2/token": {
|
|
1202
|
+
post: {
|
|
1203
|
+
operationId: "oauthToken",
|
|
1204
|
+
tags: [
|
|
1205
|
+
"agent"
|
|
1206
|
+
],
|
|
1207
|
+
summary: "Poll the claim grant for the minted API key",
|
|
1208
|
+
description: "Device-flow style poll (RFC 8628 \xA73.4/\xA73.5) with a claim grant: the\nagent presents the `stclaim_\u2026` token from POST /agent/identity as the\n`assertion` (RFC 7523 jwt-bearer shape) with grant type\n`urn:synapsetree:claim`. Before the human approves, the endpoint\nanswers `authorization_pending` (with `interval`) or `slow_down`;\nafter approval the FIRST poll mints exactly one API key (and, in the\nsame transaction, frees the claim token) and answers with it \u2014 later\npolls answer `invalid_grant`, as do expiry and absence. If the\norganization already holds 10 live agent keys the poll answers\n`key_limit_reached`, a documented extension of the RFC 6749 \xA75.2\n`error` member (not a problem+json code). Errors here are RFC 6749\n\xA75.2 bodies, never problem+json. No per-IP rate limit exists in v1.\n",
|
|
1209
|
+
security: [],
|
|
1210
|
+
"x-synapsetree-engine": "oauthToken (control plane)",
|
|
1211
|
+
requestBody: {
|
|
1212
|
+
required: true,
|
|
1213
|
+
content: {
|
|
1214
|
+
"application/x-www-form-urlencoded": {
|
|
1215
|
+
schema: {
|
|
1216
|
+
$ref: "#/components/schemas/ClaimGrantRequest"
|
|
1217
|
+
},
|
|
1218
|
+
example: {
|
|
1219
|
+
grant_type: "urn:synapsetree:claim",
|
|
1220
|
+
assertion: "stclaim_exampleclaimtoken01"
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
},
|
|
1225
|
+
responses: {
|
|
1226
|
+
"200": {
|
|
1227
|
+
description: "The claim was approved and redeemed; exactly one API key was\nminted. Polling again answers `invalid_grant`.\n",
|
|
1228
|
+
headers: {
|
|
1229
|
+
"Request-Id": {
|
|
1230
|
+
$ref: "#/components/headers/Request-Id"
|
|
1231
|
+
},
|
|
1232
|
+
"RateLimit-Policy": {
|
|
1233
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
1234
|
+
},
|
|
1235
|
+
RateLimit: {
|
|
1236
|
+
$ref: "#/components/headers/RateLimit"
|
|
1237
|
+
}
|
|
1238
|
+
},
|
|
1239
|
+
content: {
|
|
1240
|
+
"application/json": {
|
|
1241
|
+
schema: {
|
|
1242
|
+
$ref: "#/components/schemas/TokenResponse"
|
|
1243
|
+
},
|
|
1244
|
+
example: {
|
|
1245
|
+
access_token: "stree_Tq3-vZ8_kLm2NpR5sUw7YxA9bC1dE4fG6hJ0iKlMnOp",
|
|
1246
|
+
token_type: "Bearer",
|
|
1247
|
+
account_id: "01890a5d-ac96-774b-bcce-b302099a8057",
|
|
1248
|
+
scope: "memory:full"
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
},
|
|
1253
|
+
"400": {
|
|
1254
|
+
$ref: "#/components/responses/OauthErrorResponse"
|
|
1255
|
+
},
|
|
1256
|
+
"500": {
|
|
1257
|
+
$ref: "#/components/responses/OauthServerError"
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
},
|
|
1262
|
+
"/oauth2/revoke": {
|
|
1263
|
+
post: {
|
|
1264
|
+
operationId: "oauthRevoke",
|
|
1265
|
+
tags: [
|
|
1266
|
+
"agent"
|
|
1267
|
+
],
|
|
1268
|
+
summary: "Revoke a token (RFC 7009)",
|
|
1269
|
+
description: 'RFC 7009 revocation, bearer-authenticated like every other key-bearing\nendpoint. Revoking an agent key frees its seat against the\norganization\'s 10-key cap. The endpoint answers 200 on every\nrequest carrying a LIVE bearer \u2014 the response is byte-equal whether the\ntoken was revoked or was unknown. A revoked, deleted or unknown CLIENT\nbearer never reaches the handler: the edge answers 401 (the shared\n`unauthorized` problem, RFC 6750 \u2014 byte-equal for unknown and revoked\nbearers, anti-enumeration). A request with an ABSENT or MALFORMED\n`Authorization` header is refused by the API Gateway authorizer before\nthe handler runs, with the gateway\'s default native body\n`{"message":"Unauthorized"}` (not problem+json, no `WWW-Authenticate`\nchallenge). Errors from the handler are RFC 6749 \xA75.2 bodies, never\nproblem+json (the two 401 bodies above excepted).\n',
|
|
1270
|
+
"x-synapsetree-engine": "oauthRevoke (control plane)",
|
|
1271
|
+
requestBody: {
|
|
1272
|
+
required: true,
|
|
1273
|
+
content: {
|
|
1274
|
+
"application/x-www-form-urlencoded": {
|
|
1275
|
+
schema: {
|
|
1276
|
+
$ref: "#/components/schemas/RevokeRequest"
|
|
1277
|
+
},
|
|
1278
|
+
example: {
|
|
1279
|
+
token: "stree_Tq3-vZ8_kLm2NpR5sUw7YxA9bC1dE4fG6hJ0iKlMnOp",
|
|
1280
|
+
token_type_hint: "access_token"
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
},
|
|
1285
|
+
responses: {
|
|
1286
|
+
"200": {
|
|
1287
|
+
description: "The token is revoked, or was unknown; byte-equal either way. Requires a live bearer.\n",
|
|
1288
|
+
headers: {
|
|
1289
|
+
"Request-Id": {
|
|
1290
|
+
$ref: "#/components/headers/Request-Id"
|
|
1291
|
+
},
|
|
1292
|
+
"RateLimit-Policy": {
|
|
1293
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
1294
|
+
},
|
|
1295
|
+
RateLimit: {
|
|
1296
|
+
$ref: "#/components/headers/RateLimit"
|
|
1297
|
+
}
|
|
1298
|
+
},
|
|
1299
|
+
content: {
|
|
1300
|
+
"application/json": {
|
|
1301
|
+
schema: {
|
|
1302
|
+
type: "object",
|
|
1303
|
+
description: "Empty body (RFC 7009 \xA72.2 \u2014 200 confirms processing).",
|
|
1304
|
+
additionalProperties: false,
|
|
1305
|
+
required: [],
|
|
1306
|
+
properties: {}
|
|
1307
|
+
},
|
|
1308
|
+
example: {}
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
},
|
|
1312
|
+
"400": {
|
|
1313
|
+
$ref: "#/components/responses/OauthErrorResponse"
|
|
1314
|
+
},
|
|
1315
|
+
"401": {
|
|
1316
|
+
description: 'The CLIENT bearer is unknown, revoked or invalid (RFC 6750). Emitted by the\napplication\'s shared 401 emitter, byte-equal to the pool\'s \u2014 anti-enumeration\n(unknown and revoked bearers are indistinguishable). A missing/malformed\n`Authorization` header instead yields the API Gateway default 401 body\n`{"message":"Unauthorized"}` \u2014 see the operation description.\n',
|
|
1317
|
+
headers: {
|
|
1318
|
+
"Request-Id": {
|
|
1319
|
+
$ref: "#/components/headers/Request-Id"
|
|
1320
|
+
},
|
|
1321
|
+
"WWW-Authenticate": {
|
|
1322
|
+
$ref: "#/components/headers/WWW-Authenticate"
|
|
1323
|
+
}
|
|
1324
|
+
},
|
|
1325
|
+
content: {
|
|
1326
|
+
"application/problem+json": {
|
|
1327
|
+
schema: {
|
|
1328
|
+
$ref: "#/components/schemas/Problem"
|
|
1329
|
+
},
|
|
1330
|
+
example: {
|
|
1331
|
+
type: "urn:synapsetree:problem:unauthorized",
|
|
1332
|
+
title: "Unauthorized",
|
|
1333
|
+
status: 401,
|
|
1334
|
+
code: "unauthorized",
|
|
1335
|
+
detail: "The API key is missing, invalid, or revoked.",
|
|
1336
|
+
requestId: "req_01j9x5v7w8example",
|
|
1337
|
+
retryable: false
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
},
|
|
1342
|
+
"429": {
|
|
1343
|
+
description: "Per-key throttle (60 requests/min) exceeded.",
|
|
1344
|
+
headers: {
|
|
1345
|
+
"Request-Id": {
|
|
1346
|
+
$ref: "#/components/headers/Request-Id"
|
|
1347
|
+
},
|
|
1348
|
+
"Retry-After": {
|
|
1349
|
+
$ref: "#/components/headers/Retry-After"
|
|
1350
|
+
}
|
|
1351
|
+
},
|
|
1352
|
+
content: {
|
|
1353
|
+
"application/json": {
|
|
1354
|
+
schema: {
|
|
1355
|
+
$ref: "#/components/schemas/OauthErrorBody"
|
|
1356
|
+
},
|
|
1357
|
+
example: {
|
|
1358
|
+
error: "server_error",
|
|
1359
|
+
error_description: "Too many requests for this key; retry later."
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
},
|
|
1364
|
+
"500": {
|
|
1365
|
+
$ref: "#/components/responses/OauthServerError"
|
|
1366
|
+
},
|
|
1367
|
+
"503": {
|
|
1368
|
+
description: "Authorization store unavailable; the request fails closed (RFC 6749 `server_error`).",
|
|
1369
|
+
headers: {
|
|
1370
|
+
"Request-Id": {
|
|
1371
|
+
$ref: "#/components/headers/Request-Id"
|
|
1372
|
+
}
|
|
1373
|
+
},
|
|
1374
|
+
content: {
|
|
1375
|
+
"application/json": {
|
|
1376
|
+
schema: {
|
|
1377
|
+
$ref: "#/components/schemas/OauthErrorBody"
|
|
1378
|
+
},
|
|
1379
|
+
example: {
|
|
1380
|
+
error: "server_error",
|
|
1381
|
+
error_description: "Authorization is temporarily unavailable; retry later."
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
},
|
|
1390
|
+
components: {
|
|
1391
|
+
headers: {
|
|
1392
|
+
"Idempotent-Replayed": {
|
|
1393
|
+
description: "Present and `true` when the response was replayed for a repeated `Idempotency-Key`.",
|
|
1394
|
+
schema: {
|
|
1395
|
+
type: "boolean"
|
|
1396
|
+
},
|
|
1397
|
+
example: true
|
|
1398
|
+
},
|
|
1399
|
+
RateLimit: {
|
|
1400
|
+
description: "Remaining quota in the current window (draft-ietf-httpapi-ratelimit-headers).",
|
|
1401
|
+
schema: {
|
|
1402
|
+
type: "string",
|
|
1403
|
+
maxLength: 256
|
|
1404
|
+
},
|
|
1405
|
+
example: '"default";r=412;t=17'
|
|
1406
|
+
},
|
|
1407
|
+
"RateLimit-Policy": {
|
|
1408
|
+
description: "Rate-limit policy (draft-ietf-httpapi-ratelimit-headers, structured fields).",
|
|
1409
|
+
schema: {
|
|
1410
|
+
type: "string",
|
|
1411
|
+
maxLength: 256
|
|
1412
|
+
},
|
|
1413
|
+
example: '"default";q=600;w=60'
|
|
1414
|
+
},
|
|
1415
|
+
"Request-Id": {
|
|
1416
|
+
description: "Identifies this request in logs and support requests.",
|
|
1417
|
+
schema: {
|
|
1418
|
+
type: "string",
|
|
1419
|
+
pattern: "^req_[A-Za-z0-9]{8,64}$"
|
|
1420
|
+
},
|
|
1421
|
+
example: "req_01j9xb7c8d9e"
|
|
1422
|
+
},
|
|
1423
|
+
"Retry-After": {
|
|
1424
|
+
description: "Seconds to wait before retrying.",
|
|
1425
|
+
schema: {
|
|
1426
|
+
type: "integer",
|
|
1427
|
+
minimum: 0
|
|
1428
|
+
},
|
|
1429
|
+
example: 5
|
|
1430
|
+
},
|
|
1431
|
+
"WWW-Authenticate": {
|
|
1432
|
+
description: "RFC 6750 challenge emitted with application-level 401s on key-bearing\nroutes, pointing at the OAuth 2.0 Protected Resource Metadata document.\n",
|
|
1433
|
+
schema: {
|
|
1434
|
+
type: "string",
|
|
1435
|
+
maxLength: 512
|
|
1436
|
+
},
|
|
1437
|
+
example: 'Bearer resource_metadata="https://api.synapsetree.dev/.well-known/oauth-protected-resource"'
|
|
1438
|
+
}
|
|
1439
|
+
},
|
|
1440
|
+
parameters: {
|
|
1441
|
+
After: {
|
|
1442
|
+
name: "after",
|
|
1443
|
+
in: "query",
|
|
1444
|
+
required: false,
|
|
1445
|
+
description: "The `nextCursor` from the previous page. Opaque; never an offset.",
|
|
1446
|
+
schema: {
|
|
1447
|
+
type: "string",
|
|
1448
|
+
minLength: 1,
|
|
1449
|
+
maxLength: 512
|
|
1450
|
+
},
|
|
1451
|
+
example: "c_eyJrIjoiZG9jc19fcnVuYm9vay5tZCJ9.k3Jf"
|
|
1452
|
+
},
|
|
1453
|
+
FactId: {
|
|
1454
|
+
name: "factId",
|
|
1455
|
+
in: "path",
|
|
1456
|
+
required: true,
|
|
1457
|
+
description: "A fact id.",
|
|
1458
|
+
schema: {
|
|
1459
|
+
$ref: "#/components/schemas/FactId"
|
|
1460
|
+
},
|
|
1461
|
+
example: "fact_01j9x7k2m3"
|
|
1462
|
+
},
|
|
1463
|
+
IdempotencyKey: {
|
|
1464
|
+
name: "Idempotency-Key",
|
|
1465
|
+
in: "header",
|
|
1466
|
+
required: false,
|
|
1467
|
+
description: "Makes a retry safe. Retained 24 hours per API key. A replay returns the stored response\nwith `Idempotent-Replayed: true`; the same key with a different body is refused with\n`422 idempotency_key_reused`.\n",
|
|
1468
|
+
schema: {
|
|
1469
|
+
type: "string",
|
|
1470
|
+
pattern: "^[A-Za-z0-9_-]{1,255}$"
|
|
1471
|
+
},
|
|
1472
|
+
example: "7f1c2e9a-ingest-runbook"
|
|
1473
|
+
},
|
|
1474
|
+
Limit: {
|
|
1475
|
+
name: "limit",
|
|
1476
|
+
in: "query",
|
|
1477
|
+
required: false,
|
|
1478
|
+
description: "Page size.",
|
|
1479
|
+
schema: {
|
|
1480
|
+
type: "integer",
|
|
1481
|
+
minimum: 1,
|
|
1482
|
+
maximum: 100,
|
|
1483
|
+
default: 50
|
|
1484
|
+
},
|
|
1485
|
+
example: 50
|
|
1486
|
+
}
|
|
1487
|
+
},
|
|
1488
|
+
responses: {
|
|
1489
|
+
BadRequest: {
|
|
1490
|
+
description: "The request is invalid (`invalid_request`).",
|
|
1491
|
+
headers: {
|
|
1492
|
+
"Request-Id": {
|
|
1493
|
+
$ref: "#/components/headers/Request-Id"
|
|
1494
|
+
}
|
|
1495
|
+
},
|
|
1496
|
+
content: {
|
|
1497
|
+
"application/problem+json": {
|
|
1498
|
+
schema: {
|
|
1499
|
+
$ref: "#/components/schemas/Problem"
|
|
1500
|
+
},
|
|
1501
|
+
example: {
|
|
1502
|
+
type: "urn:synapsetree:problem:invalid_request",
|
|
1503
|
+
title: "Invalid request",
|
|
1504
|
+
status: 400,
|
|
1505
|
+
code: "invalid_request",
|
|
1506
|
+
detail: "The request body does not match the schema.",
|
|
1507
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1508
|
+
retryable: false,
|
|
1509
|
+
errors: [
|
|
1510
|
+
{
|
|
1511
|
+
path: "/sourceRef",
|
|
1512
|
+
message: 'must match pattern "^[A-Za-z0-9._\\- ]{1,255}$"'
|
|
1513
|
+
}
|
|
1514
|
+
]
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
Conflict: {
|
|
1520
|
+
description: "The write conflicts with current state: `conflict`, `invalid_state`,\n`source_hash_conflict`, `node_id_unavailable`, `namespace_busy`,\n`namespace_exists`, `idempotency_in_progress`, `extraction_plan_stale`, or\n`inference_not_configured`.\n",
|
|
1521
|
+
headers: {
|
|
1522
|
+
"Request-Id": {
|
|
1523
|
+
$ref: "#/components/headers/Request-Id"
|
|
1524
|
+
},
|
|
1525
|
+
"Retry-After": {
|
|
1526
|
+
$ref: "#/components/headers/Retry-After"
|
|
1527
|
+
}
|
|
1528
|
+
},
|
|
1529
|
+
content: {
|
|
1530
|
+
"application/problem+json": {
|
|
1531
|
+
schema: {
|
|
1532
|
+
$ref: "#/components/schemas/Problem"
|
|
1533
|
+
},
|
|
1534
|
+
example: {
|
|
1535
|
+
type: "urn:synapsetree:problem:source_hash_conflict",
|
|
1536
|
+
title: "Source hash already stored",
|
|
1537
|
+
status: 409,
|
|
1538
|
+
code: "source_hash_conflict",
|
|
1539
|
+
detail: "Another sourceRef in this namespace already holds this content.",
|
|
1540
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1541
|
+
retryable: false,
|
|
1542
|
+
duplicateOf: "docs__runbook-old.md"
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
},
|
|
1547
|
+
Forbidden: {
|
|
1548
|
+
description: "`application/json` (API Gateway): the key is unknown or revoked, or its database is not\nroutable. `application/problem+json`: `insufficient_scope` (a `read` key on a\n`read_write` operation, or a `memory:full` key on an export or destructive operation)\nor `quota_exceeded` (the organization is over its storage quota).\n",
|
|
1549
|
+
content: {
|
|
1550
|
+
"application/json": {
|
|
1551
|
+
schema: {
|
|
1552
|
+
$ref: "#/components/schemas/GatewayError"
|
|
1553
|
+
},
|
|
1554
|
+
example: {
|
|
1555
|
+
message: "Forbidden"
|
|
1556
|
+
}
|
|
1557
|
+
},
|
|
1558
|
+
"application/problem+json": {
|
|
1559
|
+
schema: {
|
|
1560
|
+
$ref: "#/components/schemas/Problem"
|
|
1561
|
+
},
|
|
1562
|
+
example: {
|
|
1563
|
+
type: "urn:synapsetree:problem:insufficient_scope",
|
|
1564
|
+
title: "Insufficient scope",
|
|
1565
|
+
status: 403,
|
|
1566
|
+
code: "insufficient_scope",
|
|
1567
|
+
detail: "This operation needs a read_write key.",
|
|
1568
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1569
|
+
retryable: false
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
},
|
|
1574
|
+
InternalError: {
|
|
1575
|
+
description: "Unexpected server error (`internal`).",
|
|
1576
|
+
headers: {
|
|
1577
|
+
"Request-Id": {
|
|
1578
|
+
$ref: "#/components/headers/Request-Id"
|
|
1579
|
+
}
|
|
1580
|
+
},
|
|
1581
|
+
content: {
|
|
1582
|
+
"application/problem+json": {
|
|
1583
|
+
schema: {
|
|
1584
|
+
$ref: "#/components/schemas/Problem"
|
|
1585
|
+
},
|
|
1586
|
+
example: {
|
|
1587
|
+
type: "urn:synapsetree:problem:internal",
|
|
1588
|
+
title: "Internal error",
|
|
1589
|
+
status: 500,
|
|
1590
|
+
code: "internal",
|
|
1591
|
+
detail: "An unexpected error occurred.",
|
|
1592
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1593
|
+
retryable: true
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
},
|
|
1598
|
+
NotFound: {
|
|
1599
|
+
description: "The fact or draft does not exist in this namespace (`not_found`).",
|
|
1600
|
+
headers: {
|
|
1601
|
+
"Request-Id": {
|
|
1602
|
+
$ref: "#/components/headers/Request-Id"
|
|
1603
|
+
}
|
|
1604
|
+
},
|
|
1605
|
+
content: {
|
|
1606
|
+
"application/problem+json": {
|
|
1607
|
+
schema: {
|
|
1608
|
+
$ref: "#/components/schemas/Problem"
|
|
1609
|
+
},
|
|
1610
|
+
example: {
|
|
1611
|
+
type: "urn:synapsetree:problem:not_found",
|
|
1612
|
+
title: "Not found",
|
|
1613
|
+
status: 404,
|
|
1614
|
+
code: "not_found",
|
|
1615
|
+
detail: "No fact with that id exists in this namespace.",
|
|
1616
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1617
|
+
retryable: false
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
},
|
|
1622
|
+
NotImplemented: {
|
|
1623
|
+
description: "The operation or option depends on an engine release that has not shipped (`not_implemented`).",
|
|
1624
|
+
headers: {
|
|
1625
|
+
"Request-Id": {
|
|
1626
|
+
$ref: "#/components/headers/Request-Id"
|
|
1627
|
+
}
|
|
1628
|
+
},
|
|
1629
|
+
content: {
|
|
1630
|
+
"application/problem+json": {
|
|
1631
|
+
schema: {
|
|
1632
|
+
$ref: "#/components/schemas/Problem"
|
|
1633
|
+
},
|
|
1634
|
+
example: {
|
|
1635
|
+
type: "urn:synapsetree:problem:not_implemented",
|
|
1636
|
+
title: "Not implemented",
|
|
1637
|
+
status: 501,
|
|
1638
|
+
code: "not_implemented",
|
|
1639
|
+
detail: "tokenBudget is not available yet.",
|
|
1640
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1641
|
+
retryable: false
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
},
|
|
1646
|
+
OauthErrorResponse: {
|
|
1647
|
+
description: "RFC 6749 \xA75.2 error (or an RFC 8628 \xA73.5 polling signal). JSON with an\n`error` member \u2014 never problem+json.\n",
|
|
1648
|
+
headers: {
|
|
1649
|
+
"Request-Id": {
|
|
1650
|
+
$ref: "#/components/headers/Request-Id"
|
|
1651
|
+
}
|
|
1652
|
+
},
|
|
1653
|
+
content: {
|
|
1654
|
+
"application/json": {
|
|
1655
|
+
schema: {
|
|
1656
|
+
$ref: "#/components/schemas/OauthErrorBody"
|
|
1657
|
+
},
|
|
1658
|
+
examples: {
|
|
1659
|
+
authorization_pending: {
|
|
1660
|
+
value: {
|
|
1661
|
+
error: "authorization_pending",
|
|
1662
|
+
error_description: "The claim is awaiting human approval.",
|
|
1663
|
+
interval: 5
|
|
1664
|
+
}
|
|
1665
|
+
},
|
|
1666
|
+
slow_down: {
|
|
1667
|
+
value: {
|
|
1668
|
+
error: "slow_down",
|
|
1669
|
+
error_description: "Polling faster than the granted interval."
|
|
1670
|
+
}
|
|
1671
|
+
},
|
|
1672
|
+
invalid_grant: {
|
|
1673
|
+
value: {
|
|
1674
|
+
error: "invalid_grant",
|
|
1675
|
+
error_description: "The claim grant is expired, unknown, or already redeemed."
|
|
1676
|
+
}
|
|
1677
|
+
},
|
|
1678
|
+
key_limit_reached: {
|
|
1679
|
+
value: {
|
|
1680
|
+
error: "key_limit_reached",
|
|
1681
|
+
error_description: "The organization already holds the maximum number of live agent keys."
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
},
|
|
1688
|
+
OauthServerError: {
|
|
1689
|
+
description: "A transient provisioning failure with the claim grant still\nredeemable. RFC 6749 \xA75.2 `server_error` \u2014 retry with the same grant.\n",
|
|
1690
|
+
headers: {
|
|
1691
|
+
"Request-Id": {
|
|
1692
|
+
$ref: "#/components/headers/Request-Id"
|
|
1693
|
+
}
|
|
1694
|
+
},
|
|
1695
|
+
content: {
|
|
1696
|
+
"application/json": {
|
|
1697
|
+
schema: {
|
|
1698
|
+
$ref: "#/components/schemas/OauthErrorBody"
|
|
1699
|
+
},
|
|
1700
|
+
example: {
|
|
1701
|
+
error: "server_error",
|
|
1702
|
+
error_description: "Provisioning failed transiently; retry with the same claim grant."
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
},
|
|
1707
|
+
PayloadTooLarge: {
|
|
1708
|
+
description: "The request body is over the limit for this operation (`payload_too_large`).",
|
|
1709
|
+
headers: {
|
|
1710
|
+
"Request-Id": {
|
|
1711
|
+
$ref: "#/components/headers/Request-Id"
|
|
1712
|
+
}
|
|
1713
|
+
},
|
|
1714
|
+
content: {
|
|
1715
|
+
"application/problem+json": {
|
|
1716
|
+
schema: {
|
|
1717
|
+
$ref: "#/components/schemas/Problem"
|
|
1718
|
+
},
|
|
1719
|
+
example: {
|
|
1720
|
+
type: "urn:synapsetree:problem:payload_too_large",
|
|
1721
|
+
title: "Payload too large",
|
|
1722
|
+
status: 413,
|
|
1723
|
+
code: "payload_too_large",
|
|
1724
|
+
detail: "Request bodies are limited to 1 MiB.",
|
|
1725
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1726
|
+
retryable: false
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
},
|
|
1731
|
+
PaymentRequired: {
|
|
1732
|
+
description: "The organization's paid subscription is not active (`subscription_inactive`). Reads still work.",
|
|
1733
|
+
headers: {
|
|
1734
|
+
"Request-Id": {
|
|
1735
|
+
$ref: "#/components/headers/Request-Id"
|
|
1736
|
+
}
|
|
1737
|
+
},
|
|
1738
|
+
content: {
|
|
1739
|
+
"application/problem+json": {
|
|
1740
|
+
schema: {
|
|
1741
|
+
$ref: "#/components/schemas/Problem"
|
|
1742
|
+
},
|
|
1743
|
+
example: {
|
|
1744
|
+
type: "urn:synapsetree:problem:subscription_inactive",
|
|
1745
|
+
title: "Subscription inactive",
|
|
1746
|
+
status: 402,
|
|
1747
|
+
code: "subscription_inactive",
|
|
1748
|
+
detail: "The organization's subscription is canceled; writes are disabled.",
|
|
1749
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1750
|
+
retryable: false
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
},
|
|
1755
|
+
QuotaExceeded: {
|
|
1756
|
+
description: "The email already has the maximum number of outstanding claim tokens (`quota_exceeded`).",
|
|
1757
|
+
headers: {
|
|
1758
|
+
"Request-Id": {
|
|
1759
|
+
$ref: "#/components/headers/Request-Id"
|
|
1760
|
+
}
|
|
1761
|
+
},
|
|
1762
|
+
content: {
|
|
1763
|
+
"application/problem+json": {
|
|
1764
|
+
schema: {
|
|
1765
|
+
$ref: "#/components/schemas/Problem"
|
|
1766
|
+
},
|
|
1767
|
+
example: {
|
|
1768
|
+
type: "urn:synapsetree:problem:quota_exceeded",
|
|
1769
|
+
title: "Quota exceeded",
|
|
1770
|
+
status: 403,
|
|
1771
|
+
code: "quota_exceeded",
|
|
1772
|
+
detail: "This email already has the maximum number of pending claim tokens.",
|
|
1773
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1774
|
+
retryable: false
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
},
|
|
1779
|
+
ServiceUnavailable: {
|
|
1780
|
+
description: "Temporarily unavailable: `unavailable` (tenant cold start or writer handoff) or `fenced`\n(the writer lost its lease; the write did not commit). Safe to retry.\n",
|
|
1781
|
+
headers: {
|
|
1782
|
+
"Request-Id": {
|
|
1783
|
+
$ref: "#/components/headers/Request-Id"
|
|
1784
|
+
},
|
|
1785
|
+
"Retry-After": {
|
|
1786
|
+
$ref: "#/components/headers/Retry-After"
|
|
1787
|
+
}
|
|
1788
|
+
},
|
|
1789
|
+
content: {
|
|
1790
|
+
"application/problem+json": {
|
|
1791
|
+
schema: {
|
|
1792
|
+
$ref: "#/components/schemas/Problem"
|
|
1793
|
+
},
|
|
1794
|
+
example: {
|
|
1795
|
+
type: "urn:synapsetree:problem:fenced",
|
|
1796
|
+
title: "Writer fenced",
|
|
1797
|
+
status: 503,
|
|
1798
|
+
code: "fenced",
|
|
1799
|
+
detail: "The write did not commit; retry.",
|
|
1800
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1801
|
+
retryable: true,
|
|
1802
|
+
retryAfterSeconds: 1
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
},
|
|
1807
|
+
TooManyRequests: {
|
|
1808
|
+
description: "Rate limit exceeded (`rate_limited`).",
|
|
1809
|
+
headers: {
|
|
1810
|
+
"Request-Id": {
|
|
1811
|
+
$ref: "#/components/headers/Request-Id"
|
|
1812
|
+
},
|
|
1813
|
+
"Retry-After": {
|
|
1814
|
+
$ref: "#/components/headers/Retry-After"
|
|
1815
|
+
},
|
|
1816
|
+
"RateLimit-Policy": {
|
|
1817
|
+
$ref: "#/components/headers/RateLimit-Policy"
|
|
1818
|
+
},
|
|
1819
|
+
RateLimit: {
|
|
1820
|
+
$ref: "#/components/headers/RateLimit"
|
|
1821
|
+
}
|
|
1822
|
+
},
|
|
1823
|
+
content: {
|
|
1824
|
+
"application/problem+json": {
|
|
1825
|
+
schema: {
|
|
1826
|
+
$ref: "#/components/schemas/Problem"
|
|
1827
|
+
},
|
|
1828
|
+
example: {
|
|
1829
|
+
type: "urn:synapsetree:problem:rate_limited",
|
|
1830
|
+
title: "Rate limited",
|
|
1831
|
+
status: 429,
|
|
1832
|
+
code: "rate_limited",
|
|
1833
|
+
detail: "Too many requests for this key.",
|
|
1834
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1835
|
+
retryable: true,
|
|
1836
|
+
retryAfterSeconds: 17
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
},
|
|
1841
|
+
Unauthorized: {
|
|
1842
|
+
description: "Missing or malformed bearer token. Produced by API Gateway, so the body is the gateway's\nnative shape, not problem+json.\n",
|
|
1843
|
+
content: {
|
|
1844
|
+
"application/json": {
|
|
1845
|
+
schema: {
|
|
1846
|
+
$ref: "#/components/schemas/GatewayError"
|
|
1847
|
+
},
|
|
1848
|
+
example: {
|
|
1849
|
+
message: "Unauthorized"
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
},
|
|
1854
|
+
UnprocessableContent: {
|
|
1855
|
+
description: "Well-formed but refused: `ontology_violation`, `ingest_failed`,\n`idempotency_key_reused`, or `embedding_dimension_mismatch`.\n",
|
|
1856
|
+
headers: {
|
|
1857
|
+
"Request-Id": {
|
|
1858
|
+
$ref: "#/components/headers/Request-Id"
|
|
1859
|
+
}
|
|
1860
|
+
},
|
|
1861
|
+
content: {
|
|
1862
|
+
"application/problem+json": {
|
|
1863
|
+
schema: {
|
|
1864
|
+
$ref: "#/components/schemas/Problem"
|
|
1865
|
+
},
|
|
1866
|
+
example: {
|
|
1867
|
+
type: "urn:synapsetree:problem:ontology_violation",
|
|
1868
|
+
title: "Ontology violation",
|
|
1869
|
+
status: 422,
|
|
1870
|
+
code: "ontology_violation",
|
|
1871
|
+
detail: `Node type "microservice" is not in this namespace's strict manifest.`,
|
|
1872
|
+
requestId: "req_01j9xb7c8d9e",
|
|
1873
|
+
retryable: false,
|
|
1874
|
+
kind: "node",
|
|
1875
|
+
ontologyType: "microservice"
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
},
|
|
1881
|
+
schemas: {
|
|
1882
|
+
AgentIdentityRequest: {
|
|
1883
|
+
type: "object",
|
|
1884
|
+
description: "Who the human behind the agent is. `assertion` carries whatever identity assertion the agent can present (it is logged, never used to change the flow).",
|
|
1885
|
+
additionalProperties: false,
|
|
1886
|
+
required: [
|
|
1887
|
+
"email"
|
|
1888
|
+
],
|
|
1889
|
+
properties: {
|
|
1890
|
+
email: {
|
|
1891
|
+
type: "string",
|
|
1892
|
+
format: "email",
|
|
1893
|
+
description: "The human's email; the claim link is sent here."
|
|
1894
|
+
},
|
|
1895
|
+
assertion: {
|
|
1896
|
+
type: "string",
|
|
1897
|
+
description: "Optional identity assertion from the agent's provider, parsed and logged for audit only."
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
},
|
|
1901
|
+
AgentIdentityResponse: {
|
|
1902
|
+
type: "object",
|
|
1903
|
+
description: "The pending claim's poll parameters. Byte-equal for known and unknown emails.",
|
|
1904
|
+
additionalProperties: false,
|
|
1905
|
+
required: [
|
|
1906
|
+
"claim_token",
|
|
1907
|
+
"user_code",
|
|
1908
|
+
"poll"
|
|
1909
|
+
],
|
|
1910
|
+
properties: {
|
|
1911
|
+
claim_token: {
|
|
1912
|
+
type: "string",
|
|
1913
|
+
pattern: "^stclaim_[A-Za-z0-9._-]{8,128}$",
|
|
1914
|
+
description: "The claim grant to present as the OAuth `assertion` at POST /oauth2/token."
|
|
1915
|
+
},
|
|
1916
|
+
user_code: {
|
|
1917
|
+
type: "string",
|
|
1918
|
+
pattern: "^[0-9]{6}$",
|
|
1919
|
+
description: "Six-digit code the human confirms on the consent interstitial."
|
|
1920
|
+
},
|
|
1921
|
+
poll: {
|
|
1922
|
+
$ref: "#/components/schemas/PollGrant"
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
},
|
|
1926
|
+
ChunkExtraction: {
|
|
1927
|
+
type: "object",
|
|
1928
|
+
description: "One chunk's model output, as described by the plan's `outputSchema`.",
|
|
1929
|
+
additionalProperties: false,
|
|
1930
|
+
required: [
|
|
1931
|
+
"facts",
|
|
1932
|
+
"tasks"
|
|
1933
|
+
],
|
|
1934
|
+
properties: {
|
|
1935
|
+
facts: {
|
|
1936
|
+
type: "array",
|
|
1937
|
+
maxItems: 200,
|
|
1938
|
+
items: {
|
|
1939
|
+
$ref: "#/components/schemas/ExtractedFact"
|
|
1940
|
+
}
|
|
1941
|
+
},
|
|
1942
|
+
tasks: {
|
|
1943
|
+
type: "array",
|
|
1944
|
+
maxItems: 100,
|
|
1945
|
+
items: {
|
|
1946
|
+
$ref: "#/components/schemas/ExtractedTask"
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
},
|
|
1951
|
+
ChunkFailure: {
|
|
1952
|
+
type: "object",
|
|
1953
|
+
additionalProperties: false,
|
|
1954
|
+
required: [
|
|
1955
|
+
"chunkIndex",
|
|
1956
|
+
"reason"
|
|
1957
|
+
],
|
|
1958
|
+
properties: {
|
|
1959
|
+
chunkIndex: {
|
|
1960
|
+
type: "integer",
|
|
1961
|
+
minimum: 0
|
|
1962
|
+
},
|
|
1963
|
+
reason: {
|
|
1964
|
+
type: "string",
|
|
1965
|
+
enum: [
|
|
1966
|
+
"parse",
|
|
1967
|
+
"llm",
|
|
1968
|
+
"schema"
|
|
1969
|
+
],
|
|
1970
|
+
description: "Why the chunk was not ingested. Messages never include content."
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
},
|
|
1974
|
+
ChunkResult: {
|
|
1975
|
+
type: "object",
|
|
1976
|
+
additionalProperties: false,
|
|
1977
|
+
required: [
|
|
1978
|
+
"index",
|
|
1979
|
+
"response"
|
|
1980
|
+
],
|
|
1981
|
+
properties: {
|
|
1982
|
+
index: {
|
|
1983
|
+
type: "integer",
|
|
1984
|
+
minimum: 0,
|
|
1985
|
+
description: "The chunk's position in the plan's chunking of the source."
|
|
1986
|
+
},
|
|
1987
|
+
response: {
|
|
1988
|
+
$ref: "#/components/schemas/ChunkExtraction"
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
},
|
|
1992
|
+
Chunking: {
|
|
1993
|
+
type: "object",
|
|
1994
|
+
additionalProperties: false,
|
|
1995
|
+
required: [
|
|
1996
|
+
"maxChunkLength",
|
|
1997
|
+
"chunkOverlap"
|
|
1998
|
+
],
|
|
1999
|
+
properties: {
|
|
2000
|
+
maxChunkLength: {
|
|
2001
|
+
type: "integer",
|
|
2002
|
+
minimum: 2,
|
|
2003
|
+
maximum: 1e5
|
|
2004
|
+
},
|
|
2005
|
+
chunkOverlap: {
|
|
2006
|
+
type: "integer",
|
|
2007
|
+
minimum: 0,
|
|
2008
|
+
maximum: 99999
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
},
|
|
2012
|
+
ClaimGrantRequest: {
|
|
2013
|
+
type: "object",
|
|
2014
|
+
description: "Form-urlencoded claim-grant poll body (RFC 8628-style poll with an\nRFC 7523 jwt-bearer-shaped assertion).\n",
|
|
2015
|
+
additionalProperties: false,
|
|
2016
|
+
required: [
|
|
2017
|
+
"grant_type",
|
|
2018
|
+
"assertion"
|
|
2019
|
+
],
|
|
2020
|
+
properties: {
|
|
2021
|
+
grant_type: {
|
|
2022
|
+
type: "string",
|
|
2023
|
+
const: "urn:synapsetree:claim",
|
|
2024
|
+
description: "The claim-grant flow's only grant type."
|
|
2025
|
+
},
|
|
2026
|
+
assertion: {
|
|
2027
|
+
type: "string",
|
|
2028
|
+
pattern: "^stclaim_[A-Za-z0-9._-]{8,128}$",
|
|
2029
|
+
description: "The `stclaim_\u2026` claim token from POST /agent/identity."
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
},
|
|
2033
|
+
ClientExtractionIngest: {
|
|
2034
|
+
type: "object",
|
|
2035
|
+
additionalProperties: false,
|
|
2036
|
+
required: [
|
|
2037
|
+
"mode",
|
|
2038
|
+
"namespace",
|
|
2039
|
+
"sourceRef",
|
|
2040
|
+
"sourceHash",
|
|
2041
|
+
"planFingerprint",
|
|
2042
|
+
"chunks"
|
|
2043
|
+
],
|
|
2044
|
+
properties: {
|
|
2045
|
+
mode: {
|
|
2046
|
+
type: "string",
|
|
2047
|
+
const: "client_extraction"
|
|
2048
|
+
},
|
|
2049
|
+
namespace: {
|
|
2050
|
+
$ref: "#/components/schemas/Namespace"
|
|
2051
|
+
},
|
|
2052
|
+
sourceRef: {
|
|
2053
|
+
$ref: "#/components/schemas/SourceRef"
|
|
2054
|
+
},
|
|
2055
|
+
sourceHash: {
|
|
2056
|
+
$ref: "#/components/schemas/SourceHash"
|
|
2057
|
+
},
|
|
2058
|
+
planFingerprint: {
|
|
2059
|
+
$ref: "#/components/schemas/PlanFingerprint"
|
|
2060
|
+
},
|
|
2061
|
+
onDuplicateHash: {
|
|
2062
|
+
$ref: "#/components/schemas/OnDuplicateHash"
|
|
2063
|
+
},
|
|
2064
|
+
chunks: {
|
|
2065
|
+
type: "array",
|
|
2066
|
+
minItems: 1,
|
|
2067
|
+
maxItems: 1e3,
|
|
2068
|
+
items: {
|
|
2069
|
+
$ref: "#/components/schemas/ChunkResult"
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
},
|
|
2074
|
+
Confidence: {
|
|
2075
|
+
type: "string",
|
|
2076
|
+
enum: [
|
|
2077
|
+
"certain",
|
|
2078
|
+
"inferred",
|
|
2079
|
+
"tentative"
|
|
2080
|
+
]
|
|
2081
|
+
},
|
|
2082
|
+
CreateEventRequest: {
|
|
2083
|
+
type: "object",
|
|
2084
|
+
additionalProperties: false,
|
|
2085
|
+
required: [
|
|
2086
|
+
"namespace",
|
|
2087
|
+
"eventType",
|
|
2088
|
+
"summary"
|
|
2089
|
+
],
|
|
2090
|
+
properties: {
|
|
2091
|
+
namespace: {
|
|
2092
|
+
$ref: "#/components/schemas/Namespace"
|
|
2093
|
+
},
|
|
2094
|
+
eventType: {
|
|
2095
|
+
$ref: "#/components/schemas/EventType"
|
|
2096
|
+
},
|
|
2097
|
+
summary: {
|
|
2098
|
+
type: "string",
|
|
2099
|
+
minLength: 1,
|
|
2100
|
+
maxLength: 4e3,
|
|
2101
|
+
description: "Trimmed of surrounding whitespace, then at most 4000 UTF-16 code units (the engine's limit; JSON Schema's maxLength counts code points, so astral characters count twice). Narrowed from 8000 by the dated 2026-11-01 D12 exception."
|
|
2102
|
+
},
|
|
2103
|
+
relatedFactId: {
|
|
2104
|
+
$ref: "#/components/schemas/FactId"
|
|
2105
|
+
},
|
|
2106
|
+
occurredAt: {
|
|
2107
|
+
description: "When it happened. Defaults to now.",
|
|
2108
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
},
|
|
2112
|
+
Cursor: {
|
|
2113
|
+
type: "string",
|
|
2114
|
+
description: "Opaque pagination cursor.",
|
|
2115
|
+
minLength: 1,
|
|
2116
|
+
maxLength: 512,
|
|
2117
|
+
examples: [
|
|
2118
|
+
"c_eyJrIjoiZG9jc19fcnVuYm9vay5tZCJ9.k3Jf"
|
|
2119
|
+
]
|
|
2120
|
+
},
|
|
2121
|
+
Direction: {
|
|
2122
|
+
type: "string",
|
|
2123
|
+
enum: [
|
|
2124
|
+
"inbound",
|
|
2125
|
+
"outbound",
|
|
2126
|
+
"both"
|
|
2127
|
+
]
|
|
2128
|
+
},
|
|
2129
|
+
Edge: {
|
|
2130
|
+
type: "object",
|
|
2131
|
+
additionalProperties: false,
|
|
2132
|
+
required: [
|
|
2133
|
+
"id",
|
|
2134
|
+
"namespace",
|
|
2135
|
+
"sourceId",
|
|
2136
|
+
"targetId",
|
|
2137
|
+
"edgeType",
|
|
2138
|
+
"createdAt"
|
|
2139
|
+
],
|
|
2140
|
+
properties: {
|
|
2141
|
+
id: {
|
|
2142
|
+
type: "string",
|
|
2143
|
+
minLength: 1,
|
|
2144
|
+
maxLength: 255
|
|
2145
|
+
},
|
|
2146
|
+
namespace: {
|
|
2147
|
+
$ref: "#/components/schemas/Namespace"
|
|
2148
|
+
},
|
|
2149
|
+
sourceId: {
|
|
2150
|
+
$ref: "#/components/schemas/FactId"
|
|
2151
|
+
},
|
|
2152
|
+
targetId: {
|
|
2153
|
+
$ref: "#/components/schemas/FactId"
|
|
2154
|
+
},
|
|
2155
|
+
edgeType: {
|
|
2156
|
+
$ref: "#/components/schemas/EdgeType"
|
|
2157
|
+
},
|
|
2158
|
+
createdAt: {
|
|
2159
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
},
|
|
2163
|
+
EdgeType: {
|
|
2164
|
+
description: "Edge type. Open, like OkfType; the listed values are the schema-software-org edges.",
|
|
2165
|
+
anyOf: [
|
|
2166
|
+
{
|
|
2167
|
+
type: "string",
|
|
2168
|
+
enum: [
|
|
2169
|
+
"knows",
|
|
2170
|
+
"spouse",
|
|
2171
|
+
"parent",
|
|
2172
|
+
"worksFor",
|
|
2173
|
+
"memberOf",
|
|
2174
|
+
"homeLocation",
|
|
2175
|
+
"workLocation",
|
|
2176
|
+
"location",
|
|
2177
|
+
"containedInPlace",
|
|
2178
|
+
"subOrganization",
|
|
2179
|
+
"object",
|
|
2180
|
+
"agent",
|
|
2181
|
+
"attendee",
|
|
2182
|
+
"organizer",
|
|
2183
|
+
"author",
|
|
2184
|
+
"publisher",
|
|
2185
|
+
"about",
|
|
2186
|
+
"itemReviewed",
|
|
2187
|
+
"owns",
|
|
2188
|
+
"dependsOn",
|
|
2189
|
+
"specifies",
|
|
2190
|
+
"documents",
|
|
2191
|
+
"handoffFor",
|
|
2192
|
+
"supersedes",
|
|
2193
|
+
"hasRole",
|
|
2194
|
+
"operates",
|
|
2195
|
+
"provides",
|
|
2196
|
+
"maintains"
|
|
2197
|
+
]
|
|
2198
|
+
},
|
|
2199
|
+
{
|
|
2200
|
+
type: "string",
|
|
2201
|
+
minLength: 1,
|
|
2202
|
+
maxLength: 128
|
|
2203
|
+
}
|
|
2204
|
+
]
|
|
2205
|
+
},
|
|
2206
|
+
Embedding: {
|
|
2207
|
+
type: "array",
|
|
2208
|
+
description: "A client-computed embedding vector. All vectors in a namespace must share one model and\ndimension; a different dimension is refused with `422 embedding_dimension_mismatch`.\n",
|
|
2209
|
+
minItems: 1,
|
|
2210
|
+
maxItems: 8192,
|
|
2211
|
+
items: {
|
|
2212
|
+
type: "number"
|
|
2213
|
+
},
|
|
2214
|
+
examples: [
|
|
2215
|
+
[
|
|
2216
|
+
0.0123,
|
|
2217
|
+
-0.0456,
|
|
2218
|
+
0.0789
|
|
2219
|
+
]
|
|
2220
|
+
]
|
|
2221
|
+
},
|
|
2222
|
+
Event: {
|
|
2223
|
+
type: "object",
|
|
2224
|
+
additionalProperties: false,
|
|
2225
|
+
required: [
|
|
2226
|
+
"id",
|
|
2227
|
+
"namespace",
|
|
2228
|
+
"eventType",
|
|
2229
|
+
"summary",
|
|
2230
|
+
"relatedFactId",
|
|
2231
|
+
"occurredAt",
|
|
2232
|
+
"createdAt"
|
|
2233
|
+
],
|
|
2234
|
+
properties: {
|
|
2235
|
+
id: {
|
|
2236
|
+
type: "string",
|
|
2237
|
+
minLength: 1,
|
|
2238
|
+
maxLength: 255
|
|
2239
|
+
},
|
|
2240
|
+
namespace: {
|
|
2241
|
+
$ref: "#/components/schemas/Namespace"
|
|
2242
|
+
},
|
|
2243
|
+
eventType: {
|
|
2244
|
+
$ref: "#/components/schemas/EventType"
|
|
2245
|
+
},
|
|
2246
|
+
summary: {
|
|
2247
|
+
type: "string",
|
|
2248
|
+
minLength: 1,
|
|
2249
|
+
maxLength: 8e3
|
|
2250
|
+
},
|
|
2251
|
+
relatedFactId: {
|
|
2252
|
+
anyOf: [
|
|
2253
|
+
{
|
|
2254
|
+
$ref: "#/components/schemas/FactId"
|
|
2255
|
+
},
|
|
2256
|
+
{
|
|
2257
|
+
type: "null"
|
|
2258
|
+
}
|
|
2259
|
+
]
|
|
2260
|
+
},
|
|
2261
|
+
occurredAt: {
|
|
2262
|
+
description: "When the event happened. Null means at `createdAt`.",
|
|
2263
|
+
anyOf: [
|
|
2264
|
+
{
|
|
2265
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2266
|
+
},
|
|
2267
|
+
{
|
|
2268
|
+
type: "null"
|
|
2269
|
+
}
|
|
2270
|
+
]
|
|
2271
|
+
},
|
|
2272
|
+
createdAt: {
|
|
2273
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
},
|
|
2277
|
+
EventType: {
|
|
2278
|
+
type: "string",
|
|
2279
|
+
enum: [
|
|
2280
|
+
"observation",
|
|
2281
|
+
"decision",
|
|
2282
|
+
"action",
|
|
2283
|
+
"outcome"
|
|
2284
|
+
]
|
|
2285
|
+
},
|
|
2286
|
+
ExistingFactReplacement: {
|
|
2287
|
+
type: "object",
|
|
2288
|
+
additionalProperties: false,
|
|
2289
|
+
required: [
|
|
2290
|
+
"kind",
|
|
2291
|
+
"factId"
|
|
2292
|
+
],
|
|
2293
|
+
properties: {
|
|
2294
|
+
kind: {
|
|
2295
|
+
type: "string",
|
|
2296
|
+
const: "existing"
|
|
2297
|
+
},
|
|
2298
|
+
factId: {
|
|
2299
|
+
$ref: "#/components/schemas/FactId"
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
},
|
|
2303
|
+
ExtractedEdge: {
|
|
2304
|
+
type: "object",
|
|
2305
|
+
additionalProperties: false,
|
|
2306
|
+
required: [
|
|
2307
|
+
"edgeType",
|
|
2308
|
+
"targetTitle"
|
|
2309
|
+
],
|
|
2310
|
+
properties: {
|
|
2311
|
+
edgeType: {
|
|
2312
|
+
$ref: "#/components/schemas/EdgeType"
|
|
2313
|
+
},
|
|
2314
|
+
targetTitle: {
|
|
2315
|
+
type: "string",
|
|
2316
|
+
minLength: 1,
|
|
2317
|
+
maxLength: 1e3,
|
|
2318
|
+
description: "Title of another fact in this response or already in the namespace."
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
},
|
|
2322
|
+
ExtractedFact: {
|
|
2323
|
+
type: "object",
|
|
2324
|
+
additionalProperties: false,
|
|
2325
|
+
required: [
|
|
2326
|
+
"title",
|
|
2327
|
+
"body",
|
|
2328
|
+
"tags",
|
|
2329
|
+
"confidence"
|
|
2330
|
+
],
|
|
2331
|
+
properties: {
|
|
2332
|
+
title: {
|
|
2333
|
+
type: "string",
|
|
2334
|
+
minLength: 1,
|
|
2335
|
+
maxLength: 1e3
|
|
2336
|
+
},
|
|
2337
|
+
body: {
|
|
2338
|
+
type: "string",
|
|
2339
|
+
minLength: 1,
|
|
2340
|
+
maxLength: 1e5
|
|
2341
|
+
},
|
|
2342
|
+
tags: {
|
|
2343
|
+
type: "array",
|
|
2344
|
+
maxItems: 100,
|
|
2345
|
+
items: {
|
|
2346
|
+
type: "string",
|
|
2347
|
+
minLength: 1,
|
|
2348
|
+
maxLength: 100
|
|
2349
|
+
}
|
|
2350
|
+
},
|
|
2351
|
+
confidence: {
|
|
2352
|
+
$ref: "#/components/schemas/Confidence"
|
|
2353
|
+
},
|
|
2354
|
+
okfType: {
|
|
2355
|
+
$ref: "#/components/schemas/OkfType"
|
|
2356
|
+
},
|
|
2357
|
+
evidence: {
|
|
2358
|
+
type: "array",
|
|
2359
|
+
description: "Quotes copied from the chunk, checked when grounding is on. Never stored.",
|
|
2360
|
+
maxItems: 10,
|
|
2361
|
+
items: {
|
|
2362
|
+
type: "string",
|
|
2363
|
+
minLength: 1,
|
|
2364
|
+
maxLength: 2e3
|
|
2365
|
+
}
|
|
2366
|
+
},
|
|
2367
|
+
edges: {
|
|
2368
|
+
type: "array",
|
|
2369
|
+
maxItems: 50,
|
|
2370
|
+
items: {
|
|
2371
|
+
$ref: "#/components/schemas/ExtractedEdge"
|
|
2372
|
+
}
|
|
2373
|
+
},
|
|
2374
|
+
embedding: {
|
|
2375
|
+
$ref: "#/components/schemas/Embedding"
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
},
|
|
2379
|
+
ExtractedTask: {
|
|
2380
|
+
type: "object",
|
|
2381
|
+
additionalProperties: false,
|
|
2382
|
+
required: [
|
|
2383
|
+
"description",
|
|
2384
|
+
"priority"
|
|
2385
|
+
],
|
|
2386
|
+
properties: {
|
|
2387
|
+
description: {
|
|
2388
|
+
type: "string",
|
|
2389
|
+
minLength: 1,
|
|
2390
|
+
maxLength: 4e3
|
|
2391
|
+
},
|
|
2392
|
+
priority: {
|
|
2393
|
+
type: "integer",
|
|
2394
|
+
minimum: 0,
|
|
2395
|
+
maximum: 10
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
},
|
|
2399
|
+
Fact: {
|
|
2400
|
+
description: "A fact, discriminated by `sourceType`.",
|
|
2401
|
+
oneOf: [
|
|
2402
|
+
{
|
|
2403
|
+
$ref: "#/components/schemas/ImmutableDocumentFact"
|
|
2404
|
+
},
|
|
2405
|
+
{
|
|
2406
|
+
$ref: "#/components/schemas/LibrarianInferredFact"
|
|
2407
|
+
},
|
|
2408
|
+
{
|
|
2409
|
+
$ref: "#/components/schemas/UserStatedFact"
|
|
2410
|
+
},
|
|
2411
|
+
{
|
|
2412
|
+
$ref: "#/components/schemas/UserConfirmedFact"
|
|
2413
|
+
}
|
|
2414
|
+
],
|
|
2415
|
+
discriminator: {
|
|
2416
|
+
propertyName: "sourceType",
|
|
2417
|
+
mapping: {
|
|
2418
|
+
immutable_document: "#/components/schemas/ImmutableDocumentFact",
|
|
2419
|
+
librarian_inferred: "#/components/schemas/LibrarianInferredFact",
|
|
2420
|
+
user_stated: "#/components/schemas/UserStatedFact",
|
|
2421
|
+
user_confirmed: "#/components/schemas/UserConfirmedFact"
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
},
|
|
2425
|
+
FactBase: {
|
|
2426
|
+
type: "object",
|
|
2427
|
+
description: "Fields shared by every fact. Not used on its own; see `Fact`.",
|
|
2428
|
+
required: [
|
|
2429
|
+
"id",
|
|
2430
|
+
"namespace",
|
|
2431
|
+
"title",
|
|
2432
|
+
"body",
|
|
2433
|
+
"tags",
|
|
2434
|
+
"confidence",
|
|
2435
|
+
"okfType",
|
|
2436
|
+
"lifecycleStatus",
|
|
2437
|
+
"trustTier",
|
|
2438
|
+
"isStale",
|
|
2439
|
+
"generatedBy",
|
|
2440
|
+
"lastVerifiedAt",
|
|
2441
|
+
"lastVerifiedBy",
|
|
2442
|
+
"validFrom",
|
|
2443
|
+
"validTo",
|
|
2444
|
+
"supersededBy",
|
|
2445
|
+
"supersededAt",
|
|
2446
|
+
"accessCount",
|
|
2447
|
+
"lastAccessedAt",
|
|
2448
|
+
"createdAt",
|
|
2449
|
+
"updatedAt"
|
|
2450
|
+
],
|
|
2451
|
+
properties: {
|
|
2452
|
+
id: {
|
|
2453
|
+
$ref: "#/components/schemas/FactId"
|
|
2454
|
+
},
|
|
2455
|
+
namespace: {
|
|
2456
|
+
$ref: "#/components/schemas/Namespace"
|
|
2457
|
+
},
|
|
2458
|
+
title: {
|
|
2459
|
+
type: "string",
|
|
2460
|
+
minLength: 1,
|
|
2461
|
+
maxLength: 1e3
|
|
2462
|
+
},
|
|
2463
|
+
body: {
|
|
2464
|
+
type: "string",
|
|
2465
|
+
maxLength: 1e5
|
|
2466
|
+
},
|
|
2467
|
+
tags: {
|
|
2468
|
+
type: "array",
|
|
2469
|
+
maxItems: 100,
|
|
2470
|
+
items: {
|
|
2471
|
+
type: "string",
|
|
2472
|
+
minLength: 1,
|
|
2473
|
+
maxLength: 100
|
|
2474
|
+
}
|
|
2475
|
+
},
|
|
2476
|
+
confidence: {
|
|
2477
|
+
$ref: "#/components/schemas/Confidence"
|
|
2478
|
+
},
|
|
2479
|
+
okfType: {
|
|
2480
|
+
description: "Ontology node type, or null when untyped.",
|
|
2481
|
+
anyOf: [
|
|
2482
|
+
{
|
|
2483
|
+
$ref: "#/components/schemas/OkfType"
|
|
2484
|
+
},
|
|
2485
|
+
{
|
|
2486
|
+
type: "null"
|
|
2487
|
+
}
|
|
2488
|
+
]
|
|
2489
|
+
},
|
|
2490
|
+
lifecycleStatus: {
|
|
2491
|
+
$ref: "#/components/schemas/LifecycleStatus"
|
|
2492
|
+
},
|
|
2493
|
+
trustTier: {
|
|
2494
|
+
$ref: "#/components/schemas/TrustTier"
|
|
2495
|
+
},
|
|
2496
|
+
isStale: {
|
|
2497
|
+
type: "boolean"
|
|
2498
|
+
},
|
|
2499
|
+
generatedBy: {
|
|
2500
|
+
type: [
|
|
2501
|
+
"string",
|
|
2502
|
+
"null"
|
|
2503
|
+
],
|
|
2504
|
+
maxLength: 256,
|
|
2505
|
+
description: "Producing actor, e.g. `process:librarian` or `human:kurt`."
|
|
2506
|
+
},
|
|
2507
|
+
lastVerifiedAt: {
|
|
2508
|
+
anyOf: [
|
|
2509
|
+
{
|
|
2510
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2511
|
+
},
|
|
2512
|
+
{
|
|
2513
|
+
type: "null"
|
|
2514
|
+
}
|
|
2515
|
+
]
|
|
2516
|
+
},
|
|
2517
|
+
lastVerifiedBy: {
|
|
2518
|
+
type: [
|
|
2519
|
+
"string",
|
|
2520
|
+
"null"
|
|
2521
|
+
],
|
|
2522
|
+
maxLength: 256
|
|
2523
|
+
},
|
|
2524
|
+
validFrom: {
|
|
2525
|
+
description: "When the fact became true in the world. Null means since `createdAt`.",
|
|
2526
|
+
anyOf: [
|
|
2527
|
+
{
|
|
2528
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2529
|
+
},
|
|
2530
|
+
{
|
|
2531
|
+
type: "null"
|
|
2532
|
+
}
|
|
2533
|
+
]
|
|
2534
|
+
},
|
|
2535
|
+
validTo: {
|
|
2536
|
+
description: "When the fact stopped being true. Null means still current.",
|
|
2537
|
+
anyOf: [
|
|
2538
|
+
{
|
|
2539
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2540
|
+
},
|
|
2541
|
+
{
|
|
2542
|
+
type: "null"
|
|
2543
|
+
}
|
|
2544
|
+
]
|
|
2545
|
+
},
|
|
2546
|
+
supersededBy: {
|
|
2547
|
+
description: "The fact that replaced this one.",
|
|
2548
|
+
anyOf: [
|
|
2549
|
+
{
|
|
2550
|
+
$ref: "#/components/schemas/FactId"
|
|
2551
|
+
},
|
|
2552
|
+
{
|
|
2553
|
+
type: "null"
|
|
2554
|
+
}
|
|
2555
|
+
]
|
|
2556
|
+
},
|
|
2557
|
+
supersededAt: {
|
|
2558
|
+
description: "When the replacement was recorded.",
|
|
2559
|
+
anyOf: [
|
|
2560
|
+
{
|
|
2561
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2562
|
+
},
|
|
2563
|
+
{
|
|
2564
|
+
type: "null"
|
|
2565
|
+
}
|
|
2566
|
+
]
|
|
2567
|
+
},
|
|
2568
|
+
accessCount: {
|
|
2569
|
+
type: "integer",
|
|
2570
|
+
minimum: 0
|
|
2571
|
+
},
|
|
2572
|
+
lastAccessedAt: {
|
|
2573
|
+
anyOf: [
|
|
2574
|
+
{
|
|
2575
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2576
|
+
},
|
|
2577
|
+
{
|
|
2578
|
+
type: "null"
|
|
2579
|
+
}
|
|
2580
|
+
]
|
|
2581
|
+
},
|
|
2582
|
+
createdAt: {
|
|
2583
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2584
|
+
},
|
|
2585
|
+
updatedAt: {
|
|
2586
|
+
$ref: "#/components/schemas/Timestamp"
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
},
|
|
2590
|
+
FactId: {
|
|
2591
|
+
type: "string",
|
|
2592
|
+
description: "An opaque fact id. Engine-generated ids start with `fact_`; graph node ids are caller-chosen.",
|
|
2593
|
+
minLength: 1,
|
|
2594
|
+
maxLength: 255,
|
|
2595
|
+
examples: [
|
|
2596
|
+
"fact_01j9x7k2m3"
|
|
2597
|
+
]
|
|
2598
|
+
},
|
|
2599
|
+
GatewayError: {
|
|
2600
|
+
type: "object",
|
|
2601
|
+
description: "API Gateway's native error body (authorizer denials). Not problem+json.",
|
|
2602
|
+
additionalProperties: false,
|
|
2603
|
+
required: [
|
|
2604
|
+
"message"
|
|
2605
|
+
],
|
|
2606
|
+
properties: {
|
|
2607
|
+
message: {
|
|
2608
|
+
type: "string"
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
},
|
|
2612
|
+
ImmutableDocumentFact: {
|
|
2613
|
+
type: "object",
|
|
2614
|
+
description: "A fact extracted from or written for a source document. Changes only by re-ingesting the source.",
|
|
2615
|
+
allOf: [
|
|
2616
|
+
{
|
|
2617
|
+
$ref: "#/components/schemas/FactBase"
|
|
2618
|
+
},
|
|
2619
|
+
{
|
|
2620
|
+
type: "object",
|
|
2621
|
+
required: [
|
|
2622
|
+
"sourceType",
|
|
2623
|
+
"mutable",
|
|
2624
|
+
"sourceRef",
|
|
2625
|
+
"sourceHash"
|
|
2626
|
+
],
|
|
2627
|
+
properties: {
|
|
2628
|
+
sourceType: {
|
|
2629
|
+
type: "string",
|
|
2630
|
+
const: "immutable_document"
|
|
2631
|
+
},
|
|
2632
|
+
mutable: {
|
|
2633
|
+
type: "boolean",
|
|
2634
|
+
const: false
|
|
2635
|
+
},
|
|
2636
|
+
sourceRef: {
|
|
2637
|
+
$ref: "#/components/schemas/SourceRef"
|
|
2638
|
+
},
|
|
2639
|
+
sourceHash: {
|
|
2640
|
+
description: "Null after a partially failed ingest; re-ingest to complete it.",
|
|
2641
|
+
anyOf: [
|
|
2642
|
+
{
|
|
2643
|
+
$ref: "#/components/schemas/SourceHash"
|
|
2644
|
+
},
|
|
2645
|
+
{
|
|
2646
|
+
type: "null"
|
|
2647
|
+
}
|
|
2648
|
+
]
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
],
|
|
2653
|
+
unevaluatedProperties: false
|
|
2654
|
+
},
|
|
2655
|
+
IngestRequest: {
|
|
2656
|
+
oneOf: [
|
|
2657
|
+
{
|
|
2658
|
+
$ref: "#/components/schemas/ServerExtractionIngest"
|
|
2659
|
+
},
|
|
2660
|
+
{
|
|
2661
|
+
$ref: "#/components/schemas/ClientExtractionIngest"
|
|
2662
|
+
}
|
|
2663
|
+
],
|
|
2664
|
+
discriminator: {
|
|
2665
|
+
propertyName: "mode",
|
|
2666
|
+
mapping: {
|
|
2667
|
+
server_extraction: "#/components/schemas/ServerExtractionIngest",
|
|
2668
|
+
client_extraction: "#/components/schemas/ClientExtractionIngest"
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
},
|
|
2672
|
+
IngestResponse: {
|
|
2673
|
+
type: "object",
|
|
2674
|
+
additionalProperties: false,
|
|
2675
|
+
required: [
|
|
2676
|
+
"chunks",
|
|
2677
|
+
"ingestedChunks",
|
|
2678
|
+
"failedChunks",
|
|
2679
|
+
"truncated",
|
|
2680
|
+
"duplicateOf",
|
|
2681
|
+
"parseFailures"
|
|
2682
|
+
],
|
|
2683
|
+
properties: {
|
|
2684
|
+
chunks: {
|
|
2685
|
+
type: "integer",
|
|
2686
|
+
minimum: 0
|
|
2687
|
+
},
|
|
2688
|
+
ingestedChunks: {
|
|
2689
|
+
type: "integer",
|
|
2690
|
+
minimum: 0
|
|
2691
|
+
},
|
|
2692
|
+
failedChunks: {
|
|
2693
|
+
type: "integer",
|
|
2694
|
+
minimum: 0
|
|
2695
|
+
},
|
|
2696
|
+
truncated: {
|
|
2697
|
+
type: "boolean",
|
|
2698
|
+
description: "True when chunking had to hard-cut text with no natural break."
|
|
2699
|
+
},
|
|
2700
|
+
duplicateOf: {
|
|
2701
|
+
description: "Set when `onDuplicateHash` is `skip` and another sourceRef already holds the content.",
|
|
2702
|
+
anyOf: [
|
|
2703
|
+
{
|
|
2704
|
+
$ref: "#/components/schemas/SourceRef"
|
|
2705
|
+
},
|
|
2706
|
+
{
|
|
2707
|
+
type: "null"
|
|
2708
|
+
}
|
|
2709
|
+
]
|
|
2710
|
+
},
|
|
2711
|
+
parseFailures: {
|
|
2712
|
+
type: "array",
|
|
2713
|
+
items: {
|
|
2714
|
+
$ref: "#/components/schemas/ChunkFailure"
|
|
2715
|
+
}
|
|
2716
|
+
},
|
|
2717
|
+
embeddingFailures: {
|
|
2718
|
+
type: "integer",
|
|
2719
|
+
minimum: 0,
|
|
2720
|
+
description: "Write-phase embed failures counted during this ingest (`{ok: false}` per fact);\nthe facts commit keyword-only and the re-embed maintenance path repairs them.\nAbsent when every embed succeeded.\n"
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
},
|
|
2724
|
+
LibrarianInferredFact: {
|
|
2725
|
+
type: "object",
|
|
2726
|
+
description: "A fact consolidated from events by the librarian.",
|
|
2727
|
+
allOf: [
|
|
2728
|
+
{
|
|
2729
|
+
$ref: "#/components/schemas/FactBase"
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
$ref: "#/components/schemas/MutableFactFields"
|
|
2733
|
+
},
|
|
2734
|
+
{
|
|
2735
|
+
type: "object",
|
|
2736
|
+
required: [
|
|
2737
|
+
"sourceType"
|
|
2738
|
+
],
|
|
2739
|
+
properties: {
|
|
2740
|
+
sourceType: {
|
|
2741
|
+
type: "string",
|
|
2742
|
+
const: "librarian_inferred"
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
],
|
|
2747
|
+
unevaluatedProperties: false
|
|
2748
|
+
},
|
|
2749
|
+
LifecycleStatus: {
|
|
2750
|
+
type: "string",
|
|
2751
|
+
enum: [
|
|
2752
|
+
"draft",
|
|
2753
|
+
"stable",
|
|
2754
|
+
"deprecated"
|
|
2755
|
+
]
|
|
2756
|
+
},
|
|
2757
|
+
MutableFactFields: {
|
|
2758
|
+
type: "object",
|
|
2759
|
+
description: "Fields shared by mutable facts. Not used on its own; see `Fact`.",
|
|
2760
|
+
required: [
|
|
2761
|
+
"mutable",
|
|
2762
|
+
"sourceRef",
|
|
2763
|
+
"sourceHash"
|
|
2764
|
+
],
|
|
2765
|
+
properties: {
|
|
2766
|
+
mutable: {
|
|
2767
|
+
type: "boolean",
|
|
2768
|
+
const: true
|
|
2769
|
+
},
|
|
2770
|
+
sourceRef: {
|
|
2771
|
+
type: "null"
|
|
2772
|
+
},
|
|
2773
|
+
sourceHash: {
|
|
2774
|
+
type: "null"
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
},
|
|
2778
|
+
MutableSourceType: {
|
|
2779
|
+
type: "string",
|
|
2780
|
+
enum: [
|
|
2781
|
+
"user_stated",
|
|
2782
|
+
"user_confirmed",
|
|
2783
|
+
"librarian_inferred"
|
|
2784
|
+
]
|
|
2785
|
+
},
|
|
2786
|
+
Namespace: {
|
|
2787
|
+
type: "string",
|
|
2788
|
+
description: "A namespace inside the tenant database (the engine's entity_id).",
|
|
2789
|
+
pattern: "^[a-z0-9][a-z0-9._:-]{0,127}$",
|
|
2790
|
+
examples: [
|
|
2791
|
+
"repo:synapsetree"
|
|
2792
|
+
]
|
|
2793
|
+
},
|
|
2794
|
+
NamespaceList: {
|
|
2795
|
+
type: "object",
|
|
2796
|
+
additionalProperties: false,
|
|
2797
|
+
required: [
|
|
2798
|
+
"data",
|
|
2799
|
+
"hasMore",
|
|
2800
|
+
"nextCursor"
|
|
2801
|
+
],
|
|
2802
|
+
properties: {
|
|
2803
|
+
data: {
|
|
2804
|
+
type: "array",
|
|
2805
|
+
items: {
|
|
2806
|
+
$ref: "#/components/schemas/NamespaceSummary"
|
|
2807
|
+
}
|
|
2808
|
+
},
|
|
2809
|
+
hasMore: {
|
|
2810
|
+
type: "boolean"
|
|
2811
|
+
},
|
|
2812
|
+
nextCursor: {
|
|
2813
|
+
anyOf: [
|
|
2814
|
+
{
|
|
2815
|
+
$ref: "#/components/schemas/Cursor"
|
|
2816
|
+
},
|
|
2817
|
+
{
|
|
2818
|
+
type: "null"
|
|
2819
|
+
}
|
|
2820
|
+
]
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
},
|
|
2824
|
+
NamespaceSummary: {
|
|
2825
|
+
type: "object",
|
|
2826
|
+
additionalProperties: false,
|
|
2827
|
+
required: [
|
|
2828
|
+
"namespace"
|
|
2829
|
+
],
|
|
2830
|
+
properties: {
|
|
2831
|
+
namespace: {
|
|
2832
|
+
$ref: "#/components/schemas/Namespace"
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
},
|
|
2836
|
+
NewFactReplacement: {
|
|
2837
|
+
type: "object",
|
|
2838
|
+
additionalProperties: false,
|
|
2839
|
+
required: [
|
|
2840
|
+
"kind",
|
|
2841
|
+
"title",
|
|
2842
|
+
"body"
|
|
2843
|
+
],
|
|
2844
|
+
properties: {
|
|
2845
|
+
kind: {
|
|
2846
|
+
type: "string",
|
|
2847
|
+
const: "new"
|
|
2848
|
+
},
|
|
2849
|
+
title: {
|
|
2850
|
+
type: "string",
|
|
2851
|
+
minLength: 1,
|
|
2852
|
+
maxLength: 1e3
|
|
2853
|
+
},
|
|
2854
|
+
body: {
|
|
2855
|
+
type: "string",
|
|
2856
|
+
minLength: 1,
|
|
2857
|
+
maxLength: 1e5
|
|
2858
|
+
},
|
|
2859
|
+
tags: {
|
|
2860
|
+
type: "array",
|
|
2861
|
+
maxItems: 100,
|
|
2862
|
+
items: {
|
|
2863
|
+
type: "string",
|
|
2864
|
+
minLength: 1,
|
|
2865
|
+
maxLength: 100
|
|
2866
|
+
}
|
|
2867
|
+
},
|
|
2868
|
+
confidence: {
|
|
2869
|
+
$ref: "#/components/schemas/Confidence"
|
|
2870
|
+
},
|
|
2871
|
+
sourceType: {
|
|
2872
|
+
$ref: "#/components/schemas/MutableSourceType"
|
|
2873
|
+
},
|
|
2874
|
+
embedding: {
|
|
2875
|
+
$ref: "#/components/schemas/Embedding"
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
},
|
|
2879
|
+
OauthErrorBody: {
|
|
2880
|
+
type: "object",
|
|
2881
|
+
description: "RFC 6749 \xA75.2 error body: `error` plus optional `error_description`;\n`interval` rides on `authorization_pending` (RFC 8628 \xA73.5).\n`key_limit_reached`, `database_name_taken` and `database_quota_exceeded`\nare documented SynapseTree extensions of the `error` member \u2014 account\nwalls a human must clear, after which the agent resumes polling (the\nclaim grant survives until its TTL):\n`key_limit_reached` (the organization's 10-key cap \u2014 prune keys in the\ndashboard), `database_name_taken` (the default database name is held by\na deleted database until GC cleanup \u2014 create a differently-named\ndatabase in the dashboard), `database_quota_exceeded` (the plan has no\nfree database slot \u2014 delete a database or upgrade, then poll again).\nThey are error-member values here, not problem+json ProblemCodes.\n",
|
|
2882
|
+
additionalProperties: false,
|
|
2883
|
+
required: [
|
|
2884
|
+
"error"
|
|
2885
|
+
],
|
|
2886
|
+
properties: {
|
|
2887
|
+
error: {
|
|
2888
|
+
type: "string",
|
|
2889
|
+
description: "An RFC 6749 \xA75.2 code, an RFC 8628 \xA73.5 code, or a documented SynapseTree extension (`key_limit_reached`, `database_name_taken`, `database_quota_exceeded`).",
|
|
2890
|
+
enum: [
|
|
2891
|
+
"invalid_request",
|
|
2892
|
+
"invalid_grant",
|
|
2893
|
+
"authorization_pending",
|
|
2894
|
+
"slow_down",
|
|
2895
|
+
"unsupported_grant_type",
|
|
2896
|
+
"server_error",
|
|
2897
|
+
"key_limit_reached",
|
|
2898
|
+
"database_name_taken",
|
|
2899
|
+
"database_quota_exceeded"
|
|
2900
|
+
]
|
|
2901
|
+
},
|
|
2902
|
+
error_description: {
|
|
2903
|
+
type: "string",
|
|
2904
|
+
description: "Human-readable detail (RFC 6749 \xA75.2)."
|
|
2905
|
+
},
|
|
2906
|
+
error_uri: {
|
|
2907
|
+
type: "string",
|
|
2908
|
+
format: "uri",
|
|
2909
|
+
description: "Optional RFC 6749 \xA75.2 pointer to the dashboard page that clears the wall."
|
|
2910
|
+
},
|
|
2911
|
+
interval: {
|
|
2912
|
+
type: "integer",
|
|
2913
|
+
minimum: 1,
|
|
2914
|
+
description: "Seconds to wait before polling again (RFC 8628 \xA73.5)."
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
},
|
|
2918
|
+
OkfType: {
|
|
2919
|
+
description: "Ontology node type. Open: each namespace's manifest defines its own types and `emergent`\nmode adds more; facts imported from OKF bundles keep their original type string. The\nlisted values are the schema-software-org types.\n",
|
|
2920
|
+
anyOf: [
|
|
2921
|
+
{
|
|
2922
|
+
type: "string",
|
|
2923
|
+
enum: [
|
|
2924
|
+
"person",
|
|
2925
|
+
"organization",
|
|
2926
|
+
"place",
|
|
2927
|
+
"event",
|
|
2928
|
+
"project",
|
|
2929
|
+
"action",
|
|
2930
|
+
"creativework",
|
|
2931
|
+
"review",
|
|
2932
|
+
"product",
|
|
2933
|
+
"software_application",
|
|
2934
|
+
"service",
|
|
2935
|
+
"role",
|
|
2936
|
+
"design_spec",
|
|
2937
|
+
"handoff",
|
|
2938
|
+
"procedure",
|
|
2939
|
+
"session_recap",
|
|
2940
|
+
"reference_doc"
|
|
2941
|
+
]
|
|
2942
|
+
},
|
|
2943
|
+
{
|
|
2944
|
+
type: "string",
|
|
2945
|
+
minLength: 1,
|
|
2946
|
+
maxLength: 128
|
|
2947
|
+
}
|
|
2948
|
+
]
|
|
2949
|
+
},
|
|
2950
|
+
OnDuplicateHash: {
|
|
2951
|
+
type: "string",
|
|
2952
|
+
description: "When another sourceRef already holds this content: `skip` (write nothing), `ingest` anyway, or `error` (409 source_hash_conflict).",
|
|
2953
|
+
enum: [
|
|
2954
|
+
"skip",
|
|
2955
|
+
"ingest",
|
|
2956
|
+
"error"
|
|
2957
|
+
],
|
|
2958
|
+
default: "skip"
|
|
2959
|
+
},
|
|
2960
|
+
PlanFingerprint: {
|
|
2961
|
+
type: "string",
|
|
2962
|
+
pattern: "^sha256:[0-9a-f]{64}$",
|
|
2963
|
+
examples: [
|
|
2964
|
+
"sha256:4e6a8c0b2d4f6a8c0e2b4d6f8a0c2e4b6d8f0a2c4e6b8d0f2a4c6e8b0d2f4a6c"
|
|
2965
|
+
]
|
|
2966
|
+
},
|
|
2967
|
+
PollGrant: {
|
|
2968
|
+
type: "object",
|
|
2969
|
+
description: "Where and how to poll for the minted key.",
|
|
2970
|
+
additionalProperties: false,
|
|
2971
|
+
required: [
|
|
2972
|
+
"token_endpoint",
|
|
2973
|
+
"grant",
|
|
2974
|
+
"interval"
|
|
2975
|
+
],
|
|
2976
|
+
properties: {
|
|
2977
|
+
token_endpoint: {
|
|
2978
|
+
type: "string",
|
|
2979
|
+
format: "uri",
|
|
2980
|
+
description: "The api.-host token endpoint."
|
|
2981
|
+
},
|
|
2982
|
+
grant: {
|
|
2983
|
+
type: "string",
|
|
2984
|
+
const: "urn:synapsetree:claim",
|
|
2985
|
+
description: "The claim-grant type to send as `grant_type`."
|
|
2986
|
+
},
|
|
2987
|
+
interval: {
|
|
2988
|
+
type: "integer",
|
|
2989
|
+
minimum: 1,
|
|
2990
|
+
description: "Seconds to wait between polls of `token_endpoint` (ruled\n2026-11-01). Modeled on the RFC 8628 \xA73.2 `interval`, but nested in\n`poll` rather than at the top level. An `authorization_pending` or\n`slow_down` answer carries an `interval` too (`slow_down` a larger\none), which replaces this one from then on.\n"
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
},
|
|
2994
|
+
Problem: {
|
|
2995
|
+
type: "object",
|
|
2996
|
+
description: "RFC 7807 problem details.",
|
|
2997
|
+
additionalProperties: false,
|
|
2998
|
+
required: [
|
|
2999
|
+
"type",
|
|
3000
|
+
"title",
|
|
3001
|
+
"status",
|
|
3002
|
+
"code",
|
|
3003
|
+
"detail",
|
|
3004
|
+
"requestId",
|
|
3005
|
+
"retryable"
|
|
3006
|
+
],
|
|
3007
|
+
properties: {
|
|
3008
|
+
type: {
|
|
3009
|
+
type: "string",
|
|
3010
|
+
format: "uri",
|
|
3011
|
+
description: "`urn:synapsetree:problem:<code>`.",
|
|
3012
|
+
pattern: "^urn:synapsetree:problem:[a-z_]+$"
|
|
3013
|
+
},
|
|
3014
|
+
title: {
|
|
3015
|
+
type: "string",
|
|
3016
|
+
minLength: 1
|
|
3017
|
+
},
|
|
3018
|
+
status: {
|
|
3019
|
+
type: "integer",
|
|
3020
|
+
minimum: 400,
|
|
3021
|
+
maximum: 599
|
|
3022
|
+
},
|
|
3023
|
+
code: {
|
|
3024
|
+
$ref: "#/components/schemas/ProblemCode"
|
|
3025
|
+
},
|
|
3026
|
+
detail: {
|
|
3027
|
+
type: "string"
|
|
3028
|
+
},
|
|
3029
|
+
requestId: {
|
|
3030
|
+
type: "string",
|
|
3031
|
+
pattern: "^req_[A-Za-z0-9]{8,64}$"
|
|
3032
|
+
},
|
|
3033
|
+
retryable: {
|
|
3034
|
+
type: "boolean"
|
|
3035
|
+
},
|
|
3036
|
+
retryAfterSeconds: {
|
|
3037
|
+
type: "integer",
|
|
3038
|
+
minimum: 0
|
|
3039
|
+
},
|
|
3040
|
+
errors: {
|
|
3041
|
+
type: "array",
|
|
3042
|
+
description: "Validation failures (`invalid_request`).",
|
|
3043
|
+
items: {
|
|
3044
|
+
type: "object",
|
|
3045
|
+
additionalProperties: false,
|
|
3046
|
+
required: [
|
|
3047
|
+
"path",
|
|
3048
|
+
"message"
|
|
3049
|
+
],
|
|
3050
|
+
properties: {
|
|
3051
|
+
path: {
|
|
3052
|
+
type: "string",
|
|
3053
|
+
description: "JSON Pointer into the request."
|
|
3054
|
+
},
|
|
3055
|
+
message: {
|
|
3056
|
+
type: "string"
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
},
|
|
3061
|
+
parseFailures: {
|
|
3062
|
+
type: "array",
|
|
3063
|
+
description: "Per-chunk failures (`ingest_failed`).",
|
|
3064
|
+
items: {
|
|
3065
|
+
$ref: "#/components/schemas/ChunkFailure"
|
|
3066
|
+
}
|
|
3067
|
+
},
|
|
3068
|
+
duplicateOf: {
|
|
3069
|
+
description: "The sourceRef already holding this content (`source_hash_conflict`).",
|
|
3070
|
+
$ref: "#/components/schemas/SourceRef"
|
|
3071
|
+
},
|
|
3072
|
+
kind: {
|
|
3073
|
+
type: "string",
|
|
3074
|
+
enum: [
|
|
3075
|
+
"node",
|
|
3076
|
+
"edge"
|
|
3077
|
+
],
|
|
3078
|
+
description: "What violated the ontology (`ontology_violation`)."
|
|
3079
|
+
},
|
|
3080
|
+
ontologyType: {
|
|
3081
|
+
type: "string",
|
|
3082
|
+
description: "The out-of-manifest type (`ontology_violation`)."
|
|
3083
|
+
},
|
|
3084
|
+
reason: {
|
|
3085
|
+
type: "string",
|
|
3086
|
+
description: "Machine-readable sub-reason, e.g. `immutable_target` for `invalid_state`."
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
},
|
|
3090
|
+
ProblemCode: {
|
|
3091
|
+
description: "Stable machine-readable error code. Open: new codes may be added in minor versions, so\nclients must treat an unlisted code as a generic error of its HTTP status. The listed\nvalues are the codes this version defines.\n",
|
|
3092
|
+
anyOf: [
|
|
3093
|
+
{
|
|
3094
|
+
type: "string",
|
|
3095
|
+
enum: [
|
|
3096
|
+
"invalid_request",
|
|
3097
|
+
"insufficient_scope",
|
|
3098
|
+
"subscription_inactive",
|
|
3099
|
+
"quota_exceeded",
|
|
3100
|
+
"not_found",
|
|
3101
|
+
"namespace_exists",
|
|
3102
|
+
"conflict",
|
|
3103
|
+
"invalid_state",
|
|
3104
|
+
"source_hash_conflict",
|
|
3105
|
+
"node_id_unavailable",
|
|
3106
|
+
"namespace_busy",
|
|
3107
|
+
"idempotency_in_progress",
|
|
3108
|
+
"extraction_plan_stale",
|
|
3109
|
+
"inference_not_configured",
|
|
3110
|
+
"inference_config_invalid",
|
|
3111
|
+
"payload_too_large",
|
|
3112
|
+
"idempotency_key_reused",
|
|
3113
|
+
"ontology_violation",
|
|
3114
|
+
"ingest_failed",
|
|
3115
|
+
"embedding_dimension_mismatch",
|
|
3116
|
+
"embedding_model_mismatch",
|
|
3117
|
+
"rate_limited",
|
|
3118
|
+
"internal",
|
|
3119
|
+
"not_implemented",
|
|
3120
|
+
"unavailable",
|
|
3121
|
+
"upstream_inference_unavailable",
|
|
3122
|
+
"fenced",
|
|
3123
|
+
"unauthorized"
|
|
3124
|
+
]
|
|
3125
|
+
},
|
|
3126
|
+
{
|
|
3127
|
+
type: "string",
|
|
3128
|
+
pattern: "^[a-z_]+$",
|
|
3129
|
+
maxLength: 64
|
|
3130
|
+
}
|
|
3131
|
+
]
|
|
3132
|
+
},
|
|
3133
|
+
QueryDiagnostics: {
|
|
3134
|
+
type: "object",
|
|
3135
|
+
description: "Named BYOK diagnostics for a query response. A typed map: keys are diagnostic\nnames, values are scalars; unknown names are legal and clients must ignore them.\nReported reasons include `keyword_only: true` (the organization has no embeddings\nregistration) and `embed_unavailable: <reason>` (key or provider fault, or the tier\ncap exhausted). While a maintenance run holds the namespace, vector search is\npaused and reads answer keyword-only; the run itself is surfaced through\n`currentRunId` and `currentRunState` on the pending-maintenance object. All of\nthese are normal keyword-only degradation, not errors.\n",
|
|
3136
|
+
additionalProperties: {
|
|
3137
|
+
description: "A named diagnostic flag, count or label.",
|
|
3138
|
+
anyOf: [
|
|
3139
|
+
{
|
|
3140
|
+
type: "string"
|
|
3141
|
+
},
|
|
3142
|
+
{
|
|
3143
|
+
type: "number"
|
|
3144
|
+
},
|
|
3145
|
+
{
|
|
3146
|
+
type: "boolean"
|
|
3147
|
+
},
|
|
3148
|
+
{
|
|
3149
|
+
type: "null"
|
|
3150
|
+
}
|
|
3151
|
+
]
|
|
3152
|
+
},
|
|
3153
|
+
examples: [
|
|
3154
|
+
{
|
|
3155
|
+
keyword_only: true
|
|
3156
|
+
}
|
|
3157
|
+
]
|
|
3158
|
+
},
|
|
3159
|
+
QueryRequest: {
|
|
3160
|
+
type: "object",
|
|
3161
|
+
additionalProperties: false,
|
|
3162
|
+
required: [
|
|
3163
|
+
"namespaces",
|
|
3164
|
+
"query"
|
|
3165
|
+
],
|
|
3166
|
+
properties: {
|
|
3167
|
+
namespaces: {
|
|
3168
|
+
type: "array",
|
|
3169
|
+
minItems: 1,
|
|
3170
|
+
maxItems: 20,
|
|
3171
|
+
uniqueItems: true,
|
|
3172
|
+
items: {
|
|
3173
|
+
$ref: "#/components/schemas/Namespace"
|
|
3174
|
+
}
|
|
3175
|
+
},
|
|
3176
|
+
query: {
|
|
3177
|
+
type: "string",
|
|
3178
|
+
maxLength: 4096,
|
|
3179
|
+
description: "Search text. Empty returns the most recent facts."
|
|
3180
|
+
},
|
|
3181
|
+
queryEmbedding: {
|
|
3182
|
+
$ref: "#/components/schemas/Embedding"
|
|
3183
|
+
},
|
|
3184
|
+
limit: {
|
|
3185
|
+
type: "integer",
|
|
3186
|
+
minimum: 1,
|
|
3187
|
+
maximum: 100,
|
|
3188
|
+
default: 10
|
|
3189
|
+
},
|
|
3190
|
+
hybridWeight: {
|
|
3191
|
+
type: "number",
|
|
3192
|
+
minimum: 0,
|
|
3193
|
+
maximum: 1,
|
|
3194
|
+
description: "0 = keyword only, 1 = semantic only. Omit for the default semantic ranking."
|
|
3195
|
+
},
|
|
3196
|
+
excludeDrafts: {
|
|
3197
|
+
type: "boolean",
|
|
3198
|
+
default: false
|
|
3199
|
+
},
|
|
3200
|
+
asOf: {
|
|
3201
|
+
description: "Return facts that were true at this instant, using current knowledge.",
|
|
3202
|
+
$ref: "#/components/schemas/Timestamp"
|
|
3203
|
+
},
|
|
3204
|
+
weights: {
|
|
3205
|
+
type: "object",
|
|
3206
|
+
description: "Per-namespace score multipliers (default 1; 0 skips the namespace).",
|
|
3207
|
+
propertyNames: {
|
|
3208
|
+
$ref: "#/components/schemas/Namespace"
|
|
3209
|
+
},
|
|
3210
|
+
additionalProperties: {
|
|
3211
|
+
type: "number",
|
|
3212
|
+
minimum: 0
|
|
3213
|
+
}
|
|
3214
|
+
},
|
|
3215
|
+
floors: {
|
|
3216
|
+
type: "object",
|
|
3217
|
+
description: "Minimum results reserved per namespace before the global `limit` cut.",
|
|
3218
|
+
propertyNames: {
|
|
3219
|
+
$ref: "#/components/schemas/Namespace"
|
|
3220
|
+
},
|
|
3221
|
+
additionalProperties: {
|
|
3222
|
+
type: "integer",
|
|
3223
|
+
minimum: 0,
|
|
3224
|
+
maximum: 100
|
|
3225
|
+
}
|
|
3226
|
+
},
|
|
3227
|
+
tokenBudget: {
|
|
3228
|
+
type: "integer",
|
|
3229
|
+
minimum: 1,
|
|
3230
|
+
maximum: 2e5,
|
|
3231
|
+
description: "Pack facts into this many estimated tokens.",
|
|
3232
|
+
"x-synapsetree-engine": "read({ tokenBudget }) (core-llm-wiki 7.8.0 phase D)"
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
},
|
|
3236
|
+
QueryResponse: {
|
|
3237
|
+
type: "object",
|
|
3238
|
+
additionalProperties: false,
|
|
3239
|
+
required: [
|
|
3240
|
+
"facts",
|
|
3241
|
+
"scores",
|
|
3242
|
+
"tasks",
|
|
3243
|
+
"events"
|
|
3244
|
+
],
|
|
3245
|
+
properties: {
|
|
3246
|
+
facts: {
|
|
3247
|
+
type: "array",
|
|
3248
|
+
items: {
|
|
3249
|
+
$ref: "#/components/schemas/Fact"
|
|
3250
|
+
}
|
|
3251
|
+
},
|
|
3252
|
+
scores: {
|
|
3253
|
+
type: "object",
|
|
3254
|
+
description: "Score per returned fact id (empty for recency reads).",
|
|
3255
|
+
additionalProperties: {
|
|
3256
|
+
type: "number"
|
|
3257
|
+
}
|
|
3258
|
+
},
|
|
3259
|
+
tasks: {
|
|
3260
|
+
type: "array",
|
|
3261
|
+
items: {
|
|
3262
|
+
$ref: "#/components/schemas/Task"
|
|
3263
|
+
}
|
|
3264
|
+
},
|
|
3265
|
+
events: {
|
|
3266
|
+
type: "array",
|
|
3267
|
+
items: {
|
|
3268
|
+
$ref: "#/components/schemas/Event"
|
|
3269
|
+
}
|
|
3270
|
+
},
|
|
3271
|
+
diagnostics: {
|
|
3272
|
+
description: "Additive BYOK diagnostics; present only when there is something to report\n(e.g. the searched namespaces serve keyword-only facts because the org has\nno embeddings registration).\n",
|
|
3273
|
+
$ref: "#/components/schemas/QueryDiagnostics"
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
},
|
|
3277
|
+
RememberRequest: {
|
|
3278
|
+
type: "object",
|
|
3279
|
+
additionalProperties: false,
|
|
3280
|
+
required: [
|
|
3281
|
+
"namespace",
|
|
3282
|
+
"title",
|
|
3283
|
+
"body"
|
|
3284
|
+
],
|
|
3285
|
+
properties: {
|
|
3286
|
+
namespace: {
|
|
3287
|
+
$ref: "#/components/schemas/Namespace"
|
|
3288
|
+
},
|
|
3289
|
+
title: {
|
|
3290
|
+
type: "string",
|
|
3291
|
+
minLength: 1,
|
|
3292
|
+
maxLength: 1e3
|
|
3293
|
+
},
|
|
3294
|
+
body: {
|
|
3295
|
+
type: "string",
|
|
3296
|
+
minLength: 1,
|
|
3297
|
+
maxLength: 1e5
|
|
3298
|
+
},
|
|
3299
|
+
tags: {
|
|
3300
|
+
type: "array",
|
|
3301
|
+
maxItems: 100,
|
|
3302
|
+
items: {
|
|
3303
|
+
type: "string",
|
|
3304
|
+
minLength: 1,
|
|
3305
|
+
maxLength: 100
|
|
3306
|
+
}
|
|
3307
|
+
},
|
|
3308
|
+
confidence: {
|
|
3309
|
+
$ref: "#/components/schemas/Confidence"
|
|
3310
|
+
},
|
|
3311
|
+
sourceType: {
|
|
3312
|
+
type: "string",
|
|
3313
|
+
enum: [
|
|
3314
|
+
"user_stated",
|
|
3315
|
+
"user_confirmed"
|
|
3316
|
+
],
|
|
3317
|
+
default: "user_stated"
|
|
3318
|
+
},
|
|
3319
|
+
okfType: {
|
|
3320
|
+
$ref: "#/components/schemas/OkfType"
|
|
3321
|
+
},
|
|
3322
|
+
validFrom: {
|
|
3323
|
+
$ref: "#/components/schemas/Timestamp"
|
|
3324
|
+
},
|
|
3325
|
+
embedding: {
|
|
3326
|
+
$ref: "#/components/schemas/Embedding"
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
},
|
|
3330
|
+
RevokeRequest: {
|
|
3331
|
+
type: "object",
|
|
3332
|
+
description: "Form-urlencoded revocation body (RFC 7009 \xA72.1).",
|
|
3333
|
+
additionalProperties: false,
|
|
3334
|
+
required: [
|
|
3335
|
+
"token"
|
|
3336
|
+
],
|
|
3337
|
+
properties: {
|
|
3338
|
+
token: {
|
|
3339
|
+
type: "string",
|
|
3340
|
+
minLength: 1,
|
|
3341
|
+
description: "The API key to revoke (revocation is defined for keys only)."
|
|
3342
|
+
},
|
|
3343
|
+
token_type_hint: {
|
|
3344
|
+
type: "string",
|
|
3345
|
+
enum: [
|
|
3346
|
+
"access_token"
|
|
3347
|
+
],
|
|
3348
|
+
description: "Optional RFC 7009 \xA72.1 hint."
|
|
3349
|
+
}
|
|
3350
|
+
}
|
|
3351
|
+
},
|
|
3352
|
+
ServerExtractionIngest: {
|
|
3353
|
+
type: "object",
|
|
3354
|
+
additionalProperties: false,
|
|
3355
|
+
required: [
|
|
3356
|
+
"mode",
|
|
3357
|
+
"namespace",
|
|
3358
|
+
"sourceRef",
|
|
3359
|
+
"sourceHash",
|
|
3360
|
+
"content"
|
|
3361
|
+
],
|
|
3362
|
+
properties: {
|
|
3363
|
+
mode: {
|
|
3364
|
+
type: "string",
|
|
3365
|
+
const: "server_extraction"
|
|
3366
|
+
},
|
|
3367
|
+
namespace: {
|
|
3368
|
+
$ref: "#/components/schemas/Namespace"
|
|
3369
|
+
},
|
|
3370
|
+
sourceRef: {
|
|
3371
|
+
$ref: "#/components/schemas/SourceRef"
|
|
3372
|
+
},
|
|
3373
|
+
sourceHash: {
|
|
3374
|
+
$ref: "#/components/schemas/SourceHash"
|
|
3375
|
+
},
|
|
3376
|
+
content: {
|
|
3377
|
+
type: "string",
|
|
3378
|
+
minLength: 1,
|
|
3379
|
+
maxLength: 524288
|
|
3380
|
+
},
|
|
3381
|
+
onDuplicateHash: {
|
|
3382
|
+
$ref: "#/components/schemas/OnDuplicateHash"
|
|
3383
|
+
},
|
|
3384
|
+
chunking: {
|
|
3385
|
+
$ref: "#/components/schemas/Chunking"
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
},
|
|
3389
|
+
SourceHash: {
|
|
3390
|
+
type: "string",
|
|
3391
|
+
description: "Lowercase hex SHA-256 of the source's bytes.",
|
|
3392
|
+
pattern: "^[0-9a-f]{64}$",
|
|
3393
|
+
examples: [
|
|
3394
|
+
"9f2c4b8e1a7d3f6c5b0e2d4a8c1f3e5b7d9a0c2e4f6b8d0a1c3e5f7b9d1a3c5e"
|
|
3395
|
+
]
|
|
3396
|
+
},
|
|
3397
|
+
SourceRef: {
|
|
3398
|
+
type: "string",
|
|
3399
|
+
description: "Identifies one source document within a namespace. Restricted to characters the engine\nstores unchanged; the SDK's `toSourceRef(path)` encodes `/` as `__`.\n",
|
|
3400
|
+
pattern: "^[A-Za-z0-9._\\- ]{1,255}$",
|
|
3401
|
+
examples: [
|
|
3402
|
+
"infra__stack.ts"
|
|
3403
|
+
]
|
|
3404
|
+
},
|
|
3405
|
+
SourceType: {
|
|
3406
|
+
type: "string",
|
|
3407
|
+
description: "How a fact was produced. `immutable_document` facts change only by re-ingesting their source.",
|
|
3408
|
+
enum: [
|
|
3409
|
+
"immutable_document",
|
|
3410
|
+
"librarian_inferred",
|
|
3411
|
+
"user_stated",
|
|
3412
|
+
"user_confirmed"
|
|
3413
|
+
]
|
|
3414
|
+
},
|
|
3415
|
+
SupersedeRequest: {
|
|
3416
|
+
type: "object",
|
|
3417
|
+
additionalProperties: false,
|
|
3418
|
+
required: [
|
|
3419
|
+
"namespace",
|
|
3420
|
+
"replacement"
|
|
3421
|
+
],
|
|
3422
|
+
properties: {
|
|
3423
|
+
namespace: {
|
|
3424
|
+
$ref: "#/components/schemas/Namespace"
|
|
3425
|
+
},
|
|
3426
|
+
validFrom: {
|
|
3427
|
+
description: "When the old fact stopped being true and the replacement became true. Defaults to now.",
|
|
3428
|
+
$ref: "#/components/schemas/Timestamp"
|
|
3429
|
+
},
|
|
3430
|
+
replacement: {
|
|
3431
|
+
oneOf: [
|
|
3432
|
+
{
|
|
3433
|
+
$ref: "#/components/schemas/NewFactReplacement"
|
|
3434
|
+
},
|
|
3435
|
+
{
|
|
3436
|
+
$ref: "#/components/schemas/ExistingFactReplacement"
|
|
3437
|
+
}
|
|
3438
|
+
],
|
|
3439
|
+
discriminator: {
|
|
3440
|
+
propertyName: "kind",
|
|
3441
|
+
mapping: {
|
|
3442
|
+
new: "#/components/schemas/NewFactReplacement",
|
|
3443
|
+
existing: "#/components/schemas/ExistingFactReplacement"
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
},
|
|
3449
|
+
SupersedeResponse: {
|
|
3450
|
+
type: "object",
|
|
3451
|
+
additionalProperties: false,
|
|
3452
|
+
required: [
|
|
3453
|
+
"superseded",
|
|
3454
|
+
"replacement"
|
|
3455
|
+
],
|
|
3456
|
+
properties: {
|
|
3457
|
+
superseded: {
|
|
3458
|
+
$ref: "#/components/schemas/Fact"
|
|
3459
|
+
},
|
|
3460
|
+
replacement: {
|
|
3461
|
+
$ref: "#/components/schemas/Fact"
|
|
3462
|
+
}
|
|
3463
|
+
}
|
|
3464
|
+
},
|
|
3465
|
+
Task: {
|
|
3466
|
+
type: "object",
|
|
3467
|
+
additionalProperties: false,
|
|
3468
|
+
required: [
|
|
3469
|
+
"id",
|
|
3470
|
+
"namespace",
|
|
3471
|
+
"description",
|
|
3472
|
+
"status",
|
|
3473
|
+
"priority",
|
|
3474
|
+
"okfType",
|
|
3475
|
+
"createdAt",
|
|
3476
|
+
"updatedAt",
|
|
3477
|
+
"resolvedAt"
|
|
3478
|
+
],
|
|
3479
|
+
properties: {
|
|
3480
|
+
id: {
|
|
3481
|
+
type: "string",
|
|
3482
|
+
minLength: 1,
|
|
3483
|
+
maxLength: 255
|
|
3484
|
+
},
|
|
3485
|
+
namespace: {
|
|
3486
|
+
$ref: "#/components/schemas/Namespace"
|
|
3487
|
+
},
|
|
3488
|
+
description: {
|
|
3489
|
+
type: "string",
|
|
3490
|
+
minLength: 1,
|
|
3491
|
+
maxLength: 4e3
|
|
3492
|
+
},
|
|
3493
|
+
status: {
|
|
3494
|
+
type: "string",
|
|
3495
|
+
enum: [
|
|
3496
|
+
"pending",
|
|
3497
|
+
"in_progress",
|
|
3498
|
+
"done",
|
|
3499
|
+
"abandoned"
|
|
3500
|
+
]
|
|
3501
|
+
},
|
|
3502
|
+
priority: {
|
|
3503
|
+
type: "integer",
|
|
3504
|
+
minimum: 0,
|
|
3505
|
+
maximum: 10
|
|
3506
|
+
},
|
|
3507
|
+
okfType: {
|
|
3508
|
+
anyOf: [
|
|
3509
|
+
{
|
|
3510
|
+
$ref: "#/components/schemas/OkfType"
|
|
3511
|
+
},
|
|
3512
|
+
{
|
|
3513
|
+
type: "null"
|
|
3514
|
+
}
|
|
3515
|
+
]
|
|
3516
|
+
},
|
|
3517
|
+
createdAt: {
|
|
3518
|
+
$ref: "#/components/schemas/Timestamp"
|
|
3519
|
+
},
|
|
3520
|
+
updatedAt: {
|
|
3521
|
+
$ref: "#/components/schemas/Timestamp"
|
|
3522
|
+
},
|
|
3523
|
+
resolvedAt: {
|
|
3524
|
+
anyOf: [
|
|
3525
|
+
{
|
|
3526
|
+
$ref: "#/components/schemas/Timestamp"
|
|
3527
|
+
},
|
|
3528
|
+
{
|
|
3529
|
+
type: "null"
|
|
3530
|
+
}
|
|
3531
|
+
]
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
},
|
|
3535
|
+
Timestamp: {
|
|
3536
|
+
type: "string",
|
|
3537
|
+
format: "date-time",
|
|
3538
|
+
description: "RFC 3339 timestamp, UTC.",
|
|
3539
|
+
examples: [
|
|
3540
|
+
"2026-09-29T10:00:00Z"
|
|
3541
|
+
]
|
|
3542
|
+
},
|
|
3543
|
+
TokenResponse: {
|
|
3544
|
+
type: "object",
|
|
3545
|
+
description: "RFC 6749 \xA75.1 success response \u2014 exactly one freshly minted API key.",
|
|
3546
|
+
additionalProperties: false,
|
|
3547
|
+
required: [
|
|
3548
|
+
"access_token",
|
|
3549
|
+
"token_type",
|
|
3550
|
+
"account_id",
|
|
3551
|
+
"scope"
|
|
3552
|
+
],
|
|
3553
|
+
properties: {
|
|
3554
|
+
access_token: {
|
|
3555
|
+
type: "string",
|
|
3556
|
+
pattern: "^stree_[A-Za-z0-9_-]{43}$",
|
|
3557
|
+
description: "The minted API key. The only time it is ever shown."
|
|
3558
|
+
},
|
|
3559
|
+
token_type: {
|
|
3560
|
+
type: "string",
|
|
3561
|
+
enum: [
|
|
3562
|
+
"Bearer"
|
|
3563
|
+
],
|
|
3564
|
+
description: "RFC 6749 \xA75.1 \u2014 keys authenticate as bearer tokens."
|
|
3565
|
+
},
|
|
3566
|
+
account_id: {
|
|
3567
|
+
type: "string",
|
|
3568
|
+
description: "The organization the key belongs to (its `account_id` context)."
|
|
3569
|
+
},
|
|
3570
|
+
scope: {
|
|
3571
|
+
type: "string",
|
|
3572
|
+
const: "memory:full",
|
|
3573
|
+
description: "Agent keys always carry the full memory scope."
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
},
|
|
3577
|
+
TraverseRequest: {
|
|
3578
|
+
type: "object",
|
|
3579
|
+
additionalProperties: false,
|
|
3580
|
+
required: [
|
|
3581
|
+
"namespace",
|
|
3582
|
+
"sourceId"
|
|
3583
|
+
],
|
|
3584
|
+
properties: {
|
|
3585
|
+
namespace: {
|
|
3586
|
+
$ref: "#/components/schemas/Namespace"
|
|
3587
|
+
},
|
|
3588
|
+
sourceId: {
|
|
3589
|
+
$ref: "#/components/schemas/FactId"
|
|
3590
|
+
},
|
|
3591
|
+
maxDepth: {
|
|
3592
|
+
type: "integer",
|
|
3593
|
+
minimum: 1,
|
|
3594
|
+
maximum: 3,
|
|
3595
|
+
default: 1
|
|
3596
|
+
},
|
|
3597
|
+
direction: {
|
|
3598
|
+
$ref: "#/components/schemas/Direction"
|
|
3599
|
+
},
|
|
3600
|
+
edgeTypes: {
|
|
3601
|
+
type: "array",
|
|
3602
|
+
description: "Allowed edge types. Omit for all; an empty array matches none.",
|
|
3603
|
+
maxItems: 100,
|
|
3604
|
+
items: {
|
|
3605
|
+
$ref: "#/components/schemas/EdgeType"
|
|
3606
|
+
}
|
|
3607
|
+
},
|
|
3608
|
+
maxNodes: {
|
|
3609
|
+
type: "integer",
|
|
3610
|
+
minimum: 1,
|
|
3611
|
+
maximum: 200,
|
|
3612
|
+
default: 20
|
|
3613
|
+
},
|
|
3614
|
+
minConfidence: {
|
|
3615
|
+
$ref: "#/components/schemas/Confidence"
|
|
3616
|
+
},
|
|
3617
|
+
excludeSourceTypes: {
|
|
3618
|
+
type: "array",
|
|
3619
|
+
maxItems: 4,
|
|
3620
|
+
uniqueItems: true,
|
|
3621
|
+
items: {
|
|
3622
|
+
$ref: "#/components/schemas/SourceType"
|
|
3623
|
+
}
|
|
3624
|
+
},
|
|
3625
|
+
excludeDrafts: {
|
|
3626
|
+
type: "boolean",
|
|
3627
|
+
default: false
|
|
3628
|
+
},
|
|
3629
|
+
asOf: {
|
|
3630
|
+
$ref: "#/components/schemas/Timestamp"
|
|
3631
|
+
},
|
|
3632
|
+
tokenBudget: {
|
|
3633
|
+
type: "integer",
|
|
3634
|
+
minimum: 1,
|
|
3635
|
+
maximum: 2e5,
|
|
3636
|
+
"x-synapsetree-engine": "traverseGraph({ tokenBudget }) (core-llm-wiki 7.8.0 phase D)"
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
},
|
|
3640
|
+
TraverseResponse: {
|
|
3641
|
+
type: "object",
|
|
3642
|
+
additionalProperties: false,
|
|
3643
|
+
required: [
|
|
3644
|
+
"nodes",
|
|
3645
|
+
"edges"
|
|
3646
|
+
],
|
|
3647
|
+
properties: {
|
|
3648
|
+
nodes: {
|
|
3649
|
+
type: "array",
|
|
3650
|
+
description: "Anchor first, then neighbours by depth.",
|
|
3651
|
+
items: {
|
|
3652
|
+
$ref: "#/components/schemas/Fact"
|
|
3653
|
+
}
|
|
3654
|
+
},
|
|
3655
|
+
edges: {
|
|
3656
|
+
type: "array",
|
|
3657
|
+
items: {
|
|
3658
|
+
$ref: "#/components/schemas/Edge"
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
},
|
|
3663
|
+
TrustTier: {
|
|
3664
|
+
type: "string",
|
|
3665
|
+
enum: [
|
|
3666
|
+
"unverified",
|
|
3667
|
+
"machine-confirmed",
|
|
3668
|
+
"human-reviewed"
|
|
3669
|
+
]
|
|
3670
|
+
},
|
|
3671
|
+
UserConfirmedFact: {
|
|
3672
|
+
type: "object",
|
|
3673
|
+
description: "A fact a user has confirmed.",
|
|
3674
|
+
allOf: [
|
|
3675
|
+
{
|
|
3676
|
+
$ref: "#/components/schemas/FactBase"
|
|
3677
|
+
},
|
|
3678
|
+
{
|
|
3679
|
+
$ref: "#/components/schemas/MutableFactFields"
|
|
3680
|
+
},
|
|
3681
|
+
{
|
|
3682
|
+
type: "object",
|
|
3683
|
+
required: [
|
|
3684
|
+
"sourceType"
|
|
3685
|
+
],
|
|
3686
|
+
properties: {
|
|
3687
|
+
sourceType: {
|
|
3688
|
+
type: "string",
|
|
3689
|
+
const: "user_confirmed"
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
],
|
|
3694
|
+
unevaluatedProperties: false
|
|
3695
|
+
},
|
|
3696
|
+
UserStatedFact: {
|
|
3697
|
+
type: "object",
|
|
3698
|
+
description: "A fact stated directly by a user or agent.",
|
|
3699
|
+
allOf: [
|
|
3700
|
+
{
|
|
3701
|
+
$ref: "#/components/schemas/FactBase"
|
|
3702
|
+
},
|
|
3703
|
+
{
|
|
3704
|
+
$ref: "#/components/schemas/MutableFactFields"
|
|
3705
|
+
},
|
|
3706
|
+
{
|
|
3707
|
+
type: "object",
|
|
3708
|
+
required: [
|
|
3709
|
+
"sourceType"
|
|
3710
|
+
],
|
|
3711
|
+
properties: {
|
|
3712
|
+
sourceType: {
|
|
3713
|
+
type: "string",
|
|
3714
|
+
const: "user_stated"
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
],
|
|
3719
|
+
unevaluatedProperties: false
|
|
3720
|
+
},
|
|
3721
|
+
Whoami: {
|
|
3722
|
+
type: "object",
|
|
3723
|
+
additionalProperties: false,
|
|
3724
|
+
required: [
|
|
3725
|
+
"apiKeyId",
|
|
3726
|
+
"organizationId",
|
|
3727
|
+
"tenantDatabaseId",
|
|
3728
|
+
"scope",
|
|
3729
|
+
"planCode",
|
|
3730
|
+
"subscriptionStatus"
|
|
3731
|
+
],
|
|
3732
|
+
properties: {
|
|
3733
|
+
apiKeyId: {
|
|
3734
|
+
type: "string",
|
|
3735
|
+
minLength: 1
|
|
3736
|
+
},
|
|
3737
|
+
organizationId: {
|
|
3738
|
+
type: "string",
|
|
3739
|
+
minLength: 1
|
|
3740
|
+
},
|
|
3741
|
+
tenantDatabaseId: {
|
|
3742
|
+
type: "string",
|
|
3743
|
+
minLength: 1
|
|
3744
|
+
},
|
|
3745
|
+
scope: {
|
|
3746
|
+
type: "string",
|
|
3747
|
+
enum: [
|
|
3748
|
+
"read",
|
|
3749
|
+
"read_write",
|
|
3750
|
+
"memory:full",
|
|
3751
|
+
"memory:admin"
|
|
3752
|
+
],
|
|
3753
|
+
description: "The key's scope. `read` and `read_write` are dashboard-issued keys; `memory:full`\nis the agent key issued through auth.md; `memory:admin` is accepted but not issued\nin v1. A `memory:full` key is refused the export and destructive operations;\n`memory:admin` passes them.\n"
|
|
3754
|
+
},
|
|
3755
|
+
planCode: {
|
|
3756
|
+
description: "Open; new plans may be added.",
|
|
3757
|
+
anyOf: [
|
|
3758
|
+
{
|
|
3759
|
+
type: "string",
|
|
3760
|
+
enum: [
|
|
3761
|
+
"hobby",
|
|
3762
|
+
"pro",
|
|
3763
|
+
"team"
|
|
3764
|
+
]
|
|
3765
|
+
},
|
|
3766
|
+
{
|
|
3767
|
+
type: "string",
|
|
3768
|
+
minLength: 1
|
|
3769
|
+
}
|
|
3770
|
+
]
|
|
3771
|
+
},
|
|
3772
|
+
subscriptionStatus: {
|
|
3773
|
+
type: "string",
|
|
3774
|
+
enum: [
|
|
3775
|
+
"inactive",
|
|
3776
|
+
"trialing",
|
|
3777
|
+
"active",
|
|
3778
|
+
"past_due",
|
|
3779
|
+
"canceled",
|
|
3780
|
+
"unpaid",
|
|
3781
|
+
"incomplete",
|
|
3782
|
+
"incomplete_expired",
|
|
3783
|
+
"paused"
|
|
3784
|
+
]
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
},
|
|
3789
|
+
securitySchemes: {
|
|
3790
|
+
bearerAuth: {
|
|
3791
|
+
type: "http",
|
|
3792
|
+
scheme: "bearer",
|
|
3793
|
+
bearerFormat: "stree_<43 base64url chars>",
|
|
3794
|
+
description: "A SynapseTree API key: `Authorization: Bearer stree_\u2026`."
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
}};
|
|
3798
|
+
|
|
3799
|
+
// src/contract.ts
|
|
3800
|
+
var OPERATION_IDS = [
|
|
3801
|
+
"queryMemory",
|
|
3802
|
+
"rememberFact",
|
|
3803
|
+
"supersedeFact",
|
|
3804
|
+
"ingestDocument",
|
|
3805
|
+
"createEvent",
|
|
3806
|
+
"traverseGraph",
|
|
3807
|
+
"listNamespaces",
|
|
3808
|
+
"whoami",
|
|
3809
|
+
"registerAgentIdentity",
|
|
3810
|
+
"oauthToken",
|
|
3811
|
+
"oauthRevoke"
|
|
3812
|
+
];
|
|
3813
|
+
var WITHHELD_OPERATION_IDS = [
|
|
3814
|
+
"exportMemory",
|
|
3815
|
+
"importMemory",
|
|
3816
|
+
"forgetFact",
|
|
3817
|
+
"forgetSource",
|
|
3818
|
+
"deleteNamespace",
|
|
3819
|
+
"createMaintenanceRun",
|
|
3820
|
+
"putOntology"
|
|
3821
|
+
];
|
|
3822
|
+
var doc = synapsetree_openapi_subset_default;
|
|
3823
|
+
function resolve(node) {
|
|
3824
|
+
if (!node || typeof node !== "object") return void 0;
|
|
3825
|
+
const ref = node.$ref;
|
|
3826
|
+
if (typeof ref === "string") {
|
|
3827
|
+
const [, , kind, name] = ref.split("/");
|
|
3828
|
+
return resolve(doc.components[kind]?.[name]);
|
|
3829
|
+
}
|
|
3830
|
+
return node;
|
|
3831
|
+
}
|
|
3832
|
+
function shape(schema) {
|
|
3833
|
+
const props = /* @__PURE__ */ new Set();
|
|
3834
|
+
const required = /* @__PURE__ */ new Set();
|
|
3835
|
+
const s = resolve(schema);
|
|
3836
|
+
if (!s) return { props, required };
|
|
3837
|
+
const branches = s.oneOf ?? s.anyOf;
|
|
3838
|
+
if (branches && branches.length > 0) {
|
|
3839
|
+
const shapes = branches.map(shape);
|
|
3840
|
+
for (const sh of shapes) for (const p of sh.props) props.add(p);
|
|
3841
|
+
for (const p of shapes[0].required) if (shapes.every((sh) => sh.required.has(p))) required.add(p);
|
|
3842
|
+
}
|
|
3843
|
+
for (const part of s.allOf ?? []) {
|
|
3844
|
+
const sh = shape(part);
|
|
3845
|
+
for (const p of sh.props) props.add(p);
|
|
3846
|
+
for (const p of sh.required) required.add(p);
|
|
3847
|
+
}
|
|
3848
|
+
for (const p of Object.keys(s.properties ?? {})) props.add(p);
|
|
3849
|
+
for (const p of s.required ?? []) required.add(p);
|
|
3850
|
+
return { props, required };
|
|
3851
|
+
}
|
|
3852
|
+
function parameters(pathItem, op) {
|
|
3853
|
+
const raw = [...pathItem.parameters ?? [], ...op.parameters ?? []];
|
|
3854
|
+
return raw.map((p) => resolve(p)).filter((p) => p !== void 0);
|
|
3855
|
+
}
|
|
3856
|
+
function build() {
|
|
3857
|
+
const table = {};
|
|
3858
|
+
for (const [path, pathItem] of Object.entries(doc.paths)) {
|
|
3859
|
+
for (const method of ["get", "post"]) {
|
|
3860
|
+
const op = pathItem[method];
|
|
3861
|
+
if (!op) continue;
|
|
3862
|
+
const id = op.operationId;
|
|
3863
|
+
if (!OPERATION_IDS.includes(id)) continue;
|
|
3864
|
+
const params = parameters(pathItem, op);
|
|
3865
|
+
const body = resolve(op.requestBody);
|
|
3866
|
+
const content = body?.content ?? {};
|
|
3867
|
+
const media = Object.values(content)[0];
|
|
3868
|
+
const { props, required } = shape(media?.schema);
|
|
3869
|
+
table[id] = {
|
|
3870
|
+
operationId: id,
|
|
3871
|
+
method: method.toUpperCase(),
|
|
3872
|
+
path,
|
|
3873
|
+
scope: op["x-synapsetree-scope"] ?? null,
|
|
3874
|
+
requestProperties: [...props],
|
|
3875
|
+
requiredProperties: [...required],
|
|
3876
|
+
queryParameters: params.filter((p) => p.in === "query").map((p) => String(p.name)),
|
|
3877
|
+
pathParameters: params.filter((p) => p.in === "path").map((p) => String(p.name)),
|
|
3878
|
+
acceptsIdempotencyKey: params.some((p) => p.in === "header" && p.name === "Idempotency-Key")
|
|
3879
|
+
};
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3882
|
+
const missing = OPERATION_IDS.filter((id) => !(id in table));
|
|
3883
|
+
if (missing.length > 0) throw new Error(`contract subset is missing operations: ${missing.join(", ")}`);
|
|
3884
|
+
return table;
|
|
3885
|
+
}
|
|
3886
|
+
var OPERATIONS = build();
|
|
3887
|
+
var CONTRACT_INFO = {
|
|
3888
|
+
version: String(doc.info.version),
|
|
3889
|
+
operations: [...doc.info["x-operations"] ?? []]
|
|
3890
|
+
};
|
|
3891
|
+
var SynapseTreeError = class extends Error {
|
|
3892
|
+
status;
|
|
3893
|
+
code;
|
|
3894
|
+
detail;
|
|
3895
|
+
requestId;
|
|
3896
|
+
retryAfterSeconds;
|
|
3897
|
+
constructor(init) {
|
|
3898
|
+
super(init.detail ? `${init.code}: ${init.detail}` : init.code);
|
|
3899
|
+
this.name = "SynapseTreeError";
|
|
3900
|
+
this.status = init.status;
|
|
3901
|
+
this.code = init.code;
|
|
3902
|
+
this.detail = init.detail;
|
|
3903
|
+
this.requestId = init.requestId;
|
|
3904
|
+
this.retryAfterSeconds = init.retryAfterSeconds;
|
|
3905
|
+
}
|
|
3906
|
+
};
|
|
3907
|
+
var UsageError = class extends Error {
|
|
3908
|
+
constructor(message) {
|
|
3909
|
+
super(message);
|
|
3910
|
+
this.name = "UsageError";
|
|
3911
|
+
}
|
|
3912
|
+
};
|
|
3913
|
+
var NO_NAMESPACE_MESSAGE = "No namespace configured. Run `synapsetree-mcp config set namespace repo:<name>`, or pass `namespace`.";
|
|
3914
|
+
var NO_KEY_MESSAGE = "No API key. Run `synapsetree-mcp auth --key stree_\u2026` or `synapsetree-mcp auth --email you@example.com`.";
|
|
3915
|
+
var INGEST_PROVIDER_MESSAGE = "Requires the account owner to have registered an extraction provider in the dashboard (bring-your-own-key). Otherwise the server answers `inference_not_configured`; tell the user to register a provider at https://synapsetree.dev/dashboard.";
|
|
3916
|
+
var DETAIL_CODES = /* @__PURE__ */ new Set([
|
|
3917
|
+
"quota_exceeded",
|
|
3918
|
+
"payload_too_large",
|
|
3919
|
+
"invalid_request",
|
|
3920
|
+
"not_found",
|
|
3921
|
+
"conflict",
|
|
3922
|
+
"invalid_state",
|
|
3923
|
+
"source_hash_conflict",
|
|
3924
|
+
"idempotency_key_reused",
|
|
3925
|
+
"ontology_violation"
|
|
3926
|
+
]);
|
|
3927
|
+
var TRANSIENT_CODES = /* @__PURE__ */ new Set(["namespace_busy", "fenced", "unavailable", "idempotency_in_progress"]);
|
|
3928
|
+
function describe(err) {
|
|
3929
|
+
switch (err.code) {
|
|
3930
|
+
case "unauthorized":
|
|
3931
|
+
return "SynapseTree rejected the stored API key (revoked, unknown, or its database is not reachable). Ask the user to run `synapsetree-mcp auth`.";
|
|
3932
|
+
case "insufficient_scope":
|
|
3933
|
+
return "This key cannot do that. The account owner does it in the dashboard at https://synapsetree.dev/dashboard.";
|
|
3934
|
+
case "subscription_inactive":
|
|
3935
|
+
return "The organization's SynapseTree plan is paused. Reads and export still work in the dashboard.";
|
|
3936
|
+
case "inference_not_configured":
|
|
3937
|
+
return INGEST_PROVIDER_MESSAGE;
|
|
3938
|
+
case "upstream_inference_unavailable":
|
|
3939
|
+
return "The account owner's inference provider is failing; searches fall back to keywords. Retry ingest later.";
|
|
3940
|
+
case "rate_limited":
|
|
3941
|
+
return `Rate limited by SynapseTree; retry after ${err.retryAfterSeconds !== void 0 ? `${err.retryAfterSeconds} seconds` : "a few seconds"}.`;
|
|
3942
|
+
case "not_implemented":
|
|
3943
|
+
return "SynapseTree has not enabled this operation yet (501). Tell the user; nothing to fix locally.";
|
|
3944
|
+
default:
|
|
3945
|
+
if (DETAIL_CODES.has(err.code)) return `${err.code}: ${err.detail ?? ""}`.trimEnd();
|
|
3946
|
+
if (TRANSIENT_CODES.has(err.code)) return "SynapseTree is temporarily unavailable; retry in a few seconds.";
|
|
3947
|
+
return `${err.code}${err.detail ? `: ${err.detail}` : ""} (HTTP ${err.status})`;
|
|
3948
|
+
}
|
|
3949
|
+
}
|
|
3950
|
+
function toolErrorText(err) {
|
|
3951
|
+
if (err instanceof SynapseTreeError) {
|
|
3952
|
+
const text = describe(err);
|
|
3953
|
+
return err.requestId ? `${text} (request-id: ${err.requestId})` : text;
|
|
3954
|
+
}
|
|
3955
|
+
if (err instanceof ZodError) {
|
|
3956
|
+
return err.issues.map((i) => `${i.path.join(".") || "(input)"}: ${i.message}`).join("\n");
|
|
3957
|
+
}
|
|
3958
|
+
if (err instanceof Error) return err.message;
|
|
3959
|
+
if (typeof err === "string") return err;
|
|
3960
|
+
return "Unknown error";
|
|
3961
|
+
}
|
|
3962
|
+
|
|
3963
|
+
// src/client.ts
|
|
3964
|
+
var DEFAULT_BASE_URL = "https://api.synapsetree.dev";
|
|
3965
|
+
function stripTrailingSlashes(url) {
|
|
3966
|
+
let end = url.length;
|
|
3967
|
+
while (end > 0 && url[end - 1] === "/") end--;
|
|
3968
|
+
return url.slice(0, end);
|
|
3969
|
+
}
|
|
3970
|
+
var RETRY_STATUSES = /* @__PURE__ */ new Set([408, 429, 502, 503, 504]);
|
|
3971
|
+
var MAX_ATTEMPTS = 3;
|
|
3972
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
3973
|
+
var TIMEOUTS = { ingestDocument: 12e4 };
|
|
3974
|
+
var UNAUTHENTICATED = /* @__PURE__ */ new Set(["registerAgentIdentity", "oauthToken"]);
|
|
3975
|
+
function buildUrl(baseUrl, op, input) {
|
|
3976
|
+
let path = op.path;
|
|
3977
|
+
for (const name of op.pathParameters) {
|
|
3978
|
+
const value = input.path?.[name];
|
|
3979
|
+
if (value === void 0) throw new UsageError(`missing path parameter ${name} for ${op.operationId}`);
|
|
3980
|
+
path = path.replace(`{${name}}`, encodeURIComponent(value));
|
|
3981
|
+
}
|
|
3982
|
+
const url = new URL(baseUrl + path);
|
|
3983
|
+
for (const [k, v] of Object.entries(input.query ?? {})) {
|
|
3984
|
+
if (v !== void 0) url.searchParams.set(k, String(v));
|
|
3985
|
+
}
|
|
3986
|
+
return url.toString();
|
|
3987
|
+
}
|
|
3988
|
+
var MAX_RETRY_AFTER_MS = 3e4;
|
|
3989
|
+
function retryAfterMs(res, body) {
|
|
3990
|
+
const cap = (ms) => Math.min(MAX_RETRY_AFTER_MS, ms);
|
|
3991
|
+
const header = res.headers.get("retry-after");
|
|
3992
|
+
if (header) {
|
|
3993
|
+
const seconds = Number(header);
|
|
3994
|
+
if (Number.isFinite(seconds)) return cap(Math.max(0, seconds * 1e3));
|
|
3995
|
+
const date = Date.parse(header);
|
|
3996
|
+
if (Number.isFinite(date)) return cap(Math.max(0, date - Date.now()));
|
|
3997
|
+
}
|
|
3998
|
+
const fromBody = body?.retryAfterSeconds;
|
|
3999
|
+
return typeof fromBody === "number" ? cap(fromBody * 1e3) : void 0;
|
|
4000
|
+
}
|
|
4001
|
+
async function readBody(res) {
|
|
4002
|
+
const type = res.headers.get("content-type") ?? "";
|
|
4003
|
+
const text = await res.text();
|
|
4004
|
+
const isProblem = type.startsWith("application/problem+json");
|
|
4005
|
+
const isJson = isProblem || type.startsWith("application/json");
|
|
4006
|
+
let json;
|
|
4007
|
+
if (isJson && text.length > 0) {
|
|
4008
|
+
try {
|
|
4009
|
+
json = JSON.parse(text);
|
|
4010
|
+
} catch {
|
|
4011
|
+
json = void 0;
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
return { text, json, isProblem, isJson: json !== void 0 };
|
|
4015
|
+
}
|
|
4016
|
+
function toError(res, parsed) {
|
|
4017
|
+
const requestId = res.headers.get("request-id") ?? void 0;
|
|
4018
|
+
const body = parsed.json ?? {};
|
|
4019
|
+
if (parsed.isProblem && typeof body.code === "string") {
|
|
4020
|
+
return new SynapseTreeError({
|
|
4021
|
+
status: res.status,
|
|
4022
|
+
code: body.code,
|
|
4023
|
+
detail: typeof body.detail === "string" ? body.detail : void 0,
|
|
4024
|
+
requestId: typeof body.requestId === "string" ? body.requestId : requestId,
|
|
4025
|
+
retryAfterSeconds: typeof body.retryAfterSeconds === "number" ? body.retryAfterSeconds : void 0
|
|
4026
|
+
});
|
|
4027
|
+
}
|
|
4028
|
+
if (parsed.isJson && typeof body.error === "string") {
|
|
4029
|
+
return new SynapseTreeError({ status: res.status, code: body.error, detail: typeof body.error_description === "string" ? body.error_description : void 0, requestId });
|
|
4030
|
+
}
|
|
4031
|
+
if (res.status === 401 || res.status === 403) {
|
|
4032
|
+
return new SynapseTreeError({ status: res.status, code: "unauthorized", detail: parsed.text.slice(0, 500) || void 0, requestId });
|
|
4033
|
+
}
|
|
4034
|
+
return new SynapseTreeError({ status: res.status, code: `http_${res.status}`, detail: parsed.text.slice(0, 500) || void 0, requestId });
|
|
4035
|
+
}
|
|
4036
|
+
var SynapseTreeClient = class {
|
|
4037
|
+
baseUrl;
|
|
4038
|
+
apiKey;
|
|
4039
|
+
userAgent;
|
|
4040
|
+
fetchImpl;
|
|
4041
|
+
sleep;
|
|
4042
|
+
random;
|
|
4043
|
+
constructor(opts) {
|
|
4044
|
+
this.apiKey = opts.apiKey;
|
|
4045
|
+
this.baseUrl = stripTrailingSlashes(opts.baseUrl);
|
|
4046
|
+
this.userAgent = opts.userAgent;
|
|
4047
|
+
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
4048
|
+
this.sleep = opts.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
4049
|
+
this.random = opts.random ?? Math.random;
|
|
4050
|
+
}
|
|
4051
|
+
get hasKey() {
|
|
4052
|
+
return this.apiKey !== void 0;
|
|
4053
|
+
}
|
|
4054
|
+
async call(opId, input = {}) {
|
|
4055
|
+
const op = OPERATIONS[opId];
|
|
4056
|
+
const authenticated = !UNAUTHENTICATED.has(opId);
|
|
4057
|
+
if (authenticated && !this.apiKey) throw new UsageError(NO_KEY_MESSAGE);
|
|
4058
|
+
const url = buildUrl(this.baseUrl, op, input);
|
|
4059
|
+
const headers = {
|
|
4060
|
+
Accept: "application/json, application/problem+json",
|
|
4061
|
+
"User-Agent": this.userAgent
|
|
4062
|
+
};
|
|
4063
|
+
if (authenticated && this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`;
|
|
4064
|
+
let body;
|
|
4065
|
+
if (input.form) {
|
|
4066
|
+
headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
4067
|
+
const params = new URLSearchParams();
|
|
4068
|
+
for (const [k, v] of Object.entries(input.form)) if (v !== void 0) params.set(k, v);
|
|
4069
|
+
body = params.toString();
|
|
4070
|
+
} else if (input.body !== void 0) {
|
|
4071
|
+
headers["Content-Type"] = "application/json";
|
|
4072
|
+
body = JSON.stringify(input.body);
|
|
4073
|
+
}
|
|
4074
|
+
if (op.acceptsIdempotencyKey) headers["Idempotency-Key"] = randomUUID();
|
|
4075
|
+
const timeoutMs = input.timeoutMs ?? TIMEOUTS[opId] ?? DEFAULT_TIMEOUT_MS;
|
|
4076
|
+
let lastError;
|
|
4077
|
+
let waitMs;
|
|
4078
|
+
const canRetry = opId !== "registerAgentIdentity" && opId !== "oauthToken";
|
|
4079
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
4080
|
+
if (attempt > 0) {
|
|
4081
|
+
if (!canRetry) break;
|
|
4082
|
+
await this.sleep(waitMs ?? Math.min(1e3 * 2 ** attempt, 8e3) + Math.floor(this.random() * 250));
|
|
4083
|
+
}
|
|
4084
|
+
let res;
|
|
4085
|
+
let done;
|
|
4086
|
+
try {
|
|
4087
|
+
({ res, done } = await this.send(url, { method: op.method, headers, body }, timeoutMs));
|
|
4088
|
+
} catch (err) {
|
|
4089
|
+
lastError = new SynapseTreeError({ status: 0, code: "network_error", detail: err instanceof Error ? err.message : String(err) });
|
|
4090
|
+
waitMs = void 0;
|
|
4091
|
+
continue;
|
|
4092
|
+
}
|
|
4093
|
+
try {
|
|
4094
|
+
let parsed;
|
|
4095
|
+
try {
|
|
4096
|
+
parsed = await readBody(res);
|
|
4097
|
+
} catch (err) {
|
|
4098
|
+
if (err instanceof SynapseTreeError) throw err;
|
|
4099
|
+
lastError = new SynapseTreeError({ status: 0, code: "network_error", detail: err instanceof Error ? err.message : String(err) });
|
|
4100
|
+
waitMs = void 0;
|
|
4101
|
+
continue;
|
|
4102
|
+
}
|
|
4103
|
+
if (RETRY_STATUSES.has(res.status)) {
|
|
4104
|
+
lastError = toError(res, parsed);
|
|
4105
|
+
waitMs = retryAfterMs(res, parsed.json);
|
|
4106
|
+
continue;
|
|
4107
|
+
}
|
|
4108
|
+
if (res.ok || opId === "oauthToken" && res.status === 400) {
|
|
4109
|
+
return {
|
|
4110
|
+
status: res.status,
|
|
4111
|
+
data: parsed.json,
|
|
4112
|
+
requestId: res.headers.get("request-id") ?? void 0,
|
|
4113
|
+
rateLimit: res.headers.get("ratelimit") ?? void 0,
|
|
4114
|
+
rateLimitPolicy: res.headers.get("ratelimit-policy") ?? void 0,
|
|
4115
|
+
idempotentReplayed: res.headers.get("idempotent-replayed") === "true"
|
|
4116
|
+
};
|
|
4117
|
+
}
|
|
4118
|
+
throw toError(res, parsed);
|
|
4119
|
+
} finally {
|
|
4120
|
+
done();
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
throw lastError ?? new SynapseTreeError({ status: 0, code: "network_error" });
|
|
4124
|
+
}
|
|
4125
|
+
async send(url, init, timeoutMs) {
|
|
4126
|
+
const controller = new AbortController();
|
|
4127
|
+
const timer = setTimeout(() => controller.abort(new Error(`timeout after ${timeoutMs} ms`)), timeoutMs);
|
|
4128
|
+
let res;
|
|
4129
|
+
try {
|
|
4130
|
+
res = await this.fetchImpl(url, { ...init, signal: controller.signal });
|
|
4131
|
+
} catch (err) {
|
|
4132
|
+
clearTimeout(timer);
|
|
4133
|
+
throw err;
|
|
4134
|
+
}
|
|
4135
|
+
return { res, done: () => clearTimeout(timer) };
|
|
4136
|
+
}
|
|
4137
|
+
};
|
|
4138
|
+
function defineTool(def) {
|
|
4139
|
+
return def;
|
|
4140
|
+
}
|
|
4141
|
+
var NAMESPACE_PATTERN = /^[a-z0-9][a-z0-9._:-]{0,127}$/;
|
|
4142
|
+
var namespaceField = z.string().regex(NAMESPACE_PATTERN, "namespace must match ^[a-z0-9][a-z0-9._:-]{0,127}$").optional().describe("Namespace to use. Defaults to the configured namespace (synapsetree-mcp config set namespace repo:<name>).");
|
|
4143
|
+
var dateTimeField = z.iso.datetime({ offset: true });
|
|
4144
|
+
var confidenceField = z.enum(["certain", "inferred", "tentative"]);
|
|
4145
|
+
function resolveNamespace(given, ctx) {
|
|
4146
|
+
const namespace = given ?? ctx.defaultNamespace;
|
|
4147
|
+
if (!namespace) throw new UsageError(NO_NAMESPACE_MESSAGE);
|
|
4148
|
+
return namespace;
|
|
4149
|
+
}
|
|
4150
|
+
function compact(obj) {
|
|
4151
|
+
const out = {};
|
|
4152
|
+
for (const [k, v] of Object.entries(obj)) if (v !== void 0) out[k] = v;
|
|
4153
|
+
return out;
|
|
4154
|
+
}
|
|
4155
|
+
|
|
4156
|
+
// src/tools/graph-traverse.ts
|
|
4157
|
+
var graphTraverse = defineTool({
|
|
4158
|
+
name: "graph_traverse",
|
|
4159
|
+
description: "Walk the knowledge graph from a fact or node id, up to three hops. Returns the anchor first, then neighbours by depth, and the edges between them.",
|
|
4160
|
+
operation: "traverseGraph",
|
|
4161
|
+
inputSchema: z.object({
|
|
4162
|
+
namespace: namespaceField,
|
|
4163
|
+
sourceId: z.string().min(1).max(255).describe("The fact or graph node id to start from."),
|
|
4164
|
+
maxDepth: z.number().int().min(1).max(3).default(1),
|
|
4165
|
+
direction: z.enum(["inbound", "outbound", "both"]).optional(),
|
|
4166
|
+
edgeTypes: z.array(z.string().min(1).max(128)).max(100).optional().describe("Allowed edge types, e.g. dependsOn, documents, supersedes. Omit for all."),
|
|
4167
|
+
maxNodes: z.number().int().min(1).max(200).default(20),
|
|
4168
|
+
excludeDrafts: z.boolean().optional()
|
|
4169
|
+
}),
|
|
4170
|
+
async handler(input, ctx) {
|
|
4171
|
+
const namespace = resolveNamespace(input.namespace, ctx);
|
|
4172
|
+
const res = await ctx.client.call("traverseGraph", {
|
|
4173
|
+
body: compact({
|
|
4174
|
+
namespace,
|
|
4175
|
+
sourceId: input.sourceId,
|
|
4176
|
+
maxDepth: input.maxDepth,
|
|
4177
|
+
direction: input.direction,
|
|
4178
|
+
edgeTypes: input.edgeTypes,
|
|
4179
|
+
maxNodes: input.maxNodes,
|
|
4180
|
+
excludeDrafts: input.excludeDrafts
|
|
4181
|
+
})
|
|
4182
|
+
});
|
|
4183
|
+
return res.data;
|
|
4184
|
+
}
|
|
4185
|
+
});
|
|
4186
|
+
var SOURCE_REF_PATTERN = /^[A-Za-z0-9._\- ]{1,255}$/;
|
|
4187
|
+
function encodeSourceRef(raw) {
|
|
4188
|
+
const encoded = raw.replace(/\//g, "__");
|
|
4189
|
+
if (!SOURCE_REF_PATTERN.test(encoded)) {
|
|
4190
|
+
const bad = [...new Set(encoded.replace(/[A-Za-z0-9._\- ]/g, ""))].join(" ");
|
|
4191
|
+
throw new UsageError(`sourceRef may only contain letters, digits, ".", "_", "-", and spaces (1\u2013255 chars); "/" is encoded as "__". Illegal: ${bad || "length"}`);
|
|
4192
|
+
}
|
|
4193
|
+
return encoded;
|
|
4194
|
+
}
|
|
4195
|
+
var memoryIngest = defineTool({
|
|
4196
|
+
name: "memory_ingest",
|
|
4197
|
+
description: `Store a whole document; SynapseTree extracts the facts. ${INGEST_PROVIDER_MESSAGE}`,
|
|
4198
|
+
operation: "ingestDocument",
|
|
4199
|
+
inputSchema: z.object({
|
|
4200
|
+
namespace: namespaceField,
|
|
4201
|
+
sourceRef: z.string().min(1).max(255).describe('Identifies the document, e.g. a repo-relative path. "/" is encoded as "__".'),
|
|
4202
|
+
content: z.string().min(1).max(524288),
|
|
4203
|
+
onDuplicateHash: z.enum(["skip", "ingest", "error"]).default("skip").describe("What to do when another sourceRef already holds identical content.")
|
|
4204
|
+
}),
|
|
4205
|
+
async handler(input, ctx) {
|
|
4206
|
+
const namespace = resolveNamespace(input.namespace, ctx);
|
|
4207
|
+
const sourceRef = encodeSourceRef(input.sourceRef);
|
|
4208
|
+
const sourceHash = createHash("sha256").update(input.content, "utf8").digest("hex");
|
|
4209
|
+
const res = await ctx.client.call("ingestDocument", {
|
|
4210
|
+
body: compact({ mode: "server_extraction", namespace, sourceRef, sourceHash, content: input.content, onDuplicateHash: input.onDuplicateHash })
|
|
4211
|
+
});
|
|
4212
|
+
return res.data;
|
|
4213
|
+
}
|
|
4214
|
+
});
|
|
4215
|
+
var memoryLogEvent = defineTool({
|
|
4216
|
+
name: "memory_log_event",
|
|
4217
|
+
description: "Record that something happened: an observation, decision, action, or outcome, optionally tied to a fact.",
|
|
4218
|
+
operation: "createEvent",
|
|
4219
|
+
inputSchema: z.object({
|
|
4220
|
+
namespace: namespaceField,
|
|
4221
|
+
eventType: z.enum(["observation", "decision", "action", "outcome"]),
|
|
4222
|
+
// SynapseTree trims, then allows 1-4000 UTF-16 units (contract CreateEventRequest.summary).
|
|
4223
|
+
// zod's max() and JSON Schema's maxLength count code points, so the refine enforces UTF-16 units.
|
|
4224
|
+
summary: z.string().trim().min(1).max(4e3).refine((s) => s.length <= 4e3, { message: "summary is over 4000 UTF-16 code units (astral characters count twice)" }),
|
|
4225
|
+
relatedFactId: z.string().min(1).max(255).optional(),
|
|
4226
|
+
occurredAt: dateTimeField.optional().describe("When it happened. Defaults to now.")
|
|
4227
|
+
}),
|
|
4228
|
+
async handler(input, ctx) {
|
|
4229
|
+
const namespace = resolveNamespace(input.namespace, ctx);
|
|
4230
|
+
const res = await ctx.client.call("createEvent", {
|
|
4231
|
+
body: compact({ namespace, eventType: input.eventType, summary: input.summary, relatedFactId: input.relatedFactId, occurredAt: input.occurredAt })
|
|
4232
|
+
});
|
|
4233
|
+
return res.data;
|
|
4234
|
+
}
|
|
4235
|
+
});
|
|
4236
|
+
var memoryRemember = defineTool({
|
|
4237
|
+
name: "memory_remember",
|
|
4238
|
+
description: "Store one fact the user decided or you observed. Works with no provider registered. Use `memory_ingest` for a whole document.",
|
|
4239
|
+
operation: "rememberFact",
|
|
4240
|
+
inputSchema: z.object({
|
|
4241
|
+
namespace: namespaceField,
|
|
4242
|
+
title: z.string().min(1).max(1e3),
|
|
4243
|
+
body: z.string().min(1).max(1e5),
|
|
4244
|
+
tags: z.array(z.string().min(1).max(100)).max(100).optional(),
|
|
4245
|
+
confidence: confidenceField.optional(),
|
|
4246
|
+
okfType: z.string().min(1).max(128).optional().describe("Ontology node type, e.g. project, person, design_spec, procedure."),
|
|
4247
|
+
validFrom: dateTimeField.optional().describe("When the fact became true. Defaults to now.")
|
|
4248
|
+
}),
|
|
4249
|
+
async handler(input, ctx) {
|
|
4250
|
+
const namespace = resolveNamespace(input.namespace, ctx);
|
|
4251
|
+
const res = await ctx.client.call("rememberFact", {
|
|
4252
|
+
body: compact({
|
|
4253
|
+
namespace,
|
|
4254
|
+
title: input.title,
|
|
4255
|
+
body: input.body,
|
|
4256
|
+
tags: input.tags,
|
|
4257
|
+
confidence: input.confidence,
|
|
4258
|
+
sourceType: "user_stated",
|
|
4259
|
+
okfType: input.okfType,
|
|
4260
|
+
validFrom: input.validFrom
|
|
4261
|
+
})
|
|
4262
|
+
});
|
|
4263
|
+
return res.data;
|
|
4264
|
+
}
|
|
4265
|
+
});
|
|
4266
|
+
var memorySearch = defineTool({
|
|
4267
|
+
name: "memory_search",
|
|
4268
|
+
description: "Search the user's SynapseTree memory. Semantic search needs an embeddings provider registered by the account owner in the dashboard; without one this is keyword search and `diagnostics.keyword_only` says so. That is normal, not an error. Returns facts with scores, pending tasks, recent events, and diagnostics. Not paginated: raise `limit` (max 100) for more.",
|
|
4269
|
+
operation: "queryMemory",
|
|
4270
|
+
inputSchema: z.object({
|
|
4271
|
+
namespace: namespaceField,
|
|
4272
|
+
query: z.string().max(4096).describe("Search text. Empty returns the most recent facts."),
|
|
4273
|
+
limit: z.number().int().min(1).max(100).default(10),
|
|
4274
|
+
excludeDrafts: z.boolean().optional(),
|
|
4275
|
+
asOf: dateTimeField.optional().describe("RFC 3339 timestamp; search memory as it was at that moment.")
|
|
4276
|
+
}),
|
|
4277
|
+
async handler(input, ctx) {
|
|
4278
|
+
const namespace = resolveNamespace(input.namespace, ctx);
|
|
4279
|
+
const res = await ctx.client.call("queryMemory", {
|
|
4280
|
+
body: compact({ namespaces: [namespace], query: input.query, limit: input.limit, excludeDrafts: input.excludeDrafts, asOf: input.asOf })
|
|
4281
|
+
});
|
|
4282
|
+
return res.data;
|
|
4283
|
+
}
|
|
4284
|
+
});
|
|
4285
|
+
var memorySupersede = defineTool({
|
|
4286
|
+
name: "memory_supersede",
|
|
4287
|
+
description: "Replace a fact with a corrected one and keep the old one in history. Never deletes.",
|
|
4288
|
+
operation: "supersedeFact",
|
|
4289
|
+
inputSchema: z.object({
|
|
4290
|
+
namespace: namespaceField,
|
|
4291
|
+
factId: z.string().min(1).max(255).describe("The fact to replace."),
|
|
4292
|
+
title: z.string().min(1).max(1e3),
|
|
4293
|
+
body: z.string().min(1).max(1e5),
|
|
4294
|
+
tags: z.array(z.string().min(1).max(100)).max(100).optional(),
|
|
4295
|
+
confidence: confidenceField.optional(),
|
|
4296
|
+
validFrom: dateTimeField.optional().describe("When the replacement became true. Defaults to now.")
|
|
4297
|
+
}),
|
|
4298
|
+
async handler(input, ctx) {
|
|
4299
|
+
const namespace = resolveNamespace(input.namespace, ctx);
|
|
4300
|
+
const res = await ctx.client.call("supersedeFact", {
|
|
4301
|
+
path: { factId: input.factId },
|
|
4302
|
+
body: compact({
|
|
4303
|
+
namespace,
|
|
4304
|
+
validFrom: input.validFrom,
|
|
4305
|
+
replacement: compact({ kind: "new", title: input.title, body: input.body, tags: input.tags, confidence: input.confidence, sourceType: "user_stated" })
|
|
4306
|
+
})
|
|
4307
|
+
});
|
|
4308
|
+
return res.data;
|
|
4309
|
+
}
|
|
4310
|
+
});
|
|
4311
|
+
var PAGE = 100;
|
|
4312
|
+
var CAP = 500;
|
|
4313
|
+
var namespacesList = defineTool({
|
|
4314
|
+
name: "namespaces_list",
|
|
4315
|
+
description: "List the namespaces in the user's database, optionally by prefix. Stops after 500 names and sets `truncated`.",
|
|
4316
|
+
operation: "listNamespaces",
|
|
4317
|
+
inputSchema: z.object({
|
|
4318
|
+
// Accepted for uniformity (spec §5.6, §8) but never sent: listNamespaces is database-wide in the contract.
|
|
4319
|
+
namespace: namespaceField.describe("Ignored: listing is database-wide. Use `prefix` to filter."),
|
|
4320
|
+
prefix: z.string().max(128).optional()
|
|
4321
|
+
}),
|
|
4322
|
+
async handler(input, ctx) {
|
|
4323
|
+
const namespaces = [];
|
|
4324
|
+
let after;
|
|
4325
|
+
let truncated = false;
|
|
4326
|
+
for (; ; ) {
|
|
4327
|
+
const res = await ctx.client.call("listNamespaces", { query: { prefix: input.prefix, limit: PAGE, after } });
|
|
4328
|
+
for (const row of res.data.data) namespaces.push(row.namespace);
|
|
4329
|
+
if (!res.data.data.length) break;
|
|
4330
|
+
if (!res.data.hasMore || !res.data.nextCursor) break;
|
|
4331
|
+
if (namespaces.length >= CAP) {
|
|
4332
|
+
truncated = true;
|
|
4333
|
+
break;
|
|
4334
|
+
}
|
|
4335
|
+
after = res.data.nextCursor;
|
|
4336
|
+
}
|
|
4337
|
+
return { namespaces: namespaces.slice(0, CAP), truncated };
|
|
4338
|
+
}
|
|
4339
|
+
});
|
|
4340
|
+
var whoami = defineTool({
|
|
4341
|
+
name: "whoami",
|
|
4342
|
+
description: "Show which SynapseTree account, database, scope, and plan this server is using.",
|
|
4343
|
+
operation: "whoami",
|
|
4344
|
+
inputSchema: z.object({}),
|
|
4345
|
+
async handler(_input, ctx) {
|
|
4346
|
+
const res = await ctx.client.call("whoami");
|
|
4347
|
+
return res.data;
|
|
4348
|
+
}
|
|
4349
|
+
});
|
|
4350
|
+
|
|
4351
|
+
// src/tools/index.ts
|
|
4352
|
+
var TOOLS = [
|
|
4353
|
+
memorySearch,
|
|
4354
|
+
memoryRemember,
|
|
4355
|
+
memorySupersede,
|
|
4356
|
+
memoryIngest,
|
|
4357
|
+
memoryLogEvent,
|
|
4358
|
+
graphTraverse,
|
|
4359
|
+
namespacesList,
|
|
4360
|
+
whoami
|
|
4361
|
+
];
|
|
4362
|
+
var TOOL_NAMES = TOOLS.map((t) => t.name);
|
|
4363
|
+
|
|
4364
|
+
// src/version.ts
|
|
4365
|
+
var VERSION = "7.15.2" ;
|
|
4366
|
+
|
|
4367
|
+
// src/server.ts
|
|
4368
|
+
var SERVER_NAME = "synapsetree";
|
|
4369
|
+
function createServer(ctx) {
|
|
4370
|
+
const server = new McpServer({ name: SERVER_NAME, version: VERSION });
|
|
4371
|
+
for (const tool of TOOLS) {
|
|
4372
|
+
server.registerTool(
|
|
4373
|
+
tool.name,
|
|
4374
|
+
{ description: tool.description, inputSchema: tool.inputSchema.shape },
|
|
4375
|
+
async (args) => {
|
|
4376
|
+
try {
|
|
4377
|
+
const input = tool.inputSchema.parse(args ?? {});
|
|
4378
|
+
const result = await tool.handler(input, ctx);
|
|
4379
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? null, null, 2) }] };
|
|
4380
|
+
} catch (err) {
|
|
4381
|
+
return { isError: true, content: [{ type: "text", text: toolErrorText(err) }] };
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4384
|
+
);
|
|
4385
|
+
}
|
|
4386
|
+
return server;
|
|
4387
|
+
}
|
|
4388
|
+
|
|
4389
|
+
export { CONTRACT_INFO, DEFAULT_BASE_URL, OPERATIONS, OPERATION_IDS, SERVER_NAME, SynapseTreeClient, SynapseTreeError, TOOLS, TOOL_NAMES, UsageError, VERSION, WITHHELD_OPERATION_IDS, createServer, toolErrorText };
|
|
4390
|
+
//# sourceMappingURL=index.mjs.map
|
|
4391
|
+
//# sourceMappingURL=index.mjs.map
|