docsgraph 0.1.0a2__py3-none-any.whl
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.
- cairn/__init__.py +5 -0
- cairn/bench/__init__.py +37 -0
- cairn/bench/baseline.py +236 -0
- cairn/bench/dataset.py +109 -0
- cairn/bench/judge.py +126 -0
- cairn/bench/metrics.py +32 -0
- cairn/bench/report.py +143 -0
- cairn/bench/runner.py +219 -0
- cairn/cli/__init__.py +5 -0
- cairn/cli/app.py +776 -0
- cairn/cli/config.py +105 -0
- cairn/core/__init__.py +41 -0
- cairn/core/errors.py +68 -0
- cairn/core/types.py +147 -0
- cairn/embed/__init__.py +17 -0
- cairn/embed/base.py +31 -0
- cairn/embed/doubao.py +167 -0
- cairn/embed/fake.py +36 -0
- cairn/embed/openai_compatible.py +155 -0
- cairn/engine/__init__.py +18 -0
- cairn/engine/indexer.py +298 -0
- cairn/engine/manifest.py +83 -0
- cairn/entity/__init__.py +21 -0
- cairn/entity/base.py +52 -0
- cairn/entity/fake.py +34 -0
- cairn/entity/heuristic.py +148 -0
- cairn/index/__init__.py +39 -0
- cairn/index/entities.py +244 -0
- cairn/index/summaries.py +269 -0
- cairn/index/tree.py +274 -0
- cairn/index/vectors.py +287 -0
- cairn/index/xrefs.py +195 -0
- cairn/ingest/__init__.py +36 -0
- cairn/ingest/base.py +46 -0
- cairn/ingest/markdown.py +244 -0
- cairn/ingest/markitdown.py +145 -0
- cairn/ingest/pdf.py +357 -0
- cairn/inspection.py +971 -0
- cairn/mcp/__init__.py +12 -0
- cairn/mcp/schemas.py +547 -0
- cairn/mcp/server.py +363 -0
- cairn/providers.py +50 -0
- cairn/py.typed +0 -0
- cairn/repo.py +1486 -0
- cairn/repo_search.py +1505 -0
- cairn/summarize/__init__.py +18 -0
- cairn/summarize/base.py +56 -0
- cairn/summarize/cache.py +66 -0
- cairn/summarize/fake.py +43 -0
- cairn/summarize/openai_compatible.py +148 -0
- cairn/summarize/prompts.py +73 -0
- cairn/tools/__init__.py +31 -0
- cairn/tools/base.py +126 -0
- cairn/tools/find_mentions.py +93 -0
- cairn/tools/get_related.py +140 -0
- cairn/tools/get_section.py +130 -0
- cairn/tools/outline.py +75 -0
- cairn/tools/read_range.py +94 -0
- cairn/tools/search_keyword.py +94 -0
- cairn/tools/search_semantic.py +181 -0
- cairn/xref/__init__.py +24 -0
- cairn/xref/base.py +50 -0
- cairn/xref/fake.py +40 -0
- cairn/xref/heuristic.py +217 -0
- docsgraph-0.1.0a2.dist-info/METADATA +688 -0
- docsgraph-0.1.0a2.dist-info/RECORD +69 -0
- docsgraph-0.1.0a2.dist-info/WHEEL +4 -0
- docsgraph-0.1.0a2.dist-info/entry_points.txt +3 -0
- docsgraph-0.1.0a2.dist-info/licenses/LICENSE +201 -0
cairn/mcp/__init__.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""MCP server — the wire layer.
|
|
2
|
+
|
|
3
|
+
Exposes the v0.1 retrieval tools as Model Context Protocol tools over stdio.
|
|
4
|
+
The translation of :class:`cairn.tools.ToolResponse` and
|
|
5
|
+
:class:`cairn.core.errors.CairnError` to MCP envelopes lives here so the
|
|
6
|
+
tool functions stay transport-agnostic.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from cairn.mcp.schemas import CAIRN_TOOLS
|
|
10
|
+
from cairn.mcp.server import dispatch_tool, serve_stdio
|
|
11
|
+
|
|
12
|
+
__all__ = ["CAIRN_TOOLS", "dispatch_tool", "serve_stdio"]
|
cairn/mcp/schemas.py
ADDED
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
"""JSON Schemas for the five v0.1 retrieval tools.
|
|
2
|
+
|
|
3
|
+
These are advertised to MCP clients via the ``list_tools`` handler. They
|
|
4
|
+
are the public contract; updates here are versioned breaking changes per
|
|
5
|
+
``docs/specs/mcp-tools.md`` §10.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import copy
|
|
11
|
+
from typing import Any, Final
|
|
12
|
+
|
|
13
|
+
from mcp.types import Tool, ToolAnnotations
|
|
14
|
+
|
|
15
|
+
_TRACE_SCHEMA: Final[dict[str, Any]] = {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"additionalProperties": True,
|
|
18
|
+
"required": ["server", "tool", "mode", "status", "arguments", "steps"],
|
|
19
|
+
"properties": {
|
|
20
|
+
"server": {"const": "cairn"},
|
|
21
|
+
"tool": {"type": "string"},
|
|
22
|
+
"mode": {"enum": ["document", "repo", "repo_document"]},
|
|
23
|
+
"status": {"enum": ["ok", "error"]},
|
|
24
|
+
"arguments": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"additionalProperties": True,
|
|
27
|
+
"description": "Normalized MCP arguments received for the tool call.",
|
|
28
|
+
},
|
|
29
|
+
"steps": {
|
|
30
|
+
"type": "array",
|
|
31
|
+
"description": "Human-readable execution steps for AI client inspection.",
|
|
32
|
+
"items": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"additionalProperties": True,
|
|
35
|
+
"required": ["name", "status"],
|
|
36
|
+
"properties": {
|
|
37
|
+
"name": {"type": "string"},
|
|
38
|
+
"status": {"enum": ["ok", "error"]},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_ERROR_SCHEMA: Final[dict[str, Any]] = {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"additionalProperties": True,
|
|
48
|
+
"required": ["code", "message", "details"],
|
|
49
|
+
"properties": {
|
|
50
|
+
"code": {"type": "string"},
|
|
51
|
+
"message": {"type": "string"},
|
|
52
|
+
"details": {"type": "object", "additionalProperties": True},
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_ENVELOPE_OUTPUT_SCHEMA: Final[dict[str, Any]] = {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"description": (
|
|
59
|
+
"Cairn MCP envelope. Successful calls include data and trace; failed "
|
|
60
|
+
"calls include error and trace."
|
|
61
|
+
),
|
|
62
|
+
"oneOf": [
|
|
63
|
+
{
|
|
64
|
+
"type": "object",
|
|
65
|
+
"additionalProperties": False,
|
|
66
|
+
"required": ["ok", "tokens_returned", "data", "trace"],
|
|
67
|
+
"properties": {
|
|
68
|
+
"ok": {"const": True},
|
|
69
|
+
"tokens_returned": {"type": "integer", "minimum": 0},
|
|
70
|
+
"data": {"type": "object", "additionalProperties": True},
|
|
71
|
+
"trace": _TRACE_SCHEMA,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": False,
|
|
77
|
+
"required": ["ok", "error", "trace"],
|
|
78
|
+
"properties": {
|
|
79
|
+
"ok": {"const": False},
|
|
80
|
+
"error": _ERROR_SCHEMA,
|
|
81
|
+
"trace": _TRACE_SCHEMA,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _read_only(title: str) -> ToolAnnotations:
|
|
89
|
+
return ToolAnnotations(title=title, readOnlyHint=True)
|
|
90
|
+
|
|
91
|
+
_OUTLINE_SCHEMA: Final[dict[str, Any]] = {
|
|
92
|
+
"type": "object",
|
|
93
|
+
"additionalProperties": False,
|
|
94
|
+
"properties": {
|
|
95
|
+
"depth": {
|
|
96
|
+
"type": "integer",
|
|
97
|
+
"minimum": 1,
|
|
98
|
+
"maximum": 6,
|
|
99
|
+
"default": 2,
|
|
100
|
+
"description": "Maximum heading level to include.",
|
|
101
|
+
},
|
|
102
|
+
"focus": {
|
|
103
|
+
"type": ["string", "null"],
|
|
104
|
+
"default": None,
|
|
105
|
+
"description": "Section id to restrict the outline to.",
|
|
106
|
+
},
|
|
107
|
+
"include": {
|
|
108
|
+
"type": "array",
|
|
109
|
+
"items": {"enum": ["gist", "synopsis"]},
|
|
110
|
+
"default": ["gist"],
|
|
111
|
+
"description": "Which summary levels to attach to each node.",
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
_GET_SECTION_SCHEMA: Final[dict[str, Any]] = {
|
|
117
|
+
"type": "object",
|
|
118
|
+
"additionalProperties": False,
|
|
119
|
+
"required": ["id"],
|
|
120
|
+
"properties": {
|
|
121
|
+
"id": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Section id (hierarchical, slug-based).",
|
|
124
|
+
},
|
|
125
|
+
"level": {
|
|
126
|
+
"enum": ["gist", "synopsis", "digest", "full"],
|
|
127
|
+
"default": "synopsis",
|
|
128
|
+
"description": "Granularity. digest is reserved for v0.2.",
|
|
129
|
+
},
|
|
130
|
+
"include_children": {
|
|
131
|
+
"type": "boolean",
|
|
132
|
+
"default": False,
|
|
133
|
+
"description": "Reserved for v0.2.",
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
_EXPAND_SCHEMA: Final[dict[str, Any]] = {
|
|
139
|
+
"type": "object",
|
|
140
|
+
"additionalProperties": False,
|
|
141
|
+
"required": ["id", "to"],
|
|
142
|
+
"properties": {
|
|
143
|
+
"id": {"type": "string"},
|
|
144
|
+
"to": {"enum": ["synopsis", "digest", "full"]},
|
|
145
|
+
},
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_SEARCH_SEMANTIC_SCHEMA: Final[dict[str, Any]] = {
|
|
149
|
+
"type": "object",
|
|
150
|
+
"additionalProperties": False,
|
|
151
|
+
"required": ["query"],
|
|
152
|
+
"properties": {
|
|
153
|
+
"query": {"type": "string", "minLength": 1},
|
|
154
|
+
"scope": {"type": ["string", "null"], "default": None},
|
|
155
|
+
"k": {"type": "integer", "minimum": 1, "maximum": 32, "default": 8},
|
|
156
|
+
"include": {
|
|
157
|
+
"type": "array",
|
|
158
|
+
"items": {"enum": ["synopsis", "head", "evidence"]},
|
|
159
|
+
"default": ["synopsis", "head", "evidence"],
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
_SEARCH_KEYWORD_SCHEMA: Final[dict[str, Any]] = {
|
|
165
|
+
"type": "object",
|
|
166
|
+
"additionalProperties": False,
|
|
167
|
+
"required": ["terms"],
|
|
168
|
+
"properties": {
|
|
169
|
+
"terms": {
|
|
170
|
+
"type": "array",
|
|
171
|
+
"items": {"type": "string", "minLength": 1},
|
|
172
|
+
"minItems": 1,
|
|
173
|
+
"maxItems": 8,
|
|
174
|
+
},
|
|
175
|
+
"scope": {"type": ["string", "null"], "default": None},
|
|
176
|
+
"k": {"type": "integer", "minimum": 1, "maximum": 32, "default": 12},
|
|
177
|
+
"mode": {"enum": ["any", "all"], "default": "any"},
|
|
178
|
+
},
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
_FIND_MENTIONS_SCHEMA: Final[dict[str, Any]] = {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"additionalProperties": False,
|
|
184
|
+
"required": ["entity"],
|
|
185
|
+
"properties": {
|
|
186
|
+
"entity": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"minLength": 1,
|
|
189
|
+
"description": "Entity name (canonical or any registered surface form).",
|
|
190
|
+
},
|
|
191
|
+
"scope": {"type": ["string", "null"], "default": None},
|
|
192
|
+
"kinds": {
|
|
193
|
+
"type": ["array", "null"],
|
|
194
|
+
"items": {"enum": ["term", "code", "proper", "defined"]},
|
|
195
|
+
"default": None,
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
_GET_RELATED_SCHEMA: Final[dict[str, Any]] = {
|
|
201
|
+
"type": "object",
|
|
202
|
+
"additionalProperties": False,
|
|
203
|
+
"required": ["id"],
|
|
204
|
+
"properties": {
|
|
205
|
+
"id": {"type": "string", "description": "Section id to find neighbors of."},
|
|
206
|
+
"kinds": {
|
|
207
|
+
"type": "array",
|
|
208
|
+
"items": {"enum": ["xref", "sibling", "parent", "child"]},
|
|
209
|
+
"default": ["xref"],
|
|
210
|
+
"description": "Which relation channels to traverse.",
|
|
211
|
+
},
|
|
212
|
+
"k": {"type": "integer", "minimum": 1, "maximum": 32, "default": 8},
|
|
213
|
+
},
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
_READ_RANGE_SCHEMA: Final[dict[str, Any]] = {
|
|
217
|
+
"type": "object",
|
|
218
|
+
"additionalProperties": False,
|
|
219
|
+
"required": ["start_id", "end_id"],
|
|
220
|
+
"properties": {
|
|
221
|
+
"start_id": {"type": "string", "description": "First section to include."},
|
|
222
|
+
"end_id": {
|
|
223
|
+
"type": "string",
|
|
224
|
+
"description": "Last section to include (inclusive).",
|
|
225
|
+
},
|
|
226
|
+
"max_tokens": {
|
|
227
|
+
"type": "integer",
|
|
228
|
+
"minimum": 1,
|
|
229
|
+
"default": 4000,
|
|
230
|
+
"description": "Soft cap on the returned content's token count.",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
CAIRN_TOOLS: Final[list[Tool]] = [
|
|
237
|
+
Tool(
|
|
238
|
+
name="outline",
|
|
239
|
+
annotations=_read_only("Cairn Outline"),
|
|
240
|
+
description=(
|
|
241
|
+
"Get a structural map of the document. The cheapest tool; "
|
|
242
|
+
"agents should call it first."
|
|
243
|
+
),
|
|
244
|
+
inputSchema=_OUTLINE_SCHEMA,
|
|
245
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
246
|
+
),
|
|
247
|
+
Tool(
|
|
248
|
+
name="get_section",
|
|
249
|
+
annotations=_read_only("Cairn Get Section"),
|
|
250
|
+
description=(
|
|
251
|
+
"Fetch one section at a chosen summary level (gist/synopsis/full)."
|
|
252
|
+
),
|
|
253
|
+
inputSchema=_GET_SECTION_SCHEMA,
|
|
254
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
255
|
+
),
|
|
256
|
+
Tool(
|
|
257
|
+
name="expand",
|
|
258
|
+
annotations=_read_only("Cairn Expand Section"),
|
|
259
|
+
description=(
|
|
260
|
+
"Move from a shallower summary to a deeper one for a known section. "
|
|
261
|
+
"Equivalent to get_section(id, level=to)."
|
|
262
|
+
),
|
|
263
|
+
inputSchema=_EXPAND_SCHEMA,
|
|
264
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
265
|
+
),
|
|
266
|
+
Tool(
|
|
267
|
+
name="search_semantic",
|
|
268
|
+
annotations=_read_only("Cairn Semantic Search"),
|
|
269
|
+
description=(
|
|
270
|
+
"Dense vector search. Use for conceptual queries where exact "
|
|
271
|
+
"wording is unknown."
|
|
272
|
+
),
|
|
273
|
+
inputSchema=_SEARCH_SEMANTIC_SCHEMA,
|
|
274
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
275
|
+
),
|
|
276
|
+
Tool(
|
|
277
|
+
name="search_keyword",
|
|
278
|
+
annotations=_read_only("Cairn Keyword Search"),
|
|
279
|
+
description=(
|
|
280
|
+
"Exact (case-insensitive) lexical search. Use for known entities, "
|
|
281
|
+
"code symbols, technical terms."
|
|
282
|
+
),
|
|
283
|
+
inputSchema=_SEARCH_KEYWORD_SCHEMA,
|
|
284
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
285
|
+
),
|
|
286
|
+
Tool(
|
|
287
|
+
name="find_mentions",
|
|
288
|
+
annotations=_read_only("Cairn Find Mentions"),
|
|
289
|
+
description=(
|
|
290
|
+
"Locate every section where a named entity is mentioned. Requires "
|
|
291
|
+
"the entities sub-index (v0.2+)."
|
|
292
|
+
),
|
|
293
|
+
inputSchema=_FIND_MENTIONS_SCHEMA,
|
|
294
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
295
|
+
),
|
|
296
|
+
Tool(
|
|
297
|
+
name="get_related",
|
|
298
|
+
annotations=_read_only("Cairn Get Related"),
|
|
299
|
+
description=(
|
|
300
|
+
"Return neighbors of a section across the cross-reference graph "
|
|
301
|
+
"and the structural tree (xref/sibling/parent/child)."
|
|
302
|
+
),
|
|
303
|
+
inputSchema=_GET_RELATED_SCHEMA,
|
|
304
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
305
|
+
),
|
|
306
|
+
Tool(
|
|
307
|
+
name="read_range",
|
|
308
|
+
annotations=_read_only("Cairn Read Range"),
|
|
309
|
+
description=(
|
|
310
|
+
"Read continuous content across consecutive sections from "
|
|
311
|
+
"start_id through end_id, truncating at max_tokens."
|
|
312
|
+
),
|
|
313
|
+
inputSchema=_READ_RANGE_SCHEMA,
|
|
314
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
315
|
+
),
|
|
316
|
+
]
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def _with_doc(schema: dict[str, Any]) -> dict[str, Any]:
|
|
320
|
+
out = copy.deepcopy(schema)
|
|
321
|
+
properties = out.setdefault("properties", {})
|
|
322
|
+
properties["doc"] = {
|
|
323
|
+
"type": ["string", "null"],
|
|
324
|
+
"default": None,
|
|
325
|
+
"description": (
|
|
326
|
+
"Repository document id. Omit to use the configured primary doc."
|
|
327
|
+
),
|
|
328
|
+
}
|
|
329
|
+
return out
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def _repo_doc_tool(tool: Tool) -> Tool:
|
|
333
|
+
title = (
|
|
334
|
+
tool.annotations.title
|
|
335
|
+
if tool.annotations is not None and tool.annotations.title is not None
|
|
336
|
+
else tool.name.replace("_", " ").title()
|
|
337
|
+
)
|
|
338
|
+
return Tool(
|
|
339
|
+
name=tool.name,
|
|
340
|
+
annotations=_read_only(f"Cairn Repo {title.removeprefix('Cairn ')}"),
|
|
341
|
+
description=(
|
|
342
|
+
f"{tool.description} Accepts optional `doc` in repo mode. "
|
|
343
|
+
"Returns a structured envelope with `trace.steps` for AI clients."
|
|
344
|
+
),
|
|
345
|
+
inputSchema=_with_doc(tool.inputSchema),
|
|
346
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
_LIST_DOCUMENTS_SCHEMA: Final[dict[str, Any]] = {
|
|
351
|
+
"type": "object",
|
|
352
|
+
"additionalProperties": False,
|
|
353
|
+
"properties": {
|
|
354
|
+
"state": {
|
|
355
|
+
"type": ["string", "null"],
|
|
356
|
+
"enum": ["indexed", "stale", "missing", "error", "orphaned", None],
|
|
357
|
+
"default": None,
|
|
358
|
+
"description": "Optional state filter.",
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
_SEARCH_DOCUMENTS_SCHEMA: Final[dict[str, Any]] = {
|
|
365
|
+
"type": "object",
|
|
366
|
+
"additionalProperties": False,
|
|
367
|
+
"required": ["query"],
|
|
368
|
+
"properties": {
|
|
369
|
+
"query": {
|
|
370
|
+
"type": "string",
|
|
371
|
+
"minLength": 1,
|
|
372
|
+
"description": "Conceptual query to search across all indexed repo docs.",
|
|
373
|
+
},
|
|
374
|
+
"k": {"type": "integer", "minimum": 1, "maximum": 32, "default": 8},
|
|
375
|
+
"sections_per_doc": {
|
|
376
|
+
"type": ["integer", "null"],
|
|
377
|
+
"minimum": 1,
|
|
378
|
+
"maximum": 8,
|
|
379
|
+
"default": None,
|
|
380
|
+
"description": (
|
|
381
|
+
"Maximum section hits per document. Omit to use "
|
|
382
|
+
".cairn/config.toml search_sections_per_doc."
|
|
383
|
+
),
|
|
384
|
+
},
|
|
385
|
+
"include": {
|
|
386
|
+
"type": "array",
|
|
387
|
+
"items": {"enum": ["synopsis", "head", "evidence"]},
|
|
388
|
+
"default": ["synopsis", "head", "evidence"],
|
|
389
|
+
"description": "Fields to attach to each cross-document hit.",
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
_REPO_CONTEXT_SCHEMA: Final[dict[str, Any]] = {
|
|
396
|
+
"type": "object",
|
|
397
|
+
"additionalProperties": False,
|
|
398
|
+
"required": ["query"],
|
|
399
|
+
"properties": {
|
|
400
|
+
"query": {
|
|
401
|
+
"type": "string",
|
|
402
|
+
"minLength": 1,
|
|
403
|
+
"description": (
|
|
404
|
+
"Conceptual query. Cairn returns a compact context pack with "
|
|
405
|
+
"ranked hits, selected section content, and a relationship map."
|
|
406
|
+
),
|
|
407
|
+
},
|
|
408
|
+
"k": {"type": "integer", "minimum": 1, "maximum": 32, "default": 5},
|
|
409
|
+
"sections_per_doc": {
|
|
410
|
+
"type": ["integer", "null"],
|
|
411
|
+
"minimum": 1,
|
|
412
|
+
"maximum": 8,
|
|
413
|
+
"default": None,
|
|
414
|
+
},
|
|
415
|
+
"related_k": {
|
|
416
|
+
"type": "integer",
|
|
417
|
+
"minimum": 0,
|
|
418
|
+
"maximum": 12,
|
|
419
|
+
"default": 3,
|
|
420
|
+
"description": "Related sections to attach per selected hit.",
|
|
421
|
+
},
|
|
422
|
+
"level": {
|
|
423
|
+
"enum": ["gist", "synopsis", "full"],
|
|
424
|
+
"default": "synopsis",
|
|
425
|
+
"description": "Content granularity for context_sections.",
|
|
426
|
+
},
|
|
427
|
+
"max_section_chars": {
|
|
428
|
+
"type": "integer",
|
|
429
|
+
"minimum": 200,
|
|
430
|
+
"maximum": 8000,
|
|
431
|
+
"default": 1600,
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
_REPO_GRAPH_SCHEMA: Final[dict[str, Any]] = {
|
|
438
|
+
"type": "object",
|
|
439
|
+
"additionalProperties": False,
|
|
440
|
+
"properties": {
|
|
441
|
+
"doc": {
|
|
442
|
+
"type": ["string", "null"],
|
|
443
|
+
"default": None,
|
|
444
|
+
"description": "Optional document id to restrict the graph.",
|
|
445
|
+
},
|
|
446
|
+
"max_sections": {
|
|
447
|
+
"type": "integer",
|
|
448
|
+
"minimum": 1,
|
|
449
|
+
"maximum": 500,
|
|
450
|
+
"default": 120,
|
|
451
|
+
},
|
|
452
|
+
"max_entities": {
|
|
453
|
+
"type": "integer",
|
|
454
|
+
"minimum": 0,
|
|
455
|
+
"maximum": 200,
|
|
456
|
+
"default": 40,
|
|
457
|
+
},
|
|
458
|
+
"include_entities": {"type": "boolean", "default": True},
|
|
459
|
+
"include_xrefs": {"type": "boolean", "default": True},
|
|
460
|
+
},
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
_REPO_IMPACT_SCHEMA: Final[dict[str, Any]] = {
|
|
465
|
+
"type": "object",
|
|
466
|
+
"additionalProperties": False,
|
|
467
|
+
"required": ["doc"],
|
|
468
|
+
"properties": {
|
|
469
|
+
"doc": {
|
|
470
|
+
"type": "string",
|
|
471
|
+
"minLength": 1,
|
|
472
|
+
"description": "Repository document id to inspect.",
|
|
473
|
+
},
|
|
474
|
+
"id": {
|
|
475
|
+
"type": ["string", "null"],
|
|
476
|
+
"default": None,
|
|
477
|
+
"description": (
|
|
478
|
+
"Optional section id. Omit for document-level impact; provide "
|
|
479
|
+
"for section-level impact."
|
|
480
|
+
),
|
|
481
|
+
},
|
|
482
|
+
"max_results": {
|
|
483
|
+
"type": "integer",
|
|
484
|
+
"minimum": 1,
|
|
485
|
+
"maximum": 100,
|
|
486
|
+
"default": 24,
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
REPO_TOOLS: Final[list[Tool]] = [
|
|
493
|
+
Tool(
|
|
494
|
+
name="list_documents",
|
|
495
|
+
annotations=_read_only("Cairn List Documents"),
|
|
496
|
+
description=(
|
|
497
|
+
"List repository documents known to Cairn and their index status. "
|
|
498
|
+
"Use this first when serving a repo-scoped Cairn index."
|
|
499
|
+
),
|
|
500
|
+
inputSchema=_LIST_DOCUMENTS_SCHEMA,
|
|
501
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
502
|
+
),
|
|
503
|
+
Tool(
|
|
504
|
+
name="search_documents",
|
|
505
|
+
annotations=_read_only("Cairn Search Documents"),
|
|
506
|
+
description=(
|
|
507
|
+
"Search across every indexed repository document and return globally "
|
|
508
|
+
"ranked section hits with doc ids. Use this before drilling into a "
|
|
509
|
+
"specific document."
|
|
510
|
+
),
|
|
511
|
+
inputSchema=_SEARCH_DOCUMENTS_SCHEMA,
|
|
512
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
513
|
+
),
|
|
514
|
+
Tool(
|
|
515
|
+
name="repo_context",
|
|
516
|
+
annotations=_read_only("Cairn Repo Context"),
|
|
517
|
+
description=(
|
|
518
|
+
"Composite repo retrieval: search across documents, attach compact "
|
|
519
|
+
"section content, explanations, related sections, and a relationship "
|
|
520
|
+
"map in one call. Use this when an agent needs ready-to-read context."
|
|
521
|
+
),
|
|
522
|
+
inputSchema=_REPO_CONTEXT_SCHEMA,
|
|
523
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
524
|
+
),
|
|
525
|
+
Tool(
|
|
526
|
+
name="repo_graph",
|
|
527
|
+
annotations=_read_only("Cairn Repo Graph"),
|
|
528
|
+
description=(
|
|
529
|
+
"Return a repository documentation relationship map with document, "
|
|
530
|
+
"section, entity, contains, xref, and mention edges. This is docs-only; "
|
|
531
|
+
"use CodeGraph for source-code AST graphs."
|
|
532
|
+
),
|
|
533
|
+
inputSchema=_REPO_GRAPH_SCHEMA,
|
|
534
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
535
|
+
),
|
|
536
|
+
Tool(
|
|
537
|
+
name="repo_impact",
|
|
538
|
+
annotations=_read_only("Cairn Repo Impact"),
|
|
539
|
+
description=(
|
|
540
|
+
"Estimate documentation surfaces affected by a document or section "
|
|
541
|
+
"change. This is docs graph impact, not code symbol impact."
|
|
542
|
+
),
|
|
543
|
+
inputSchema=_REPO_IMPACT_SCHEMA,
|
|
544
|
+
outputSchema=_ENVELOPE_OUTPUT_SCHEMA,
|
|
545
|
+
),
|
|
546
|
+
*[_repo_doc_tool(tool) for tool in CAIRN_TOOLS],
|
|
547
|
+
]
|