Repository navigation
Expand file tree
/
Copy pathxerj.proto
More file actions
162 lines (143 loc) · 4.95 KB
/
Copy pathxerj.proto
File metadata and controls
162 lines (143 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
syntax = "proto3";
package xerj.v1;
service XerjSearch {
rpc Search(SearchRequest) returns (SearchResponse);
rpc Index(IndexRequest) returns (IndexResponse);
rpc BulkIndex(stream IndexRequest) returns (BulkResponse);
rpc GetDocument(GetRequest) returns (GetResponse);
rpc DeleteDocument(DeleteRequest) returns (DeleteResponse);
rpc Health(HealthRequest) returns (HealthResponse);
}
message SearchRequest {
string index = 1;
string query_json = 2; // ES-compatible query DSL as JSON
int32 size = 3;
int32 from = 4;
}
message SearchResponse {
int64 total_hits = 1;
repeated Hit hits = 2;
int64 took_ms = 3;
bool timed_out = 4;
}
message Hit {
string id = 1;
float score = 2;
string source_json = 3;
string index = 4;
}
message IndexRequest {
string index = 1;
string id = 2;
string source_json = 3;
}
message IndexResponse {
string id = 1;
int64 version = 2;
string result = 3;
}
message BulkResponse {
int64 took_ms = 1;
bool errors = 2;
int32 indexed = 3;
}
message GetRequest {
string index = 1;
string id = 2;
}
message GetResponse {
bool found = 1;
string id = 2;
string source_json = 3;
int64 version = 4;
}
message DeleteRequest {
string index = 1;
string id = 2;
}
message DeleteResponse {
string result = 1;
}
message HealthRequest {}
message HealthResponse {
string status = 1;
int32 num_indices = 2;
int64 total_docs = 3;
}
// ===========================================================================
// Corpus Hub v2 — pack query surface (discussion #1374).
//
// Contract locked by docs/CORPUS_HUB_V2_IMPLEMENTATION.md §7. The messages
// mirror the shared Rust types in engine/crates/xerj-common/src/hub.rs
// (`Answer`, `Hit`) one-to-one so gRPC, the MCP tools and the CLI speak one
// vocabulary. Both gRPC and MCP must call `xerj_hub::ask`/`def` rather than
// reimplement the flow — see docs/hub-v2-grpc-mcp-notes.md for the field
// mapping and the MCP tool specs.
//
// FIELD NUMBERS ARE PERMANENT. They are fixed by §7 and §11 ("do not …
// renumber proto fields") of the plan: once this lands they must never be
// renumbered, reused, or repurposed — this is a wire contract. Each message
// below records its live field-number range in a comment; new fields may only
// be appended with the next free number.
//
// The service trait and client are generated by build.rs (tonic/prost); the
// server impl is engine/crates/xerj-server/src/grpc_hub.rs, registered in
// grpc.rs next to XerjSearch behind the same interceptor.
// ===========================================================================
service XerjHub {
rpc Ask(HubAskRequest) returns (HubAnswer);
rpc Def(HubDefRequest) returns (HubAnswer);
rpc Catalogue(HubCatalogueRequest) returns (HubCatalogueResponse);
}
// Fields 1-4 (permanent). The corpus is never required in the question; when
// `corpus` is empty the sketch router picks it. `mode` is empty for auto.
message HubAskRequest {
string question = 1; // natural-language question
string corpus = 2; // optional explicit corpus slug; "" = route by sketch
string mode = 3; // "def" | "how" | "files"; "" = auto
uint32 max_tokens = 4; // soft output budget; 0 = default
}
// Fields 1-3 (permanent).
message HubDefRequest {
string slug = 1; // corpus slug to resolve the symbol in
string symbol = 2; // exact definition name
uint32 k = 3; // max hits; 0 = default
}
// No fields (permanent). A catalogue fetch takes no arguments.
message HubCatalogueRequest {}
// Fields 1-2 (permanent). `catalogue_json` is the serialized `Catalogue`
// (hub.rs) as the exact bytes the signature covers.
message HubCatalogueResponse {
bytes catalogue_json = 1; // serialized `Catalogue`, verbatim signed bytes
bytes signature = 2; // ed25519 signature over catalogue_json
}
// Fields 1-7 (permanent). Mirror of hub.rs `Hit`. Rust `value` and
// `licence_warning` are `Option<String>`; proto3 has no null, so `None` maps
// to the empty string "".
message HubHit {
string file = 1;
uint32 line = 2;
string kind = 3;
string text = 4;
string value = 5; // Rust Option<String>; None -> ""
float score = 6;
string licence_warning = 7; // Rust Option<String>; None -> ""
}
// Fields 1-11 (permanent). Mirror of hub.rs `Answer`. The enum fields carry the
// serde string forms of the Rust enums: `licence_class` is LicenceClass
// kebab-case ("adapt-with-attribution" | "approach-only" | "excluded"),
// `answered_from` is AnsweredFrom snake_case ("local_pack" | "hosted" |
// "local_index"), `mode` is AnswerMode snake_case ("def" | "how" | "files").
message HubAnswer {
string corpus = 1;
string pin_sha = 2;
string pin_date = 3;
uint32 age_days = 4;
string licence_spdx = 5;
string licence_class = 6; // LicenceClass serde kebab-case
string answered_from = 7; // AnsweredFrom serde snake_case
string mode = 8; // AnswerMode serde snake_case
repeated HubHit hits = 9;
bool truncated = 10;
repeated string warnings = 11;
}