@zvndev/darkmown 2.4.0 → 2.5.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/CHANGELOG.md +10 -0
- package/README.md +33 -0
- package/docs/spec-alignment.md +12 -1
- package/package.json +5 -1
- package/site/pages/docs/index.wd +22 -0
- package/src/compiler/actions.js +25 -1
- package/src/compiler/body.js +5 -1
- package/src/compiler/context.js +107 -1
- package/src/compiler/fetch.js +2 -1
- package/src/compiler/forms.js +19 -1
- package/src/compiler/loops.js +14 -1
- package/src/compiler/markdown.js +2 -1
- package/src/compiler/page.js +3 -1
- package/src/compiler/state.js +9 -1
- package/src/compiler/structure.js +3 -1
- package/src/tools/apply.js +274 -0
- package/src/tools/grammar.js +171 -0
- package/src/tools/index.js +170 -0
- package/src/tools/outline.js +321 -0
- package/src/tools/parse.js +81 -0
- package/src/tools/validate.js +169 -0
- package/types/builder.d.ts +21 -0
- package/types/catalog.d.ts +80 -1
- package/types/compiler/context.d.ts +155 -0
- package/types/compiler/page.d.ts +33 -6
- package/types/compiler/schema.d.ts +88 -0
- package/types/compiler.d.ts +2 -1
- package/types/feeds.d.ts +47 -4
- package/types/index.d.ts +3 -0
- package/types/scaffold.d.ts +3 -1
- package/types/tools/apply.d.ts +68 -0
- package/types/tools/grammar.d.ts +44 -0
- package/types/tools/index.d.ts +75 -0
- package/types/tools/outline.d.ts +102 -0
- package/types/tools/parse.d.ts +26 -0
- package/types/tools/validate.d.ts +36 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** @returns {string[]} Every category name, for callers that want to enumerate. */
|
|
2
|
+
export function categoryNames(): string[];
|
|
3
|
+
/**
|
|
4
|
+
* TOOL ENTRY POINT.
|
|
5
|
+
*
|
|
6
|
+
* @param {string[]} [categories] Category names. Omitted or empty means all of
|
|
7
|
+
* them, which is the whole cheatsheet and is the thing this tool exists to
|
|
8
|
+
* avoid sending.
|
|
9
|
+
* Failures use the same {ok, text, data} shape as every other tool. It used to
|
|
10
|
+
* answer {ok: false, error}, which `Session` never reads, so an unknown category
|
|
11
|
+
* handed the model an undefined message.
|
|
12
|
+
*
|
|
13
|
+
* @returns {{ok: boolean, text: string, data: object}}
|
|
14
|
+
*/
|
|
15
|
+
export function grammar(categories?: string[]): {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
text: string;
|
|
18
|
+
data: object;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* How much a slice saves against sending everything.
|
|
22
|
+
*
|
|
23
|
+
* The plan claims filtering the cheatsheet is both a context saving and a
|
|
24
|
+
* hallucination guard. The saving half is measurable, so it gets measured
|
|
25
|
+
* rather than asserted.
|
|
26
|
+
*
|
|
27
|
+
* @param {string[]} categories
|
|
28
|
+
* @returns {{sliceChars: number, fullChars: number, saved: number, savedPct: number}}
|
|
29
|
+
*/
|
|
30
|
+
export function grammarCost(categories: string[]): {
|
|
31
|
+
sliceChars: number;
|
|
32
|
+
fullChars: number;
|
|
33
|
+
saved: number;
|
|
34
|
+
savedPct: number;
|
|
35
|
+
};
|
|
36
|
+
export namespace CATEGORIES {
|
|
37
|
+
let state: string[];
|
|
38
|
+
let loops: string[];
|
|
39
|
+
let actions: string[];
|
|
40
|
+
let forms: string[];
|
|
41
|
+
let fetch: string[];
|
|
42
|
+
let structure: string[];
|
|
43
|
+
let media: string[];
|
|
44
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tool list rendered for a system prompt.
|
|
3
|
+
*
|
|
4
|
+
* Same discipline as the cheatsheet: concrete argument examples, never
|
|
5
|
+
* `[optional]` bracket notation, because small models copy schematic notation
|
|
6
|
+
* into their output verbatim.
|
|
7
|
+
*
|
|
8
|
+
* @returns {string}
|
|
9
|
+
*/
|
|
10
|
+
export function toolPrompt(): string;
|
|
11
|
+
/**
|
|
12
|
+
* The tool list as a model should be told about it: name, when to reach for it,
|
|
13
|
+
* and the exact argument shape. Kept here rather than in a prompt file so the
|
|
14
|
+
* description can never drift from the dispatcher.
|
|
15
|
+
*/
|
|
16
|
+
export const TOOL_SPECS: {
|
|
17
|
+
name: string;
|
|
18
|
+
args: string;
|
|
19
|
+
use: string;
|
|
20
|
+
}[];
|
|
21
|
+
/**
|
|
22
|
+
* A working copy of a project plus the tools that operate on it.
|
|
23
|
+
*
|
|
24
|
+
* Edits are staged in the session, not written to disk, so a caller can apply,
|
|
25
|
+
* validate, and roll back without touching a filesystem. `history` exists so a
|
|
26
|
+
* run can be scored later on how many calls it took, which is the number that
|
|
27
|
+
* decides whether the tool surface is worth its context budget.
|
|
28
|
+
*/
|
|
29
|
+
export class Session {
|
|
30
|
+
/**
|
|
31
|
+
* @param {Record<string, string>} files Project-relative path → contents.
|
|
32
|
+
* @param {string} entry The file being edited.
|
|
33
|
+
*/
|
|
34
|
+
constructor(files: Record<string, string>, entry: string);
|
|
35
|
+
files: {
|
|
36
|
+
[x: string]: string;
|
|
37
|
+
};
|
|
38
|
+
entry: string;
|
|
39
|
+
original: string;
|
|
40
|
+
/** @type {{tool: string, args: object, ok: boolean}[]} */
|
|
41
|
+
history: {
|
|
42
|
+
tool: string;
|
|
43
|
+
args: object;
|
|
44
|
+
ok: boolean;
|
|
45
|
+
}[];
|
|
46
|
+
/**
|
|
47
|
+
* Dispatch one tool call.
|
|
48
|
+
*
|
|
49
|
+
* An unknown tool name is answered with the list rather than an exception,
|
|
50
|
+
* because a model that guessed a name can recover from a list and cannot
|
|
51
|
+
* recover from a stack trace.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} tool
|
|
54
|
+
* @param {object} [args]
|
|
55
|
+
* @returns {{ok: boolean, text: string, data?: object}}
|
|
56
|
+
*/
|
|
57
|
+
call(tool: string, args?: object): {
|
|
58
|
+
ok: boolean;
|
|
59
|
+
text: string;
|
|
60
|
+
data?: object;
|
|
61
|
+
};
|
|
62
|
+
/** @returns {string} The current content of the file under edit. */
|
|
63
|
+
content(): string;
|
|
64
|
+
/** Discard all staged edits. @returns {void} */
|
|
65
|
+
reset(): void;
|
|
66
|
+
#private;
|
|
67
|
+
}
|
|
68
|
+
import { apply } from "./apply.js";
|
|
69
|
+
import { deps } from "./outline.js";
|
|
70
|
+
import { grammar } from "./grammar.js";
|
|
71
|
+
import { outline } from "./outline.js";
|
|
72
|
+
import { parseToolCall } from "./parse.js";
|
|
73
|
+
import { refs } from "./outline.js";
|
|
74
|
+
import { validate } from "./validate.js";
|
|
75
|
+
export { apply, deps, grammar, outline, parseToolCall, refs, validate };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile and return one symbol per source construct, with every line resolved.
|
|
3
|
+
*
|
|
4
|
+
* Two foldings happen here, both forced by how the compiler works rather than by
|
|
5
|
+
* taste. A statically-unrolled `@loop` recompiles its body once per row, so a
|
|
6
|
+
* directive inside it records N identical symbols at one `file:line`; and a prose
|
|
7
|
+
* read inside such a loop records N line-less reads. Both collapse to one.
|
|
8
|
+
*
|
|
9
|
+
* The `compiled` half is the compiler's own result, derived from the function
|
|
10
|
+
* rather than restated here: widening it to `object` compiled fine while these
|
|
11
|
+
* lived under bench/, and silently lost every property check the moment they
|
|
12
|
+
* became part of the package.
|
|
13
|
+
*
|
|
14
|
+
* @typedef {ReturnType<typeof compileFromMemory>} Compiled
|
|
15
|
+
* @typedef {import("../compiler/context.js").Symbol} Symbol
|
|
16
|
+
*
|
|
17
|
+
* @param {Record<string, string>} files
|
|
18
|
+
* @param {string} entry
|
|
19
|
+
* @returns {{ok: true, symbols: Symbol[], compiled: Compiled} | {ok: false, error: string}}
|
|
20
|
+
*/
|
|
21
|
+
export function symbolsOf(files: Record<string, string>, entry: string): {
|
|
22
|
+
ok: true;
|
|
23
|
+
symbols: Symbol[];
|
|
24
|
+
compiled: Compiled;
|
|
25
|
+
} | {
|
|
26
|
+
ok: false;
|
|
27
|
+
error: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* TOOL ENTRY POINT: outline(files, entry)
|
|
31
|
+
*
|
|
32
|
+
* @param {Record<string, string>} files
|
|
33
|
+
* @param {string} entry
|
|
34
|
+
* @returns {{ok: boolean, text: string, data: object}}
|
|
35
|
+
*/
|
|
36
|
+
export function outline(files: Record<string, string>, entry: string): {
|
|
37
|
+
ok: boolean;
|
|
38
|
+
text: string;
|
|
39
|
+
data: object;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* TOOL ENTRY POINT: refs(files, entry, name)
|
|
43
|
+
*
|
|
44
|
+
* Every place a symbol is declared, written, or read, across the entry and
|
|
45
|
+
* everything it includes. This is the query behind impact expansion: "what else
|
|
46
|
+
* needs to change" is a lookup, not something a model should be recalling.
|
|
47
|
+
*
|
|
48
|
+
* @param {Record<string, string>} files
|
|
49
|
+
* @param {string} entry
|
|
50
|
+
* @param {string} [name] Symbol name, e.g. `cart`. Missing is reported, not thrown.
|
|
51
|
+
* @returns {{ok: boolean, text: string, data: object}}
|
|
52
|
+
*/
|
|
53
|
+
export function refs(files: Record<string, string>, entry: string, name?: string): {
|
|
54
|
+
ok: boolean;
|
|
55
|
+
text: string;
|
|
56
|
+
data: object;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* TOOL ENTRY POINT: deps(files, entry)
|
|
60
|
+
*
|
|
61
|
+
* What this page pulls in (includes, data files, collections) and, for any other
|
|
62
|
+
* page in the project, whether it pulls in the same thing. The reverse direction
|
|
63
|
+
* is what makes "I changed a partial, what breaks" answerable.
|
|
64
|
+
*
|
|
65
|
+
* @param {Record<string, string>} files
|
|
66
|
+
* @param {string} entry
|
|
67
|
+
* @returns {{ok: boolean, text: string, data: object}}
|
|
68
|
+
*/
|
|
69
|
+
export function deps(files: Record<string, string>, entry: string): {
|
|
70
|
+
ok: boolean;
|
|
71
|
+
text: string;
|
|
72
|
+
data: object;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Compile and return one symbol per source construct, with every line resolved.
|
|
76
|
+
*
|
|
77
|
+
* Two foldings happen here, both forced by how the compiler works rather than by
|
|
78
|
+
* taste. A statically-unrolled `@loop` recompiles its body once per row, so a
|
|
79
|
+
* directive inside it records N identical symbols at one `file:line`; and a prose
|
|
80
|
+
* read inside such a loop records N line-less reads. Both collapse to one.
|
|
81
|
+
*
|
|
82
|
+
* The `compiled` half is the compiler's own result, derived from the function
|
|
83
|
+
* rather than restated here: widening it to `object` compiled fine while these
|
|
84
|
+
* lived under bench/, and silently lost every property check the moment they
|
|
85
|
+
* became part of the package.
|
|
86
|
+
*/
|
|
87
|
+
export type Compiled = ReturnType<typeof compileFromMemory>;
|
|
88
|
+
/**
|
|
89
|
+
* Compile and return one symbol per source construct, with every line resolved.
|
|
90
|
+
*
|
|
91
|
+
* Two foldings happen here, both forced by how the compiler works rather than by
|
|
92
|
+
* taste. A statically-unrolled `@loop` recompiles its body once per row, so a
|
|
93
|
+
* directive inside it records N identical symbols at one `file:line`; and a prose
|
|
94
|
+
* read inside such a loop records N line-less reads. Both collapse to one.
|
|
95
|
+
*
|
|
96
|
+
* The `compiled` half is the compiler's own result, derived from the function
|
|
97
|
+
* rather than restated here: widening it to `object` compiled fine while these
|
|
98
|
+
* lived under bench/, and silently lost every property check the moment they
|
|
99
|
+
* became part of the package.
|
|
100
|
+
*/
|
|
101
|
+
export type Symbol = import("../compiler/context.js").Symbol;
|
|
102
|
+
import { compileFromMemory } from "../compiler.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} ToolCall
|
|
3
|
+
* @property {string} tool
|
|
4
|
+
* @property {object} args
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Pull the first complete JSON object out of a reply.
|
|
8
|
+
*
|
|
9
|
+
* Scans with a brace counter that is string- and escape-aware, because the one
|
|
10
|
+
* thing a Darkmown edit reliably contains is `{ count }`, and a naive
|
|
11
|
+
* `indexOf("}")` truncates exactly the calls that matter most.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} reply
|
|
14
|
+
* @returns {{ok: true, call: ToolCall} | {ok: false, error: string}}
|
|
15
|
+
*/
|
|
16
|
+
export function parseToolCall(reply: string): {
|
|
17
|
+
ok: true;
|
|
18
|
+
call: ToolCall;
|
|
19
|
+
} | {
|
|
20
|
+
ok: false;
|
|
21
|
+
error: string;
|
|
22
|
+
};
|
|
23
|
+
export type ToolCall = {
|
|
24
|
+
tool: string;
|
|
25
|
+
args: object;
|
|
26
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reduce any path the compiler hands back to the caller's own key form.
|
|
3
|
+
*
|
|
4
|
+
* The caller addresses files with POSIX keys (`site/pages/index.wd`), but
|
|
5
|
+
* `compileFromMemory` resolves them against its virtual root with
|
|
6
|
+
* `path.resolve`, which is PLATFORM-NATIVE: on Windows the same file comes back
|
|
7
|
+
* as `C:\site\pages\index.wd`. Comparing that to the caller's keys matches
|
|
8
|
+
* nothing, so every symbol gets filed under a path that is not in the project
|
|
9
|
+
* and every symbol-targeted edit fails. The virtual root is not a real
|
|
10
|
+
* filesystem and its separator is an accident of the host, so normalising here
|
|
11
|
+
* is the fix rather than a workaround.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} p
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
16
|
+
export function posixKey(p: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Shorten a virtual absolute path to what the author would call the file.
|
|
19
|
+
* The model never saw `/site/pages/`, so echoing it back is noise it may copy.
|
|
20
|
+
* @param {string} p
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
export function shortPath(p: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* TOOL ENTRY POINT.
|
|
26
|
+
*
|
|
27
|
+
* @param {Record<string, string>} files Project-relative path → contents, e.g.
|
|
28
|
+
* `{"site/pages/index.wd": "---\ntitle: X\n---\n"}`.
|
|
29
|
+
* @param {string} entry Which file to compile, in the same key form.
|
|
30
|
+
* @returns {{ok: boolean, text: string, data: object}}
|
|
31
|
+
*/
|
|
32
|
+
export function validate(files: Record<string, string>, entry: string): {
|
|
33
|
+
ok: boolean;
|
|
34
|
+
text: string;
|
|
35
|
+
data: object;
|
|
36
|
+
};
|