@origintrail-official/dkg-local-llm 10.0.15
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/LICENSE +17 -0
- package/README.md +173 -0
- package/dist/dkg-tool-validation.d.ts +41 -0
- package/dist/dkg-tool-validation.d.ts.map +1 -0
- package/dist/dkg-tool-validation.js +171 -0
- package/dist/dkg-tool-validation.js.map +1 -0
- package/dist/domain-profile.d.ts +10 -0
- package/dist/domain-profile.d.ts.map +1 -0
- package/dist/domain-profile.js +53 -0
- package/dist/domain-profile.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/model-endpoint.d.ts +33 -0
- package/dist/model-endpoint.d.ts.map +1 -0
- package/dist/model-endpoint.js +182 -0
- package/dist/model-endpoint.js.map +1 -0
- package/dist/model-response.d.ts +4 -0
- package/dist/model-response.d.ts.map +1 -0
- package/dist/model-response.js +18 -0
- package/dist/model-response.js.map +1 -0
- package/dist/relevance-router.d.ts +36 -0
- package/dist/relevance-router.d.ts.map +1 -0
- package/dist/relevance-router.js +147 -0
- package/dist/relevance-router.js.map +1 -0
- package/dist/runtime.d.ts +138 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +741 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema.d.ts +36 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +279 -0
- package/dist/schema.js.map +1 -0
- package/dist/sparql-preflight-scanner.d.ts +15 -0
- package/dist/sparql-preflight-scanner.d.ts.map +1 -0
- package/dist/sparql-preflight-scanner.js +140 -0
- package/dist/sparql-preflight-scanner.js.map +1 -0
- package/dist/system-context.d.ts +10 -0
- package/dist/system-context.d.ts.map +1 -0
- package/dist/system-context.js +48 -0
- package/dist/system-context.js.map +1 -0
- package/dist/text-trace.d.ts +17 -0
- package/dist/text-trace.d.ts.map +1 -0
- package/dist/text-trace.js +53 -0
- package/dist/text-trace.js.map +1 -0
- package/dist/tool-router.d.ts +37 -0
- package/dist/tool-router.d.ts.map +1 -0
- package/dist/tool-router.js +312 -0
- package/dist/tool-router.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Copyright 2026 OriginTrail
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# `@origintrail-official/dkg-local-llm`
|
|
2
|
+
|
|
3
|
+
Bounded local-model orchestration for the DKG MCP surface. The package talks to
|
|
4
|
+
an OpenAI-compatible llama.cpp or Ollama endpoint and receives its tools
|
|
5
|
+
dynamically from MCP `tools/list`.
|
|
6
|
+
|
|
7
|
+
The runtime is read-only by default. It tokenizes each prompt and dynamically
|
|
8
|
+
ranks the discovered MCP tools by their names, descriptions, and input schemas
|
|
9
|
+
instead of maintaining a use-case allowlist. The default shortlist is bounded
|
|
10
|
+
to eight schemas and 18,000 serialized JSON bytes. Mutations require
|
|
11
|
+
`allowWrite: true` and an explicit action/target request.
|
|
12
|
+
|
|
13
|
+
It also provides:
|
|
14
|
+
|
|
15
|
+
- local-server-safe JSON Schema normalization (`\\d` becomes `[0-9]` losslessly);
|
|
16
|
+
- local argument validation and one repair retry;
|
|
17
|
+
- repeated-call and tool-call-count guards;
|
|
18
|
+
- bounded chat history whose old evidence is never treated as fresh;
|
|
19
|
+
- plain-text interaction traces with secret redaction and `0600` permissions;
|
|
20
|
+
- system context v4.2, without benchmark fixtures or domain-specific IDs.
|
|
21
|
+
|
|
22
|
+
Partner integrations can supply a validated JSON domain profile containing
|
|
23
|
+
literal routing keywords, read/write adapter tool hints, and a domain context
|
|
24
|
+
addendum. Profiles boost dynamically discovered tools; they do not patch the
|
|
25
|
+
core router or weaken the runtime's read-only default.
|
|
26
|
+
|
|
27
|
+
The package is a library. The umbrella `dkg llm` CLI owns MCP stdio lifecycle,
|
|
28
|
+
configuration, and operator-facing write opt-in.
|
|
29
|
+
|
|
30
|
+
For agent and operator copy/paste setup, model recommendations, and the required
|
|
31
|
+
Query-Catalog-first workflow for small models, see
|
|
32
|
+
[`Run a Local LLM with DKG`](../../docs/use-dkg/local-llm.md).
|
|
33
|
+
|
|
34
|
+
## Interactive chat from a source checkout
|
|
35
|
+
|
|
36
|
+
Start the DKG daemon first. Then use two terminals for the model server and the
|
|
37
|
+
interactive DKG client.
|
|
38
|
+
|
|
39
|
+
### Terminal 1: start Qwen with llama.cpp or Ollama
|
|
40
|
+
|
|
41
|
+
llama.cpp remains the reference backend:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
/absolute/path/to/llama-server \
|
|
45
|
+
-hf Qwen/Qwen3-8B-GGUF:Q4_K_M \
|
|
46
|
+
-ngl 999 \
|
|
47
|
+
-c 8192 \
|
|
48
|
+
--flash-attn on \
|
|
49
|
+
--jinja \
|
|
50
|
+
--temp 0.15 \
|
|
51
|
+
--top-p 0.9 \
|
|
52
|
+
--repeat-penalty 1.05 \
|
|
53
|
+
--host 127.0.0.1 \
|
|
54
|
+
--port 8080
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Leave that terminal running. Wait for the model to load, then verify it from
|
|
58
|
+
another terminal:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
curl -sS http://127.0.0.1:8080/health
|
|
62
|
+
curl -sS http://127.0.0.1:8080/v1/models
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Continue only when `/v1/models` returns HTTP 200. The llama.cpp `/health`
|
|
66
|
+
response should also be `{"status":"ok"}`.
|
|
67
|
+
|
|
68
|
+
Alternatively, complete the full guide's canonical
|
|
69
|
+
[Ollama setup procedure](../../docs/use-dkg/local-llm.md#install-and-run-ollama).
|
|
70
|
+
That section is the sole source for installation, server ownership, context,
|
|
71
|
+
model loading, and readiness policy. Leave the verified server running, then
|
|
72
|
+
use the Ollama client options below.
|
|
73
|
+
|
|
74
|
+
### Terminal 2: start interactive DKG chat
|
|
75
|
+
|
|
76
|
+
From the DKG repository root, start an interactive Qwen session against the
|
|
77
|
+
`testing` Context Graph with an explicit session pin:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
DKG_HOME=/absolute/path/to/dkg-home \
|
|
81
|
+
pnpm dkg llm \
|
|
82
|
+
--interactive \
|
|
83
|
+
--project testing \
|
|
84
|
+
--llama-url http://127.0.0.1:8080/v1/chat/completions \
|
|
85
|
+
--model qwen3-8b-q4-k-m \
|
|
86
|
+
--allow-write
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`pnpm dkg` runs the source checkout's built CLI from
|
|
90
|
+
`packages/cli/dist/cli.js`. Build the workspace first if that file is absent or
|
|
91
|
+
stale.
|
|
92
|
+
|
|
93
|
+
`--allow-write` exposes relevant mutation tools, but a mutation still requires
|
|
94
|
+
an explicit user request. Omit `--allow-write` for the recommended read-only
|
|
95
|
+
chat:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
DKG_HOME=/absolute/path/to/dkg-home \
|
|
99
|
+
pnpm dkg llm \
|
|
100
|
+
--interactive \
|
|
101
|
+
--project testing \
|
|
102
|
+
--llama-url http://127.0.0.1:8080/v1/chat/completions \
|
|
103
|
+
--model qwen3-8b-q4-k-m
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For Ollama, replace the last two options with:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
--llama-url http://127.0.0.1:11434/v1/chat/completions \
|
|
110
|
+
--model qwen3:8b
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The legacy option name `--llama-url` accepts either supported backend.
|
|
114
|
+
|
|
115
|
+
`--project` is an explicit LLM-session pin. The local-LLM command does not
|
|
116
|
+
inherit `DKG_PROJECT` as an invisible default. A scoped tool call always carries
|
|
117
|
+
`projectId` in the logged MCP arguments: the runtime copies it from exact
|
|
118
|
+
catalog evidence first, then from the explicit session pin. Without either, the
|
|
119
|
+
call is rejected instead of falling through to the first graph in DKG config.
|
|
120
|
+
|
|
121
|
+
## Real DKG benchmark
|
|
122
|
+
|
|
123
|
+
The bundled benchmark uses this production runtime, a real `dkg mcp serve`
|
|
124
|
+
child, a real DKG daemon/store, and a real OpenAI-compatible local model. It
|
|
125
|
+
creates persistent local data, so `--allow-write` is mandatory and each run
|
|
126
|
+
should use unique graph/asset names.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Terminal 1: start DKG from this checkout
|
|
130
|
+
DKG_HOME=/absolute/path/to/dkg-home \
|
|
131
|
+
node packages/cli/dist/cli.js daemon-foreground-worker
|
|
132
|
+
|
|
133
|
+
# Terminal 2: start llama.cpp with one model
|
|
134
|
+
/absolute/path/to/llama-server \
|
|
135
|
+
-hf Qwen/Qwen3-8B-GGUF:Q4_K_M -ngl 999 -c 8192 \
|
|
136
|
+
--flash-attn on --jinja --temp 0.15 --top-p 0.9 --repeat-penalty 1.05
|
|
137
|
+
|
|
138
|
+
# Terminal 3: run 8 core scenarios plus 5 holdouts
|
|
139
|
+
RUN_ID="$(date +%Y%m%d-%H%M%S)"
|
|
140
|
+
DKG_HOME=/absolute/path/to/dkg-home \
|
|
141
|
+
DKG_CLI_PATH="$PWD/packages/cli/dist/cli.js" \
|
|
142
|
+
pnpm --filter @origintrail-official/dkg-local-llm benchmark:dkg -- \
|
|
143
|
+
--allow-write \
|
|
144
|
+
--graph-id "dkg-llm-qwen8-$RUN_ID" \
|
|
145
|
+
--asset-name "model-families-qwen8-$RUN_ID" \
|
|
146
|
+
--model qwen3-8b-q4-k-m \
|
|
147
|
+
--label "qwen3-8b-q4-k-m-$RUN_ID"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
To validate Ollama rather than assume parity, start it with the intended model
|
|
151
|
+
tag and add
|
|
152
|
+
`--llama-url http://127.0.0.1:11434/v1/chat/completions --model qwen3:8b`
|
|
153
|
+
to the benchmark command. On the sub-24-GiB acceptance machine, retain
|
|
154
|
+
`ollama ps` evidence showing at least `8192` context immediately before the run,
|
|
155
|
+
then require the complete 13-scenario benchmark to finish without prompt or tool
|
|
156
|
+
schema truncation at the default eight-tool/18,000-byte routing budget. Keep
|
|
157
|
+
each model/server pair's output and score separate from the llama.cpp reference
|
|
158
|
+
result.
|
|
159
|
+
|
|
160
|
+
The suite covers Context Graph creation, two subgraphs, model-authored RDF,
|
|
161
|
+
asset retrieval, raw SPARQL, parameterized query-catalog save/list/run, and five
|
|
162
|
+
generalization holdouts. Prerequisite fixture repairs are tagged `source:
|
|
163
|
+
"fixture"` and excluded from model scores, so an early write failure cannot
|
|
164
|
+
turn every later read into a cascade failure. The output directory contains:
|
|
165
|
+
|
|
166
|
+
- `interaction.log` — complete readable, redacted request/tool/result trace;
|
|
167
|
+
- `results.json` — phase scores plus every guarded MCP call;
|
|
168
|
+
- `report.md` — compact comparison table and independent DKG verification.
|
|
169
|
+
|
|
170
|
+
The guard permits only local benchmark mutations (graph/subgraph creation,
|
|
171
|
+
Working Memory asset write/finalize, and catalog save). Share, publish,
|
|
172
|
+
registration, messaging, and destructive operations are blocked even when the
|
|
173
|
+
runtime is in benchmark write mode.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { McpToolDefinition } from './schema.js';
|
|
2
|
+
export interface DkgToolValidationResult {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
errors: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface SanitizedContextGraphArguments {
|
|
7
|
+
args: Record<string, unknown>;
|
|
8
|
+
removed: Array<'projectId' | 'contextGraphId'>;
|
|
9
|
+
reasons: Array<{
|
|
10
|
+
key: 'projectId' | 'contextGraphId';
|
|
11
|
+
reason: 'config-path' | 'default-placeholder';
|
|
12
|
+
value: unknown;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
export declare function isDkgConfigPath(value: unknown): boolean;
|
|
16
|
+
export declare function isDefaultContextGraphPlaceholder(value: unknown): boolean;
|
|
17
|
+
export declare function referencesUnresolvedContextGraphAlias(value: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Ported from the qwen-dkg harness. Local models sometimes copy prose from a
|
|
20
|
+
* schema description and send `.dkg/config.yaml` (or a placeholder such as
|
|
21
|
+
* `default-context-graph-id`) as if it were a real graph id. Remove those
|
|
22
|
+
* synthetic values before scope materialization so they can never reach MCP.
|
|
23
|
+
*/
|
|
24
|
+
export declare function sanitizeContextGraphArguments(args: Record<string, unknown>): SanitizedContextGraphArguments;
|
|
25
|
+
/** Remove MCP-default wording that local models can mistake for a literal id. */
|
|
26
|
+
export declare function sanitizeDkgToolForLocalLlm(tool: McpToolDefinition): McpToolDefinition;
|
|
27
|
+
/**
|
|
28
|
+
* Cheap, deterministic checks for mistakes small local models commonly make.
|
|
29
|
+
* This is deliberately a preflight rather than a SPARQL parser: the DKG query
|
|
30
|
+
* engine remains authoritative, while obvious malformed calls get the
|
|
31
|
+
* runtime's single bounded repair attempt instead of a daemon round trip.
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateSparqlForDkg(value: unknown): DkgToolValidationResult;
|
|
34
|
+
export declare function validateDkgToolCall(name: string, args: Record<string, unknown>): DkgToolValidationResult;
|
|
35
|
+
/**
|
|
36
|
+
* Produce one conservative alternate for data written through the DKG quad
|
|
37
|
+
* API, which preserves compact predicate strings such as `rdf:type`. This is
|
|
38
|
+
* used only after the original, syntactically-valid read returned no evidence.
|
|
39
|
+
*/
|
|
40
|
+
export declare function rewriteCompactPredicatesForDkg(sparql: string): string;
|
|
41
|
+
//# sourceMappingURL=dkg-tool-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dkg-tool-validation.d.ts","sourceRoot":"","sources":["../src/dkg-tool-validation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGrD,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAID,MAAM,WAAW,8BAA8B;IAC7C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,KAAK,CAAC,WAAW,GAAG,gBAAgB,CAAC,CAAC;IAC/C,OAAO,EAAE,KAAK,CAAC;QACb,GAAG,EAAE,WAAW,GAAG,gBAAgB,CAAC;QACpC,MAAM,EAAE,aAAa,GAAG,qBAAqB,CAAC;QAC9C,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;CACJ;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGvD;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAKxE;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG5E;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,8BAA8B,CAgBhC;AAiBD,iFAAiF;AACjF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,iBAAiB,GAAG,iBAAiB,CAKrF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CA0C5E;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,uBAAuB,CAKzB;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAiDrE"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { prepareSparql } from '@origintrail-official/dkg-rdf-utils/sparql';
|
|
2
|
+
import { scanSparqlPreflight } from './sparql-preflight-scanner.js';
|
|
3
|
+
const MAX_SPARQL_PREFLIGHT_CHARS = 65_536;
|
|
4
|
+
export function isDkgConfigPath(value) {
|
|
5
|
+
return typeof value === 'string'
|
|
6
|
+
&& /(?:^|[/\\])(?:\.dkg[/\\])?config\.(?:ya?ml|json)$/i.test(value.trim());
|
|
7
|
+
}
|
|
8
|
+
export function isDefaultContextGraphPlaceholder(value) {
|
|
9
|
+
if (typeof value !== 'string')
|
|
10
|
+
return false;
|
|
11
|
+
const normalized = value.trim().toLowerCase();
|
|
12
|
+
return /^(?:the[-_ ]?)?default(?:[-_ ]?(?:context[-_ ]?graph)(?:[-_ ]?id)?)?$/.test(normalized)
|
|
13
|
+
|| /^(?:context[-_ ]?graph|project)[-_ ]?id$/.test(normalized);
|
|
14
|
+
}
|
|
15
|
+
export function referencesUnresolvedContextGraphAlias(value) {
|
|
16
|
+
return /\b(?:default|current)\s+(?:dkg\s+)?(?:context\s+graphs?|cgs?)\b/i.test(value)
|
|
17
|
+
|| /\b(?:context\s+graphs?|cgs?)\s+(?:called\s+)?(?:the\s+)?(?:default|current)\b/i.test(value);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Ported from the qwen-dkg harness. Local models sometimes copy prose from a
|
|
21
|
+
* schema description and send `.dkg/config.yaml` (or a placeholder such as
|
|
22
|
+
* `default-context-graph-id`) as if it were a real graph id. Remove those
|
|
23
|
+
* synthetic values before scope materialization so they can never reach MCP.
|
|
24
|
+
*/
|
|
25
|
+
export function sanitizeContextGraphArguments(args) {
|
|
26
|
+
const cleaned = { ...args };
|
|
27
|
+
const removed = [];
|
|
28
|
+
const reasons = [];
|
|
29
|
+
for (const key of ['projectId', 'contextGraphId']) {
|
|
30
|
+
const reason = isDkgConfigPath(cleaned[key])
|
|
31
|
+
? 'config-path'
|
|
32
|
+
: isDefaultContextGraphPlaceholder(cleaned[key])
|
|
33
|
+
? 'default-placeholder'
|
|
34
|
+
: undefined;
|
|
35
|
+
if (!reason)
|
|
36
|
+
continue;
|
|
37
|
+
reasons.push({ key, reason, value: cleaned[key] });
|
|
38
|
+
delete cleaned[key];
|
|
39
|
+
removed.push(key);
|
|
40
|
+
}
|
|
41
|
+
return { args: cleaned, removed, reasons };
|
|
42
|
+
}
|
|
43
|
+
function rewriteLocalLlmScopeDescriptions(value) {
|
|
44
|
+
if (Array.isArray(value))
|
|
45
|
+
return value.map(rewriteLocalLlmScopeDescriptions);
|
|
46
|
+
if (!value || typeof value !== 'object')
|
|
47
|
+
return value;
|
|
48
|
+
const output = {};
|
|
49
|
+
for (const [key, child] of Object.entries(value)) {
|
|
50
|
+
output[key] = key === 'description' && typeof child === 'string'
|
|
51
|
+
? child.replace(/Defaults to \.dkg\/config\.yaml\.?/gi, 'Omit only when an explicit Session Context Graph is selected. Never pass a config filename or generic placeholder as a graph id.')
|
|
52
|
+
: rewriteLocalLlmScopeDescriptions(child);
|
|
53
|
+
}
|
|
54
|
+
return output;
|
|
55
|
+
}
|
|
56
|
+
/** Remove MCP-default wording that local models can mistake for a literal id. */
|
|
57
|
+
export function sanitizeDkgToolForLocalLlm(tool) {
|
|
58
|
+
return {
|
|
59
|
+
...tool,
|
|
60
|
+
inputSchema: rewriteLocalLlmScopeDescriptions(tool.inputSchema),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Cheap, deterministic checks for mistakes small local models commonly make.
|
|
65
|
+
* This is deliberately a preflight rather than a SPARQL parser: the DKG query
|
|
66
|
+
* engine remains authoritative, while obvious malformed calls get the
|
|
67
|
+
* runtime's single bounded repair attempt instead of a daemon round trip.
|
|
68
|
+
*/
|
|
69
|
+
export function validateSparqlForDkg(value) {
|
|
70
|
+
const rawSparql = typeof value === 'string' ? value : '';
|
|
71
|
+
if (rawSparql.length > MAX_SPARQL_PREFLIGHT_CHARS) {
|
|
72
|
+
return {
|
|
73
|
+
ok: false,
|
|
74
|
+
errors: [`sparql must not exceed ${MAX_SPARQL_PREFLIGHT_CHARS} characters`],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const sparql = rawSparql.trim();
|
|
78
|
+
const errors = [];
|
|
79
|
+
if (!sparql)
|
|
80
|
+
return { ok: false, errors: ['sparql must not be empty'] };
|
|
81
|
+
if (/```/.test(sparql))
|
|
82
|
+
errors.push('remove Markdown fences and send raw SPARQL only');
|
|
83
|
+
const scan = scanSparqlPreflight(sparql);
|
|
84
|
+
if (scan.unterminated)
|
|
85
|
+
errors.push('close the unterminated string literal or IRI');
|
|
86
|
+
if (!scan.operation) {
|
|
87
|
+
errors.push('query must start with SELECT, ASK, or CONSTRUCT');
|
|
88
|
+
}
|
|
89
|
+
if (!scan.bracesBalanced)
|
|
90
|
+
errors.push('balance SPARQL braces');
|
|
91
|
+
if (!scan.parenthesesBalanced)
|
|
92
|
+
errors.push('balance SPARQL parentheses');
|
|
93
|
+
if (scan.hasFrom) {
|
|
94
|
+
errors.push('remove FROM because projectId, subGraphName, and view already scope the query');
|
|
95
|
+
}
|
|
96
|
+
if (scan.hasFilterNotExistsParentheses) {
|
|
97
|
+
errors.push('use braces for FILTER NOT EXISTS');
|
|
98
|
+
}
|
|
99
|
+
if (scan.hasStrcontains) {
|
|
100
|
+
errors.push('use SPARQL CONTAINS instead of STRCONTAINS');
|
|
101
|
+
}
|
|
102
|
+
if (scan.hasUnwrappedAggregateAlias) {
|
|
103
|
+
errors.push('wrap aggregate aliases as (COUNT(...) AS ?count)');
|
|
104
|
+
}
|
|
105
|
+
// Prefixed names (schema:name) are valid. Absolute identifiers copied from
|
|
106
|
+
// DKG evidence (urn:..., did:..., http://...) are not prefixed names and
|
|
107
|
+
// must be enclosed in <...> when used as SPARQL terms.
|
|
108
|
+
if (scan.bareAbsoluteIri) {
|
|
109
|
+
errors.push(`wrap absolute IRI ${scan.bareAbsoluteIri} in angle brackets`);
|
|
110
|
+
}
|
|
111
|
+
const unique = [...new Set(errors)];
|
|
112
|
+
return { ok: unique.length === 0, errors: unique };
|
|
113
|
+
}
|
|
114
|
+
export function validateDkgToolCall(name, args) {
|
|
115
|
+
if (name === 'dkg_query' || name === 'dkg_query_catalog_save') {
|
|
116
|
+
return validateSparqlForDkg(args.sparql);
|
|
117
|
+
}
|
|
118
|
+
return { ok: true, errors: [] };
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Produce one conservative alternate for data written through the DKG quad
|
|
122
|
+
* API, which preserves compact predicate strings such as `rdf:type`. This is
|
|
123
|
+
* used only after the original, syntactically-valid read returned no evidence.
|
|
124
|
+
*/
|
|
125
|
+
export function rewriteCompactPredicatesForDkg(sparql) {
|
|
126
|
+
const scan = prepareSparql(sparql);
|
|
127
|
+
if (scan.unterminated)
|
|
128
|
+
return sparql;
|
|
129
|
+
const edits = [];
|
|
130
|
+
const hasWhitespaceGap = (start, end) => (end > start && /^\s+$/u.test(scan.masked.slice(start, end)));
|
|
131
|
+
const canPrecedePredicate = (index) => {
|
|
132
|
+
const token = scan.tokens[index];
|
|
133
|
+
if (!token)
|
|
134
|
+
return false;
|
|
135
|
+
if (token.kind === 'iri')
|
|
136
|
+
return true;
|
|
137
|
+
if (token.kind === 'variable')
|
|
138
|
+
return token.logicalValue.startsWith('?');
|
|
139
|
+
return token.kind === 'prefixed-name';
|
|
140
|
+
};
|
|
141
|
+
for (let index = 1; index < scan.tokens.length - 1; index++) {
|
|
142
|
+
const previous = scan.tokens[index - 1];
|
|
143
|
+
const candidate = scan.tokens[index];
|
|
144
|
+
const next = scan.tokens[index + 1];
|
|
145
|
+
const followsSubject = canPrecedePredicate(index - 1)
|
|
146
|
+
&& hasWhitespaceGap(previous.end, candidate.start);
|
|
147
|
+
const followsSemicolon = previous.kind === 'symbol'
|
|
148
|
+
&& previous.logicalValue === ';'
|
|
149
|
+
&& hasWhitespaceGap(previous.end, candidate.start);
|
|
150
|
+
if (!followsSubject && !followsSemicolon)
|
|
151
|
+
continue;
|
|
152
|
+
if (!hasWhitespaceGap(candidate.end, next.start))
|
|
153
|
+
continue;
|
|
154
|
+
if (candidate.kind === 'word' && candidate.upper === 'A') {
|
|
155
|
+
edits.push({ start: candidate.start, end: candidate.end, value: '<rdf:type>' });
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (candidate.kind === 'prefixed-name'
|
|
159
|
+
&& /^(?:rdf|rdfs|schema):[A-Za-z_][A-Za-z0-9_.-]*$/iu.test(candidate.logicalValue)) {
|
|
160
|
+
edits.push({
|
|
161
|
+
start: candidate.start,
|
|
162
|
+
end: candidate.end,
|
|
163
|
+
value: `<${candidate.raw}>`,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return edits
|
|
168
|
+
.sort((left, right) => right.start - left.start)
|
|
169
|
+
.reduce((rewritten, edit) => rewritten.slice(0, edit.start) + edit.value + rewritten.slice(edit.end), sparql);
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=dkg-tool-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dkg-tool-validation.js","sourceRoot":"","sources":["../src/dkg-tool-validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface DkgLocalLlmDomainProfile {
|
|
2
|
+
name: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
routingKeywords: string[];
|
|
5
|
+
readTools: string[];
|
|
6
|
+
writeTools?: string[];
|
|
7
|
+
systemContext?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseDomainProfile(value: unknown): DkgLocalLlmDomainProfile;
|
|
10
|
+
//# sourceMappingURL=domain-profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-profile.d.ts","sourceRoot":"","sources":["../src/domain-profile.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAoCD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAmB3E"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const TOOL_NAME = /^[A-Za-z0-9_.:-]{1,128}$/;
|
|
2
|
+
function stringField(record, key, required = false) {
|
|
3
|
+
const value = record[key];
|
|
4
|
+
if (value === undefined && !required)
|
|
5
|
+
return undefined;
|
|
6
|
+
if (typeof value !== 'string' || !value.trim())
|
|
7
|
+
throw new Error(`Domain profile '${key}' must be a non-empty string.`);
|
|
8
|
+
return value.trim();
|
|
9
|
+
}
|
|
10
|
+
function stringList(record, key, options = {}) {
|
|
11
|
+
const value = record[key];
|
|
12
|
+
if (value === undefined && !options.required)
|
|
13
|
+
return [];
|
|
14
|
+
if (!Array.isArray(value) || (options.required && value.length === 0)) {
|
|
15
|
+
throw new Error(`Domain profile '${key}' must be a${options.required ? ' non-empty' : ''} string array.`);
|
|
16
|
+
}
|
|
17
|
+
if (value.length > 64)
|
|
18
|
+
throw new Error(`Domain profile '${key}' allows at most 64 entries.`);
|
|
19
|
+
const entries = value.map((entry) => {
|
|
20
|
+
if (typeof entry !== 'string' || !entry.trim()) {
|
|
21
|
+
throw new Error(`Domain profile '${key}' must contain only non-empty strings.`);
|
|
22
|
+
}
|
|
23
|
+
const normalized = entry.trim();
|
|
24
|
+
if (normalized.length > 128)
|
|
25
|
+
throw new Error(`Domain profile '${key}' entries must be at most 128 characters.`);
|
|
26
|
+
if (options.toolNames && !TOOL_NAME.test(normalized)) {
|
|
27
|
+
throw new Error(`Domain profile '${key}' contains an invalid MCP tool name: ${normalized}`);
|
|
28
|
+
}
|
|
29
|
+
return normalized;
|
|
30
|
+
});
|
|
31
|
+
return [...new Set(entries)];
|
|
32
|
+
}
|
|
33
|
+
export function parseDomainProfile(value) {
|
|
34
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
35
|
+
throw new Error('Domain profile must be a JSON object.');
|
|
36
|
+
}
|
|
37
|
+
const record = value;
|
|
38
|
+
const systemContext = stringField(record, 'systemContext');
|
|
39
|
+
if (systemContext && systemContext.length > 20_000) {
|
|
40
|
+
throw new Error("Domain profile 'systemContext' must be at most 20000 characters.");
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
name: stringField(record, 'name', true),
|
|
44
|
+
...(stringField(record, 'description') ? { description: stringField(record, 'description') } : {}),
|
|
45
|
+
routingKeywords: stringList(record, 'routingKeywords', { required: true }),
|
|
46
|
+
readTools: stringList(record, 'readTools', { required: true, toolNames: true }),
|
|
47
|
+
...(record.writeTools !== undefined
|
|
48
|
+
? { writeTools: stringList(record, 'writeTools', { toolNames: true }) }
|
|
49
|
+
: {}),
|
|
50
|
+
...(systemContext ? { systemContext } : {}),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=domain-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-profile.js","sourceRoot":"","sources":["../src/domain-profile.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { parseDomainProfile, type DkgLocalLlmDomainProfile, } from './domain-profile.js';
|
|
2
|
+
export { rewriteCompactPredicatesForDkg, validateDkgToolCall, validateSparqlForDkg, type DkgToolValidationResult, } from './dkg-tool-validation.js';
|
|
3
|
+
export { DkgLocalLlmRuntime, normalizeFinalAnswer, type DkgChatEvidence, type DkgChatSessionInfo, type DkgChatTurn, type DkgLocalLlmOptions, type DkgLocalLlmResult, type McpClientLike, } from './runtime.js';
|
|
4
|
+
export { probeLocalModelEndpoint, type LocalModelEndpointAvailability, type LocalModelEndpointProbeStrategy, type ProbeLocalModelEndpointOptions, } from './model-endpoint.js';
|
|
5
|
+
export { normalizeToolForLlama, parseAndValidateToolArguments, stableJson, validateAgainstSchema, type JsonSchema, type McpToolAnnotations, type McpToolDefinition, type OpenAiToolDefinition, } from './schema.js';
|
|
6
|
+
export { DKG_LOCAL_LLM_SYSTEM_CONTEXT_VERSION, dkgLocalLlmSystemContext, } from './system-context.js';
|
|
7
|
+
export { classifyTool, createToolRouter, isMutatingTool, routeTools, type ResolvedToolProfile, type ToolCategory, type ToolProfile, type ToolRoute, type ToolRouteRequest, } from './tool-router.js';
|
|
8
|
+
export { createRelevanceRanker, tokenizeToolText, type RelevanceDocument, type RelevanceRankOptions, type RelevanceRankResult, type RelevanceRankedItem, } from './relevance-router.js';
|
|
9
|
+
export { NOOP_TRACE, TextInteractionTrace, redactSecrets, type InteractionTrace, } from './text-trace.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,8BAA8B,EAC9B,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,uBAAuB,GAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uBAAuB,EACvB,KAAK,8BAA8B,EACnC,KAAK,+BAA+B,EACpC,KAAK,8BAA8B,GACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,qBAAqB,EACrB,6BAA6B,EAC7B,UAAU,EACV,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oCAAoC,EACpC,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,aAAa,EACb,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { parseDomainProfile, } from './domain-profile.js';
|
|
2
|
+
export { rewriteCompactPredicatesForDkg, validateDkgToolCall, validateSparqlForDkg, } from './dkg-tool-validation.js';
|
|
3
|
+
export { DkgLocalLlmRuntime, normalizeFinalAnswer, } from './runtime.js';
|
|
4
|
+
export { probeLocalModelEndpoint, } from './model-endpoint.js';
|
|
5
|
+
export { normalizeToolForLlama, parseAndValidateToolArguments, stableJson, validateAgainstSchema, } from './schema.js';
|
|
6
|
+
export { DKG_LOCAL_LLM_SYSTEM_CONTEXT_VERSION, dkgLocalLlmSystemContext, } from './system-context.js';
|
|
7
|
+
export { classifyTool, createToolRouter, isMutatingTool, routeTools, } from './tool-router.js';
|
|
8
|
+
export { createRelevanceRanker, tokenizeToolText, } from './relevance-router.js';
|
|
9
|
+
export { NOOP_TRACE, TextInteractionTrace, redactSecrets, } from './text-trace.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAEnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,8BAA8B,EAC9B,mBAAmB,EACnB,oBAAoB,GAErB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,GAOrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uBAAuB,GAIxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,qBAAqB,EACrB,6BAA6B,EAC7B,UAAU,EACV,qBAAqB,GAKtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oCAAoC,EACpC,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,UAAU,GAMX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GAKjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,aAAa,GAEd,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type LocalModelEndpointProbeStrategy = Readonly<{
|
|
2
|
+
kind: 'auto';
|
|
3
|
+
}> | Readonly<{
|
|
4
|
+
kind: 'ollama';
|
|
5
|
+
}> | Readonly<{
|
|
6
|
+
kind: 'llama.cpp';
|
|
7
|
+
}>;
|
|
8
|
+
export type LocalModelEndpointAvailability = Readonly<{
|
|
9
|
+
status: 'ready';
|
|
10
|
+
reachable: true;
|
|
11
|
+
}> | Readonly<{
|
|
12
|
+
status: 'not-ready';
|
|
13
|
+
reachable: true;
|
|
14
|
+
error: string;
|
|
15
|
+
}> | Readonly<{
|
|
16
|
+
status: 'offline';
|
|
17
|
+
reachable: false;
|
|
18
|
+
error: string;
|
|
19
|
+
}>;
|
|
20
|
+
export interface ProbeLocalModelEndpointOptions {
|
|
21
|
+
chatCompletionsUrl: string;
|
|
22
|
+
model: string;
|
|
23
|
+
strategy?: LocalModelEndpointProbeStrategy;
|
|
24
|
+
fetch?: typeof fetch;
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Probe the exact configured model through an explicit backend strategy.
|
|
29
|
+
* `auto` preserves legacy llama.cpp and Ollama configuration; callers that know
|
|
30
|
+
* their backend can select its strategy without exposing endpoint details.
|
|
31
|
+
*/
|
|
32
|
+
export declare function probeLocalModelEndpoint(options: ProbeLocalModelEndpointOptions): Promise<LocalModelEndpointAvailability>;
|
|
33
|
+
//# sourceMappingURL=model-endpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-endpoint.d.ts","sourceRoot":"","sources":["../src/model-endpoint.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,+BAA+B,GACvC,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1B,QAAQ,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAC5B,QAAQ,CAAC;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC;AAEpC,MAAM,MAAM,8BAA8B,GACtC,QAAQ,CAAC;IACT,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB,CAAC,GACA,QAAQ,CAAC;IACT,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,GACA,QAAQ,CAAC;IACT,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,KAAK,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEL,MAAM,WAAW,8BAA8B;IAC7C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,+BAA+B,CAAC;IAC3C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuHD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,8BAA8B,CAAC,CAqFzC"}
|