@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.
@@ -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
+ };