@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
|
@@ -3,6 +3,7 @@ import type { HttpGatewayOverrides } from "../../mcp/http-security";
|
|
|
3
3
|
import type { BackgroundRuntimeResult } from "../../serve/background-runtime";
|
|
4
4
|
import type { FindingsPassResult } from "../../serve/findings-pass";
|
|
5
5
|
import type { ResidentRuntime } from "../../serve/resident-runtime";
|
|
6
|
+
import type { SessionAutomationRunResult } from "../../sessions/types";
|
|
6
7
|
|
|
7
8
|
import {
|
|
8
9
|
enforceCollectionEgress,
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
import { startBackgroundRuntime } from "../../serve/background-runtime";
|
|
18
19
|
import { handleResidentStatus, handleStatus } from "../../serve/routes/api";
|
|
19
20
|
import { createMcpHttpGateway } from "../../serve/routes/mcp";
|
|
21
|
+
import { SessionsError } from "../../sessions/types";
|
|
20
22
|
|
|
21
23
|
export interface DaemonOptions extends HttpGatewayOverrides {
|
|
22
24
|
configPath?: string;
|
|
@@ -67,6 +69,31 @@ export function logFindingsPassResult(
|
|
|
67
69
|
);
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
/** Content-free: counts and reason codes only; clean no-ops stay silent. */
|
|
73
|
+
export function logSessionAutomationResult(
|
|
74
|
+
result: SessionAutomationRunResult,
|
|
75
|
+
logger: DaemonLogger,
|
|
76
|
+
options: { quiet?: boolean }
|
|
77
|
+
): void {
|
|
78
|
+
if (!result.ran) return;
|
|
79
|
+
if (result.outcome === "failed") {
|
|
80
|
+
logger.error(
|
|
81
|
+
`session automation ${result.profileId}: failed (${result.reason ?? "unknown"})`
|
|
82
|
+
);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (result.outcome === "up_to_date" || options.quiet) return;
|
|
86
|
+
let imported = 0;
|
|
87
|
+
let updated = 0;
|
|
88
|
+
for (const receipt of result.receipts) {
|
|
89
|
+
imported += receipt.counts.imported;
|
|
90
|
+
updated += receipt.counts.updated;
|
|
91
|
+
}
|
|
92
|
+
logger.log(
|
|
93
|
+
`session automation ${result.profileId}: ${result.outcome}${result.reason ? ` (${result.reason})` : ""}; ${imported} threads imported, ${updated} updated`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
70
97
|
function formatCollectionSyncSummary(result: CollectionSyncResult): string {
|
|
71
98
|
return `${result.collection}: ${result.filesAdded} added, ${result.filesUpdated} updated, ${result.filesUnchanged} unchanged, ${result.filesErrored} errors`;
|
|
72
99
|
}
|
|
@@ -175,6 +202,20 @@ export async function daemon(
|
|
|
175
202
|
quiet: options.quiet,
|
|
176
203
|
verbose: options.verbose,
|
|
177
204
|
}),
|
|
205
|
+
onSessionAutomationResult: (result) =>
|
|
206
|
+
logSessionAutomationResult(result, logger, { quiet: options.quiet }),
|
|
207
|
+
onSessionAutomationError: (error) => {
|
|
208
|
+
// Busy state (a run or state change in progress) is retried next tick.
|
|
209
|
+
if (error instanceof SessionsError && error.code === "SESSIONS_BUSY") {
|
|
210
|
+
if (options.verbose) {
|
|
211
|
+
logger.log("session automation: run in progress; next tick retries");
|
|
212
|
+
}
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
logger.error(
|
|
216
|
+
`session automation tick failed: ${error instanceof SessionsError ? error.code : "runtime error"}`
|
|
217
|
+
);
|
|
218
|
+
},
|
|
178
219
|
watchCallbacks: {
|
|
179
220
|
onSyncStart: ({ collection, relPaths }) => {
|
|
180
221
|
if (!options.quiet) {
|
package/src/cli/commands/ls.ts
CHANGED
|
@@ -14,6 +14,8 @@ import { initStore } from "./shared";
|
|
|
14
14
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
15
|
|
|
16
16
|
export interface LsCommandOptions {
|
|
17
|
+
/** Index name (defaults to "default"). */
|
|
18
|
+
indexName?: string;
|
|
17
19
|
/** Override config path */
|
|
18
20
|
configPath?: string;
|
|
19
21
|
/** Max results (default 20) */
|
|
@@ -111,6 +113,7 @@ export async function ls(
|
|
|
111
113
|
|
|
112
114
|
const initResult = await initStore({
|
|
113
115
|
configPath: options.configPath,
|
|
116
|
+
indexName: options.indexName,
|
|
114
117
|
syncConfig: false,
|
|
115
118
|
});
|
|
116
119
|
if (!initResult.ok) {
|
|
@@ -24,11 +24,15 @@ import {
|
|
|
24
24
|
type RememberInput,
|
|
25
25
|
type RememberResult,
|
|
26
26
|
} from "../../core/memory";
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
formatRequestReceiptLine,
|
|
29
|
+
localRequestLedger,
|
|
30
|
+
} from "../../core/request-receipts";
|
|
28
31
|
import { LlmAdapter } from "../../llm/nodeLlamaCpp/adapter";
|
|
29
32
|
import { resolveModelUri } from "../../llm/registry";
|
|
30
33
|
import { createVectorIndexPort } from "../../store/vector";
|
|
31
34
|
import { CliError, type CliErrorCode } from "../errors";
|
|
35
|
+
import { requestErrorToCli } from "./request-status";
|
|
32
36
|
import { initStore } from "./shared";
|
|
33
37
|
|
|
34
38
|
/** Environment overrides for the identity defaults. */
|
|
@@ -62,6 +66,7 @@ export interface RememberCliOptions
|
|
|
62
66
|
receipt?: string;
|
|
63
67
|
derivedFrom?: string[];
|
|
64
68
|
source?: string;
|
|
69
|
+
requestId?: string;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
export interface RecallCliOptions
|
|
@@ -254,7 +259,7 @@ const MEMORY_ERROR_TO_CLI: Record<MemoryErrorCode, CliErrorCode> = {
|
|
|
254
259
|
|
|
255
260
|
/** Map a core `MemoryError` onto the CLI error model (code carried in details). */
|
|
256
261
|
export function toCliError(error: unknown): unknown {
|
|
257
|
-
if (!(error instanceof MemoryError)) return error;
|
|
262
|
+
if (!(error instanceof MemoryError)) return requestErrorToCli(error);
|
|
258
263
|
return new CliError(MEMORY_ERROR_TO_CLI[error.code], error.message, {
|
|
259
264
|
details: { memoryCode: error.code },
|
|
260
265
|
});
|
|
@@ -322,11 +327,13 @@ async function openMemoryRuntime(
|
|
|
322
327
|
await embedResult.value.dispose();
|
|
323
328
|
}
|
|
324
329
|
}
|
|
330
|
+
const ledger = localRequestLedger(getIndexDbPath(options.indexName));
|
|
325
331
|
const service = new MemoryService({
|
|
326
332
|
store,
|
|
327
333
|
config,
|
|
328
334
|
collections,
|
|
329
|
-
lockPath:
|
|
335
|
+
lockPath: ledger.lockPath,
|
|
336
|
+
requests: ledger,
|
|
330
337
|
embedPort,
|
|
331
338
|
vectorIndex,
|
|
332
339
|
});
|
|
@@ -361,6 +368,7 @@ export async function remember(
|
|
|
361
368
|
? options.derivedFrom
|
|
362
369
|
: undefined,
|
|
363
370
|
source: options.source,
|
|
371
|
+
requestId: options.requestId,
|
|
364
372
|
};
|
|
365
373
|
return await runtime.service.remember(input);
|
|
366
374
|
} catch (error) {
|
|
@@ -457,6 +465,7 @@ export function formatRememberResult(
|
|
|
457
465
|
lines.push(`Sync: ${result.sync.status}`);
|
|
458
466
|
}
|
|
459
467
|
lines.push(`Matching: ${formatMatching(result.matching)}`);
|
|
468
|
+
if (result.request) lines.push(formatRequestReceiptLine(result.request));
|
|
460
469
|
return lines.join("\n");
|
|
461
470
|
}
|
|
462
471
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gno request-status: look up a write request ID before retrying it, plus
|
|
3
|
+
* the CLI mapping for request receipt errors.
|
|
4
|
+
*
|
|
5
|
+
* @module src/cli/commands/request-status
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { getIndexDbPath } from "../../app/constants";
|
|
9
|
+
import {
|
|
10
|
+
formatRequestStatus,
|
|
11
|
+
localRequestLedger,
|
|
12
|
+
readRequestStatus,
|
|
13
|
+
RequestReceiptError,
|
|
14
|
+
type RequestReceiptErrorCode,
|
|
15
|
+
type RequestStatusResult,
|
|
16
|
+
} from "../../core/request-receipts";
|
|
17
|
+
import { CliError, type CliErrorCode } from "../errors";
|
|
18
|
+
|
|
19
|
+
const REQUEST_ERROR_TO_CLI: Record<RequestReceiptErrorCode, CliErrorCode> = {
|
|
20
|
+
REQUEST_ID_INVALID: "VALIDATION",
|
|
21
|
+
REQUEST_ID_CONFLICT: "VALIDATION",
|
|
22
|
+
REQUEST_EXPIRED: "VALIDATION",
|
|
23
|
+
// Accepted and still in progress elsewhere: exit 4 like lease contention.
|
|
24
|
+
REQUEST_PENDING: "BUSY",
|
|
25
|
+
REQUEST_RECOVERY_CONFLICT: "RUNTIME",
|
|
26
|
+
REQUEST_CAPACITY_EXHAUSTED: "RUNTIME",
|
|
27
|
+
REQUEST_LEDGER_UNAVAILABLE: "RUNTIME",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Map a request receipt error onto the CLI error model (code in details). */
|
|
31
|
+
export function requestErrorToCli(error: unknown): unknown {
|
|
32
|
+
if (!(error instanceof RequestReceiptError)) return error;
|
|
33
|
+
return new CliError(REQUEST_ERROR_TO_CLI[error.code], error.message, {
|
|
34
|
+
details: { requestCode: error.code },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function requestStatus(options: {
|
|
39
|
+
requestId: string;
|
|
40
|
+
indexName?: string;
|
|
41
|
+
}): Promise<RequestStatusResult> {
|
|
42
|
+
try {
|
|
43
|
+
return await readRequestStatus({
|
|
44
|
+
...localRequestLedger(getIndexDbPath(options.indexName)),
|
|
45
|
+
requestId: options.requestId,
|
|
46
|
+
});
|
|
47
|
+
} catch (error) {
|
|
48
|
+
throw requestErrorToCli(error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function formatRequestStatusOutput(
|
|
53
|
+
result: RequestStatusResult,
|
|
54
|
+
options: { json?: boolean } = {}
|
|
55
|
+
): string {
|
|
56
|
+
return options.json
|
|
57
|
+
? JSON.stringify(result, null, 2)
|
|
58
|
+
: formatRequestStatus(result);
|
|
59
|
+
}
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* gno reset - Reset GNO to fresh state
|
|
3
3
|
*
|
|
4
|
-
* Deletes all config, data, and cache directories.
|
|
4
|
+
* Deletes all config, data, and cache directories. The request ledger
|
|
5
|
+
* (`<dataDir>/write-receipts/`) is kept so request IDs that already ran
|
|
6
|
+
* can never run again.
|
|
5
7
|
*/
|
|
6
8
|
|
|
7
9
|
// node:fs/promises: rm and stat for recursive directory deletion (no Bun equivalent)
|
|
8
|
-
import { rm, stat } from "node:fs/promises";
|
|
10
|
+
import { readdir, rm, stat } from "node:fs/promises";
|
|
9
11
|
// node:os: homedir for platform-agnostic home directory (no Bun equivalent)
|
|
10
12
|
import { homedir } from "node:os";
|
|
11
13
|
// node:path: path manipulation utilities (no Bun equivalent)
|
|
12
|
-
import { isAbsolute, normalize, sep } from "node:path";
|
|
14
|
+
import { isAbsolute, join, normalize, sep } from "node:path";
|
|
13
15
|
|
|
14
16
|
import { resolveDirs } from "../../app/constants";
|
|
17
|
+
import { REQUEST_LEDGER_DIR } from "../../core/request-receipts";
|
|
15
18
|
import { CliError } from "../errors";
|
|
16
19
|
|
|
17
20
|
interface ResetOptions {
|
|
@@ -103,8 +106,8 @@ export async function reset(options: ResetOptions): Promise<ResetResult> {
|
|
|
103
106
|
assertSafePath(dirs.cache, "Cache");
|
|
104
107
|
}
|
|
105
108
|
|
|
106
|
-
//
|
|
107
|
-
results.push(await
|
|
109
|
+
// Empty the data directory (index DBs, caches) but keep the request ledger.
|
|
110
|
+
results.push(...(await clearDataDir(dirs.data)));
|
|
108
111
|
|
|
109
112
|
// Delete config unless --keep-config
|
|
110
113
|
if (options.keepConfig) {
|
|
@@ -134,6 +137,37 @@ export async function reset(options: ResetOptions): Promise<ResetResult> {
|
|
|
134
137
|
return { results, errors };
|
|
135
138
|
}
|
|
136
139
|
|
|
140
|
+
/** Empty the data directory except the request ledger (what reset runs). */
|
|
141
|
+
export async function clearDataDir(path: string): Promise<DirResult[]> {
|
|
142
|
+
let entries: string[];
|
|
143
|
+
try {
|
|
144
|
+
entries = await readdir(path);
|
|
145
|
+
} catch (e) {
|
|
146
|
+
const err = e as NodeJS.ErrnoException;
|
|
147
|
+
return [
|
|
148
|
+
err.code === "ENOENT"
|
|
149
|
+
? { path, status: "missing" }
|
|
150
|
+
: { path, status: "missing", error: err.message },
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
if (!entries.includes(REQUEST_LEDGER_DIR)) return [await rmDir(path)];
|
|
154
|
+
const failures: string[] = [];
|
|
155
|
+
for (const entry of entries) {
|
|
156
|
+
if (entry === REQUEST_LEDGER_DIR) continue;
|
|
157
|
+
try {
|
|
158
|
+
await rm(join(path, entry), { recursive: true, force: true });
|
|
159
|
+
} catch (e) {
|
|
160
|
+
failures.push(`${entry}: ${(e as Error).message}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return [
|
|
164
|
+
failures.length > 0
|
|
165
|
+
? { path, status: "missing", error: failures.join("; ") }
|
|
166
|
+
: { path, status: "deleted" },
|
|
167
|
+
{ path: join(path, REQUEST_LEDGER_DIR), status: "kept" },
|
|
168
|
+
];
|
|
169
|
+
}
|
|
170
|
+
|
|
137
171
|
async function rmDir(path: string): Promise<DirResult> {
|
|
138
172
|
try {
|
|
139
173
|
// Check if exists first
|