@gmickel/gno 1.17.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -4
- package/assets/skill/SKILL.md +44 -1
- package/assets/skill/mcp-reference.md +21 -0
- package/package.json +3 -2
- package/spec/AGENTS.md +83 -0
- package/spec/CLAUDE.md +83 -0
- package/spec/bench-fixture.schema.json +137 -0
- package/spec/cli.md +2894 -0
- package/spec/db/schema.sql +442 -0
- package/spec/evals-agentic.md +510 -0
- package/spec/evals.md +1106 -0
- package/spec/mcp.md +2229 -0
- package/spec/output-schemas/activation-verification.schema.json +515 -0
- package/spec/output-schemas/ask.schema.json +366 -0
- package/spec/output-schemas/backlinks.schema.json +131 -0
- package/spec/output-schemas/bench-result.schema.json +120 -0
- package/spec/output-schemas/capture-receipt.schema.json +143 -0
- package/spec/output-schemas/collection-list.schema.json +45 -0
- package/spec/output-schemas/context-capsule-v1.schema.json +691 -0
- package/spec/output-schemas/context-capsule-verification.schema.json +1338 -0
- package/spec/output-schemas/context-list.schema.json +21 -0
- package/spec/output-schemas/doctor.schema.json +313 -0
- package/spec/output-schemas/error.schema.json +30 -0
- package/spec/output-schemas/expansion.schema.json +37 -0
- package/spec/output-schemas/get.schema.json +140 -0
- package/spec/output-schemas/graph-query.schema.json +99 -0
- package/spec/output-schemas/graph.schema.json +371 -0
- package/spec/output-schemas/links-list.schema.json +186 -0
- package/spec/output-schemas/mcp-add-collection-result.schema.json +23 -0
- package/spec/output-schemas/mcp-capture-result.schema.json +152 -0
- package/spec/output-schemas/mcp-http-error.schema.json +30 -0
- package/spec/output-schemas/mcp-job-list.schema.json +58 -0
- package/spec/output-schemas/mcp-job-status.schema.json +224 -0
- package/spec/output-schemas/mcp-remove-result.schema.json +39 -0
- package/spec/output-schemas/mcp-sync-result.schema.json +41 -0
- package/spec/output-schemas/mcp-tag-result.schema.json +33 -0
- package/spec/output-schemas/models-list.schema.json +93 -0
- package/spec/output-schemas/multi-get.schema.json +103 -0
- package/spec/output-schemas/process-status.schema.json +119 -0
- package/spec/output-schemas/query-diagnose.schema.json +123 -0
- package/spec/output-schemas/resident-status.schema.json +154 -0
- package/spec/output-schemas/retrieval-trace-common.schema.json +492 -0
- package/spec/output-schemas/retrieval-trace-delete.schema.json +16 -0
- package/spec/output-schemas/retrieval-trace-export.schema.json +61 -0
- package/spec/output-schemas/retrieval-trace-filters.schema.json +139 -0
- package/spec/output-schemas/retrieval-trace-judgment.schema.json +15 -0
- package/spec/output-schemas/retrieval-trace-list.schema.json +18 -0
- package/spec/output-schemas/retrieval-trace-payloads.schema.json +178 -0
- package/spec/output-schemas/retrieval-trace-purge.schema.json +31 -0
- package/spec/output-schemas/retrieval-trace-qrels.schema.json +303 -0
- package/spec/output-schemas/retrieval-trace-replay.schema.json +286 -0
- package/spec/output-schemas/retrieval-trace-show.schema.json +69 -0
- package/spec/output-schemas/retrieval-trace-summary.schema.json +65 -0
- package/spec/output-schemas/search-result.schema.json +154 -0
- package/spec/output-schemas/search-results.schema.json +338 -0
- package/spec/output-schemas/similar.schema.json +84 -0
- package/spec/output-schemas/status.schema.json +676 -0
- package/spec/output-schemas/tags-list.schema.json +48 -0
- package/src/app/context-runtime-types.ts +3 -0
- package/src/app/context-runtime.ts +15 -1
- package/src/cli/commands/ask.ts +106 -36
- package/src/cli/commands/context-build.ts +56 -9
- package/src/cli/commands/daemon.ts +69 -2
- package/src/cli/commands/get.ts +64 -3
- package/src/cli/commands/models/pull.ts +13 -3
- package/src/cli/commands/query.ts +62 -23
- package/src/cli/commands/replay.ts +140 -0
- package/src/cli/commands/search.ts +48 -3
- package/src/cli/commands/shared.ts +3 -1
- package/src/cli/commands/status.ts +2 -0
- package/src/cli/commands/trace.ts +200 -0
- package/src/cli/commands/vsearch.ts +75 -53
- package/src/cli/detach.ts +37 -20
- package/src/cli/program.ts +329 -27
- package/src/config/index.ts +12 -0
- package/src/config/retrieval-traces.ts +56 -0
- package/src/config/types.ts +41 -0
- package/src/core/context-compiler.ts +11 -4
- package/src/core/job-manager.ts +19 -0
- package/src/core/mutation-generations.ts +33 -0
- package/src/core/retrieval-qrels.ts +405 -0
- package/src/core/retrieval-replay-candidate.ts +368 -0
- package/src/core/retrieval-replay-types.ts +109 -0
- package/src/core/retrieval-replay-validation.ts +89 -0
- package/src/core/retrieval-replay.ts +441 -0
- package/src/core/retrieval-trace-evidence-origin.ts +175 -0
- package/src/core/retrieval-trace-export.ts +113 -0
- package/src/core/retrieval-trace-filter-normalization.ts +27 -0
- package/src/core/retrieval-trace-filters.ts +19 -0
- package/src/core/retrieval-trace-management-helpers.ts +247 -0
- package/src/core/retrieval-trace-management-types.ts +132 -0
- package/src/core/retrieval-trace-management.ts +422 -0
- package/src/core/retrieval-trace-request.ts +141 -0
- package/src/core/retrieval-trace-session.ts +494 -0
- package/src/core/retrieval-trace.ts +472 -0
- package/src/llm/cache.ts +13 -3
- package/src/llm/nodeLlamaCpp/adapter.ts +10 -1
- package/src/llm/nodeLlamaCpp/lifecycle.ts +71 -0
- package/src/mcp/context.ts +161 -0
- package/src/mcp/http-security.ts +477 -0
- package/src/mcp/http-session.ts +272 -0
- package/src/mcp/http-transport.ts +370 -0
- package/src/mcp/resources/index.ts +141 -134
- package/src/mcp/server.ts +19 -79
- package/src/mcp/tools/add-collection.ts +3 -1
- package/src/mcp/tools/capture.ts +3 -0
- package/src/mcp/tools/clear-collection-embeddings.ts +2 -0
- package/src/mcp/tools/context.ts +68 -16
- package/src/mcp/tools/embed.ts +62 -52
- package/src/mcp/tools/get.ts +35 -1
- package/src/mcp/tools/index-cmd.ts +88 -74
- package/src/mcp/tools/index.ts +96 -2
- package/src/mcp/tools/query.ts +95 -64
- package/src/mcp/tools/remove-collection.ts +2 -0
- package/src/mcp/tools/search.ts +36 -13
- package/src/mcp/tools/status.ts +11 -0
- package/src/mcp/tools/sync.ts +16 -14
- package/src/mcp/tools/trace.ts +143 -0
- package/src/mcp/tools/vsearch.ts +71 -38
- package/src/mcp/tools/workspace-write.ts +7 -3
- package/src/pipeline/answer.ts +167 -26
- package/src/pipeline/graph-retrieval.ts +15 -1
- package/src/pipeline/hybrid.ts +151 -43
- package/src/pipeline/search.ts +36 -3
- package/src/pipeline/trace-metadata.ts +47 -0
- package/src/pipeline/types.ts +43 -0
- package/src/pipeline/vsearch.ts +101 -38
- package/src/sdk/client.ts +380 -71
- package/src/sdk/documents.ts +48 -1
- package/src/sdk/index.ts +17 -0
- package/src/sdk/types.ts +28 -0
- package/src/serve/background-runtime.ts +12 -212
- package/src/serve/context-capsule.ts +67 -8
- package/src/serve/embed-scheduler.ts +74 -43
- package/src/serve/index.ts +9 -0
- package/src/serve/jobs.ts +78 -80
- package/src/serve/public/app.tsx +12 -1
- package/src/serve/public/components/HealthCenter.tsx +74 -1
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/workspace-tabs.ts +2 -0
- package/src/serve/public/pages/Dashboard.tsx +11 -0
- package/src/serve/public/pages/TraceHistory.tsx +478 -0
- package/src/serve/public/pages/trace-history-detail.tsx +224 -0
- package/src/serve/resident-admission.ts +159 -0
- package/src/serve/resident-background-work.ts +39 -0
- package/src/serve/resident-request.ts +55 -0
- package/src/serve/resident-runtime.ts +490 -0
- package/src/serve/resident-status.ts +96 -0
- package/src/serve/retrieval-trace.ts +28 -0
- package/src/serve/routes/api.ts +629 -239
- package/src/serve/routes/mcp.ts +69 -0
- package/src/serve/routes/traces.ts +156 -0
- package/src/serve/server.ts +276 -37
- package/src/serve/status-model.ts +51 -0
- package/src/serve/status.ts +5 -0
- package/src/store/index.ts +31 -0
- package/src/store/migrations/014-retrieval-traces.ts +303 -0
- package/src/store/migrations/index.ts +2 -0
- package/src/store/retrieval-trace-codec.ts +384 -0
- package/src/store/sqlite/adapter.ts +179 -10
- package/src/store/sqlite/retrieval-trace-management-store.ts +341 -0
- package/src/store/sqlite/retrieval-trace-retention.ts +349 -0
- package/src/store/sqlite/retrieval-trace-rows.ts +267 -0
- package/src/store/sqlite/retrieval-trace-store.ts +515 -0
- package/src/store/types.ts +297 -0
- package/src/store/vector/sqlite-vec.ts +76 -1
- package/src/store/vector/types.ts +1 -1
package/src/serve/server.ts
CHANGED
|
@@ -6,13 +6,20 @@
|
|
|
6
6
|
* @module src/serve/server
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { HttpGatewayOverrides } from "../mcp/http-security";
|
|
10
|
+
import type { ResidentRuntime } from "./resident-runtime";
|
|
9
11
|
import type { ContextHolder } from "./routes/api";
|
|
10
12
|
|
|
13
|
+
import {
|
|
14
|
+
isHttpGatewayLoopbackBind,
|
|
15
|
+
resolveHttpGatewayConfig,
|
|
16
|
+
} from "../mcp/http-security";
|
|
11
17
|
import { startBackgroundRuntime } from "./background-runtime";
|
|
12
18
|
import { handleContextBuild, handleContextVerify } from "./context-capsule";
|
|
13
19
|
import { DocumentEventBus } from "./doc-events";
|
|
14
20
|
// HTML import - Bun handles bundling TSX/CSS automatically via routes
|
|
15
21
|
import homepage from "./public/index.html";
|
|
22
|
+
import { handleResidentRead } from "./resident-request";
|
|
16
23
|
import {
|
|
17
24
|
handleActiveJob,
|
|
18
25
|
handleAsk,
|
|
@@ -49,6 +56,7 @@ import {
|
|
|
49
56
|
handleQuery,
|
|
50
57
|
handleQueryDiagnose,
|
|
51
58
|
handleRefactorPlan,
|
|
59
|
+
handleResidentStatus,
|
|
52
60
|
handleRenameDoc,
|
|
53
61
|
handleRevealDoc,
|
|
54
62
|
handleSearch,
|
|
@@ -67,9 +75,18 @@ import {
|
|
|
67
75
|
handleDocLinks,
|
|
68
76
|
handleDocSimilar,
|
|
69
77
|
} from "./routes/links";
|
|
78
|
+
import { createMcpHttpGateway } from "./routes/mcp";
|
|
79
|
+
import {
|
|
80
|
+
handleTraceDelete,
|
|
81
|
+
handleTraceExport,
|
|
82
|
+
handleTraceLabel,
|
|
83
|
+
handleTraceList,
|
|
84
|
+
handleTracePurge,
|
|
85
|
+
handleTraceShow,
|
|
86
|
+
} from "./routes/traces";
|
|
70
87
|
import { forbiddenResponse, isRequestAllowed } from "./security";
|
|
71
88
|
|
|
72
|
-
export interface ServeOptions {
|
|
89
|
+
export interface ServeOptions extends HttpGatewayOverrides {
|
|
73
90
|
/** Port to listen on (default: 3000) */
|
|
74
91
|
port?: number;
|
|
75
92
|
/** Config path override */
|
|
@@ -85,8 +102,14 @@ export interface ServeResult {
|
|
|
85
102
|
|
|
86
103
|
interface StartServerDependencies {
|
|
87
104
|
startBackgroundRuntime?: typeof startBackgroundRuntime;
|
|
105
|
+
createMcpHttpGateway?: typeof createMcpHttpGateway;
|
|
88
106
|
serve?: typeof Bun.serve;
|
|
89
107
|
handleInstallConnector?: typeof handleInstallConnector;
|
|
108
|
+
handleDocs?: typeof handleDocs;
|
|
109
|
+
handleVerifyConnector?: typeof handleVerifyConnector;
|
|
110
|
+
handleImportPreview?: typeof handleImportPreview;
|
|
111
|
+
handlePublishExport?: typeof handlePublishExport;
|
|
112
|
+
handleRefactorPlan?: typeof handleRefactorPlan;
|
|
90
113
|
waitForShutdown?: (signal: AbortSignal) => Promise<void>;
|
|
91
114
|
}
|
|
92
115
|
|
|
@@ -152,6 +175,7 @@ export async function startServer(
|
|
|
152
175
|
const runtimeResult = await (
|
|
153
176
|
dependencies.startBackgroundRuntime ?? startBackgroundRuntime
|
|
154
177
|
)({
|
|
178
|
+
mode: "serve",
|
|
155
179
|
configPath: options.configPath,
|
|
156
180
|
index: options.index,
|
|
157
181
|
requireCollections: false,
|
|
@@ -163,6 +187,35 @@ export async function startServer(
|
|
|
163
187
|
const runtime = runtimeResult.runtime;
|
|
164
188
|
const store = runtime.store;
|
|
165
189
|
const ctxHolder: ContextHolder = runtime.ctxHolder;
|
|
190
|
+
const gatewayConfig = resolveHttpGatewayConfig(runtime.config.gateway, {
|
|
191
|
+
host: options.host,
|
|
192
|
+
port,
|
|
193
|
+
tokenFile: options.tokenFile,
|
|
194
|
+
allowedHosts: options.allowedHosts,
|
|
195
|
+
allowedOrigins: options.allowedOrigins,
|
|
196
|
+
enableWrite: options.enableWrite,
|
|
197
|
+
});
|
|
198
|
+
if (!isHttpGatewayLoopbackBind(gatewayConfig.host)) {
|
|
199
|
+
await runtime.dispose();
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
error:
|
|
203
|
+
"gno serve remains loopback-only because Web and REST share its listener; use gno daemon for authenticated non-loopback MCP",
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
let gateway: Awaited<ReturnType<typeof createMcpHttpGateway>>;
|
|
207
|
+
try {
|
|
208
|
+
gateway = await (dependencies.createMcpHttpGateway ?? createMcpHttpGateway)(
|
|
209
|
+
runtime as ResidentRuntime,
|
|
210
|
+
gatewayConfig
|
|
211
|
+
);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
await runtime.dispose();
|
|
214
|
+
return {
|
|
215
|
+
success: false,
|
|
216
|
+
error: error instanceof Error ? error.message : String(error),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
166
219
|
|
|
167
220
|
// Shutdown controller for clean lifecycle
|
|
168
221
|
const shutdownController = new AbortController();
|
|
@@ -185,13 +238,14 @@ export async function startServer(
|
|
|
185
238
|
try {
|
|
186
239
|
server = (dependencies.serve ?? Bun.serve)({
|
|
187
240
|
port,
|
|
188
|
-
hostname:
|
|
241
|
+
hostname: gatewayConfig.host,
|
|
189
242
|
|
|
190
243
|
// Enable development mode for HMR and console logging
|
|
191
244
|
development: isDev,
|
|
192
245
|
|
|
193
246
|
// Static routes - Bun handles HTML bundling and /_bun/* assets automatically
|
|
194
247
|
routes: {
|
|
248
|
+
"/mcp": gateway.route,
|
|
195
249
|
// SPA routes - all serve the same React app
|
|
196
250
|
"/": homepage,
|
|
197
251
|
"/search": homepage,
|
|
@@ -200,6 +254,7 @@ export async function startServer(
|
|
|
200
254
|
"/edit": homepage,
|
|
201
255
|
"/collections": homepage,
|
|
202
256
|
"/connectors": homepage,
|
|
257
|
+
"/traces": homepage,
|
|
203
258
|
"/ask": homepage,
|
|
204
259
|
"/graph": homepage,
|
|
205
260
|
|
|
@@ -208,8 +263,101 @@ export async function startServer(
|
|
|
208
263
|
GET: () => withSecurityHeaders(handleHealth(), isDev),
|
|
209
264
|
},
|
|
210
265
|
"/api/status": {
|
|
211
|
-
GET: async () =>
|
|
212
|
-
withSecurityHeaders(
|
|
266
|
+
GET: async (req: Request) =>
|
|
267
|
+
withSecurityHeaders(
|
|
268
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
269
|
+
handleStatus(ctxHolder.current, {
|
|
270
|
+
getResidentStatus: () =>
|
|
271
|
+
(runtime as ResidentRuntime).getStatus(),
|
|
272
|
+
})
|
|
273
|
+
),
|
|
274
|
+
isDev
|
|
275
|
+
),
|
|
276
|
+
},
|
|
277
|
+
"/api/traces/export": {
|
|
278
|
+
POST: async (req: Request) => {
|
|
279
|
+
if (!isRequestAllowed(req, port)) {
|
|
280
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
281
|
+
}
|
|
282
|
+
return withSecurityHeaders(
|
|
283
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
284
|
+
handleTraceExport(store, req)
|
|
285
|
+
),
|
|
286
|
+
isDev
|
|
287
|
+
);
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
"/api/traces/:traceId/judgments": {
|
|
291
|
+
POST: async (req: Request) => {
|
|
292
|
+
if (!isRequestAllowed(req, port)) {
|
|
293
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
294
|
+
}
|
|
295
|
+
const traceId = decodeURIComponent(
|
|
296
|
+
new URL(req.url).pathname.split("/")[3] ?? ""
|
|
297
|
+
);
|
|
298
|
+
return withSecurityHeaders(
|
|
299
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
300
|
+
handleTraceLabel(store, traceId, req)
|
|
301
|
+
),
|
|
302
|
+
isDev
|
|
303
|
+
);
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
"/api/traces/:traceId": {
|
|
307
|
+
GET: async (req: Request) => {
|
|
308
|
+
const traceId = decodeURIComponent(
|
|
309
|
+
new URL(req.url).pathname.split("/")[3] ?? ""
|
|
310
|
+
);
|
|
311
|
+
return withSecurityHeaders(
|
|
312
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
313
|
+
handleTraceShow(store, traceId, req)
|
|
314
|
+
),
|
|
315
|
+
isDev
|
|
316
|
+
);
|
|
317
|
+
},
|
|
318
|
+
DELETE: async (req: Request) => {
|
|
319
|
+
if (!isRequestAllowed(req, port)) {
|
|
320
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
321
|
+
}
|
|
322
|
+
const traceId = decodeURIComponent(
|
|
323
|
+
new URL(req.url).pathname.split("/")[3] ?? ""
|
|
324
|
+
);
|
|
325
|
+
return withSecurityHeaders(
|
|
326
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
327
|
+
handleTraceDelete(store, traceId)
|
|
328
|
+
),
|
|
329
|
+
isDev
|
|
330
|
+
);
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
"/api/traces": {
|
|
334
|
+
GET: async (req: Request) =>
|
|
335
|
+
withSecurityHeaders(
|
|
336
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
337
|
+
handleTraceList(store, req)
|
|
338
|
+
),
|
|
339
|
+
isDev
|
|
340
|
+
),
|
|
341
|
+
DELETE: async (req: Request) => {
|
|
342
|
+
if (!isRequestAllowed(req, port)) {
|
|
343
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
344
|
+
}
|
|
345
|
+
return withSecurityHeaders(
|
|
346
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
347
|
+
handleTracePurge(store)
|
|
348
|
+
),
|
|
349
|
+
isDev
|
|
350
|
+
);
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
"/api/resident/status": {
|
|
354
|
+
GET: () =>
|
|
355
|
+
withSecurityHeaders(
|
|
356
|
+
handleResidentStatus(() =>
|
|
357
|
+
(runtime as ResidentRuntime).getStatus()
|
|
358
|
+
),
|
|
359
|
+
isDev
|
|
360
|
+
),
|
|
213
361
|
},
|
|
214
362
|
"/api/collections": {
|
|
215
363
|
GET: async () =>
|
|
@@ -228,9 +376,11 @@ export async function startServer(
|
|
|
228
376
|
},
|
|
229
377
|
},
|
|
230
378
|
"/api/connectors": {
|
|
231
|
-
GET: async () =>
|
|
379
|
+
GET: async (req: Request) =>
|
|
232
380
|
withSecurityHeaders(
|
|
233
|
-
await
|
|
381
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
382
|
+
handleConnectors(ctxHolder.config)
|
|
383
|
+
),
|
|
234
384
|
isDev
|
|
235
385
|
),
|
|
236
386
|
},
|
|
@@ -256,7 +406,13 @@ export async function startServer(
|
|
|
256
406
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
257
407
|
}
|
|
258
408
|
return withSecurityHeaders(
|
|
259
|
-
await
|
|
409
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
410
|
+
(dependencies.handleVerifyConnector ?? handleVerifyConnector)(
|
|
411
|
+
ctxHolder.config,
|
|
412
|
+
store,
|
|
413
|
+
req
|
|
414
|
+
)
|
|
415
|
+
),
|
|
260
416
|
isDev
|
|
261
417
|
);
|
|
262
418
|
},
|
|
@@ -267,7 +423,12 @@ export async function startServer(
|
|
|
267
423
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
268
424
|
}
|
|
269
425
|
return withSecurityHeaders(
|
|
270
|
-
await
|
|
426
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
427
|
+
(dependencies.handleImportPreview ?? handleImportPreview)(
|
|
428
|
+
ctxHolder,
|
|
429
|
+
req
|
|
430
|
+
)
|
|
431
|
+
),
|
|
271
432
|
isDev
|
|
272
433
|
);
|
|
273
434
|
},
|
|
@@ -278,7 +439,13 @@ export async function startServer(
|
|
|
278
439
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
279
440
|
}
|
|
280
441
|
return withSecurityHeaders(
|
|
281
|
-
await
|
|
442
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
443
|
+
(dependencies.handlePublishExport ?? handlePublishExport)(
|
|
444
|
+
ctxHolder.config,
|
|
445
|
+
store,
|
|
446
|
+
req
|
|
447
|
+
)
|
|
448
|
+
),
|
|
282
449
|
isDev
|
|
283
450
|
);
|
|
284
451
|
},
|
|
@@ -308,7 +475,12 @@ export async function startServer(
|
|
|
308
475
|
"/api/docs": {
|
|
309
476
|
GET: async (req: Request) => {
|
|
310
477
|
const url = new URL(req.url);
|
|
311
|
-
return withSecurityHeaders(
|
|
478
|
+
return withSecurityHeaders(
|
|
479
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
480
|
+
(dependencies.handleDocs ?? handleDocs)(store, url)
|
|
481
|
+
),
|
|
482
|
+
isDev
|
|
483
|
+
);
|
|
312
484
|
},
|
|
313
485
|
POST: async (req: Request) => {
|
|
314
486
|
if (!isRequestAllowed(req, port)) {
|
|
@@ -324,7 +496,9 @@ export async function startServer(
|
|
|
324
496
|
GET: async (req: Request) => {
|
|
325
497
|
const url = new URL(req.url);
|
|
326
498
|
return withSecurityHeaders(
|
|
327
|
-
await
|
|
499
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
500
|
+
handleDocsAutocomplete(store, url)
|
|
501
|
+
),
|
|
328
502
|
isDev
|
|
329
503
|
);
|
|
330
504
|
},
|
|
@@ -345,8 +519,13 @@ export async function startServer(
|
|
|
345
519
|
},
|
|
346
520
|
},
|
|
347
521
|
"/api/browse/tree": {
|
|
348
|
-
GET: async () =>
|
|
349
|
-
withSecurityHeaders(
|
|
522
|
+
GET: async (req: Request) =>
|
|
523
|
+
withSecurityHeaders(
|
|
524
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
525
|
+
handleBrowseTree(store)
|
|
526
|
+
),
|
|
527
|
+
isDev
|
|
528
|
+
),
|
|
350
529
|
},
|
|
351
530
|
"/api/docs/:id/deactivate": {
|
|
352
531
|
POST: async (req: Request) => {
|
|
@@ -358,7 +537,7 @@ export async function startServer(
|
|
|
358
537
|
const parts = url.pathname.split("/");
|
|
359
538
|
const id = decodeURIComponent(parts[3] || "");
|
|
360
539
|
return withSecurityHeaders(
|
|
361
|
-
await handleDeactivateDoc(store, id, req),
|
|
540
|
+
await handleDeactivateDoc(ctxHolder, store, id, req),
|
|
362
541
|
isDev
|
|
363
542
|
);
|
|
364
543
|
},
|
|
@@ -414,7 +593,14 @@ export async function startServer(
|
|
|
414
593
|
const parts = url.pathname.split("/");
|
|
415
594
|
const id = decodeURIComponent(parts[3] || "");
|
|
416
595
|
return withSecurityHeaders(
|
|
417
|
-
await
|
|
596
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
597
|
+
(dependencies.handleRefactorPlan ?? handleRefactorPlan)(
|
|
598
|
+
ctxHolder,
|
|
599
|
+
store,
|
|
600
|
+
id,
|
|
601
|
+
req
|
|
602
|
+
)
|
|
603
|
+
),
|
|
418
604
|
isDev
|
|
419
605
|
);
|
|
420
606
|
},
|
|
@@ -479,7 +665,9 @@ export async function startServer(
|
|
|
479
665
|
GET: async (req: Request) => {
|
|
480
666
|
const url = new URL(req.url);
|
|
481
667
|
return withSecurityHeaders(
|
|
482
|
-
await
|
|
668
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
669
|
+
handleDoc(store, ctxHolder.config, url, req)
|
|
670
|
+
),
|
|
483
671
|
isDev
|
|
484
672
|
);
|
|
485
673
|
},
|
|
@@ -488,7 +676,9 @@ export async function startServer(
|
|
|
488
676
|
GET: async (req: Request) => {
|
|
489
677
|
const url = new URL(req.url);
|
|
490
678
|
return withSecurityHeaders(
|
|
491
|
-
await
|
|
679
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
680
|
+
handleDocAsset(store, ctxHolder.config, url)
|
|
681
|
+
),
|
|
492
682
|
isDev
|
|
493
683
|
);
|
|
494
684
|
},
|
|
@@ -504,7 +694,12 @@ export async function startServer(
|
|
|
504
694
|
"/api/tags": {
|
|
505
695
|
GET: async (req: Request) => {
|
|
506
696
|
const url = new URL(req.url);
|
|
507
|
-
return withSecurityHeaders(
|
|
697
|
+
return withSecurityHeaders(
|
|
698
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
699
|
+
handleTags(store, url)
|
|
700
|
+
),
|
|
701
|
+
isDev
|
|
702
|
+
);
|
|
508
703
|
},
|
|
509
704
|
},
|
|
510
705
|
"/api/search": {
|
|
@@ -512,7 +707,12 @@ export async function startServer(
|
|
|
512
707
|
if (!isRequestAllowed(req, port)) {
|
|
513
708
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
514
709
|
}
|
|
515
|
-
return withSecurityHeaders(
|
|
710
|
+
return withSecurityHeaders(
|
|
711
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
712
|
+
handleSearch(ctxHolder.current, req)
|
|
713
|
+
),
|
|
714
|
+
isDev
|
|
715
|
+
);
|
|
516
716
|
},
|
|
517
717
|
},
|
|
518
718
|
"/api/query": {
|
|
@@ -521,7 +721,9 @@ export async function startServer(
|
|
|
521
721
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
522
722
|
}
|
|
523
723
|
return withSecurityHeaders(
|
|
524
|
-
await
|
|
724
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
725
|
+
handleQuery(ctxHolder.current, req)
|
|
726
|
+
),
|
|
525
727
|
isDev
|
|
526
728
|
);
|
|
527
729
|
},
|
|
@@ -532,7 +734,9 @@ export async function startServer(
|
|
|
532
734
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
533
735
|
}
|
|
534
736
|
return withSecurityHeaders(
|
|
535
|
-
await
|
|
737
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
738
|
+
handleContextBuild(ctxHolder.current, req)
|
|
739
|
+
),
|
|
536
740
|
isDev
|
|
537
741
|
);
|
|
538
742
|
},
|
|
@@ -543,7 +747,9 @@ export async function startServer(
|
|
|
543
747
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
544
748
|
}
|
|
545
749
|
return withSecurityHeaders(
|
|
546
|
-
await
|
|
750
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
751
|
+
handleContextVerify(ctxHolder.current, req)
|
|
752
|
+
),
|
|
547
753
|
isDev
|
|
548
754
|
);
|
|
549
755
|
},
|
|
@@ -554,7 +760,9 @@ export async function startServer(
|
|
|
554
760
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
555
761
|
}
|
|
556
762
|
return withSecurityHeaders(
|
|
557
|
-
await
|
|
763
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
764
|
+
handleQueryDiagnose(ctxHolder.current, req)
|
|
765
|
+
),
|
|
558
766
|
isDev
|
|
559
767
|
);
|
|
560
768
|
},
|
|
@@ -565,7 +773,9 @@ export async function startServer(
|
|
|
565
773
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
566
774
|
}
|
|
567
775
|
return withSecurityHeaders(
|
|
568
|
-
await
|
|
776
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
777
|
+
handleAsk(ctxHolder.current, req)
|
|
778
|
+
),
|
|
569
779
|
isDev
|
|
570
780
|
);
|
|
571
781
|
},
|
|
@@ -591,21 +801,30 @@ export async function startServer(
|
|
|
591
801
|
GET: () => withSecurityHeaders(handleModelStatus(), isDev),
|
|
592
802
|
},
|
|
593
803
|
"/api/models/pull": {
|
|
594
|
-
POST: (req: Request) => {
|
|
804
|
+
POST: async (req: Request) => {
|
|
595
805
|
if (!isRequestAllowed(req, port)) {
|
|
596
806
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
597
807
|
}
|
|
598
|
-
return withSecurityHeaders(
|
|
808
|
+
return withSecurityHeaders(
|
|
809
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
810
|
+
handleModelPull(ctxHolder)
|
|
811
|
+
),
|
|
812
|
+
isDev
|
|
813
|
+
);
|
|
599
814
|
},
|
|
600
815
|
},
|
|
601
816
|
"/api/jobs/active": {
|
|
602
|
-
GET: () =>
|
|
817
|
+
GET: () =>
|
|
818
|
+
withSecurityHeaders(handleActiveJob(ctxHolder.jobManager), isDev),
|
|
603
819
|
},
|
|
604
820
|
"/api/jobs/:id": {
|
|
605
821
|
GET: (req: Request) => {
|
|
606
822
|
const url = new URL(req.url);
|
|
607
823
|
const id = decodeURIComponent(url.pathname.split("/").pop() || "");
|
|
608
|
-
return withSecurityHeaders(
|
|
824
|
+
return withSecurityHeaders(
|
|
825
|
+
handleJob(id, ctxHolder.jobManager),
|
|
826
|
+
isDev
|
|
827
|
+
);
|
|
609
828
|
},
|
|
610
829
|
},
|
|
611
830
|
"/api/embed": {
|
|
@@ -677,7 +896,9 @@ export async function startServer(
|
|
|
677
896
|
const parts = url.pathname.split("/");
|
|
678
897
|
const id = decodeURIComponent(parts[3] || "");
|
|
679
898
|
return withSecurityHeaders(
|
|
680
|
-
await
|
|
899
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
900
|
+
handleDocLinks(store, id, url)
|
|
901
|
+
),
|
|
681
902
|
isDev
|
|
682
903
|
);
|
|
683
904
|
},
|
|
@@ -688,7 +909,9 @@ export async function startServer(
|
|
|
688
909
|
const parts = url.pathname.split("/");
|
|
689
910
|
const id = decodeURIComponent(parts[3] || "");
|
|
690
911
|
return withSecurityHeaders(
|
|
691
|
-
await
|
|
912
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
913
|
+
handleDocSections(store, id, req)
|
|
914
|
+
),
|
|
692
915
|
isDev
|
|
693
916
|
);
|
|
694
917
|
},
|
|
@@ -700,7 +923,9 @@ export async function startServer(
|
|
|
700
923
|
const parts = url.pathname.split("/");
|
|
701
924
|
const id = decodeURIComponent(parts[3] || "");
|
|
702
925
|
return withSecurityHeaders(
|
|
703
|
-
await
|
|
926
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
927
|
+
handleDocBacklinks(store, id)
|
|
928
|
+
),
|
|
704
929
|
isDev
|
|
705
930
|
);
|
|
706
931
|
},
|
|
@@ -712,7 +937,9 @@ export async function startServer(
|
|
|
712
937
|
const parts = url.pathname.split("/");
|
|
713
938
|
const id = decodeURIComponent(parts[3] || "");
|
|
714
939
|
return withSecurityHeaders(
|
|
715
|
-
await
|
|
940
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
941
|
+
handleDocSimilar(ctxHolder.current, id, url)
|
|
942
|
+
),
|
|
716
943
|
isDev
|
|
717
944
|
);
|
|
718
945
|
},
|
|
@@ -720,7 +947,12 @@ export async function startServer(
|
|
|
720
947
|
"/api/graph": {
|
|
721
948
|
GET: async (req: Request) => {
|
|
722
949
|
const url = new URL(req.url);
|
|
723
|
-
return withSecurityHeaders(
|
|
950
|
+
return withSecurityHeaders(
|
|
951
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
952
|
+
handleGraph(store, url)
|
|
953
|
+
),
|
|
954
|
+
isDev
|
|
955
|
+
);
|
|
724
956
|
},
|
|
725
957
|
},
|
|
726
958
|
"/api/graph/query": {
|
|
@@ -729,7 +961,9 @@ export async function startServer(
|
|
|
729
961
|
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
730
962
|
}
|
|
731
963
|
return withSecurityHeaders(
|
|
732
|
-
await
|
|
964
|
+
await handleResidentRead(runtime as ResidentRuntime, req, () =>
|
|
965
|
+
handleGraphQuery(store, ctxHolder.config, req)
|
|
966
|
+
),
|
|
733
967
|
isDev
|
|
734
968
|
);
|
|
735
969
|
},
|
|
@@ -738,14 +972,18 @@ export async function startServer(
|
|
|
738
972
|
});
|
|
739
973
|
} catch (e) {
|
|
740
974
|
removeShutdownHandlers();
|
|
741
|
-
await
|
|
975
|
+
await Promise.allSettled([gateway.close()]);
|
|
976
|
+
await Promise.allSettled([runtime.dispose()]);
|
|
742
977
|
return {
|
|
743
978
|
success: false,
|
|
744
979
|
error: e instanceof Error ? e.message : String(e),
|
|
745
980
|
};
|
|
746
981
|
}
|
|
982
|
+
(runtime as Partial<ResidentRuntime>).setListenerPort?.(server.port ?? port);
|
|
747
983
|
|
|
748
|
-
console.log(
|
|
984
|
+
console.log(
|
|
985
|
+
`GNO server running at http://${gatewayConfig.host}:${server.port}`
|
|
986
|
+
);
|
|
749
987
|
console.log("Press Ctrl+C to stop");
|
|
750
988
|
|
|
751
989
|
// Block until shutdown signal
|
|
@@ -763,7 +1001,8 @@ export async function startServer(
|
|
|
763
1001
|
try {
|
|
764
1002
|
await server.stop(true);
|
|
765
1003
|
} finally {
|
|
766
|
-
await
|
|
1004
|
+
await Promise.allSettled([gateway.close()]);
|
|
1005
|
+
await Promise.allSettled([runtime.dispose()]);
|
|
767
1006
|
}
|
|
768
1007
|
return { success: true };
|
|
769
1008
|
}
|
|
@@ -59,6 +59,56 @@ export interface HealthCenterState {
|
|
|
59
59
|
checks: HealthCheck[];
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
export type RuntimeMode = "serve" | "daemon" | "stdio" | "direct-cli";
|
|
63
|
+
|
|
64
|
+
export interface ResidentStatus {
|
|
65
|
+
schemaVersion: "1.0";
|
|
66
|
+
mode: RuntimeMode;
|
|
67
|
+
resident: boolean;
|
|
68
|
+
uptimeSeconds: number | null;
|
|
69
|
+
listenerPort: number | null;
|
|
70
|
+
admission: {
|
|
71
|
+
state: "accepting" | "draining" | "closed";
|
|
72
|
+
activeRequests: number;
|
|
73
|
+
};
|
|
74
|
+
shutdown: {
|
|
75
|
+
state: "none" | "graceful" | "deadline";
|
|
76
|
+
};
|
|
77
|
+
transport: {
|
|
78
|
+
activeRequests: number;
|
|
79
|
+
activeSessions: number;
|
|
80
|
+
queuedRequests: number;
|
|
81
|
+
maxConcurrentRequests: number;
|
|
82
|
+
maxQueuedRequests: number;
|
|
83
|
+
maxSessions: number;
|
|
84
|
+
};
|
|
85
|
+
readers: {
|
|
86
|
+
active: number;
|
|
87
|
+
queued: number;
|
|
88
|
+
limit: number;
|
|
89
|
+
maxQueued: number;
|
|
90
|
+
};
|
|
91
|
+
models: {
|
|
92
|
+
activeLeases: number;
|
|
93
|
+
leaseAcquisitions: number;
|
|
94
|
+
leaseReleases: number;
|
|
95
|
+
loadedModels: number;
|
|
96
|
+
loadAttempts: number;
|
|
97
|
+
loadSuccesses: number;
|
|
98
|
+
loadFailures: number;
|
|
99
|
+
inflightLoads: number;
|
|
100
|
+
};
|
|
101
|
+
jobs: {
|
|
102
|
+
active: number;
|
|
103
|
+
recent: number;
|
|
104
|
+
failed: number;
|
|
105
|
+
};
|
|
106
|
+
generations: {
|
|
107
|
+
content: number;
|
|
108
|
+
index: number;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
62
112
|
export interface BackgroundServiceState {
|
|
63
113
|
watcher: {
|
|
64
114
|
expectedCollections: string[];
|
|
@@ -125,6 +175,7 @@ export interface BootstrapState {
|
|
|
125
175
|
}
|
|
126
176
|
|
|
127
177
|
export interface AppStatusResponse {
|
|
178
|
+
resident: ResidentStatus;
|
|
128
179
|
indexName: string;
|
|
129
180
|
configPath: string;
|
|
130
181
|
dbPath: string;
|
package/src/serve/status.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from "./activation-health";
|
|
27
27
|
import { getConnectorVerificationTargets } from "./connectors";
|
|
28
28
|
import { downloadState, type ServerContext } from "./context";
|
|
29
|
+
import { createStandaloneResidentStatus } from "./resident-status";
|
|
29
30
|
|
|
30
31
|
const GIGABYTE = 1024 * 1024 * 1024;
|
|
31
32
|
const DISK_WARN_BYTES = 4 * GIGABYTE;
|
|
@@ -71,6 +72,7 @@ export interface StatusBuildDeps {
|
|
|
71
72
|
listSuggestedCollections?: () => Promise<SuggestedCollection[]>;
|
|
72
73
|
buildActivation?: typeof buildActivationStatus;
|
|
73
74
|
listConnectorTargets?: typeof getConnectorVerificationTargets;
|
|
75
|
+
getResidentStatus?: () => AppStatusResponse["resident"];
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
function formatBytes(bytes: number): string {
|
|
@@ -714,6 +716,9 @@ export async function buildAppStatus(
|
|
|
714
716
|
: "GNO works, but a few issues still need attention before it feels reliable.";
|
|
715
717
|
|
|
716
718
|
return {
|
|
719
|
+
resident:
|
|
720
|
+
deps.getResidentStatus?.() ??
|
|
721
|
+
createStandaloneResidentStatus("direct-cli"),
|
|
717
722
|
indexName: status.indexName,
|
|
718
723
|
configPath: status.configPath,
|
|
719
724
|
dbPath: status.dbPath,
|