@gmickel/gno 2.5.1 → 2.6.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 +60 -5
- package/assets/skill/README.md +5 -1
- package/assets/skill/SKILL.md +75 -1
- package/assets/skill/cli-reference.md +123 -0
- package/assets/skill/examples.md +30 -0
- package/assets/skill/mcp-reference.md +52 -0
- package/assets/skill/recipes/capture-and-file.md +6 -0
- package/assets/skill/recipes/memory-file-decision.md +6 -0
- package/assets/skill/recipes/memory-supersede-fact.md +5 -0
- package/assets/skill/recipes/session-evidence-lookup.md +98 -0
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/{gno-browser-clipper-v2.5.1.zip → gno-browser-clipper-v2.6.0.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.6.0.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +2 -1
- package/spec/cli.md +347 -24
- package/spec/mcp.md +198 -2
- package/spec/output-schemas/capture-receipt.schema.json +3 -0
- package/spec/output-schemas/mcp-capture-result.schema.json +3 -0
- package/spec/output-schemas/memory-remember.schema.json +8 -2
- package/spec/output-schemas/request-status.schema.json +113 -0
- package/spec/output-schemas/sessions-automation-run.schema.json +46 -0
- package/spec/output-schemas/sessions-discovery.schema.json +38 -0
- package/spec/output-schemas/sessions-import-receipt.schema.json +156 -0
- package/spec/output-schemas/sessions-status.schema.json +432 -0
- package/src/cli/commands/ask.ts +14 -2
- package/src/cli/commands/capture.ts +55 -96
- package/src/cli/commands/daemon.ts +41 -0
- package/src/cli/commands/ls.ts +3 -0
- package/src/cli/commands/memory.ts +12 -3
- package/src/cli/commands/request-status.ts +59 -0
- package/src/cli/commands/reset.ts +39 -5
- package/src/cli/commands/sessions.ts +713 -0
- package/src/cli/commands/shared.ts +14 -1
- package/src/cli/program.ts +388 -1
- package/src/cli/session-binding.ts +49 -0
- package/src/config/types.ts +8 -0
- package/src/core/capture-publish.ts +239 -0
- package/src/core/capture-sync.ts +3 -0
- package/src/core/memory-remember.ts +233 -122
- package/src/core/memory-types.ts +11 -0
- package/src/core/network-boundary-inventory.ts +8 -0
- package/src/core/request-receipts.ts +671 -0
- package/src/index.ts +9 -0
- package/src/mcp/context.ts +8 -0
- package/src/mcp/http-egress.ts +4 -0
- package/src/mcp/http-transport.ts +2 -0
- package/src/mcp/tools/capture.ts +87 -83
- package/src/mcp/tools/index.ts +66 -0
- package/src/mcp/tools/memory-remember.ts +7 -0
- package/src/mcp/tools/memory-shared.ts +7 -1
- package/src/mcp/tools/request-status.ts +73 -0
- package/src/mcp/tools/sessions.ts +208 -0
- package/src/sdk/client.ts +180 -84
- package/src/sdk/index.ts +6 -0
- package/src/sdk/types.ts +54 -2
- package/src/serve/capture-service.ts +98 -32
- package/src/serve/config-sync.ts +3 -2
- package/src/serve/public/app.tsx +4 -1
- package/src/serve/public/components/CaptureModal.tsx +26 -8
- package/src/serve/public/components/sessions/AutomationPanel.tsx +800 -0
- package/src/serve/public/components/sessions/ImportReceipt.tsx +238 -0
- package/src/serve/public/components/sessions/SessionSearch.tsx +286 -0
- package/src/serve/public/components/sessions/SourcesPanel.tsx +541 -0
- package/src/serve/public/components/sessions/api.ts +40 -0
- package/src/serve/public/components/sessions/snippet.tsx +53 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/hooks/use-api.ts +10 -2
- package/src/serve/public/lib/request-intent.ts +69 -0
- package/src/serve/public/lib/workspace-actions.ts +12 -1
- package/src/serve/public/lib/workspace-tabs.ts +2 -0
- package/src/serve/public/pages/Dashboard.tsx +10 -0
- package/src/serve/public/pages/DocView.tsx +15 -1
- package/src/serve/public/pages/DocumentEditor.tsx +139 -96
- package/src/serve/public/pages/Sessions.tsx +350 -0
- package/src/serve/resident-runtime.ts +43 -3
- package/src/serve/routes/api.ts +476 -147
- package/src/serve/routes/sessions.ts +766 -0
- package/src/serve/security.ts +9 -0
- package/src/serve/server.ts +205 -1
- package/src/serve/session-automation.ts +146 -0
- package/src/sessions/archive.ts +348 -0
- package/src/sessions/automation-state.ts +444 -0
- package/src/sessions/automation-status.ts +239 -0
- package/src/sessions/automation.ts +1169 -0
- package/src/sessions/binding.ts +105 -0
- package/src/sessions/claude-hook.ts +240 -0
- package/src/sessions/config.ts +176 -0
- package/src/sessions/format.ts +191 -0
- package/src/sessions/import-child-env.ts +8 -0
- package/src/sessions/import-child.ts +152 -0
- package/src/sessions/parsers/claude-code.ts +259 -0
- package/src/sessions/parsers/codex.ts +303 -0
- package/src/sessions/parsers/hermes.ts +248 -0
- package/src/sessions/parsers/openclaw.ts +496 -0
- package/src/sessions/parsers/shared.ts +184 -0
- package/src/sessions/sanitize.ts +222 -0
- package/src/sessions/service.ts +1533 -0
- package/src/sessions/setup.ts +477 -0
- package/src/sessions/sources.ts +518 -0
- package/src/sessions/state.ts +118 -0
- package/src/sessions/types.ts +457 -0
- package/src/store/sqlite/adapter.ts +54 -15
- package/src/store/sqlite/scoped-index.ts +9 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.5.1.zip.sha256 +0 -1
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "gno://schemas/sessions-status@1.0",
|
|
4
|
+
"title": "GNO Session Archive Status",
|
|
5
|
+
"description": "Shared status of a session archive on every surface (CLI `gno sessions status --json`, MCP gno_sessions_status, REST GET /api/sessions/status, SDK client.sessionsStatus()). Derived from SessionsStatus in src/sessions/types.ts. Includes opt-in automation state. Contains no host paths and no session content.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"schemaVersion",
|
|
10
|
+
"configured",
|
|
11
|
+
"index",
|
|
12
|
+
"collections",
|
|
13
|
+
"sources",
|
|
14
|
+
"automation",
|
|
15
|
+
"warnings"
|
|
16
|
+
],
|
|
17
|
+
"properties": {
|
|
18
|
+
"schemaVersion": {
|
|
19
|
+
"const": "1"
|
|
20
|
+
},
|
|
21
|
+
"configured": {
|
|
22
|
+
"const": true
|
|
23
|
+
},
|
|
24
|
+
"index": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"minLength": 1
|
|
27
|
+
},
|
|
28
|
+
"collections": {
|
|
29
|
+
"type": "array",
|
|
30
|
+
"items": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"additionalProperties": false,
|
|
33
|
+
"required": ["name", "threads"],
|
|
34
|
+
"properties": {
|
|
35
|
+
"name": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"threads": {
|
|
39
|
+
"type": "integer",
|
|
40
|
+
"minimum": 0
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"sources": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"additionalProperties": false,
|
|
50
|
+
"required": [
|
|
51
|
+
"id",
|
|
52
|
+
"harness",
|
|
53
|
+
"collection",
|
|
54
|
+
"available",
|
|
55
|
+
"units",
|
|
56
|
+
"archivedThreads",
|
|
57
|
+
"staleParser",
|
|
58
|
+
"sourceUnavailable",
|
|
59
|
+
"lastImportAt"
|
|
60
|
+
],
|
|
61
|
+
"properties": {
|
|
62
|
+
"id": { "type": "string" },
|
|
63
|
+
"harness": { "enum": ["codex", "claude-code", "openclaw", "hermes"] },
|
|
64
|
+
"collection": { "type": "string" },
|
|
65
|
+
"available": {
|
|
66
|
+
"type": "boolean",
|
|
67
|
+
"description": "False when the source root is missing or cannot be listed."
|
|
68
|
+
},
|
|
69
|
+
"units": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"additionalProperties": false,
|
|
72
|
+
"required": [
|
|
73
|
+
"total",
|
|
74
|
+
"complete",
|
|
75
|
+
"incomplete",
|
|
76
|
+
"failed",
|
|
77
|
+
"pending"
|
|
78
|
+
],
|
|
79
|
+
"properties": {
|
|
80
|
+
"total": {
|
|
81
|
+
"type": "integer",
|
|
82
|
+
"minimum": 0
|
|
83
|
+
},
|
|
84
|
+
"complete": {
|
|
85
|
+
"type": "integer",
|
|
86
|
+
"minimum": 0
|
|
87
|
+
},
|
|
88
|
+
"incomplete": {
|
|
89
|
+
"type": "integer",
|
|
90
|
+
"minimum": 0
|
|
91
|
+
},
|
|
92
|
+
"failed": {
|
|
93
|
+
"type": "integer",
|
|
94
|
+
"minimum": 0
|
|
95
|
+
},
|
|
96
|
+
"pending": {
|
|
97
|
+
"type": "integer",
|
|
98
|
+
"minimum": 0
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"archivedThreads": {
|
|
103
|
+
"type": "integer",
|
|
104
|
+
"minimum": 0
|
|
105
|
+
},
|
|
106
|
+
"staleParser": {
|
|
107
|
+
"type": "integer",
|
|
108
|
+
"minimum": 0,
|
|
109
|
+
"description": "Archived units produced by an older parser whose source is no longer available to reparse."
|
|
110
|
+
},
|
|
111
|
+
"sourceUnavailable": {
|
|
112
|
+
"type": "integer",
|
|
113
|
+
"minimum": 0,
|
|
114
|
+
"description": "Archived units whose source no longer exists; their archive is retained until an explicit prune."
|
|
115
|
+
},
|
|
116
|
+
"lastImportAt": {
|
|
117
|
+
"type": ["string", "null"],
|
|
118
|
+
"format": "date-time"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"automation": {
|
|
124
|
+
"type": "object",
|
|
125
|
+
"additionalProperties": false,
|
|
126
|
+
"required": ["daemon", "timezone", "profiles"],
|
|
127
|
+
"properties": {
|
|
128
|
+
"daemon": {
|
|
129
|
+
"type": "object",
|
|
130
|
+
"additionalProperties": false,
|
|
131
|
+
"required": ["state", "heartbeatAt"],
|
|
132
|
+
"properties": {
|
|
133
|
+
"state": {
|
|
134
|
+
"enum": ["running", "not_running", "stale"],
|
|
135
|
+
"description": "running only with a fresh heartbeat from a live daemon on this archive; serve never counts."
|
|
136
|
+
},
|
|
137
|
+
"heartbeatAt": {
|
|
138
|
+
"type": ["string", "null"],
|
|
139
|
+
"format": "date-time"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"timezone": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "IANA timezone for human-readable times; stored instants are UTC."
|
|
146
|
+
},
|
|
147
|
+
"profiles": {
|
|
148
|
+
"type": "array",
|
|
149
|
+
"items": {
|
|
150
|
+
"type": "object",
|
|
151
|
+
"additionalProperties": false,
|
|
152
|
+
"required": [
|
|
153
|
+
"id",
|
|
154
|
+
"sources",
|
|
155
|
+
"collections",
|
|
156
|
+
"state",
|
|
157
|
+
"hook",
|
|
158
|
+
"schedule",
|
|
159
|
+
"limit",
|
|
160
|
+
"retries",
|
|
161
|
+
"pending",
|
|
162
|
+
"running",
|
|
163
|
+
"lastTrigger",
|
|
164
|
+
"lastRun",
|
|
165
|
+
"lastSuccessAt",
|
|
166
|
+
"retryAt",
|
|
167
|
+
"recovery"
|
|
168
|
+
],
|
|
169
|
+
"properties": {
|
|
170
|
+
"id": {
|
|
171
|
+
"type": "string"
|
|
172
|
+
},
|
|
173
|
+
"sources": {
|
|
174
|
+
"type": "array",
|
|
175
|
+
"items": {
|
|
176
|
+
"type": "string"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"collections": {
|
|
180
|
+
"type": "array",
|
|
181
|
+
"items": {
|
|
182
|
+
"type": "string"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"state": {
|
|
186
|
+
"enum": [
|
|
187
|
+
"off",
|
|
188
|
+
"idle",
|
|
189
|
+
"pending",
|
|
190
|
+
"running",
|
|
191
|
+
"retrying",
|
|
192
|
+
"partial",
|
|
193
|
+
"failed"
|
|
194
|
+
],
|
|
195
|
+
"description": "off: no trigger enabled and nothing pending. partial/failed describe the last run."
|
|
196
|
+
},
|
|
197
|
+
"hook": {
|
|
198
|
+
"oneOf": [
|
|
199
|
+
{
|
|
200
|
+
"type": "null"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"type": "object",
|
|
204
|
+
"additionalProperties": false,
|
|
205
|
+
"required": ["harness", "enabled", "installed"],
|
|
206
|
+
"properties": {
|
|
207
|
+
"harness": {
|
|
208
|
+
"enum": ["claude-code"]
|
|
209
|
+
},
|
|
210
|
+
"enabled": {
|
|
211
|
+
"type": "boolean"
|
|
212
|
+
},
|
|
213
|
+
"installed": {
|
|
214
|
+
"type": ["boolean", "null"],
|
|
215
|
+
"description": "Owned entry present in the host settings file; null when the file cannot be read."
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
"schedule": {
|
|
222
|
+
"oneOf": [
|
|
223
|
+
{
|
|
224
|
+
"type": "null"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"type": "object",
|
|
228
|
+
"additionalProperties": false,
|
|
229
|
+
"required": ["enabled", "cadence", "nextDueAt"],
|
|
230
|
+
"properties": {
|
|
231
|
+
"enabled": {
|
|
232
|
+
"type": "boolean"
|
|
233
|
+
},
|
|
234
|
+
"cadence": {
|
|
235
|
+
"type": "string"
|
|
236
|
+
},
|
|
237
|
+
"nextDueAt": {
|
|
238
|
+
"type": ["string", "null"],
|
|
239
|
+
"format": "date-time",
|
|
240
|
+
"description": "Null unless enabled and a daemon is running on this archive."
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
},
|
|
246
|
+
"limit": {
|
|
247
|
+
"type": "integer",
|
|
248
|
+
"minimum": 1
|
|
249
|
+
},
|
|
250
|
+
"retries": {
|
|
251
|
+
"type": "integer",
|
|
252
|
+
"minimum": 0
|
|
253
|
+
},
|
|
254
|
+
"pending": {
|
|
255
|
+
"oneOf": [
|
|
256
|
+
{
|
|
257
|
+
"type": "null"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"type": "object",
|
|
261
|
+
"additionalProperties": false,
|
|
262
|
+
"required": ["since", "triggers"],
|
|
263
|
+
"properties": {
|
|
264
|
+
"since": {
|
|
265
|
+
"type": "string",
|
|
266
|
+
"format": "date-time"
|
|
267
|
+
},
|
|
268
|
+
"triggers": {
|
|
269
|
+
"type": "array",
|
|
270
|
+
"items": {
|
|
271
|
+
"enum": ["hook", "schedule", "manual"]
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
]
|
|
277
|
+
},
|
|
278
|
+
"running": {
|
|
279
|
+
"oneOf": [
|
|
280
|
+
{
|
|
281
|
+
"type": "null"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"type": "object",
|
|
285
|
+
"additionalProperties": false,
|
|
286
|
+
"required": ["startedAt", "triggers"],
|
|
287
|
+
"properties": {
|
|
288
|
+
"startedAt": {
|
|
289
|
+
"type": "string",
|
|
290
|
+
"format": "date-time"
|
|
291
|
+
},
|
|
292
|
+
"triggers": {
|
|
293
|
+
"type": "array",
|
|
294
|
+
"items": {
|
|
295
|
+
"enum": ["hook", "schedule", "manual"]
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
"lastTrigger": {
|
|
303
|
+
"oneOf": [
|
|
304
|
+
{
|
|
305
|
+
"type": "null"
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
"type": "object",
|
|
309
|
+
"additionalProperties": false,
|
|
310
|
+
"required": ["kind", "at"],
|
|
311
|
+
"properties": {
|
|
312
|
+
"kind": {
|
|
313
|
+
"enum": ["hook", "schedule", "manual"]
|
|
314
|
+
},
|
|
315
|
+
"at": {
|
|
316
|
+
"type": "string",
|
|
317
|
+
"format": "date-time"
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
]
|
|
322
|
+
},
|
|
323
|
+
"lastRun": {
|
|
324
|
+
"oneOf": [
|
|
325
|
+
{
|
|
326
|
+
"type": "null"
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"$ref": "#/definitions/runRecord"
|
|
330
|
+
}
|
|
331
|
+
]
|
|
332
|
+
},
|
|
333
|
+
"lastSuccessAt": {
|
|
334
|
+
"type": ["string", "null"],
|
|
335
|
+
"format": "date-time"
|
|
336
|
+
},
|
|
337
|
+
"retryAt": {
|
|
338
|
+
"type": ["string", "null"],
|
|
339
|
+
"format": "date-time"
|
|
340
|
+
},
|
|
341
|
+
"recovery": {
|
|
342
|
+
"type": ["string", "null"]
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
"warnings": {
|
|
350
|
+
"type": "array",
|
|
351
|
+
"items": {
|
|
352
|
+
"type": "string"
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
"definitions": {
|
|
357
|
+
"runRecord": {
|
|
358
|
+
"type": "object",
|
|
359
|
+
"additionalProperties": false,
|
|
360
|
+
"required": [
|
|
361
|
+
"triggers",
|
|
362
|
+
"startedAt",
|
|
363
|
+
"finishedAt",
|
|
364
|
+
"outcome",
|
|
365
|
+
"reason",
|
|
366
|
+
"threads",
|
|
367
|
+
"units"
|
|
368
|
+
],
|
|
369
|
+
"properties": {
|
|
370
|
+
"triggers": {
|
|
371
|
+
"type": "array",
|
|
372
|
+
"items": {
|
|
373
|
+
"enum": ["hook", "schedule", "manual"]
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
"startedAt": {
|
|
377
|
+
"type": "string",
|
|
378
|
+
"format": "date-time"
|
|
379
|
+
},
|
|
380
|
+
"finishedAt": {
|
|
381
|
+
"type": "string",
|
|
382
|
+
"format": "date-time"
|
|
383
|
+
},
|
|
384
|
+
"outcome": {
|
|
385
|
+
"enum": ["complete", "up_to_date", "partial", "failed"]
|
|
386
|
+
},
|
|
387
|
+
"reason": {
|
|
388
|
+
"type": ["string", "null"],
|
|
389
|
+
"description": "Stable reason code for partial or failed runs, e.g. busy, runtime_error, source_revoked, source_unavailable, invalid_configuration, import_failed, interrupted, deferred, incomplete_units, index_sync_failed, unit_failures."
|
|
390
|
+
},
|
|
391
|
+
"threads": {
|
|
392
|
+
"type": "object",
|
|
393
|
+
"additionalProperties": false,
|
|
394
|
+
"required": ["imported", "updated", "unchanged"],
|
|
395
|
+
"properties": {
|
|
396
|
+
"imported": {
|
|
397
|
+
"type": "integer",
|
|
398
|
+
"minimum": 0
|
|
399
|
+
},
|
|
400
|
+
"updated": {
|
|
401
|
+
"type": "integer",
|
|
402
|
+
"minimum": 0
|
|
403
|
+
},
|
|
404
|
+
"unchanged": {
|
|
405
|
+
"type": "integer",
|
|
406
|
+
"minimum": 0
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
"units": {
|
|
411
|
+
"type": "object",
|
|
412
|
+
"additionalProperties": false,
|
|
413
|
+
"required": ["incomplete", "failed", "deferred"],
|
|
414
|
+
"properties": {
|
|
415
|
+
"incomplete": {
|
|
416
|
+
"type": "integer",
|
|
417
|
+
"minimum": 0
|
|
418
|
+
},
|
|
419
|
+
"failed": {
|
|
420
|
+
"type": "integer",
|
|
421
|
+
"minimum": 0
|
|
422
|
+
},
|
|
423
|
+
"deferred": {
|
|
424
|
+
"type": "integer",
|
|
425
|
+
"minimum": 0
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
package/src/cli/commands/ask.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
} from "../../llm/types";
|
|
16
16
|
import type { AskOptions, AskResult, Citation } from "../../pipeline/types";
|
|
17
17
|
|
|
18
|
+
import { decorateUriForIndex } from "../../app/constants";
|
|
18
19
|
import { buildVerifiedAsk } from "../../app/verified-ask";
|
|
19
20
|
import { resolveCliProjectAffinity } from "../../core/project-affinity-surface";
|
|
20
21
|
import {
|
|
@@ -96,7 +97,7 @@ export async function ask(
|
|
|
96
97
|
const globals = getGlobals();
|
|
97
98
|
|
|
98
99
|
const initResult = await initStore({
|
|
99
|
-
configPath: options.configPath,
|
|
100
|
+
configPath: options.configPath ?? globals.config,
|
|
100
101
|
indexName: globals.index,
|
|
101
102
|
collection: options.collection,
|
|
102
103
|
syncConfig: false,
|
|
@@ -434,9 +435,20 @@ export async function ask(
|
|
|
434
435
|
return { success: false, error: finalized.error.message };
|
|
435
436
|
}
|
|
436
437
|
}
|
|
438
|
+
// URIs carry `?index=` like search and Capsule results on a named index.
|
|
437
439
|
return {
|
|
438
440
|
success: true,
|
|
439
|
-
data:
|
|
441
|
+
data: {
|
|
442
|
+
...askResult,
|
|
443
|
+
results: askResult.results.map((result) => ({
|
|
444
|
+
...result,
|
|
445
|
+
uri: decorateUriForIndex(result.uri, globals.index),
|
|
446
|
+
})),
|
|
447
|
+
citations: askResult.citations?.map((citation) => ({
|
|
448
|
+
...citation,
|
|
449
|
+
uri: decorateUriForIndex(citation.uri, globals.index),
|
|
450
|
+
})),
|
|
451
|
+
},
|
|
440
452
|
metadata: traceSession?.metadata(),
|
|
441
453
|
};
|
|
442
454
|
} catch (cause) {
|
|
@@ -4,30 +4,28 @@
|
|
|
4
4
|
* @module src/cli/commands/capture
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
// node:fs/promises for mkdir (no Bun equivalent for recursive dir creation)
|
|
8
|
-
import { mkdir } from "node:fs/promises";
|
|
9
|
-
// node:path has no Bun path utilities
|
|
10
|
-
import { dirname, join } from "node:path";
|
|
11
|
-
|
|
12
7
|
import type {
|
|
13
|
-
|
|
8
|
+
CaptureInput,
|
|
14
9
|
CaptureReceipt,
|
|
15
10
|
CaptureSourceKind,
|
|
16
11
|
} from "../../core/capture";
|
|
17
12
|
import type { NoteCollisionPolicy } from "../../core/note-creation";
|
|
18
13
|
import type { NotePresetId } from "../../core/note-presets";
|
|
14
|
+
import type { RequestReceiptInfo } from "../../core/request-receipts";
|
|
19
15
|
|
|
20
16
|
import { getIndexDbPath } from "../../app/constants";
|
|
21
17
|
import {
|
|
22
|
-
buildCaptureReceipt,
|
|
23
18
|
listCaptureDiskRelPaths,
|
|
24
19
|
planCapture,
|
|
25
20
|
serializeCaptureReceipt,
|
|
26
21
|
} from "../../core/capture";
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
|
|
22
|
+
import { publishCapture } from "../../core/capture-publish";
|
|
23
|
+
import {
|
|
24
|
+
formatRequestReceiptLine,
|
|
25
|
+
localRequestLedger,
|
|
26
|
+
} from "../../core/request-receipts";
|
|
30
27
|
import { CliError } from "../errors";
|
|
28
|
+
import { requestErrorToCli } from "./request-status";
|
|
31
29
|
import { initStore } from "./shared";
|
|
32
30
|
|
|
33
31
|
export interface CaptureCliOptions {
|
|
@@ -49,6 +47,7 @@ export interface CaptureCliOptions {
|
|
|
49
47
|
sourceAuthor?: string;
|
|
50
48
|
sourceDate?: string;
|
|
51
49
|
sourceId?: string;
|
|
50
|
+
requestId?: string;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
const SOURCE_KINDS = new Set<CaptureSourceKind>([
|
|
@@ -130,7 +129,7 @@ function validateCollisionPolicy(
|
|
|
130
129
|
|
|
131
130
|
export async function capture(
|
|
132
131
|
options: CaptureCliOptions
|
|
133
|
-
): Promise<CaptureReceipt> {
|
|
132
|
+
): Promise<CaptureReceipt & { request?: RequestReceiptInfo }> {
|
|
134
133
|
const storeInit = await initStore({
|
|
135
134
|
configPath: options.configPath,
|
|
136
135
|
indexName: options.indexName,
|
|
@@ -160,102 +159,61 @@ export async function capture(
|
|
|
160
159
|
|
|
161
160
|
validateCollisionPolicy(options.collisionPolicy);
|
|
162
161
|
const content = await readContent(options);
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
162
|
+
const input: CaptureInput = {
|
|
163
|
+
collection: collection.name,
|
|
164
|
+
content,
|
|
165
|
+
title: options.title,
|
|
166
|
+
relPath: options.path,
|
|
167
|
+
folderPath: options.folder,
|
|
168
|
+
collisionPolicy: options.collisionPolicy,
|
|
169
|
+
presetId: options.preset,
|
|
170
|
+
tags: parseTags(options.tags),
|
|
171
|
+
source: buildSource(options),
|
|
172
|
+
};
|
|
173
|
+
const ledger = localRequestLedger(getIndexDbPath(options.indexName));
|
|
169
174
|
try {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
const published = await publishCapture({
|
|
176
|
+
collection,
|
|
177
|
+
store,
|
|
178
|
+
lockPath: ledger.lockPath,
|
|
179
|
+
reportSyncFailure: true,
|
|
180
|
+
config,
|
|
181
|
+
plan: async () => {
|
|
182
|
+
const existingDocs = await store.listDocuments(collection.name);
|
|
183
|
+
if (!existingDocs.ok) {
|
|
184
|
+
throw new Error(existingDocs.error.message);
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
return planCapture({
|
|
188
|
+
input,
|
|
189
|
+
existingRelPaths: existingDocs.value.map((doc) => doc.relPath),
|
|
190
|
+
diskRelPaths: await listCaptureDiskRelPaths(collection.path),
|
|
191
|
+
});
|
|
192
|
+
} catch (error) {
|
|
193
|
+
throw new CliError(
|
|
194
|
+
"VALIDATION",
|
|
195
|
+
error instanceof Error ? error.message : String(error)
|
|
196
|
+
);
|
|
197
|
+
}
|
|
181
198
|
},
|
|
182
|
-
|
|
183
|
-
|
|
199
|
+
request:
|
|
200
|
+
options.requestId === undefined
|
|
201
|
+
? undefined
|
|
202
|
+
: { ...ledger, requestId: options.requestId, input },
|
|
184
203
|
});
|
|
204
|
+
return published.request
|
|
205
|
+
? { ...published.receipt, request: published.request }
|
|
206
|
+
: published.receipt;
|
|
185
207
|
} catch (error) {
|
|
186
|
-
throw
|
|
187
|
-
"VALIDATION",
|
|
188
|
-
error instanceof Error ? error.message : String(error)
|
|
189
|
-
);
|
|
208
|
+
throw requestErrorToCli(error);
|
|
190
209
|
}
|
|
191
|
-
const absPath = join(collection.path, plan.relPath);
|
|
192
|
-
|
|
193
|
-
const lockPath = join(
|
|
194
|
-
dirname(getIndexDbPath(options.indexName)),
|
|
195
|
-
".mcp-write.lock"
|
|
196
|
-
);
|
|
197
|
-
return await withWriteLock(lockPath, async () => {
|
|
198
|
-
if (plan.openedExisting) {
|
|
199
|
-
const existingDoc = await store.getDocument(
|
|
200
|
-
collection.name,
|
|
201
|
-
plan.relPath
|
|
202
|
-
);
|
|
203
|
-
if (!existingDoc.ok) {
|
|
204
|
-
throw new Error(existingDoc.error.message);
|
|
205
|
-
}
|
|
206
|
-
return buildCaptureReceipt({
|
|
207
|
-
plan,
|
|
208
|
-
absPath,
|
|
209
|
-
docid: existingDoc.value?.docid,
|
|
210
|
-
sync: existingDoc.value
|
|
211
|
-
? { status: "completed" }
|
|
212
|
-
: {
|
|
213
|
-
status: "skipped",
|
|
214
|
-
reason: "Existing file is not indexed yet.",
|
|
215
|
-
},
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
await mkdir(dirname(absPath), { recursive: true });
|
|
220
|
-
await writeCapturePlanFile(plan, absPath);
|
|
221
|
-
const syncResults = await defaultSyncService.syncFiles(
|
|
222
|
-
collection,
|
|
223
|
-
store,
|
|
224
|
-
[plan.relPath],
|
|
225
|
-
withContentTypeRules(
|
|
226
|
-
{
|
|
227
|
-
runUpdateCmd: false,
|
|
228
|
-
gitPull: false,
|
|
229
|
-
},
|
|
230
|
-
config
|
|
231
|
-
)
|
|
232
|
-
);
|
|
233
|
-
const syncResult = syncResults[0];
|
|
234
|
-
const docResult = await store.getDocument(collection.name, plan.relPath);
|
|
235
|
-
const docid = docResult.ok ? docResult.value?.docid : undefined;
|
|
236
|
-
return buildCaptureReceipt({
|
|
237
|
-
plan,
|
|
238
|
-
absPath,
|
|
239
|
-
docid: syncResult?.docid ?? docid,
|
|
240
|
-
sync:
|
|
241
|
-
syncResult?.status === "error"
|
|
242
|
-
? {
|
|
243
|
-
status: "failed",
|
|
244
|
-
error:
|
|
245
|
-
syncResult.errorMessage ??
|
|
246
|
-
syncResult.errorCode ??
|
|
247
|
-
"Unknown sync error",
|
|
248
|
-
}
|
|
249
|
-
: { status: "completed" },
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
210
|
} finally {
|
|
253
211
|
await store.close();
|
|
254
212
|
}
|
|
255
213
|
}
|
|
256
214
|
|
|
257
215
|
export function formatCaptureReceipt(
|
|
258
|
-
receipt: CaptureReceipt,
|
|
216
|
+
receipt: CaptureReceipt & { request?: RequestReceiptInfo },
|
|
259
217
|
options: { json?: boolean; quiet?: boolean } = {}
|
|
260
218
|
): string {
|
|
261
219
|
if (options.json) {
|
|
@@ -278,5 +236,6 @@ export function formatCaptureReceipt(
|
|
|
278
236
|
if (receipt.source.url) {
|
|
279
237
|
lines.push(`Source: ${receipt.source.url}`);
|
|
280
238
|
}
|
|
239
|
+
if (receipt.request) lines.push(formatRequestReceiptLine(receipt.request));
|
|
281
240
|
return lines.join("\n");
|
|
282
241
|
}
|