@deepwatch/dsh-tools 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/lib/browser.d.ts +38 -0
- package/lib/browser.js +299 -0
- package/lib/index.d.ts +129 -0
- package/lib/index.js +710 -0
- package/lib/library-generations.d.ts +107 -0
- package/lib/library-generations.js +227 -0
- package/lib/library-search.d.ts +143 -0
- package/lib/library-search.js +407 -0
- package/lib/memory.d.ts +23 -0
- package/lib/memory.js +96 -0
- package/lib/read-plane.d.ts +237 -0
- package/lib/read-plane.js +688 -0
- package/lib/receipt-journal.d.ts +101 -0
- package/lib/receipt-journal.js +246 -0
- package/lib/sensory.d.ts +48 -0
- package/lib/sensory.js +277 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +649 -0
- package/lib/typert.remote-client.d.ts +32 -0
- package/lib/typert.remote-client.d.ts.map +1 -0
- package/lib/typert.remote-client.js +405 -0
- package/package.json +83 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The read plane, host side: what a Watch mode asks, answered.
|
|
3
|
+
*
|
|
4
|
+
* A `conversation.view` entry is handed `{ inspect, onInspectDone }` and
|
|
5
|
+
* nothing else, so Live, Memory, Library and Compare had no way to obtain
|
|
6
|
+
* their own data. This is the other end of the seam that fixes that, and it is
|
|
7
|
+
* DSH's own: a Typert Remote, dispatched through the Gateway that already
|
|
8
|
+
* owns request correlation, abort signals and structured failure. The client
|
|
9
|
+
* calls `ctx.remote.watchQuery.librarySearch(request, signal)` or
|
|
10
|
+
* `.libraryGet(request, signal)` and awaits a `RemoteResult` carrying one of
|
|
11
|
+
* the concrete outcomes in `@deepwatch/dsh-contracts/query/wire`.
|
|
12
|
+
*
|
|
13
|
+
* One method per read, rather than one `read` over a discriminated union. DSH
|
|
14
|
+
* already routes by method, so a union inside a single entry point would be a
|
|
15
|
+
* second router with its own schema to generate.
|
|
16
|
+
*
|
|
17
|
+
* It reads the same `LibraryIndex` the `watch_library_search` tool reads. One
|
|
18
|
+
* index, one set of semantics, one place where "every term must match" is
|
|
19
|
+
* decided -- two would drift inside a release and disagree about what the
|
|
20
|
+
* library contains, and the disagreement would surface as a person searching
|
|
21
|
+
* the UI and the agent searching the tool getting different answers to the
|
|
22
|
+
* same question.
|
|
23
|
+
*
|
|
24
|
+
* Four things it will not do.
|
|
25
|
+
*
|
|
26
|
+
* It performs no write. Every operation answers a question, and the request
|
|
27
|
+
* union has no member that changes anything, so a surface cannot acquire a
|
|
28
|
+
* side effect and captured or model-generated content reaching these fields
|
|
29
|
+
* cannot become an action.
|
|
30
|
+
*
|
|
31
|
+
* It reads nothing the caller names. Parameters are identifiers from a charset
|
|
32
|
+
* with no separator or colon; the roots come from configuration. A caller
|
|
33
|
+
* cannot point this at a path.
|
|
34
|
+
*
|
|
35
|
+
* It answers within the deadline it was given, or refuses. A slow host must
|
|
36
|
+
* not become a hung surface, and the timer is cleared on every exit so a
|
|
37
|
+
* completed read leaves nothing behind.
|
|
38
|
+
*
|
|
39
|
+
* And it never reports a partial answer as a whole one. A rebuilding or stale
|
|
40
|
+
* index answers `complete: false` with what it has, because a search that
|
|
41
|
+
* quietly returns less than it should is worse than one that says it is
|
|
42
|
+
* behind.
|
|
43
|
+
*
|
|
44
|
+
* @module @deepwatch/dsh-tools/read-plane
|
|
45
|
+
*/
|
|
46
|
+
import { type Context } from '@deepseek-ai/cordis';
|
|
47
|
+
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
48
|
+
import type { LibraryIndex } from '@deepwatch/dsh-library';
|
|
49
|
+
import type { CoreHealthRequest, CoreHealthResponse, LibraryGetRequest, LibraryGetResponse, LibraryRefreshRequest, LibraryRefreshResponse, LibraryIndexState, LibrarySearchRequest, LibrarySearchResponse, ProviderTestRequest, ProviderTestResponse, RouteReadinessRequest, RouteReadinessResponse } from '@deepwatch/dsh-contracts/query/wire';
|
|
50
|
+
import type { LibraryGenerations } from './library-generations.js';
|
|
51
|
+
/** What the read plane needs from its host. */
|
|
52
|
+
export interface ReadPlaneConfig {
|
|
53
|
+
/**
|
|
54
|
+
* The index to read, built and cached by whoever owns it.
|
|
55
|
+
*
|
|
56
|
+
* A function rather than a value so a rebuild behind the tool is visible
|
|
57
|
+
* here without either side holding a reference to a stale object.
|
|
58
|
+
*/
|
|
59
|
+
readonly index: () => LibraryIndex;
|
|
60
|
+
/**
|
|
61
|
+
* Which workspace this host is answering for.
|
|
62
|
+
*
|
|
63
|
+
* Cursors are bound to it, so one issued here cannot be replayed against
|
|
64
|
+
* another workspace's snapshot.
|
|
65
|
+
*/
|
|
66
|
+
readonly scope: string;
|
|
67
|
+
/**
|
|
68
|
+
* The one thing allowed to replace the index, when the host has one.
|
|
69
|
+
*
|
|
70
|
+
* Optional because a deployment may compose the read plane over an index it
|
|
71
|
+
* owns by other means. Where it is absent, `libraryRefresh` still exists and
|
|
72
|
+
* answers `refresh_failed` with a reason — which is what a surface should
|
|
73
|
+
* render, rather than a refresh that appears to work and changes nothing.
|
|
74
|
+
*/
|
|
75
|
+
readonly generations?: LibraryGenerations;
|
|
76
|
+
}
|
|
77
|
+
/** Flatten one search result into the shape a surface renders. */
|
|
78
|
+
/**
|
|
79
|
+
* The service key, on the Context both faces share.
|
|
80
|
+
*
|
|
81
|
+
* This is not documentation. Typert analyses a package's public export graph
|
|
82
|
+
* and binds a Remote through the Cordis Context declaration; without this the
|
|
83
|
+
* service is discovered as a package and emits no artifact, because nothing
|
|
84
|
+
* ties `WatchQueryService` to the key `watchQuery` that the Gateway exposes as
|
|
85
|
+
* `ctx.remote.watchQuery`.
|
|
86
|
+
*/
|
|
87
|
+
declare module '@deepseek-ai/cordis' {
|
|
88
|
+
interface Context {
|
|
89
|
+
watchQuery: WatchQueryService;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The Typert Remote a Watch surface calls.
|
|
94
|
+
*
|
|
95
|
+
* `watchQuery` is both the Cordis service key and the wire namespace, so the
|
|
96
|
+
* client reaches it as `ctx.remote.watchQuery`.
|
|
97
|
+
*/
|
|
98
|
+
export declare class WatchQueryService extends TypertRemoteService {
|
|
99
|
+
/**
|
|
100
|
+
* Deliberately not a `#private` field.
|
|
101
|
+
*
|
|
102
|
+
* Cordis hands a Service to callers through a Proxy, and a private field is
|
|
103
|
+
* unreachable through one: the Gateway invoked this method and got
|
|
104
|
+
* "Cannot read private member #config from an object whose class did not
|
|
105
|
+
* declare it". Every direct unit test passed, because a direct call has no
|
|
106
|
+
* proxy in front of it -- which is the whole argument for exercising this
|
|
107
|
+
* through the real Gateway.
|
|
108
|
+
*/
|
|
109
|
+
readonly config: ReadPlaneConfig;
|
|
110
|
+
constructor(ctx: Context, config: ReadPlaneConfig);
|
|
111
|
+
/**
|
|
112
|
+
* One concrete method per read, rather than one `read` over a union.
|
|
113
|
+
*
|
|
114
|
+
* DSH already routes by method, so a discriminated union inside a single
|
|
115
|
+
* entry point would be a second router with its own schema to generate.
|
|
116
|
+
* One request type and one response type per method is what Typert emits
|
|
117
|
+
* a strict codec from most directly.
|
|
118
|
+
*
|
|
119
|
+
* `signal` is last, as Typert requires, and is not serialised.
|
|
120
|
+
*/
|
|
121
|
+
librarySearch(request: LibrarySearchRequest, signal: AbortSignal): Promise<LibrarySearchResponse>;
|
|
122
|
+
/** One record by id. A direct lookup, not a one-result search. */
|
|
123
|
+
libraryGet(request: LibraryGetRequest, signal: AbortSignal): Promise<LibraryGetResponse>;
|
|
124
|
+
/**
|
|
125
|
+
* Read the roots again, and put the result into service if it is healthy.
|
|
126
|
+
*
|
|
127
|
+
* The only method here with a side effect, and the only one that is not a
|
|
128
|
+
* question. It is a separate method for exactly that reason: a `rebuild`
|
|
129
|
+
* flag on `librarySearch` would make every search a potential re-read of the
|
|
130
|
+
* corpus, and would leave a caller no way to ask for an answer from what the
|
|
131
|
+
* host already has.
|
|
132
|
+
*
|
|
133
|
+
* Genuinely async, unlike its siblings: the rebuild yields between files so
|
|
134
|
+
* a caller that stops waiting can be observed doing so.
|
|
135
|
+
*/
|
|
136
|
+
libraryRefresh(request: LibraryRefreshRequest, signal: AbortSignal): Promise<LibraryRefreshResponse>;
|
|
137
|
+
/**
|
|
138
|
+
* What Watch Core is doing right now, read from the running Bridge.
|
|
139
|
+
*
|
|
140
|
+
* The one method here that is not about the Library, and it is here because
|
|
141
|
+
* this is the only channel the browser has to the Host. Diagnostics used to
|
|
142
|
+
* render "Connected over stdio" and a version number as literals in a
|
|
143
|
+
* component, because there was nowhere to read them from.
|
|
144
|
+
*
|
|
145
|
+
* Nothing is defaulted. A value the Bridge has not established is `null`,
|
|
146
|
+
* and the panel renders that as "not reported" -- which is worth less than a
|
|
147
|
+
* real reading and far more than a confident wrong one.
|
|
148
|
+
*/
|
|
149
|
+
coreHealth(request: CoreHealthRequest, signal: AbortSignal): Promise<CoreHealthResponse>;
|
|
150
|
+
/** Spend one deliberately tiny provider request only after a person asks. */
|
|
151
|
+
providerTest(request: ProviderTestRequest, signal: AbortSignal): Promise<ProviderTestResponse>;
|
|
152
|
+
/**
|
|
153
|
+
* Whether the Host would serve this route right now, asked without spending
|
|
154
|
+
* anything.
|
|
155
|
+
*
|
|
156
|
+
* The browser half used to answer this from its own memory of a provider
|
|
157
|
+
* test it had run, which is a claim about a Host it cannot see. A tab that
|
|
158
|
+
* stayed open across a Host restart, or across an edit made in another tab,
|
|
159
|
+
* kept drawing a tested badge over a route the Host had already stopped
|
|
160
|
+
* being willing to serve — and the composer it gates opened onto a refusal.
|
|
161
|
+
* There is one answer, and this is where it is read from.
|
|
162
|
+
*/
|
|
163
|
+
routeReadiness(request: RouteReadinessRequest, signal: AbortSignal): Promise<RouteReadinessResponse>;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Read the Host's verdict for one route.
|
|
167
|
+
*
|
|
168
|
+
* No network, no provider, no credential. When the provenance row is not
|
|
169
|
+
* composed the honest answer is that nothing here can say, which reads as
|
|
170
|
+
* unproved — the same direction the guard fails in.
|
|
171
|
+
*/
|
|
172
|
+
export declare function readRouteReadiness(request: RouteReadinessRequest, ctx: Context): RouteReadinessResponse;
|
|
173
|
+
/** Execute a provider request without returning or logging model output. */
|
|
174
|
+
export declare function testProvider(request: ProviderTestRequest, ctx: Context, signal: AbortSignal): Promise<ProviderTestResponse>;
|
|
175
|
+
/** Route a parsed request to the namespace that answers it. */
|
|
176
|
+
/** Answer a Library read from the index the tool already owns. */
|
|
177
|
+
/** Assemble a snapshot, and say honestly whether it is whole. */
|
|
178
|
+
/** Install the read plane onto a host context. */
|
|
179
|
+
export declare function applyReadPlane(ctx: Context, config: ReadPlaneConfig): void;
|
|
180
|
+
/**
|
|
181
|
+
* Answer a Library search against the shared index.
|
|
182
|
+
*
|
|
183
|
+
* Separate from the Service so the whole path is testable without a DSH
|
|
184
|
+
* runtime, and so the Service stays a Typert adapter with no decisions in it.
|
|
185
|
+
*/
|
|
186
|
+
export declare function searchLibrary(request: LibrarySearchRequest, config: ReadPlaneConfig, signal: AbortSignal): LibrarySearchResponse;
|
|
187
|
+
/**
|
|
188
|
+
* The wire state for one index, without collapsing four answers into two.
|
|
189
|
+
*
|
|
190
|
+
* The defect this replaces was a single conditional: anything that was not
|
|
191
|
+
* `ready` became `stale`, so an index over an empty store reported "Index is
|
|
192
|
+
* behind the store". A person looking at a fresh profile was told their
|
|
193
|
+
* Library was out of date with respect to nothing, and the only honest reading
|
|
194
|
+
* of that screen — something is wrong — was the wrong one.
|
|
195
|
+
*
|
|
196
|
+
* `empty` and `stale` are opposite claims. Empty says the index agrees with a
|
|
197
|
+
* store that holds nothing. Stale says the store moved and the index has not
|
|
198
|
+
* caught up. Reporting the first as the second turns "there is nothing here
|
|
199
|
+
* yet" into "you are missing something", which is the difference between a
|
|
200
|
+
* quiet first run and a bug report.
|
|
201
|
+
*/
|
|
202
|
+
export declare function wireIndexState(health: LibraryIndex['health'], size: number): LibraryIndexState;
|
|
203
|
+
/**
|
|
204
|
+
* Answer a Library get.
|
|
205
|
+
*
|
|
206
|
+
* `index.record()` is a keyed lookup. Implementing this as a search with
|
|
207
|
+
* `limit: 1` and then checking whether the single result happened to be the
|
|
208
|
+
* requested id reports every record except the top-ranked one as absent.
|
|
209
|
+
*/
|
|
210
|
+
export declare function getLibraryRecord(request: LibraryGetRequest, config: ReadPlaneConfig, signal: AbortSignal): LibraryGetResponse;
|
|
211
|
+
/**
|
|
212
|
+
* Rebuild the index, and say what happened to the one already in service.
|
|
213
|
+
*
|
|
214
|
+
* Every outcome leaves a searchable Library, which is why none of them is an
|
|
215
|
+
* exception. A refusal, an elapsed deadline, an abandoned rebuild and a failed
|
|
216
|
+
* one are four different facts, and a surface renders each differently.
|
|
217
|
+
*
|
|
218
|
+
* Separate from the Service for the same reason the reads are: the Service
|
|
219
|
+
* stays a Typert adapter with no decisions in it, and the whole path is
|
|
220
|
+
* testable without a DSH runtime.
|
|
221
|
+
*/
|
|
222
|
+
export declare function refreshLibrary(request: LibraryRefreshRequest, config: ReadPlaneConfig, signal: AbortSignal): Promise<LibraryRefreshResponse>;
|
|
223
|
+
/**
|
|
224
|
+
* Read the Bridge's live state, and say honestly where it could not.
|
|
225
|
+
*
|
|
226
|
+
* Separate from the Service for the same reason the Library readers are: the
|
|
227
|
+
* Service is a Typert adapter with no decisions in it, and the whole path is
|
|
228
|
+
* testable without a DSH runtime.
|
|
229
|
+
*
|
|
230
|
+
* The rule this function exists to keep: **no field is defaulted.** A version
|
|
231
|
+
* the Bridge has never received is `null`, not `'unknown'` and not the version
|
|
232
|
+
* this build was compiled against. Diagnostics is the screen people open when
|
|
233
|
+
* they already suspect something is wrong, and it is the last place a
|
|
234
|
+
* plausible substitute belongs.
|
|
235
|
+
*/
|
|
236
|
+
export declare function readCoreHealth(request: CoreHealthRequest, ctx: Context, signal: AbortSignal): CoreHealthResponse;
|
|
237
|
+
//# sourceMappingURL=read-plane.d.ts.map
|