@gmickel/gno 0.28.2 → 0.29.1
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 +10 -2
- package/package.json +1 -1
- package/src/app/constants.ts +4 -2
- package/src/cli/commands/mcp/install.ts +4 -4
- package/src/cli/commands/mcp/status.ts +7 -7
- package/src/cli/commands/skill/install.ts +5 -5
- package/src/cli/program.ts +2 -2
- package/src/collection/add.ts +10 -0
- package/src/collection/types.ts +1 -0
- package/src/config/types.ts +12 -2
- package/src/core/depth-policy.ts +1 -1
- package/src/core/file-ops.ts +203 -1
- package/src/llm/registry.ts +20 -4
- package/src/serve/AGENTS.md +16 -16
- package/src/serve/CLAUDE.md +16 -16
- package/src/serve/config-sync.ts +32 -1
- package/src/serve/connectors.ts +243 -0
- package/src/serve/context.ts +9 -0
- package/src/serve/doc-events.ts +31 -1
- package/src/serve/embed-scheduler.ts +12 -0
- package/src/serve/import-preview.ts +173 -0
- package/src/serve/public/app.tsx +101 -7
- package/src/serve/public/components/AIModelSelector.tsx +383 -145
- package/src/serve/public/components/AddCollectionDialog.tsx +123 -7
- package/src/serve/public/components/BootstrapStatus.tsx +133 -0
- package/src/serve/public/components/CaptureModal.tsx +5 -2
- package/src/serve/public/components/CollectionsEmptyState.tsx +63 -0
- package/src/serve/public/components/FirstRunWizard.tsx +622 -0
- package/src/serve/public/components/HealthCenter.tsx +128 -0
- package/src/serve/public/components/IndexingProgress.tsx +21 -2
- package/src/serve/public/components/QuickSwitcher.tsx +62 -36
- package/src/serve/public/components/TagInput.tsx +5 -1
- package/src/serve/public/components/WikiLinkAutocomplete.tsx +15 -6
- package/src/serve/public/components/WorkspaceTabs.tsx +60 -0
- package/src/serve/public/hooks/use-doc-events.ts +48 -4
- package/src/serve/public/lib/local-history.ts +40 -7
- package/src/serve/public/lib/navigation-state.ts +156 -0
- package/src/serve/public/lib/workspace-tabs.ts +235 -0
- package/src/serve/public/pages/Ask.tsx +11 -1
- package/src/serve/public/pages/Browse.tsx +73 -0
- package/src/serve/public/pages/Collections.tsx +29 -13
- package/src/serve/public/pages/Connectors.tsx +178 -0
- package/src/serve/public/pages/Dashboard.tsx +493 -67
- package/src/serve/public/pages/DocView.tsx +192 -34
- package/src/serve/public/pages/DocumentEditor.tsx +127 -5
- package/src/serve/public/pages/Search.tsx +12 -1
- package/src/serve/routes/api.ts +541 -62
- package/src/serve/server.ts +79 -2
- package/src/serve/status-model.ts +149 -0
- package/src/serve/status.ts +706 -0
- package/src/serve/watch-service.ts +73 -8
- package/src/types/electrobun-shell.d.ts +43 -0
package/src/serve/server.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
handleAsk,
|
|
22
22
|
handleCapabilities,
|
|
23
23
|
handleCollections,
|
|
24
|
+
handleConnectors,
|
|
24
25
|
handleCreateCollection,
|
|
25
26
|
handleCreateEditableCopy,
|
|
26
27
|
handleCreateDoc,
|
|
@@ -32,16 +33,21 @@ import {
|
|
|
32
33
|
handleEmbed,
|
|
33
34
|
handleEmbedStatus,
|
|
34
35
|
handleHealth,
|
|
36
|
+
handleImportPreview,
|
|
37
|
+
handleInstallConnector,
|
|
35
38
|
handleJob,
|
|
36
39
|
handleModelPull,
|
|
37
40
|
handleModelStatus,
|
|
38
41
|
handlePresets,
|
|
39
42
|
handleQuery,
|
|
43
|
+
handleRenameDoc,
|
|
44
|
+
handleRevealDoc,
|
|
40
45
|
handleSearch,
|
|
41
46
|
handleSetPreset,
|
|
42
47
|
handleStatus,
|
|
43
48
|
handleSync,
|
|
44
49
|
handleTags,
|
|
50
|
+
handleTrashDoc,
|
|
45
51
|
handleUpdateDoc,
|
|
46
52
|
} from "./routes/api";
|
|
47
53
|
import { handleGraph } from "./routes/graph";
|
|
@@ -184,8 +190,10 @@ export async function startServer(
|
|
|
184
190
|
getModelUri: () => getActivePreset(ctxHolder.config).embed,
|
|
185
191
|
});
|
|
186
192
|
ctxHolder.scheduler = scheduler;
|
|
193
|
+
ctxHolder.current.scheduler = scheduler;
|
|
187
194
|
const eventBus = new DocumentEventBus();
|
|
188
195
|
ctxHolder.eventBus = eventBus;
|
|
196
|
+
ctxHolder.current.eventBus = eventBus;
|
|
189
197
|
const watchService = new CollectionWatchService({
|
|
190
198
|
collections: config.collections,
|
|
191
199
|
store,
|
|
@@ -194,6 +202,7 @@ export async function startServer(
|
|
|
194
202
|
});
|
|
195
203
|
watchService.start();
|
|
196
204
|
ctxHolder.watchService = watchService;
|
|
205
|
+
ctxHolder.current.watchService = watchService;
|
|
197
206
|
|
|
198
207
|
// Shutdown controller for clean lifecycle
|
|
199
208
|
const shutdownController = new AbortController();
|
|
@@ -231,6 +240,7 @@ export async function startServer(
|
|
|
231
240
|
"/doc": homepage,
|
|
232
241
|
"/edit": homepage,
|
|
233
242
|
"/collections": homepage,
|
|
243
|
+
"/connectors": homepage,
|
|
234
244
|
"/ask": homepage,
|
|
235
245
|
"/graph": homepage,
|
|
236
246
|
|
|
@@ -240,7 +250,7 @@ export async function startServer(
|
|
|
240
250
|
},
|
|
241
251
|
"/api/status": {
|
|
242
252
|
GET: async () =>
|
|
243
|
-
withSecurityHeaders(await handleStatus(
|
|
253
|
+
withSecurityHeaders(await handleStatus(ctxHolder.current), isDev),
|
|
244
254
|
},
|
|
245
255
|
"/api/collections": {
|
|
246
256
|
GET: async () =>
|
|
@@ -255,6 +265,31 @@ export async function startServer(
|
|
|
255
265
|
);
|
|
256
266
|
},
|
|
257
267
|
},
|
|
268
|
+
"/api/connectors": {
|
|
269
|
+
GET: async () => withSecurityHeaders(await handleConnectors(), isDev),
|
|
270
|
+
},
|
|
271
|
+
"/api/connectors/install": {
|
|
272
|
+
POST: async (req: Request) => {
|
|
273
|
+
if (!isRequestAllowed(req, port)) {
|
|
274
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
275
|
+
}
|
|
276
|
+
return withSecurityHeaders(
|
|
277
|
+
await handleInstallConnector(req),
|
|
278
|
+
isDev
|
|
279
|
+
);
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
"/api/import/preview": {
|
|
283
|
+
POST: async (req: Request) => {
|
|
284
|
+
if (!isRequestAllowed(req, port)) {
|
|
285
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
286
|
+
}
|
|
287
|
+
return withSecurityHeaders(
|
|
288
|
+
await handleImportPreview(ctxHolder, req),
|
|
289
|
+
isDev
|
|
290
|
+
);
|
|
291
|
+
},
|
|
292
|
+
},
|
|
258
293
|
"/api/sync": {
|
|
259
294
|
POST: async (req: Request) => {
|
|
260
295
|
if (!isRequestAllowed(req, port)) {
|
|
@@ -300,7 +335,49 @@ export async function startServer(
|
|
|
300
335
|
const parts = url.pathname.split("/");
|
|
301
336
|
const id = decodeURIComponent(parts[3] || "");
|
|
302
337
|
return withSecurityHeaders(
|
|
303
|
-
await handleDeactivateDoc(store, id),
|
|
338
|
+
await handleDeactivateDoc(store, id, req),
|
|
339
|
+
isDev
|
|
340
|
+
);
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
"/api/docs/:id/rename": {
|
|
344
|
+
POST: async (req: Request) => {
|
|
345
|
+
if (!isRequestAllowed(req, port)) {
|
|
346
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
347
|
+
}
|
|
348
|
+
const url = new URL(req.url);
|
|
349
|
+
const parts = url.pathname.split("/");
|
|
350
|
+
const id = decodeURIComponent(parts[3] || "");
|
|
351
|
+
return withSecurityHeaders(
|
|
352
|
+
await handleRenameDoc(ctxHolder, store, id, req),
|
|
353
|
+
isDev
|
|
354
|
+
);
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
"/api/docs/:id/trash": {
|
|
358
|
+
POST: async (req: Request) => {
|
|
359
|
+
if (!isRequestAllowed(req, port)) {
|
|
360
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
361
|
+
}
|
|
362
|
+
const url = new URL(req.url);
|
|
363
|
+
const parts = url.pathname.split("/");
|
|
364
|
+
const id = decodeURIComponent(parts[3] || "");
|
|
365
|
+
return withSecurityHeaders(
|
|
366
|
+
await handleTrashDoc(ctxHolder, store, id, req),
|
|
367
|
+
isDev
|
|
368
|
+
);
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
"/api/docs/:id/reveal": {
|
|
372
|
+
POST: async (req: Request) => {
|
|
373
|
+
if (!isRequestAllowed(req, port)) {
|
|
374
|
+
return withSecurityHeaders(forbiddenResponse(), isDev);
|
|
375
|
+
}
|
|
376
|
+
const url = new URL(req.url);
|
|
377
|
+
const parts = url.pathname.split("/");
|
|
378
|
+
const id = decodeURIComponent(parts[3] || "");
|
|
379
|
+
return withSecurityHeaders(
|
|
380
|
+
await handleRevealDoc(ctxHolder, store, id, req),
|
|
304
381
|
isDev
|
|
305
382
|
);
|
|
306
383
|
},
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
export type HealthCheckStatus = "ok" | "warn" | "error";
|
|
2
|
+
|
|
3
|
+
export type HealthActionKind =
|
|
4
|
+
| "add-collection"
|
|
5
|
+
| "open-collections"
|
|
6
|
+
| "sync"
|
|
7
|
+
| "embed"
|
|
8
|
+
| "download-models"
|
|
9
|
+
| "free-space";
|
|
10
|
+
|
|
11
|
+
export type OnboardingStepStatus = "complete" | "current" | "upcoming";
|
|
12
|
+
|
|
13
|
+
export interface StatusCollection {
|
|
14
|
+
name: string;
|
|
15
|
+
path: string;
|
|
16
|
+
documentCount: number;
|
|
17
|
+
chunkCount: number;
|
|
18
|
+
embeddedCount: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SuggestedCollection {
|
|
22
|
+
label: string;
|
|
23
|
+
path: string;
|
|
24
|
+
reason: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface OnboardingStep {
|
|
28
|
+
id: string;
|
|
29
|
+
title: string;
|
|
30
|
+
status: OnboardingStepStatus;
|
|
31
|
+
detail: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface OnboardingState {
|
|
35
|
+
ready: boolean;
|
|
36
|
+
stage: "add-collection" | "models" | "indexing" | "ready";
|
|
37
|
+
headline: string;
|
|
38
|
+
detail: string;
|
|
39
|
+
suggestedCollections: SuggestedCollection[];
|
|
40
|
+
steps: OnboardingStep[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface HealthCheck {
|
|
44
|
+
id: string;
|
|
45
|
+
title: string;
|
|
46
|
+
status: HealthCheckStatus;
|
|
47
|
+
summary: string;
|
|
48
|
+
detail: string;
|
|
49
|
+
actionLabel?: string;
|
|
50
|
+
actionKind?: HealthActionKind;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface HealthCenterState {
|
|
54
|
+
state: "healthy" | "needs-attention" | "setup-required";
|
|
55
|
+
summary: string;
|
|
56
|
+
checks: HealthCheck[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface BackgroundServiceState {
|
|
60
|
+
watcher: {
|
|
61
|
+
expectedCollections: string[];
|
|
62
|
+
activeCollections: string[];
|
|
63
|
+
failedCollections: Array<{ collection: string; reason: string }>;
|
|
64
|
+
queuedCollections: string[];
|
|
65
|
+
syncingCollections: string[];
|
|
66
|
+
lastEventAt: string | null;
|
|
67
|
+
lastSyncAt: string | null;
|
|
68
|
+
};
|
|
69
|
+
embedding: {
|
|
70
|
+
available: boolean;
|
|
71
|
+
pendingDocCount: number;
|
|
72
|
+
running: boolean;
|
|
73
|
+
nextRunAt: number | null;
|
|
74
|
+
lastRunAt: number | null;
|
|
75
|
+
lastResult: { embedded: number; errors: number } | null;
|
|
76
|
+
};
|
|
77
|
+
events: {
|
|
78
|
+
connectedClients: number;
|
|
79
|
+
retryMs: number;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface BootstrapState {
|
|
84
|
+
runtime: {
|
|
85
|
+
kind: "bun";
|
|
86
|
+
strategy: "manual-install-beta";
|
|
87
|
+
currentVersion: string;
|
|
88
|
+
requiredVersion: string;
|
|
89
|
+
ready: boolean;
|
|
90
|
+
managedByApp: boolean;
|
|
91
|
+
summary: string;
|
|
92
|
+
detail: string;
|
|
93
|
+
};
|
|
94
|
+
policy: {
|
|
95
|
+
offline: boolean;
|
|
96
|
+
allowDownload: boolean;
|
|
97
|
+
source: "default" | "hf-hub-offline" | "gno-offline" | "no-auto-download";
|
|
98
|
+
summary: string;
|
|
99
|
+
};
|
|
100
|
+
cache: {
|
|
101
|
+
path: string;
|
|
102
|
+
totalSizeBytes: number;
|
|
103
|
+
totalSizeLabel: string;
|
|
104
|
+
};
|
|
105
|
+
models: {
|
|
106
|
+
activePresetId: string;
|
|
107
|
+
activePresetName: string;
|
|
108
|
+
estimatedFootprint: string | null;
|
|
109
|
+
downloading: boolean;
|
|
110
|
+
cachedCount: number;
|
|
111
|
+
totalCount: number;
|
|
112
|
+
summary: string;
|
|
113
|
+
entries: Array<{
|
|
114
|
+
role: "embed" | "rerank" | "expand" | "gen";
|
|
115
|
+
uri: string;
|
|
116
|
+
cached: boolean;
|
|
117
|
+
path: string | null;
|
|
118
|
+
sizeBytes: number | null;
|
|
119
|
+
statusLabel: string;
|
|
120
|
+
}>;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface AppStatusResponse {
|
|
125
|
+
indexName: string;
|
|
126
|
+
configPath: string;
|
|
127
|
+
dbPath: string;
|
|
128
|
+
collections: StatusCollection[];
|
|
129
|
+
totalDocuments: number;
|
|
130
|
+
totalChunks: number;
|
|
131
|
+
embeddingBacklog: number;
|
|
132
|
+
lastUpdated: string | null;
|
|
133
|
+
recentErrors: number;
|
|
134
|
+
healthy: boolean;
|
|
135
|
+
activePreset: {
|
|
136
|
+
id: string;
|
|
137
|
+
name: string;
|
|
138
|
+
};
|
|
139
|
+
capabilities: {
|
|
140
|
+
bm25: boolean;
|
|
141
|
+
vector: boolean;
|
|
142
|
+
hybrid: boolean;
|
|
143
|
+
answer: boolean;
|
|
144
|
+
};
|
|
145
|
+
onboarding: OnboardingState;
|
|
146
|
+
health: HealthCenterState;
|
|
147
|
+
background: BackgroundServiceState;
|
|
148
|
+
bootstrap: BootstrapState;
|
|
149
|
+
}
|