@seanhogg/builderforce-memory 2026.9.31 → 2026.9.33

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.
@@ -12,4 +12,10 @@ export { EVERMIND_MIN_TEACH_CHARS } from './contract.js';
12
12
  export { rankEvermindRecall, hashRecallQuery, countReconciledMemories, } from './recall.js';
13
13
  export type { RecallScorable, RankedEvermindRecall } from './recall.js';
14
14
  export { formatEvermindMemoryBlock } from './memoryBlock.js';
15
+ export { EVERMIND_ANSWER_MIN_CHARS, assessTextCoherence, looksLikeCoherentText, isServableText, } from './textCoherence.js';
16
+ export type { CoherenceFailure, CoherenceVerdict, CoherenceOptions } from './textCoherence.js';
17
+ export { TOOL_CHOICE_MIN_MARGIN, resolveToolChoiceMinMargin, normalizeEvermindTools, resolveEvermindToolChoice, renderToolsPreamble, planEvermindToolCall, toOpenAIToolCall, } from './toolCall.js';
18
+ export type { NormalizedTool, JsonSchema, ToolChoicePlan, EvermindToolDecoder, EvermindPlannedCall, EvermindToolPlan, } from './toolCall.js';
19
+ export { messagesToPrompt, generateEvermindText, COHERENCE_PROBE_PROMPTS, assessLMCoherence, probeEvermindText, createEvermindToolDecoder, generateEvermindWithTools, } from './runtime.js';
20
+ export type { EvermindTextModel, EvermindTextTokenizer, EvermindUsage, EvermindGenerateOptions, EvermindGeneration, EvermindCoherenceSample, EvermindCoherenceAssessment, EvermindProbeGeneration, MeteredToolDecoder, EvermindToolGeneration, } from './runtime.js';
15
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/evermind/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,uBAAuB,GAC1B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/evermind/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,uBAAuB,GAC1B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAI7D,OAAO,EACH,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,GACjB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EACH,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EACR,cAAc,EACd,UAAU,EACV,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACH,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,yBAAyB,GAC5B,MAAM,cAAc,CAAC;AACtB,YAAY,EACR,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,2BAA2B,EAC3B,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,GACzB,MAAM,cAAc,CAAC"}
@@ -1,4 +1,9 @@
1
1
  export { EVERMIND_MIN_TEACH_CHARS } from './contract.js';
2
2
  export { rankEvermindRecall, hashRecallQuery, countReconciledMemories, } from './recall.js';
3
3
  export { formatEvermindMemoryBlock } from './memoryBlock.js';
4
+ // Serving: text-quality gate, tool calling by constrained decoding, and the model-driving
5
+ // runtime (structural model/tokenizer shapes — still dependency-free).
6
+ export { EVERMIND_ANSWER_MIN_CHARS, assessTextCoherence, looksLikeCoherentText, isServableText, } from './textCoherence.js';
7
+ export { TOOL_CHOICE_MIN_MARGIN, resolveToolChoiceMinMargin, normalizeEvermindTools, resolveEvermindToolChoice, renderToolsPreamble, planEvermindToolCall, toOpenAIToolCall, } from './toolCall.js';
8
+ export { messagesToPrompt, generateEvermindText, COHERENCE_PROBE_PROMPTS, assessLMCoherence, probeEvermindText, createEvermindToolDecoder, generateEvermindWithTools, } from './runtime.js';
4
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/evermind/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,uBAAuB,GAC1B,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/evermind/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,uBAAuB,GAC1B,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,0FAA0F;AAC1F,uEAAuE;AACvE,OAAO,EACH,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACH,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACnB,MAAM,eAAe,CAAC;AASvB,OAAO,EACH,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,yBAAyB,GAC5B,MAAM,cAAc,CAAC"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * The model-driving half of Evermind serving: flatten a chat into a continuation
3
+ * prompt, generate under a wall-clock budget, grade a head's fitness to serve, and
4
+ * bind a head to the tool planner's decoder port.
5
+ *
6
+ * Written against STRUCTURAL model/tokenizer shapes ({@link EvermindTextModel},
7
+ * {@link EvermindTextTokenizer}) that the engine's `EvermindLM` and `BPETokenizer`
8
+ * satisfy, so this module imports nothing and the `/evermind` subpath stays
9
+ * dependency-free. Where the head comes FROM (an R2 artifact, a file, a freshly merged
10
+ * in-memory model) is the host's business; everything here takes a loaded head.
11
+ */
12
+ import { type CoherenceFailure } from './textCoherence.js';
13
+ import { type EvermindPlannedCall, type EvermindToolDecoder, type NormalizedTool, type ToolChoicePlan } from './toolCall.js';
14
+ /** What serving needs from a loaded text head (the engine's `EvermindLM`). */
15
+ export interface EvermindTextModel {
16
+ generateText(prompt: string, tok: EvermindTextTokenizer, opts: {
17
+ maxNewTokens: number;
18
+ temperature: number;
19
+ seed?: number;
20
+ }): string;
21
+ forward(ids: number[]): {
22
+ logits: ArrayLike<number>[];
23
+ };
24
+ }
25
+ /** What serving needs from a head's tokenizer (the engine's `BPETokenizer`). */
26
+ export interface EvermindTextTokenizer {
27
+ encode(text: string): number[];
28
+ }
29
+ export interface EvermindUsage {
30
+ prompt_tokens: number;
31
+ completion_tokens: number;
32
+ total_tokens: number;
33
+ }
34
+ export interface EvermindGenerateOptions {
35
+ maxTokens?: number;
36
+ temperature?: number;
37
+ seed?: number;
38
+ /**
39
+ * Wall-clock budget for the generation loop, in ms. Evermind generation is
40
+ * SYNCHRONOUS CPU on the request path, so without this a large head on a slow host
41
+ * runs until the host kills the request — no message and no partial answer. With
42
+ * it, the loop stops at the budget and says so.
43
+ */
44
+ deadlineMs?: number;
45
+ }
46
+ export interface EvermindGeneration {
47
+ content: string;
48
+ usage: EvermindUsage;
49
+ /** True when the wall-clock budget stopped generation before `maxTokens` or a stop
50
+ * token did — the text is a real partial answer, not a complete one. */
51
+ truncated: boolean;
52
+ /** How long the generation loop actually took. */
53
+ elapsedMs: number;
54
+ }
55
+ /** Flatten chat messages into a single continuation prompt for the LM. */
56
+ export declare function messagesToPrompt(messages: Array<{
57
+ role?: unknown;
58
+ content?: unknown;
59
+ }>): string;
60
+ /**
61
+ * Generate a reply from a loaded head. Deterministic for a given (prompt, seed,
62
+ * maxTokens): each slice derives its seed from the base seed and its index, so two
63
+ * operators running the same probe see the same text.
64
+ */
65
+ export declare function generateEvermindText(lm: EvermindTextModel, tok: EvermindTextTokenizer, messages: Array<{
66
+ role?: unknown;
67
+ content?: unknown;
68
+ }>, opts?: EvermindGenerateOptions): EvermindGeneration;
69
+ /** Neutral probe prompts a project chat head should answer coherently. Fixed and
70
+ * generic (not project-specific) so the probe measures GENERATION QUALITY, not
71
+ * recall. */
72
+ export declare const COHERENCE_PROBE_PROMPTS: readonly string[];
73
+ /** One graded probe generation. */
74
+ export interface EvermindCoherenceSample {
75
+ prompt: string;
76
+ text: string;
77
+ coherent: boolean;
78
+ /** The failing signal when `coherent` is false (null when it passed) — so an
79
+ * operator sees WHY a head was refused, not just that it was. */
80
+ failure: CoherenceFailure | null;
81
+ /** Short human-readable explanation of {@link failure} (empty when coherent). */
82
+ detail: string;
83
+ }
84
+ /** A head's fitness-to-serve verdict. */
85
+ export interface EvermindCoherenceAssessment {
86
+ ready: boolean;
87
+ /** Fraction of probe samples that were substantive AND coherent (0..1). */
88
+ passRate: number;
89
+ samples: EvermindCoherenceSample[];
90
+ }
91
+ /**
92
+ * Score a loaded head's fitness to serve chat: generate from the neutral probe
93
+ * prompts and grade each with the serve-time bar ({@link isServableText}).
94
+ * Synchronous and storage-free, so the promote-to-inference gate and a learning
95
+ * coordinator holding a freshly merged model grade it the same way. Deterministic
96
+ * seeds keep the verdict reproducible; a majority must pass by default.
97
+ */
98
+ export declare function assessLMCoherence(lm: EvermindTextModel, tok: EvermindTextTokenizer, opts?: {
99
+ minPassRate?: number;
100
+ }): EvermindCoherenceAssessment;
101
+ /** One operator-run test-bench generation, graded with the serve-time bar. */
102
+ export interface EvermindProbeGeneration extends EvermindCoherenceSample {
103
+ usage: EvermindUsage;
104
+ /** True when the wall-clock budget stopped generation early — an incoherent verdict
105
+ * on a truncated sample is a statement about the clock, not about the model. */
106
+ truncated: boolean;
107
+ elapsedMs: number;
108
+ }
109
+ /**
110
+ * Test bench: run ONE prompt through a head and grade the output with the SAME bar
111
+ * the serve path uses, so "what will this model actually produce?" is answerable
112
+ * before inference is switched on. Deterministic by default (`seed`).
113
+ */
114
+ export declare function probeEvermindText(lm: EvermindTextModel, tok: EvermindTextTokenizer, prompt: string, opts?: EvermindGenerateOptions): EvermindProbeGeneration;
115
+ /** A decoder plus the token usage it accumulated, so a tool-calling turn reports real
116
+ * numbers instead of zeros. */
117
+ export interface MeteredToolDecoder extends EvermindToolDecoder {
118
+ usage(): EvermindUsage;
119
+ }
120
+ /**
121
+ * Bind a loaded head to the {@link EvermindToolDecoder} port.
122
+ *
123
+ * `score`: teacher forcing lets one forward pass over `prompt + continuation` yield
124
+ * the log-prob of EVERY continuation token at once (position `t` predicts `t+1`), so
125
+ * ranking a candidate costs one pass. The mean is returned — not the sum — so a long
126
+ * tool name is not out-voted by a short one for its length alone.
127
+ *
128
+ * `generate` is greedy by default: a tool ARGUMENT is a value to get right, not prose
129
+ * to vary, and determinism keeps a replayed run reproducible.
130
+ */
131
+ export declare function createEvermindToolDecoder(lm: EvermindTextModel, tok: EvermindTextTokenizer, opts?: {
132
+ temperature?: number;
133
+ seed?: number;
134
+ }): MeteredToolDecoder;
135
+ /** A tool-aware generation: either planned calls, or prose when the head chose to
136
+ * answer directly (`tool_choice: 'auto'`). */
137
+ export interface EvermindToolGeneration {
138
+ /** The first planned call, or null for prose. */
139
+ call: EvermindPlannedCall | null;
140
+ /** EVERY call this turn emits (the OpenAI shape is an array; frontier models emit
141
+ * parallel calls). Empty when `call` is null. */
142
+ calls: EvermindPlannedCall[];
143
+ /** Prose answer — populated only when `call` is null. */
144
+ content: string;
145
+ usage: EvermindUsage;
146
+ /** Confidence separation behind the plan — returned unjudged: the host owns the
147
+ * policy of what separation is good enough, because it owns the fallback. */
148
+ margin: number;
149
+ }
150
+ /**
151
+ * Run a TOOL-BEARING request against a loaded head: plan a call by constrained
152
+ * decoding, or fall through to ordinary prose when the head elected to answer directly.
153
+ */
154
+ export declare function generateEvermindWithTools(lm: EvermindTextModel, tok: EvermindTextTokenizer, messages: Array<{
155
+ role?: unknown;
156
+ content?: unknown;
157
+ }>, tools: NormalizedTool[], choice: ToolChoicePlan, opts?: EvermindGenerateOptions): EvermindToolGeneration;
158
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/evermind/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * The model-driving half of Evermind serving: flatten a chat into a continuation
3
+ * prompt, generate under a wall-clock budget, grade a head's fitness to serve, and
4
+ * bind a head to the tool planner's decoder port.
5
+ *
6
+ * Written against STRUCTURAL model/tokenizer shapes ({@link EvermindTextModel},
7
+ * {@link EvermindTextTokenizer}) that the engine's `EvermindLM` and `BPETokenizer`
8
+ * satisfy, so this module imports nothing and the `/evermind` subpath stays
9
+ * dependency-free. Where the head comes FROM (an R2 artifact, a file, a freshly merged
10
+ * in-memory model) is the host's business; everything here takes a loaded head.
11
+ */
12
+ import { isServableText } from './textCoherence.js';
13
+ import { planEvermindToolCall, } from './toolCall.js';
14
+ /** Flatten chat messages into a single continuation prompt for the LM. */
15
+ export function messagesToPrompt(messages) {
16
+ const lines = messages
17
+ .map((m) => {
18
+ const role = typeof m.role === 'string' ? m.role : 'user';
19
+ const content = typeof m.content === 'string' ? m.content : '';
20
+ return content ? `${role}: ${content}` : '';
21
+ })
22
+ .filter(Boolean);
23
+ return `${lines.join('\n')}\nassistant:`;
24
+ }
25
+ /**
26
+ * Tokens generated between wall-clock checks. The deadline is enforced BETWEEN slices
27
+ * because the engine's generate is one synchronous loop with no per-token hook.
28
+ * Slicing costs nothing: the forward pass already recomputes the whole sequence per
29
+ * token, so re-entering with `prompt + producedSoFar` is the work the next token was
30
+ * going to do anyway. Small enough that the overshoot is one slice.
31
+ */
32
+ const GENERATE_SLICE_TOKENS = 16;
33
+ /** Default wall-clock budget for one generation — inside a Worker's CPU allowance, so
34
+ * the caller gets a partial answer plus `truncated` rather than a killed request. */
35
+ const DEFAULT_GENERATE_DEADLINE_MS = 8000;
36
+ /**
37
+ * Generate a reply from a loaded head. Deterministic for a given (prompt, seed,
38
+ * maxTokens): each slice derives its seed from the base seed and its index, so two
39
+ * operators running the same probe see the same text.
40
+ */
41
+ export function generateEvermindText(lm, tok, messages, opts = {}) {
42
+ const prompt = messagesToPrompt(messages);
43
+ const maxTokens = opts.maxTokens ?? 256;
44
+ const temperature = opts.temperature ?? 0.7;
45
+ const baseSeed = opts.seed;
46
+ const deadlineMs = opts.deadlineMs ?? DEFAULT_GENERATE_DEADLINE_MS;
47
+ const started = Date.now();
48
+ let content = '';
49
+ let truncated = false;
50
+ let produced = 0;
51
+ let slice = 0;
52
+ while (produced < maxTokens) {
53
+ const want = Math.min(GENERATE_SLICE_TOKENS, maxTokens - produced);
54
+ const chunk = lm.generateText(`${prompt}${content}`, tok, {
55
+ maxNewTokens: want,
56
+ temperature,
57
+ ...(baseSeed != null ? { seed: baseSeed + slice } : {}),
58
+ });
59
+ slice++;
60
+ // An empty slice means the model stopped producing; continuing would spin.
61
+ if (!chunk)
62
+ break;
63
+ content += chunk;
64
+ produced += want;
65
+ if (Date.now() - started >= deadlineMs) {
66
+ truncated = produced < maxTokens;
67
+ break;
68
+ }
69
+ }
70
+ const prompt_tokens = tok.encode(prompt).length;
71
+ const completion_tokens = content ? tok.encode(content).length : 0;
72
+ return {
73
+ content,
74
+ usage: { prompt_tokens, completion_tokens, total_tokens: prompt_tokens + completion_tokens },
75
+ truncated,
76
+ elapsedMs: Date.now() - started,
77
+ };
78
+ }
79
+ // ── Fitness to serve ────────────────────────────────────────────────────────
80
+ /** Neutral probe prompts a project chat head should answer coherently. Fixed and
81
+ * generic (not project-specific) so the probe measures GENERATION QUALITY, not
82
+ * recall. */
83
+ export const COHERENCE_PROBE_PROMPTS = [
84
+ 'Summarize the current status of the project.',
85
+ 'What has the team been working on recently?',
86
+ 'List the main things left to do.',
87
+ ];
88
+ /**
89
+ * Score a loaded head's fitness to serve chat: generate from the neutral probe
90
+ * prompts and grade each with the serve-time bar ({@link isServableText}).
91
+ * Synchronous and storage-free, so the promote-to-inference gate and a learning
92
+ * coordinator holding a freshly merged model grade it the same way. Deterministic
93
+ * seeds keep the verdict reproducible; a majority must pass by default.
94
+ */
95
+ export function assessLMCoherence(lm, tok, opts = {}) {
96
+ const samples = COHERENCE_PROBE_PROMPTS.map((prompt, i) => {
97
+ const text = lm.generateText(messagesToPrompt([{ role: 'user', content: prompt }]), tok, {
98
+ maxNewTokens: 80,
99
+ temperature: 0.7,
100
+ seed: 1234 + i,
101
+ });
102
+ const verdict = isServableText(text, { context: prompt });
103
+ return { prompt, text, coherent: verdict.coherent, failure: verdict.failure, detail: verdict.detail };
104
+ });
105
+ const passRate = samples.length ? samples.filter((s) => s.coherent).length / samples.length : 0;
106
+ return { ready: passRate >= (opts.minPassRate ?? 0.5), passRate, samples };
107
+ }
108
+ /**
109
+ * Test bench: run ONE prompt through a head and grade the output with the SAME bar
110
+ * the serve path uses, so "what will this model actually produce?" is answerable
111
+ * before inference is switched on. Deterministic by default (`seed`).
112
+ */
113
+ export function probeEvermindText(lm, tok, prompt, opts = {}) {
114
+ const gen = generateEvermindText(lm, tok, [{ role: 'user', content: prompt }], {
115
+ maxTokens: opts.maxTokens ?? 120,
116
+ temperature: opts.temperature ?? 0.7,
117
+ seed: opts.seed ?? 1234,
118
+ ...(opts.deadlineMs != null ? { deadlineMs: opts.deadlineMs } : {}),
119
+ });
120
+ const verdict = isServableText(gen.content, { context: prompt });
121
+ return {
122
+ prompt,
123
+ text: gen.content,
124
+ coherent: verdict.coherent,
125
+ failure: verdict.failure,
126
+ detail: verdict.detail,
127
+ usage: gen.usage,
128
+ truncated: gen.truncated,
129
+ elapsedMs: gen.elapsedMs,
130
+ };
131
+ }
132
+ // ── Tool calling ─────────────────────────────────────────────────────────────
133
+ /**
134
+ * A tool-decision prompt is rebuilt for every candidate and every argument, and each
135
+ * costs a full forward pass, so the conversation is capped rather than replayed whole.
136
+ * Truncated from the LEFT: the most recent turns are what a tool choice depends on.
137
+ */
138
+ const MAX_TOOL_PROMPT_CHARS = 6000;
139
+ /** Log-probability the model assigned to `id` at a position, from that position's raw
140
+ * logits (log-softmax, max-shifted so long-tail logits don't overflow). */
141
+ function logProbOf(row, id) {
142
+ let max = -Infinity;
143
+ for (let i = 0; i < row.length; i++) {
144
+ const v = row[i];
145
+ if (v > max)
146
+ max = v;
147
+ }
148
+ if (!Number.isFinite(max))
149
+ return -Infinity;
150
+ let sum = 0;
151
+ for (let i = 0; i < row.length; i++)
152
+ sum += Math.exp(row[i] - max);
153
+ const logit = id >= 0 && id < row.length ? row[id] : -Infinity;
154
+ return logit - (max + Math.log(sum));
155
+ }
156
+ /** Keep the tail of an over-long prompt (see {@link MAX_TOOL_PROMPT_CHARS}). */
157
+ function clampPromptText(prompt) {
158
+ return prompt.length <= MAX_TOOL_PROMPT_CHARS ? prompt : prompt.slice(prompt.length - MAX_TOOL_PROMPT_CHARS);
159
+ }
160
+ /**
161
+ * Bind a loaded head to the {@link EvermindToolDecoder} port.
162
+ *
163
+ * `score`: teacher forcing lets one forward pass over `prompt + continuation` yield
164
+ * the log-prob of EVERY continuation token at once (position `t` predicts `t+1`), so
165
+ * ranking a candidate costs one pass. The mean is returned — not the sum — so a long
166
+ * tool name is not out-voted by a short one for its length alone.
167
+ *
168
+ * `generate` is greedy by default: a tool ARGUMENT is a value to get right, not prose
169
+ * to vary, and determinism keeps a replayed run reproducible.
170
+ */
171
+ export function createEvermindToolDecoder(lm, tok, opts = {}) {
172
+ let promptTokens = 0;
173
+ let completionTokens = 0;
174
+ return {
175
+ score(prompt, continuation) {
176
+ const contIds = tok.encode(continuation);
177
+ if (contIds.length === 0)
178
+ return -Infinity;
179
+ // A leading token is required for the first continuation token to have a
180
+ // position to be predicted FROM; an empty prompt gets the same id-0 prefix the
181
+ // engine's own sampler uses.
182
+ const promptIds = tok.encode(clampPromptText(prompt));
183
+ const prefix = promptIds.length > 0 ? promptIds : [0];
184
+ const { logits } = lm.forward([...prefix, ...contIds]);
185
+ let total = 0;
186
+ for (let i = 0; i < contIds.length; i++) {
187
+ total += logProbOf(logits[prefix.length + i - 1], contIds[i]);
188
+ }
189
+ promptTokens += prefix.length;
190
+ completionTokens += contIds.length;
191
+ return total / contIds.length;
192
+ },
193
+ generate(prompt, maxTokens) {
194
+ const text = lm.generateText(clampPromptText(prompt), tok, {
195
+ maxNewTokens: maxTokens,
196
+ temperature: opts.temperature ?? 0,
197
+ ...(opts.seed != null ? { seed: opts.seed } : {}),
198
+ });
199
+ promptTokens += tok.encode(clampPromptText(prompt)).length;
200
+ completionTokens += text ? tok.encode(text).length : 0;
201
+ return text;
202
+ },
203
+ usage: () => ({ prompt_tokens: promptTokens, completion_tokens: completionTokens, total_tokens: promptTokens + completionTokens }),
204
+ };
205
+ }
206
+ /**
207
+ * Run a TOOL-BEARING request against a loaded head: plan a call by constrained
208
+ * decoding, or fall through to ordinary prose when the head elected to answer directly.
209
+ */
210
+ export function generateEvermindWithTools(lm, tok, messages, tools, choice, opts = {}) {
211
+ const decoder = createEvermindToolDecoder(lm, tok, {
212
+ ...(opts.temperature != null ? { temperature: opts.temperature } : {}),
213
+ ...(opts.seed != null ? { seed: opts.seed } : {}),
214
+ });
215
+ // The planner is given the conversation WITHOUT the `assistant:` primer — it is
216
+ // choosing an action, not continuing a reply.
217
+ const conversation = messagesToPrompt(messages).replace(/\nassistant:$/, '');
218
+ const plan = planEvermindToolCall(decoder, conversation, tools, choice);
219
+ if (plan.call) {
220
+ return { call: plan.call, calls: plan.calls, content: '', usage: decoder.usage(), margin: plan.margin };
221
+ }
222
+ const gen = generateEvermindText(lm, tok, messages, opts);
223
+ const usage = decoder.usage();
224
+ return {
225
+ call: null,
226
+ calls: [],
227
+ content: gen.content,
228
+ usage: {
229
+ prompt_tokens: usage.prompt_tokens + gen.usage.prompt_tokens,
230
+ completion_tokens: usage.completion_tokens + gen.usage.completion_tokens,
231
+ total_tokens: usage.total_tokens + gen.usage.total_tokens,
232
+ },
233
+ margin: plan.margin,
234
+ };
235
+ }
236
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/evermind/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAAyB,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACL,oBAAoB,GAKrB,MAAM,eAAe,CAAC;AA0CvB,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB,CAAC,QAAsD;IACrF,MAAM,KAAK,GAAG,QAAQ;SACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9C,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC;sFACsF;AACtF,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAE1C;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,EAAqB,EACrB,GAA0B,EAC1B,QAAsD,EACtD,OAAgC,EAAE;IAElC,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC;IACxC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;IAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,4BAA4B,CAAC;IAEnE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,QAAQ,GAAG,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,SAAS,GAAG,QAAQ,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,MAAM,GAAG,OAAO,EAAE,EAAE,GAAG,EAAE;YACxD,YAAY,EAAE,IAAI;YAClB,WAAW;YACX,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxD,CAAC,CAAC;QACH,KAAK,EAAE,CAAC;QACR,2EAA2E;QAC3E,IAAI,CAAC,KAAK;YAAE,MAAM;QAClB,OAAO,IAAI,KAAK,CAAC;QACjB,QAAQ,IAAI,IAAI,CAAC;QACjB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,IAAI,UAAU,EAAE,CAAC;YACvC,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;YACjC,MAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAChD,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,OAAO;QACL,OAAO;QACP,KAAK,EAAE,EAAE,aAAa,EAAE,iBAAiB,EAAE,YAAY,EAAE,aAAa,GAAG,iBAAiB,EAAE;QAC5F,SAAS;QACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;KAChC,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E;;cAEc;AACd,MAAM,CAAC,MAAM,uBAAuB,GAAsB;IACxD,8CAA8C;IAC9C,6CAA6C;IAC7C,kCAAkC;CACnC,CAAC;AAsBF;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAqB,EACrB,GAA0B,EAC1B,OAAiC,EAAE;IAEnC,MAAM,OAAO,GAA8B,uBAAuB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACnF,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE;YACvF,YAAY,EAAE,EAAE;YAChB,WAAW,EAAE,GAAG;YAChB,IAAI,EAAE,IAAI,GAAG,CAAC;SACf,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1D,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IACxG,CAAC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,OAAO,EAAE,KAAK,EAAE,QAAQ,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC7E,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAqB,EACrB,GAA0B,EAC1B,MAAc,EACd,OAAgC,EAAE;IAElC,MAAM,GAAG,GAAG,oBAAoB,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE;QAC7E,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,GAAG;QAChC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,GAAG;QACpC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;QACvB,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpE,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,OAAO;QACL,MAAM;QACN,IAAI,EAAE,GAAG,CAAC,OAAO;QACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC;4EAC4E;AAC5E,SAAS,SAAS,CAAC,GAAsB,EAAE,EAAU;IACnD,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC;QAAC,IAAI,CAAC,GAAG,GAAG;YAAE,GAAG,GAAG,CAAC,CAAC;IAAC,CAAC;IACjF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,QAAQ,CAAC;IAC5C,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,GAAG,CAAC,CAAC;IACpE,MAAM,KAAK,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAChE,OAAO,KAAK,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,gFAAgF;AAChF,SAAS,eAAe,CAAC,MAAc;IACrC,OAAO,MAAM,CAAC,MAAM,IAAI,qBAAqB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,qBAAqB,CAAC,CAAC;AAC/G,CAAC;AAQD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CACvC,EAAqB,EACrB,GAA0B,EAC1B,OAAgD,EAAE;IAElD,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,OAAO;QACL,KAAK,CAAC,MAAc,EAAE,YAAoB;YACxC,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACzC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,CAAC,QAAQ,CAAC;YAC3C,yEAAyE;YACzE,+EAA+E;YAC/E,6BAA6B;YAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;YACvD,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,KAAK,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAE,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC;YAClE,CAAC;YACD,YAAY,IAAI,MAAM,CAAC,MAAM,CAAC;YAC9B,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;YACnC,OAAO,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;QAChC,CAAC;QACD,QAAQ,CAAC,MAAc,EAAE,SAAiB;YACxC,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE;gBACzD,YAAY,EAAE,SAAS;gBACvB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC;gBAClC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAClD,CAAC,CAAC;YACH,YAAY,IAAI,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;YAC3D,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,GAAG,gBAAgB,EAAE,CAAC;KACnI,CAAC;AACJ,CAAC;AAkBD;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,EAAqB,EACrB,GAA0B,EAC1B,QAAsD,EACtD,KAAuB,EACvB,MAAsB,EACtB,OAAgC,EAAE;IAElC,MAAM,OAAO,GAAG,yBAAyB,CAAC,EAAE,EAAE,GAAG,EAAE;QACjD,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClD,CAAC,CAAC;IACH,gFAAgF;IAChF,8CAA8C;IAC9C,MAAM,YAAY,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACxE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IAC1G,CAAC;IACD,MAAM,GAAG,GAAG,oBAAoB,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC9B,OAAO;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE;YACL,aAAa,EAAE,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa;YAC5D,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB;YACxE,YAAY,EAAE,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY;SAC1D;QACD,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * textCoherence — pure, zero-dependency text-quality primitives shared by every
3
+ * surface that must decide whether text a project's OWN SSM (Evermind) produced is
4
+ * fit to show a user. Kept dependency-free (no db/env/engine imports) so it can be
5
+ * imported by the memory-first resolver, the model probe and the gateway vendor —
6
+ * and by a browser client — without an import cycle.
7
+ */
8
+ /** A reply shorter than this isn't a real answer — fall through to the LLM. Mirrors
9
+ * the cloud/BrainService threshold so every surface adopts Evermind identically. */
10
+ export declare const EVERMIND_ANSWER_MIN_CHARS = 20;
11
+ /** Why the gate rejected a text. Surfaced to operators (console test bench, quarantine
12
+ * reason, vendor error) so "it produced gibberish" is never an unexplained verdict. */
13
+ export type CoherenceFailure = 'empty' | 'replacement-chars' | 'repetition' | 'dominant-token' | 'unbalanced-delimiters' | 'no-function-words' | 'non-words';
14
+ /** The gate's verdict + the specific signal that produced it. */
15
+ export interface CoherenceVerdict {
16
+ coherent: boolean;
17
+ /** The failing signal, or null when the text passed. */
18
+ failure: CoherenceFailure | null;
19
+ /** Short operator-facing explanation of {@link failure} (empty when coherent). */
20
+ detail: string;
21
+ }
22
+ export interface CoherenceOptions {
23
+ /**
24
+ * The prompt/question the text answers, when the caller has it. Domain jargon
25
+ * ("Evermind", "neocortex", a repo name) reliably echoes the ask, so treating
26
+ * context words as known is what keeps the non-word check from mis-accusing a
27
+ * legitimate, jargon-dense answer. Optional — the gate works without it.
28
+ */
29
+ context?: string;
30
+ }
31
+ /**
32
+ * Cheap coherence gate for text a project's OWN SSM (Evermind) produced. An
33
+ * under-trained head emits fluent-LOOKING garbage — broken UTF-8 (Unicode
34
+ * replacement chars from byte-level BPE), degenerate word repetition ("commit …
35
+ * commit … commit", "in the in the"), and fluent-shaped prose made entirely of
36
+ * INVENTED words — that trivially clears a length check. Serving it makes the
37
+ * assistant reply in gibberish, so this gate rejects it and the caller falls through
38
+ * to a real LLM (a garbled reply IS a memory miss).
39
+ *
40
+ * Signals 1–4 are structural and language-agnostic. Signals 5–6 consult a lexicon and
41
+ * are therefore GUARDED: they run only on predominantly-Latin, non-code text, and the
42
+ * dictionary check only when the text is confidently English — so an es/fr/de/pt/it
43
+ * reply, a CJK reply, or a code block is never judged by an English word list.
44
+ */
45
+ export declare function assessTextCoherence(text: string, opts?: CoherenceOptions): CoherenceVerdict;
46
+ /**
47
+ * Boolean form of {@link assessTextCoherence} — the shape every existing caller uses.
48
+ * Prefer the assessment when you have somewhere to SHOW the reason.
49
+ */
50
+ export declare function looksLikeCoherentText(text: string, opts?: CoherenceOptions): boolean;
51
+ /** Is this text both substantive (long enough) AND coherent — the ONE bar every serve
52
+ * path applies before showing SSM output to a user. Shared so the length threshold and
53
+ * the gate can never drift apart between the memory resolver, the vendor and the probe. */
54
+ export declare function isServableText(text: string | null | undefined, opts?: CoherenceOptions): CoherenceVerdict;
55
+ //# sourceMappingURL=textCoherence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textCoherence.d.ts","sourceRoot":"","sources":["../../src/evermind/textCoherence.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH;qFACqF;AACrF,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C;wFACwF;AACxF,MAAM,MAAM,gBAAgB,GACxB,OAAO,GACP,mBAAmB,GACnB,YAAY,GACZ,gBAAgB,GAChB,uBAAuB,GACvB,mBAAmB,GACnB,WAAW,CAAC;AAEhB,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB,GAAG,gBAAgB,CAyC/F;AA+DD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAExF;AAED;;4FAE4F;AAC5F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,GAAE,gBAAqB,GAAG,gBAAgB,CAM7G"}