@gmickel/gno 1.30.7 → 1.32.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 +6 -5
- package/assets/skill/SKILL.md +25 -0
- package/assets/skill/mcp-reference.md +6 -0
- package/browser-extension/artifacts/{gno-browser-clipper-v1.30.7.zip → gno-browser-clipper-v1.32.0.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.32.0.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/spec/cli.md +19 -0
- package/spec/db/schema.sql +55 -0
- package/spec/mcp.md +176 -11
- package/spec/output-schemas/file-refactor-apply-result.schema.json +305 -0
- package/spec/output-schemas/file-refactor-preview.schema.json +393 -0
- package/spec/output-schemas/section-target-create-result.schema.json +20 -0
- package/spec/output-schemas/section-target-resolve-result.schema.json +194 -0
- package/spec/output-schemas/section-target.schema.json +118 -0
- package/spec/output-schemas/section.schema.json +113 -0
- package/src/core/document-capabilities.ts +13 -0
- package/src/core/file-ops.ts +129 -1
- package/src/core/file-refactor-adapter.ts +329 -0
- package/src/core/file-refactor-apply-edits.ts +61 -0
- package/src/core/file-refactor-apply-fs.ts +512 -0
- package/src/core/file-refactor-apply-safety.ts +340 -0
- package/src/core/file-refactor-apply-validate.ts +401 -0
- package/src/core/file-refactor-contract.ts +486 -0
- package/src/core/file-refactor-destination.ts +123 -0
- package/src/core/file-refactor-from-snapshot.ts +148 -0
- package/src/core/file-refactor-journal-port.ts +150 -0
- package/src/core/file-refactor-journal.ts +347 -0
- package/src/core/file-refactor-paths.ts +60 -0
- package/src/core/file-refactor-plan-classify.ts +208 -0
- package/src/core/file-refactor-plan-validate.ts +169 -0
- package/src/core/file-refactor-planner-types.ts +62 -0
- package/src/core/file-refactor-planner.ts +423 -0
- package/src/core/file-refactor-resolve.ts +280 -0
- package/src/core/file-refactor-service.ts +468 -0
- package/src/core/file-refactors.ts +84 -56
- package/src/core/link-destination-parse.ts +275 -0
- package/src/core/link-inventory-markdown.ts +454 -0
- package/src/core/link-inventory-opaque.ts +244 -0
- package/src/core/link-inventory-types.ts +47 -0
- package/src/core/link-inventory.ts +182 -0
- package/src/core/link-relevance.ts +150 -0
- package/src/core/section-parse.ts +187 -0
- package/src/core/section-target-link.ts +154 -0
- package/src/core/section-target-resolve.ts +351 -0
- package/src/core/section-target-transport.ts +519 -0
- package/src/core/section-target.ts +263 -0
- package/src/core/sections.ts +60 -115
- package/src/mcp/AGENTS.md +1 -0
- package/src/mcp/CLAUDE.md +1 -0
- package/src/mcp/http-egress.ts +1 -0
- package/src/mcp/tools/index.ts +37 -17
- package/src/mcp/tools/sections.ts +512 -0
- package/src/mcp/tools/workspace-write.ts +215 -97
- package/src/sdk/client.ts +238 -116
- package/src/sdk/index.ts +12 -0
- package/src/sdk/types.ts +61 -3
- package/src/serve/file-refactor-http.ts +239 -0
- package/src/serve/public/components/RefactorImpactPreview.tsx +227 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/section-links.ts +189 -0
- package/src/serve/public/pages/DocView.tsx +395 -77
- package/src/serve/routes/api.ts +191 -104
- package/src/serve/routes/section-targets.ts +221 -0
- package/src/serve/server.ts +34 -0
- package/src/store/migrations/026-file-refactor-recovery-journal.ts +72 -0
- package/src/store/migrations/index.ts +2 -0
- package/src/store/sqlite/adapter.ts +452 -0
- package/src/store/sqlite/file-refactor-journal-store.ts +275 -0
- package/src/store/types.ts +84 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.30.7.zip.sha256 +0 -1
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Readable section deep links and optional citation-safe selectors.
|
|
3
|
+
*
|
|
4
|
+
* Copy-link stays human-readable (`#anchor` only). Citation links add a
|
|
5
|
+
* bounded, versioned `st` query param for conservative recovery.
|
|
6
|
+
*
|
|
7
|
+
* @module src/serve/public/lib/section-links
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
createSectionTarget,
|
|
12
|
+
decodeSectionTargetLinkParam,
|
|
13
|
+
encodeSectionTargetLinkParam,
|
|
14
|
+
isNavigableSectionResolution,
|
|
15
|
+
resolveSectionTarget,
|
|
16
|
+
SECTION_TARGET_LINK_PARAM,
|
|
17
|
+
type SectionResolutionStatus,
|
|
18
|
+
type SectionTargetV1,
|
|
19
|
+
} from "../../../core/sections";
|
|
20
|
+
import { buildDocDeepLink, type DocumentDeepLinkTarget } from "./deep-links";
|
|
21
|
+
|
|
22
|
+
export interface SectionLinkTarget extends DocumentDeepLinkTarget {
|
|
23
|
+
/** Readable heading anchor (HTML id). */
|
|
24
|
+
anchor: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type SectionLinkNoticeKind =
|
|
28
|
+
| "copied_link"
|
|
29
|
+
| "copied_citation"
|
|
30
|
+
| "citation_unavailable"
|
|
31
|
+
| "clipboard_unavailable"
|
|
32
|
+
| SectionResolutionStatus
|
|
33
|
+
| "invalid_citation";
|
|
34
|
+
|
|
35
|
+
/** Ephemeral, content-free status copy for outline/rail feedback. */
|
|
36
|
+
export const SECTION_LINK_NOTICE_COPY: Record<SectionLinkNoticeKind, string> = {
|
|
37
|
+
copied_link: "Copied section link",
|
|
38
|
+
copied_citation: "Copied citation link",
|
|
39
|
+
citation_unavailable: "Citation unavailable for this section",
|
|
40
|
+
clipboard_unavailable: "Could not copy link",
|
|
41
|
+
exact: "Exact section match",
|
|
42
|
+
recovered: "Section recovered",
|
|
43
|
+
ambiguous: "Ambiguous section link — not navigating",
|
|
44
|
+
stale: "Stale section link — not navigating",
|
|
45
|
+
missing: "Section link not found — not navigating",
|
|
46
|
+
invalid_citation: "Invalid section citation — not navigating",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** Absolute readable section URL for human sharing (no durable selector). */
|
|
50
|
+
export function buildReadableSectionUrl(
|
|
51
|
+
origin: string,
|
|
52
|
+
target: SectionLinkTarget
|
|
53
|
+
): string {
|
|
54
|
+
const path = `${buildDocDeepLink({
|
|
55
|
+
uri: target.uri,
|
|
56
|
+
view: target.view ?? "rendered",
|
|
57
|
+
})}#${target.anchor}`;
|
|
58
|
+
return `${origin}${path}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Absolute citation URL: readable `#anchor` plus bounded `st` selector.
|
|
63
|
+
* Returns null when a faithful bounded encoding cannot be produced.
|
|
64
|
+
*/
|
|
65
|
+
export function buildCitationSectionUrl(
|
|
66
|
+
origin: string,
|
|
67
|
+
target: SectionLinkTarget,
|
|
68
|
+
sectionTarget: SectionTargetV1
|
|
69
|
+
): string | null {
|
|
70
|
+
const encoded = encodeSectionTargetLinkParam(sectionTarget);
|
|
71
|
+
if (!encoded) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const params = new URLSearchParams({ uri: target.uri });
|
|
75
|
+
params.set("view", target.view ?? "rendered");
|
|
76
|
+
params.set(SECTION_TARGET_LINK_PARAM, encoded);
|
|
77
|
+
return `${origin}/doc?${params.toString()}#${target.anchor}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Read the raw `st` query value from a location search string. */
|
|
81
|
+
export function readSectionTargetLinkParam(search: string): string | null {
|
|
82
|
+
const value = new URLSearchParams(search).get(SECTION_TARGET_LINK_PARAM);
|
|
83
|
+
return value && value.length > 0 ? value : null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Strip the additive `st` param while preserving other query fields. */
|
|
87
|
+
export function stripSectionTargetLinkParam(search: string): string {
|
|
88
|
+
const params = new URLSearchParams(
|
|
89
|
+
search.startsWith("?") ? search.slice(1) : search
|
|
90
|
+
);
|
|
91
|
+
params.delete(SECTION_TARGET_LINK_PARAM);
|
|
92
|
+
const serialized = params.toString();
|
|
93
|
+
return serialized.length > 0 ? `?${serialized}` : "";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface ResolveSectionLinkInput {
|
|
97
|
+
content: string;
|
|
98
|
+
uri: string;
|
|
99
|
+
/** Raw `st` query value. */
|
|
100
|
+
encodedTarget: string | null;
|
|
101
|
+
/** Readable hash without leading `#`. */
|
|
102
|
+
hashAnchor: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface ResolveSectionLinkResult {
|
|
106
|
+
/** When true, hash-only scroll must not run. */
|
|
107
|
+
blockHashNavigation: boolean;
|
|
108
|
+
/** Anchor to scroll to when navigable. */
|
|
109
|
+
navigateAnchor: string | null;
|
|
110
|
+
notice: SectionLinkNoticeKind | null;
|
|
111
|
+
/** Drop `st` from the address bar after a successful recovery. */
|
|
112
|
+
cleanCitationParam: boolean;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Resolve an optional durable selector against current document content.
|
|
117
|
+
* Readable `#anchor`-only links keep legacy behavior (no block).
|
|
118
|
+
*/
|
|
119
|
+
export async function resolveSectionLinkNavigation(
|
|
120
|
+
input: ResolveSectionLinkInput
|
|
121
|
+
): Promise<ResolveSectionLinkResult> {
|
|
122
|
+
if (!input.encodedTarget) {
|
|
123
|
+
return {
|
|
124
|
+
blockHashNavigation: false,
|
|
125
|
+
navigateAnchor: input.hashAnchor || null,
|
|
126
|
+
notice: null,
|
|
127
|
+
cleanCitationParam: false,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const target = decodeSectionTargetLinkParam(input.encodedTarget);
|
|
132
|
+
if (!target) {
|
|
133
|
+
return {
|
|
134
|
+
blockHashNavigation: true,
|
|
135
|
+
navigateAnchor: null,
|
|
136
|
+
notice: "invalid_citation",
|
|
137
|
+
cleanCitationParam: false,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const resolution = await resolveSectionTarget({
|
|
142
|
+
content: input.content,
|
|
143
|
+
target,
|
|
144
|
+
uri: input.uri,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (isNavigableSectionResolution(resolution)) {
|
|
148
|
+
return {
|
|
149
|
+
blockHashNavigation: false,
|
|
150
|
+
navigateAnchor: resolution.section.anchor,
|
|
151
|
+
notice: resolution.status,
|
|
152
|
+
cleanCitationParam: true,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
blockHashNavigation: true,
|
|
158
|
+
navigateAnchor: null,
|
|
159
|
+
notice: resolution.status,
|
|
160
|
+
cleanCitationParam: false,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Create a citation URL for an outline section using shared core create. */
|
|
165
|
+
export async function createCitationSectionUrl(input: {
|
|
166
|
+
origin: string;
|
|
167
|
+
uri: string;
|
|
168
|
+
content: string;
|
|
169
|
+
anchor: string;
|
|
170
|
+
view?: "rendered" | "source";
|
|
171
|
+
}): Promise<string | null> {
|
|
172
|
+
const target = await createSectionTarget({
|
|
173
|
+
content: input.content,
|
|
174
|
+
uri: input.uri,
|
|
175
|
+
anchor: input.anchor,
|
|
176
|
+
});
|
|
177
|
+
if (!target) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
return buildCitationSectionUrl(
|
|
181
|
+
input.origin,
|
|
182
|
+
{
|
|
183
|
+
uri: input.uri,
|
|
184
|
+
view: input.view ?? "rendered",
|
|
185
|
+
anchor: input.anchor,
|
|
186
|
+
},
|
|
187
|
+
target
|
|
188
|
+
);
|
|
189
|
+
}
|