@bevel-software/platform-shared 0.15.1 → 0.20.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/dist/auth/types.d.ts +12 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/git/pr.types.d.ts +75 -11
- package/dist/git/pr.types.d.ts.map +1 -1
- package/dist/git/types.d.ts +28 -1
- package/dist/git/types.d.ts.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/workflow/events.d.ts +32 -4
- package/dist/workflow/events.d.ts.map +1 -1
- package/dist/workflow/events.js.map +1 -1
- package/dist/workflow/interface.d.ts +103 -4
- package/dist/workflow/interface.d.ts.map +1 -1
- package/dist/workflow/types.d.ts +49 -0
- package/dist/workflow/types.d.ts.map +1 -1
- package/dist/workspace/access-verbs.d.ts +83 -0
- package/dist/workspace/access-verbs.d.ts.map +1 -0
- package/dist/workspace/access-verbs.js +110 -0
- package/dist/workspace/access-verbs.js.map +1 -0
- package/dist/workspace/agent-preamble.d.ts +33 -0
- package/dist/workspace/agent-preamble.d.ts.map +1 -0
- package/dist/workspace/agent-preamble.js +45 -0
- package/dist/workspace/agent-preamble.js.map +1 -0
- package/dist/workspace/entry-exists.d.ts +27 -0
- package/dist/workspace/entry-exists.d.ts.map +1 -0
- package/dist/workspace/entry-exists.js +33 -0
- package/dist/workspace/entry-exists.js.map +1 -0
- package/dist/workspace/filename.d.ts +15 -0
- package/dist/workspace/filename.d.ts.map +1 -1
- package/dist/workspace/filename.js +30 -0
- package/dist/workspace/filename.js.map +1 -1
- package/dist/workspace/frontmatter-carriers.d.ts +44 -0
- package/dist/workspace/frontmatter-carriers.d.ts.map +1 -0
- package/dist/workspace/frontmatter-carriers.js +52 -0
- package/dist/workspace/frontmatter-carriers.js.map +1 -0
- package/dist/workspace/frontmatter.d.ts +23 -4
- package/dist/workspace/frontmatter.d.ts.map +1 -1
- package/dist/workspace/frontmatter.js +59 -9
- package/dist/workspace/frontmatter.js.map +1 -1
- package/dist/workspace/kb-layout.d.ts +226 -19
- package/dist/workspace/kb-layout.d.ts.map +1 -1
- package/dist/workspace/kb-layout.js +353 -23
- package/dist/workspace/kb-layout.js.map +1 -1
- package/dist/workspace/placeholder.d.ts +21 -0
- package/dist/workspace/placeholder.d.ts.map +1 -0
- package/dist/workspace/placeholder.js +28 -0
- package/dist/workspace/placeholder.js.map +1 -0
- package/dist/workspace/platform-files.d.ts +105 -0
- package/dist/workspace/platform-files.d.ts.map +1 -0
- package/dist/workspace/platform-files.js +147 -0
- package/dist/workspace/platform-files.js.map +1 -0
- package/dist/workspace/types.d.ts +8 -0
- package/dist/workspace/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/auth/types.ts +12 -0
- package/src/git/pr.types.ts +77 -11
- package/src/git/types.ts +35 -1
- package/src/index.ts +6 -0
- package/src/workflow/events.ts +33 -3
- package/src/workflow/interface.ts +127 -4
- package/src/workflow/types.ts +43 -0
- package/src/workspace/access-verbs.ts +124 -0
- package/src/workspace/agent-preamble.ts +47 -0
- package/src/workspace/entry-exists.ts +36 -0
- package/src/workspace/filename.ts +31 -0
- package/src/workspace/frontmatter-carriers.ts +57 -0
- package/src/workspace/frontmatter.ts +57 -8
- package/src/workspace/kb-layout.ts +388 -25
- package/src/workspace/placeholder.ts +29 -0
- package/src/workspace/platform-files.ts +188 -0
- package/src/workspace/types.ts +8 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workflow/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workflow/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The access verbs and the ONE dependency graph between them.
|
|
3
|
+
*
|
|
4
|
+
* Shared so that everything that folds verbs — the resolver in core-backend,
|
|
5
|
+
* the eligible lists it serves, and the share dialog in core-frontend that
|
|
6
|
+
* renders and edits them — reads the same table. A second fold written out by
|
|
7
|
+
* hand somewhere else is how the sheet comes to show "Owner" for someone the
|
|
8
|
+
* resolver refuses, or writes a `read:` line under an `owner:` it just granted.
|
|
9
|
+
*
|
|
10
|
+
* `read` controls who may VIEW a path. It is default-deny: a path with no
|
|
11
|
+
* effective grant of any verb is not readable. `write` is editing (and, with
|
|
12
|
+
* it, approval rights), `download` is saving a copy, `owner` is the contact
|
|
13
|
+
* point for the node and the right to manage its access.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Verbs an `access.md` frontmatter can grant, each a list of principals
|
|
17
|
+
* optionally prefixed with `deny `. `AccessFile.entries` in the backend is
|
|
18
|
+
* statically keyed on this union; keep `Verb` and `KNOWN_VERBS` in lockstep.
|
|
19
|
+
*/
|
|
20
|
+
export declare const KNOWN_VERBS: readonly ["read", "write", "download", "owner"];
|
|
21
|
+
export type Verb = (typeof KNOWN_VERBS)[number];
|
|
22
|
+
/**
|
|
23
|
+
* THE DEPENDENCY GRAPH — what holding each verb presupposes, declared once.
|
|
24
|
+
* `owner` presupposes `write` and `download`; `write` and `download` each
|
|
25
|
+
* presuppose `read`; `read` presupposes nothing. Everything about how verbs
|
|
26
|
+
* fold into one another is DERIVED from this table, in both directions:
|
|
27
|
+
*
|
|
28
|
+
* - a GRANT confers, downwards, every verb the granted one presupposes
|
|
29
|
+
* (`sourceVerbsFor`, `effectiveVerbs`): an owner may edit, save and open;
|
|
30
|
+
* an editor may open; someone trusted with a copy may open it;
|
|
31
|
+
* - a DENIAL strips, upwards, every verb that presupposes the denied one
|
|
32
|
+
* (`requiredVerbsFor`): nobody owns what they may not edit, and nobody
|
|
33
|
+
* edits or saves what they may not open.
|
|
34
|
+
*
|
|
35
|
+
* Neither converse is implied: a `deny write` says nothing about `read`, and a
|
|
36
|
+
* `read` grant confers no `write`. `write` and `download` are independent of
|
|
37
|
+
* each other. Add a verb, or change what one presupposes, HERE and nowhere
|
|
38
|
+
* else; every list and fold below follows.
|
|
39
|
+
*/
|
|
40
|
+
export declare const VERB_REQUIRES: Readonly<Record<Verb, readonly Verb[]>>;
|
|
41
|
+
/**
|
|
42
|
+
* Verbs whose GRANT confers `verb`, target verb first: `verb` itself, then
|
|
43
|
+
* every verb that presupposes it, in `KNOWN_VERBS` order.
|
|
44
|
+
*/
|
|
45
|
+
export declare function sourceVerbsFor(verb: Verb): Verb[];
|
|
46
|
+
/**
|
|
47
|
+
* Verbs whose DENIAL strips `verb`, target verb first: `verb` itself, then
|
|
48
|
+
* every verb it presupposes, in `KNOWN_VERBS` order.
|
|
49
|
+
*/
|
|
50
|
+
export declare function requiredVerbsFor(verb: Verb): Verb[];
|
|
51
|
+
/**
|
|
52
|
+
* The verbs in the order a change to a principal's set has to be APPLIED:
|
|
53
|
+
* broadest first, so every verb comes before the verbs it presupposes (ties in
|
|
54
|
+
* `KNOWN_VERBS` order). Lowering must start at the top — denying `write` while
|
|
55
|
+
* an `owner:` grant still stands in the same file is refused as ineffective,
|
|
56
|
+
* since owner confers write; stripping owner first removes what was conferring
|
|
57
|
+
* it. Raising reads the same order for the opposite reason: granting `owner`
|
|
58
|
+
* first satisfies the rest in one line.
|
|
59
|
+
*/
|
|
60
|
+
export declare const VERBS_BROADEST_FIRST: readonly Verb[];
|
|
61
|
+
/** One flag per verb: what a principal holds, or what a form has ticked. */
|
|
62
|
+
export type VerbSet = Record<Verb, boolean>;
|
|
63
|
+
/** A partial set — flags left out read as not held. */
|
|
64
|
+
export type VerbFlags = Partial<Record<Verb, boolean>>;
|
|
65
|
+
/**
|
|
66
|
+
* The grant fold, as a whole set: what a principal EFFECTIVELY holds given the
|
|
67
|
+
* verbs they are granted. Each verb is held when it, or any verb that
|
|
68
|
+
* presupposes it, is in `held`. Idempotent on an already-folded set.
|
|
69
|
+
*/
|
|
70
|
+
export declare function effectiveVerbs(held: VerbFlags): VerbSet;
|
|
71
|
+
/**
|
|
72
|
+
* True when some OTHER verb in `held` confers `verb` — it is implied, not
|
|
73
|
+
* chosen, which is what a form renders as checked-and-disabled.
|
|
74
|
+
*/
|
|
75
|
+
export declare function conferredByOthers(held: VerbFlags, verb: Verb): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* The fewest grant lines that produce `held`: every held verb that no other
|
|
78
|
+
* held verb confers, broadest first. `{ owner }` is one line; `{ write, read,
|
|
79
|
+
* download }` is `write` and `download` (read rides on either); `{ read,
|
|
80
|
+
* download }` is `download` alone. A flag left out is not granted.
|
|
81
|
+
*/
|
|
82
|
+
export declare function minimalGrantVerbs(held: VerbFlags): Verb[];
|
|
83
|
+
//# sourceMappingURL=access-verbs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-verbs.d.ts","sourceRoot":"","sources":["../../src/workspace/access-verbs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;GAIG;AACH,eAAO,MAAM,WAAW,iDAAkD,CAAC;AAC3E,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC,CAKjE,CAAC;AAcF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,CAEjD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,CAGnD;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,IAAI,EAG/C,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5C,uDAAuD;AACvD,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAIvD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAEtE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,EAAE,CAEzD"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The access verbs and the ONE dependency graph between them.
|
|
3
|
+
*
|
|
4
|
+
* Shared so that everything that folds verbs — the resolver in core-backend,
|
|
5
|
+
* the eligible lists it serves, and the share dialog in core-frontend that
|
|
6
|
+
* renders and edits them — reads the same table. A second fold written out by
|
|
7
|
+
* hand somewhere else is how the sheet comes to show "Owner" for someone the
|
|
8
|
+
* resolver refuses, or writes a `read:` line under an `owner:` it just granted.
|
|
9
|
+
*
|
|
10
|
+
* `read` controls who may VIEW a path. It is default-deny: a path with no
|
|
11
|
+
* effective grant of any verb is not readable. `write` is editing (and, with
|
|
12
|
+
* it, approval rights), `download` is saving a copy, `owner` is the contact
|
|
13
|
+
* point for the node and the right to manage its access.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Verbs an `access.md` frontmatter can grant, each a list of principals
|
|
17
|
+
* optionally prefixed with `deny `. `AccessFile.entries` in the backend is
|
|
18
|
+
* statically keyed on this union; keep `Verb` and `KNOWN_VERBS` in lockstep.
|
|
19
|
+
*/
|
|
20
|
+
export const KNOWN_VERBS = ['read', 'write', 'download', 'owner'];
|
|
21
|
+
/**
|
|
22
|
+
* THE DEPENDENCY GRAPH — what holding each verb presupposes, declared once.
|
|
23
|
+
* `owner` presupposes `write` and `download`; `write` and `download` each
|
|
24
|
+
* presuppose `read`; `read` presupposes nothing. Everything about how verbs
|
|
25
|
+
* fold into one another is DERIVED from this table, in both directions:
|
|
26
|
+
*
|
|
27
|
+
* - a GRANT confers, downwards, every verb the granted one presupposes
|
|
28
|
+
* (`sourceVerbsFor`, `effectiveVerbs`): an owner may edit, save and open;
|
|
29
|
+
* an editor may open; someone trusted with a copy may open it;
|
|
30
|
+
* - a DENIAL strips, upwards, every verb that presupposes the denied one
|
|
31
|
+
* (`requiredVerbsFor`): nobody owns what they may not edit, and nobody
|
|
32
|
+
* edits or saves what they may not open.
|
|
33
|
+
*
|
|
34
|
+
* Neither converse is implied: a `deny write` says nothing about `read`, and a
|
|
35
|
+
* `read` grant confers no `write`. `write` and `download` are independent of
|
|
36
|
+
* each other. Add a verb, or change what one presupposes, HERE and nowhere
|
|
37
|
+
* else; every list and fold below follows.
|
|
38
|
+
*/
|
|
39
|
+
export const VERB_REQUIRES = {
|
|
40
|
+
read: [],
|
|
41
|
+
write: ['read'],
|
|
42
|
+
download: ['read'],
|
|
43
|
+
owner: ['write', 'download'],
|
|
44
|
+
};
|
|
45
|
+
/** `verb` and everything it presupposes, transitively. */
|
|
46
|
+
function presupposedBy(verb) {
|
|
47
|
+
const out = new Set();
|
|
48
|
+
const visit = (v) => {
|
|
49
|
+
if (out.has(v))
|
|
50
|
+
return;
|
|
51
|
+
out.add(v);
|
|
52
|
+
for (const dep of VERB_REQUIRES[v])
|
|
53
|
+
visit(dep);
|
|
54
|
+
};
|
|
55
|
+
visit(verb);
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Verbs whose GRANT confers `verb`, target verb first: `verb` itself, then
|
|
60
|
+
* every verb that presupposes it, in `KNOWN_VERBS` order.
|
|
61
|
+
*/
|
|
62
|
+
export function sourceVerbsFor(verb) {
|
|
63
|
+
return [verb, ...KNOWN_VERBS.filter((v) => v !== verb && presupposedBy(v).has(verb))];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Verbs whose DENIAL strips `verb`, target verb first: `verb` itself, then
|
|
67
|
+
* every verb it presupposes, in `KNOWN_VERBS` order.
|
|
68
|
+
*/
|
|
69
|
+
export function requiredVerbsFor(verb) {
|
|
70
|
+
const needs = presupposedBy(verb);
|
|
71
|
+
return [verb, ...KNOWN_VERBS.filter((v) => v !== verb && needs.has(v))];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The verbs in the order a change to a principal's set has to be APPLIED:
|
|
75
|
+
* broadest first, so every verb comes before the verbs it presupposes (ties in
|
|
76
|
+
* `KNOWN_VERBS` order). Lowering must start at the top — denying `write` while
|
|
77
|
+
* an `owner:` grant still stands in the same file is refused as ineffective,
|
|
78
|
+
* since owner confers write; stripping owner first removes what was conferring
|
|
79
|
+
* it. Raising reads the same order for the opposite reason: granting `owner`
|
|
80
|
+
* first satisfies the rest in one line.
|
|
81
|
+
*/
|
|
82
|
+
export const VERBS_BROADEST_FIRST = [...KNOWN_VERBS].sort((a, b) => presupposedBy(b).size - presupposedBy(a).size || KNOWN_VERBS.indexOf(a) - KNOWN_VERBS.indexOf(b));
|
|
83
|
+
/**
|
|
84
|
+
* The grant fold, as a whole set: what a principal EFFECTIVELY holds given the
|
|
85
|
+
* verbs they are granted. Each verb is held when it, or any verb that
|
|
86
|
+
* presupposes it, is in `held`. Idempotent on an already-folded set.
|
|
87
|
+
*/
|
|
88
|
+
export function effectiveVerbs(held) {
|
|
89
|
+
const out = {};
|
|
90
|
+
for (const verb of KNOWN_VERBS)
|
|
91
|
+
out[verb] = sourceVerbsFor(verb).some((w) => held[w] === true);
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* True when some OTHER verb in `held` confers `verb` — it is implied, not
|
|
96
|
+
* chosen, which is what a form renders as checked-and-disabled.
|
|
97
|
+
*/
|
|
98
|
+
export function conferredByOthers(held, verb) {
|
|
99
|
+
return sourceVerbsFor(verb).some((w) => w !== verb && held[w] === true);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The fewest grant lines that produce `held`: every held verb that no other
|
|
103
|
+
* held verb confers, broadest first. `{ owner }` is one line; `{ write, read,
|
|
104
|
+
* download }` is `write` and `download` (read rides on either); `{ read,
|
|
105
|
+
* download }` is `download` alone. A flag left out is not granted.
|
|
106
|
+
*/
|
|
107
|
+
export function minimalGrantVerbs(held) {
|
|
108
|
+
return VERBS_BROADEST_FIRST.filter((verb) => held[verb] === true && !conferredByOthers(held, verb));
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=access-verbs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-verbs.js","sourceRoot":"","sources":["../../src/workspace/access-verbs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rules about the deployment preamble's TEXT that both sides need to
|
|
3
|
+
* agree on: the file it lives in, the caps it is cut at, and what counts as a
|
|
4
|
+
* private comment inside it.
|
|
5
|
+
*
|
|
6
|
+
* These lived in the backend composer and were mirrored by hand in the
|
|
7
|
+
* frontend editor, whose own comment said so. The two are not free to differ:
|
|
8
|
+
* the editor decides what an admin is shown and what it writes back, the
|
|
9
|
+
* composer decides what agents receive, and a drift between them shows the
|
|
10
|
+
* admin one description while agents get another.
|
|
11
|
+
*
|
|
12
|
+
* Pure: no IO, no clock, no platform assumptions.
|
|
13
|
+
*/
|
|
14
|
+
/** The repository-root file an admin edits. */
|
|
15
|
+
export declare const PREAMBLE_FILE = "mcp-description.md";
|
|
16
|
+
/** UTF-16 units of preamble sent on the handshake before the marker replaces the rest. */
|
|
17
|
+
export declare const PREAMBLE_CAP = 6000;
|
|
18
|
+
/** UTF-16 units of the whole tool prefix (fixed line included). */
|
|
19
|
+
export declare const TOOL_PREFIX_CAP = 300;
|
|
20
|
+
/**
|
|
21
|
+
* Remove every `<!-- … -->` block.
|
|
22
|
+
*
|
|
23
|
+
* A `<!--` that is never closed takes the rest of the text with it and is
|
|
24
|
+
* reported, so a caller can warn: that is the fail-closed half of the rule,
|
|
25
|
+
* and it is why an admin's private note cannot leak through the likeliest
|
|
26
|
+
* editing slip. The editor strips the same blocks to decide what to show, and
|
|
27
|
+
* closes an unterminated one when it writes back.
|
|
28
|
+
*/
|
|
29
|
+
export declare function stripHtmlComments(text: string): {
|
|
30
|
+
text: string;
|
|
31
|
+
unterminated: boolean;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=agent-preamble.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-preamble.d.ts","sourceRoot":"","sources":["../../src/workspace/agent-preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+CAA+C;AAC/C,eAAO,MAAM,aAAa,uBAAuB,CAAC;AAElD,0FAA0F;AAC1F,eAAO,MAAM,YAAY,OAAQ,CAAC;AAElC,mEAAmE;AACnE,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAcvF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rules about the deployment preamble's TEXT that both sides need to
|
|
3
|
+
* agree on: the file it lives in, the caps it is cut at, and what counts as a
|
|
4
|
+
* private comment inside it.
|
|
5
|
+
*
|
|
6
|
+
* These lived in the backend composer and were mirrored by hand in the
|
|
7
|
+
* frontend editor, whose own comment said so. The two are not free to differ:
|
|
8
|
+
* the editor decides what an admin is shown and what it writes back, the
|
|
9
|
+
* composer decides what agents receive, and a drift between them shows the
|
|
10
|
+
* admin one description while agents get another.
|
|
11
|
+
*
|
|
12
|
+
* Pure: no IO, no clock, no platform assumptions.
|
|
13
|
+
*/
|
|
14
|
+
/** The repository-root file an admin edits. */
|
|
15
|
+
export const PREAMBLE_FILE = 'mcp-description.md';
|
|
16
|
+
/** UTF-16 units of preamble sent on the handshake before the marker replaces the rest. */
|
|
17
|
+
export const PREAMBLE_CAP = 6_000;
|
|
18
|
+
/** UTF-16 units of the whole tool prefix (fixed line included). */
|
|
19
|
+
export const TOOL_PREFIX_CAP = 300;
|
|
20
|
+
/**
|
|
21
|
+
* Remove every `<!-- … -->` block.
|
|
22
|
+
*
|
|
23
|
+
* A `<!--` that is never closed takes the rest of the text with it and is
|
|
24
|
+
* reported, so a caller can warn: that is the fail-closed half of the rule,
|
|
25
|
+
* and it is why an admin's private note cannot leak through the likeliest
|
|
26
|
+
* editing slip. The editor strips the same blocks to decide what to show, and
|
|
27
|
+
* closes an unterminated one when it writes back.
|
|
28
|
+
*/
|
|
29
|
+
export function stripHtmlComments(text) {
|
|
30
|
+
let out = '';
|
|
31
|
+
let from = 0;
|
|
32
|
+
for (;;) {
|
|
33
|
+
const open = text.indexOf('<!--', from);
|
|
34
|
+
if (open === -1) {
|
|
35
|
+
out += text.slice(from);
|
|
36
|
+
return { text: out, unterminated: false };
|
|
37
|
+
}
|
|
38
|
+
out += text.slice(from, open);
|
|
39
|
+
const close = text.indexOf('-->', open + 4);
|
|
40
|
+
if (close === -1)
|
|
41
|
+
return { text: out, unterminated: true };
|
|
42
|
+
from = close + 3;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=agent-preamble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-preamble.js","sourceRoot":"","sources":["../../src/workspace/agent-preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAElD,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAElC,mEAAmE;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC;YAChB,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxB,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QAC5C,CAAC;QACD,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAC5C,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;QAC3D,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE sentence a rename, a move or a copy answers with when something is
|
|
3
|
+
* already at the destination.
|
|
4
|
+
*
|
|
5
|
+
* A rename is not a way to replace content: renaming a `.docx` onto an
|
|
6
|
+
* existing `.md` used to hand the markdown file the Word bytes and break the
|
|
7
|
+
* page. Every surface — the sidebar rename box, a drag onto a folder, the
|
|
8
|
+
* agent's `move_file` and `copy_file` — refuses with this one sentence, so a
|
|
9
|
+
* user who meets it in the sidebar and an agent that meets it in a tool
|
|
10
|
+
* result are told the same thing.
|
|
11
|
+
*
|
|
12
|
+
* Kept here, beside `filename.ts`, for the same reason that file is: the
|
|
13
|
+
* backend throws it and the frontend renders it, and neither should spell it
|
|
14
|
+
* its own way.
|
|
15
|
+
*/
|
|
16
|
+
/** What is already sitting at the destination. */
|
|
17
|
+
export type ExistingEntryKind = 'file' | 'folder';
|
|
18
|
+
/**
|
|
19
|
+
* `A file named <name> already exists in <folder>.` — `name` and `folder` are
|
|
20
|
+
* read off `destinationPath`, which may be workspace-relative or
|
|
21
|
+
* repo-relative; only its last two segments are used, so the reader sees the
|
|
22
|
+
* name they typed and the folder they were aiming at rather than a full path.
|
|
23
|
+
* A destination directly at the top of the tree has no folder segment to
|
|
24
|
+
* name, and says `the top level` instead.
|
|
25
|
+
*/
|
|
26
|
+
export declare function entryExistsMessage(kind: ExistingEntryKind, destinationPath: string): string;
|
|
27
|
+
//# sourceMappingURL=entry-exists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-exists.d.ts","sourceRoot":"","sources":["../../src/workspace/entry-exists.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,kDAAkD;AAClD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAQ3F"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE sentence a rename, a move or a copy answers with when something is
|
|
3
|
+
* already at the destination.
|
|
4
|
+
*
|
|
5
|
+
* A rename is not a way to replace content: renaming a `.docx` onto an
|
|
6
|
+
* existing `.md` used to hand the markdown file the Word bytes and break the
|
|
7
|
+
* page. Every surface — the sidebar rename box, a drag onto a folder, the
|
|
8
|
+
* agent's `move_file` and `copy_file` — refuses with this one sentence, so a
|
|
9
|
+
* user who meets it in the sidebar and an agent that meets it in a tool
|
|
10
|
+
* result are told the same thing.
|
|
11
|
+
*
|
|
12
|
+
* Kept here, beside `filename.ts`, for the same reason that file is: the
|
|
13
|
+
* backend throws it and the frontend renders it, and neither should spell it
|
|
14
|
+
* its own way.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* `A file named <name> already exists in <folder>.` — `name` and `folder` are
|
|
18
|
+
* read off `destinationPath`, which may be workspace-relative or
|
|
19
|
+
* repo-relative; only its last two segments are used, so the reader sees the
|
|
20
|
+
* name they typed and the folder they were aiming at rather than a full path.
|
|
21
|
+
* A destination directly at the top of the tree has no folder segment to
|
|
22
|
+
* name, and says `the top level` instead.
|
|
23
|
+
*/
|
|
24
|
+
export function entryExistsMessage(kind, destinationPath) {
|
|
25
|
+
const segments = destinationPath
|
|
26
|
+
.replace(/\\/g, '/')
|
|
27
|
+
.split('/')
|
|
28
|
+
.filter((segment) => segment.length > 0 && segment !== '.');
|
|
29
|
+
const name = segments[segments.length - 1] ?? destinationPath;
|
|
30
|
+
const folder = segments.length > 1 ? segments[segments.length - 2] : 'the top level';
|
|
31
|
+
return `A ${kind} named ${name} already exists in ${folder}.`;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=entry-exists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-exists.js","sourceRoot":"","sources":["../../src/workspace/entry-exists.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAuB,EAAE,eAAuB;IACjF,MAAM,QAAQ,GAAG,eAAe;SAC7B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,KAAK,GAAG,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;IACrF,OAAO,KAAK,IAAI,UAAU,IAAI,sBAAsB,MAAM,GAAG,CAAC;AAChE,CAAC"}
|
|
@@ -25,6 +25,21 @@ export declare function validateFilename(name: string): string | null;
|
|
|
25
25
|
* `\` would round-trip differently on Windows vs the Linux container.
|
|
26
26
|
*/
|
|
27
27
|
export declare function validateRelativePath(relativePath: string): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* ONE identity per file, so everything that coordinates on a path agrees about
|
|
30
|
+
* what it is coordinating on: an in-process queue, a database lock row, and
|
|
31
|
+
* the bytes on disk. {@link validateRelativePath} accepts a leading `./` and
|
|
32
|
+
* repeated slashes as spellings of the same path, and two callers spelling one
|
|
33
|
+
* file differently would otherwise take two different locks and write over
|
|
34
|
+
* each other. `.` and `..` segments are refused outright by the validator, so
|
|
35
|
+
* there is nothing to resolve here beyond the separators.
|
|
36
|
+
*
|
|
37
|
+
* Case is deliberately left alone. The deployment target is Linux, where
|
|
38
|
+
* `Foo.md` and `foo.md` are two different files; folding case to suit a
|
|
39
|
+
* case-insensitive development machine would merge two real files in
|
|
40
|
+
* production, which is a worse failure than the race it would close.
|
|
41
|
+
*/
|
|
42
|
+
export declare function canonicalRelativePath(relativePath: string): string;
|
|
28
43
|
/**
|
|
29
44
|
* Throwing wrapper for the backend service layer — keeps call sites a single
|
|
30
45
|
* line and produces a clear `Error` the route handler can surface as a 400.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filename.d.ts","sourceRoot":"","sources":["../../src/workspace/filename.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA0BH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA2B5D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBxE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAGlE"}
|
|
1
|
+
{"version":3,"file":"filename.d.ts","sourceRoot":"","sources":["../../src/workspace/filename.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA0BH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA2B5D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBxE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAelE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAGlE"}
|
|
@@ -90,6 +90,36 @@ export function validateRelativePath(relativePath) {
|
|
|
90
90
|
}
|
|
91
91
|
return null;
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* ONE identity per file, so everything that coordinates on a path agrees about
|
|
95
|
+
* what it is coordinating on: an in-process queue, a database lock row, and
|
|
96
|
+
* the bytes on disk. {@link validateRelativePath} accepts a leading `./` and
|
|
97
|
+
* repeated slashes as spellings of the same path, and two callers spelling one
|
|
98
|
+
* file differently would otherwise take two different locks and write over
|
|
99
|
+
* each other. `.` and `..` segments are refused outright by the validator, so
|
|
100
|
+
* there is nothing to resolve here beyond the separators.
|
|
101
|
+
*
|
|
102
|
+
* Case is deliberately left alone. The deployment target is Linux, where
|
|
103
|
+
* `Foo.md` and `foo.md` are two different files; folding case to suit a
|
|
104
|
+
* case-insensitive development machine would merge two real files in
|
|
105
|
+
* production, which is a worse failure than the race it would close.
|
|
106
|
+
*/
|
|
107
|
+
export function canonicalRelativePath(relativePath) {
|
|
108
|
+
// Never LAUNDER a path. Dropping empty segments would turn the absolute
|
|
109
|
+
// `/etc/passwd` into the perfectly ordinary `etc/passwd`, and an absolute
|
|
110
|
+
// path is exactly what `path.resolve` lets win over the workspace directory
|
|
111
|
+
// — which is why the workspace-boundary check refuses it today. A path this
|
|
112
|
+
// cannot canonicalise is returned UNCHANGED, so every gate downstream sees
|
|
113
|
+
// what the caller actually sent and goes on refusing it.
|
|
114
|
+
if (relativePath.startsWith('/') || validateRelativePath(relativePath) !== null) {
|
|
115
|
+
return relativePath;
|
|
116
|
+
}
|
|
117
|
+
return relativePath
|
|
118
|
+
.replace(/^\.\//, '')
|
|
119
|
+
.split('/')
|
|
120
|
+
.filter((segment) => segment.length > 0)
|
|
121
|
+
.join('/');
|
|
122
|
+
}
|
|
93
123
|
/**
|
|
94
124
|
* Throwing wrapper for the backend service layer — keeps call sites a single
|
|
95
125
|
* line and produces a clear `Error` the route handler can surface as a 400.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filename.js","sourceRoot":"","sources":["../../src/workspace/filename.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"filename.js","sourceRoot":"","sources":["../../src/workspace/filename.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which files can carry their OWN frontmatter — and therefore their own
|
|
3
|
+
* per-file access rules.
|
|
4
|
+
*
|
|
5
|
+
* A file-level grant, revoke or restriction splices a `---` YAML block into
|
|
6
|
+
* the file itself. That is right for a Markdown note and destructive for
|
|
7
|
+
* anything else: spliced into a PDF, a presentation or an image it corrupts
|
|
8
|
+
* the bytes (the preview goes blank), and the grant never even resolves.
|
|
9
|
+
* Such a file takes its folder's rules instead.
|
|
10
|
+
*
|
|
11
|
+
* THE ONE predicate for that question: the access routes refuse a file-level
|
|
12
|
+
* mutation on a file it rejects, and the Manage access dialog shows the folder
|
|
13
|
+
* pointer for the same files.
|
|
14
|
+
*
|
|
15
|
+
* The carriers are exactly the files the access resolver reads its own
|
|
16
|
+
* frontmatter from — the backend's core access-frontmatter extension set:
|
|
17
|
+
* Markdown notes (`.md`) and `.tool` definitions (whole-document YAML whose
|
|
18
|
+
* access verbs sit beside the definition). Both are served by the file-reader
|
|
19
|
+
* registry's text-editable text reader. The registry test pins both facts, so
|
|
20
|
+
* this list cannot drift from the resolver or the registry silently. (Neither
|
|
21
|
+
* can live here: the registry's document readers carry backend-only extraction
|
|
22
|
+
* dependencies, and overlays register further extensions at boot — the backend
|
|
23
|
+
* passes its full registered set as `extensions`.)
|
|
24
|
+
*
|
|
25
|
+
* Matching is case-SENSITIVE, as the resolver's is: `Note.MD` carries no
|
|
26
|
+
* enforced rule, so a grant written there would never resolve. An extensionless
|
|
27
|
+
* file is NOT a carrier either: its content may be anything, and a path alone
|
|
28
|
+
* cannot tell a note from a binary.
|
|
29
|
+
*/
|
|
30
|
+
export declare const FRONTMATTER_CARRIER_EXTENSIONS: readonly string[];
|
|
31
|
+
/**
|
|
32
|
+
* True when the file at `path` can carry its own frontmatter (and so its own
|
|
33
|
+
* access rules). `extensions` defaults to the core set; the backend passes the
|
|
34
|
+
* resolver's registered set so an overlay's kinds count too.
|
|
35
|
+
*/
|
|
36
|
+
export declare function canCarryFrontmatter(path: string, extensions?: readonly string[]): boolean;
|
|
37
|
+
/** The `kind` a refused file-level access mutation answers with. */
|
|
38
|
+
export declare const FOLDER_GOVERNS_ACCESS_KIND = "folder-governs-access";
|
|
39
|
+
/**
|
|
40
|
+
* The one sentence both the 422 and the dialog say, naming the folder whose
|
|
41
|
+
* rules govern the file.
|
|
42
|
+
*/
|
|
43
|
+
export declare function folderGovernsAccessMessage(folder: string): string;
|
|
44
|
+
//# sourceMappingURL=frontmatter-carriers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter-carriers.d.ts","sourceRoot":"","sources":["../../src/workspace/frontmatter-carriers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,8BAA8B,EAAE,SAAS,MAAM,EAAqB,CAAC;AAElF;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,SAAS,MAAM,EAAmC,GAC7D,OAAO,CAMT;AAED,oEAAoE;AACpE,eAAO,MAAM,0BAA0B,0BAA0B,CAAC;AAElE;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which files can carry their OWN frontmatter — and therefore their own
|
|
3
|
+
* per-file access rules.
|
|
4
|
+
*
|
|
5
|
+
* A file-level grant, revoke or restriction splices a `---` YAML block into
|
|
6
|
+
* the file itself. That is right for a Markdown note and destructive for
|
|
7
|
+
* anything else: spliced into a PDF, a presentation or an image it corrupts
|
|
8
|
+
* the bytes (the preview goes blank), and the grant never even resolves.
|
|
9
|
+
* Such a file takes its folder's rules instead.
|
|
10
|
+
*
|
|
11
|
+
* THE ONE predicate for that question: the access routes refuse a file-level
|
|
12
|
+
* mutation on a file it rejects, and the Manage access dialog shows the folder
|
|
13
|
+
* pointer for the same files.
|
|
14
|
+
*
|
|
15
|
+
* The carriers are exactly the files the access resolver reads its own
|
|
16
|
+
* frontmatter from — the backend's core access-frontmatter extension set:
|
|
17
|
+
* Markdown notes (`.md`) and `.tool` definitions (whole-document YAML whose
|
|
18
|
+
* access verbs sit beside the definition). Both are served by the file-reader
|
|
19
|
+
* registry's text-editable text reader. The registry test pins both facts, so
|
|
20
|
+
* this list cannot drift from the resolver or the registry silently. (Neither
|
|
21
|
+
* can live here: the registry's document readers carry backend-only extraction
|
|
22
|
+
* dependencies, and overlays register further extensions at boot — the backend
|
|
23
|
+
* passes its full registered set as `extensions`.)
|
|
24
|
+
*
|
|
25
|
+
* Matching is case-SENSITIVE, as the resolver's is: `Note.MD` carries no
|
|
26
|
+
* enforced rule, so a grant written there would never resolve. An extensionless
|
|
27
|
+
* file is NOT a carrier either: its content may be anything, and a path alone
|
|
28
|
+
* cannot tell a note from a binary.
|
|
29
|
+
*/
|
|
30
|
+
export const FRONTMATTER_CARRIER_EXTENSIONS = ['.md', '.tool'];
|
|
31
|
+
/**
|
|
32
|
+
* True when the file at `path` can carry its own frontmatter (and so its own
|
|
33
|
+
* access rules). `extensions` defaults to the core set; the backend passes the
|
|
34
|
+
* resolver's registered set so an overlay's kinds count too.
|
|
35
|
+
*/
|
|
36
|
+
export function canCarryFrontmatter(path, extensions = FRONTMATTER_CARRIER_EXTENSIONS) {
|
|
37
|
+
const name = path.slice(path.lastIndexOf('/') + 1);
|
|
38
|
+
// The resolver's own rule is a plain suffix match, so a file named exactly
|
|
39
|
+
// `.md` is read for its frontmatter there — and must be a carrier here too,
|
|
40
|
+
// or a rule the resolver honours could not be managed.
|
|
41
|
+
return extensions.some((ext) => name.endsWith(ext));
|
|
42
|
+
}
|
|
43
|
+
/** The `kind` a refused file-level access mutation answers with. */
|
|
44
|
+
export const FOLDER_GOVERNS_ACCESS_KIND = 'folder-governs-access';
|
|
45
|
+
/**
|
|
46
|
+
* The one sentence both the 422 and the dialog say, naming the folder whose
|
|
47
|
+
* rules govern the file.
|
|
48
|
+
*/
|
|
49
|
+
export function folderGovernsAccessMessage(folder) {
|
|
50
|
+
return `This file's access comes from its folder. Manage access on ${folder} instead.`;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=frontmatter-carriers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter-carriers.js","sourceRoot":"","sources":["../../src/workspace/frontmatter-carriers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAsB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAElF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,aAAgC,8BAA8B;IAE9D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACnD,2EAA2E;IAC3E,4EAA4E;IAC5E,uDAAuD;IACvD,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,MAAM,0BAA0B,GAAG,uBAAuB,CAAC;AAElE;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAc;IACvD,OAAO,8DAA8D,MAAM,WAAW,CAAC;AACzF,CAAC"}
|
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE fence rule: a line is a frontmatter fence when, whitespace aside, it is
|
|
3
|
+
* exactly `---`. Forgiving on purpose — an opening fence with a trailing space
|
|
4
|
+
* or an indented fence is still a fence.
|
|
5
|
+
*
|
|
6
|
+
* Every reader in the platform asks this one function. The access model's
|
|
7
|
+
* line scan always judged fences this way while the splitter below demanded
|
|
8
|
+
* `---` at column 0, so a file written with a near-miss fence had access
|
|
9
|
+
* rules that applied while the catalog, the tool manuals and the frontmatter
|
|
10
|
+
* panel saw no frontmatter at all. One rule, asked everywhere, is what keeps
|
|
11
|
+
* a file from meaning two things.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isFrontmatterFence(line: string | undefined): boolean;
|
|
1
14
|
/**
|
|
2
15
|
* The ONE `---` frontmatter splitter, shared by backend and frontend so no file
|
|
3
|
-
* type grows its own
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
16
|
+
* type grows its own reader. Splits a leading fenced YAML block from the body;
|
|
17
|
+
* null when the first line is not a fence or no later line closes it. Fences
|
|
18
|
+
* are judged by {@link isFrontmatterFence}. Parsing the YAML inside is the
|
|
19
|
+
* caller's concern (the access model keeps its own line scan, on the same
|
|
20
|
+
* fence rule, because a splice must put bytes back exactly as it found them).
|
|
21
|
+
*
|
|
22
|
+
* `frontmatter` is the raw text between the fence lines and `body` the raw
|
|
23
|
+
* text after the closing fence's line break, both byte for byte — line
|
|
24
|
+
* endings included — so a caller that rebuilds the file changes nothing it
|
|
25
|
+
* did not mean to.
|
|
7
26
|
*/
|
|
8
27
|
export declare function extractFrontmatter(text: string): {
|
|
9
28
|
frontmatter: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/workspace/frontmatter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/workspace/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4B7F;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAwBpF"}
|