@beingmartinbmc/ojas 0.2.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/LICENSE +21 -0
- package/README.md +308 -0
- package/dist/aahar/index.d.ts +179 -0
- package/dist/aahar/index.d.ts.map +1 -0
- package/dist/aahar/index.js +657 -0
- package/dist/aahar/index.js.map +1 -0
- package/dist/aahar/scoring.d.ts +85 -0
- package/dist/aahar/scoring.d.ts.map +1 -0
- package/dist/aahar/scoring.js +268 -0
- package/dist/aahar/scoring.js.map +1 -0
- package/dist/agni/index.d.ts +113 -0
- package/dist/agni/index.d.ts.map +1 -0
- package/dist/agni/index.js +328 -0
- package/dist/agni/index.js.map +1 -0
- package/dist/agni/model-router.d.ts +77 -0
- package/dist/agni/model-router.d.ts.map +1 -0
- package/dist/agni/model-router.js +163 -0
- package/dist/agni/model-router.js.map +1 -0
- package/dist/agni/response-distiller.d.ts +37 -0
- package/dist/agni/response-distiller.d.ts.map +1 -0
- package/dist/agni/response-distiller.js +193 -0
- package/dist/agni/response-distiller.js.map +1 -0
- package/dist/agni/tiktoken-adapter.d.ts +55 -0
- package/dist/agni/tiktoken-adapter.d.ts.map +1 -0
- package/dist/agni/tiktoken-adapter.js +113 -0
- package/dist/agni/tiktoken-adapter.js.map +1 -0
- package/dist/chikitsa/index.d.ts +130 -0
- package/dist/chikitsa/index.d.ts.map +1 -0
- package/dist/chikitsa/index.js +565 -0
- package/dist/chikitsa/index.js.map +1 -0
- package/dist/demo.d.ts +15 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +278 -0
- package/dist/demo.js.map +1 -0
- package/dist/index.d.ts +201 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +588 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/audit.d.ts +39 -0
- package/dist/mcp/audit.d.ts.map +1 -0
- package/dist/mcp/audit.js +73 -0
- package/dist/mcp/audit.js.map +1 -0
- package/dist/mcp/contracts.d.ts +76 -0
- package/dist/mcp/contracts.d.ts.map +1 -0
- package/dist/mcp/contracts.js +44 -0
- package/dist/mcp/contracts.js.map +1 -0
- package/dist/mcp/envelope.d.ts +107 -0
- package/dist/mcp/envelope.d.ts.map +1 -0
- package/dist/mcp/envelope.js +162 -0
- package/dist/mcp/envelope.js.map +1 -0
- package/dist/mcp/registry.d.ts +110 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +258 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/server.d.ts +26 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +107 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/agent.d.ts +4 -0
- package/dist/mcp/tools/agent.d.ts.map +1 -0
- package/dist/mcp/tools/agent.js +300 -0
- package/dist/mcp/tools/agent.js.map +1 -0
- package/dist/mcp/tools/context.d.ts +4 -0
- package/dist/mcp/tools/context.d.ts.map +1 -0
- package/dist/mcp/tools/context.js +261 -0
- package/dist/mcp/tools/context.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +5 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +20 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/memory.d.ts +4 -0
- package/dist/mcp/tools/memory.d.ts.map +1 -0
- package/dist/mcp/tools/memory.js +220 -0
- package/dist/mcp/tools/memory.js.map +1 -0
- package/dist/mcp/tools/output.d.ts +4 -0
- package/dist/mcp/tools/output.d.ts.map +1 -0
- package/dist/mcp/tools/output.js +206 -0
- package/dist/mcp/tools/output.js.map +1 -0
- package/dist/mcp/tools/recovery.d.ts +4 -0
- package/dist/mcp/tools/recovery.d.ts.map +1 -0
- package/dist/mcp/tools/recovery.js +165 -0
- package/dist/mcp/tools/recovery.js.map +1 -0
- package/dist/mcp/tools/registrar.d.ts +4 -0
- package/dist/mcp/tools/registrar.d.ts.map +1 -0
- package/dist/mcp/tools/registrar.js +17 -0
- package/dist/mcp/tools/registrar.js.map +1 -0
- package/dist/mcp/tools/report.d.ts +4 -0
- package/dist/mcp/tools/report.d.ts.map +1 -0
- package/dist/mcp/tools/report.js +68 -0
- package/dist/mcp/tools/report.js.map +1 -0
- package/dist/mcp/tools/shared.d.ts +37 -0
- package/dist/mcp/tools/shared.d.ts.map +1 -0
- package/dist/mcp/tools/shared.js +214 -0
- package/dist/mcp/tools/shared.js.map +1 -0
- package/dist/mcp/trace.d.ts +47 -0
- package/dist/mcp/trace.d.ts.map +1 -0
- package/dist/mcp/trace.js +216 -0
- package/dist/mcp/trace.js.map +1 -0
- package/dist/nidra/index.d.ts +275 -0
- package/dist/nidra/index.d.ts.map +1 -0
- package/dist/nidra/index.js +889 -0
- package/dist/nidra/index.js.map +1 -0
- package/dist/persistence/migrations.d.ts +10 -0
- package/dist/persistence/migrations.d.ts.map +1 -0
- package/dist/persistence/migrations.js +77 -0
- package/dist/persistence/migrations.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +30 -0
- package/dist/persistence/sqlite.d.ts.map +1 -0
- package/dist/persistence/sqlite.js +209 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/persistence/types.d.ts +104 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +5 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/pulse/index.d.ts +144 -0
- package/dist/pulse/index.d.ts.map +1 -0
- package/dist/pulse/index.js +453 -0
- package/dist/pulse/index.js.map +1 -0
- package/dist/raksha/classifiers/http-classifier.d.ts +26 -0
- package/dist/raksha/classifiers/http-classifier.d.ts.map +1 -0
- package/dist/raksha/classifiers/http-classifier.js +62 -0
- package/dist/raksha/classifiers/http-classifier.js.map +1 -0
- package/dist/raksha/classifiers/index.d.ts +5 -0
- package/dist/raksha/classifiers/index.d.ts.map +1 -0
- package/dist/raksha/classifiers/index.js +8 -0
- package/dist/raksha/classifiers/index.js.map +1 -0
- package/dist/raksha/classifiers/onnx-classifier.d.ts +41 -0
- package/dist/raksha/classifiers/onnx-classifier.d.ts.map +1 -0
- package/dist/raksha/classifiers/onnx-classifier.js +99 -0
- package/dist/raksha/classifiers/onnx-classifier.js.map +1 -0
- package/dist/raksha/hallucination-detectors.d.ts +106 -0
- package/dist/raksha/hallucination-detectors.d.ts.map +1 -0
- package/dist/raksha/hallucination-detectors.js +327 -0
- package/dist/raksha/hallucination-detectors.js.map +1 -0
- package/dist/raksha/index.d.ts +168 -0
- package/dist/raksha/index.d.ts.map +1 -0
- package/dist/raksha/index.js +597 -0
- package/dist/raksha/index.js.map +1 -0
- package/dist/raksha/prompt-injection-detectors.d.ts +30 -0
- package/dist/raksha/prompt-injection-detectors.d.ts.map +1 -0
- package/dist/raksha/prompt-injection-detectors.js +153 -0
- package/dist/raksha/prompt-injection-detectors.js.map +1 -0
- package/dist/types.d.ts +1115 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +71 -0
- package/dist/types.js.map +1 -0
- package/dist/util/calibration.d.ts +32 -0
- package/dist/util/calibration.d.ts.map +1 -0
- package/dist/util/calibration.js +108 -0
- package/dist/util/calibration.js.map +1 -0
- package/dist/util/id.d.ts +2 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +9 -0
- package/dist/util/id.js.map +1 -0
- package/dist/vyayam/index.d.ts +76 -0
- package/dist/vyayam/index.d.ts.map +1 -0
- package/dist/vyayam/index.js +528 -0
- package/dist/vyayam/index.js.map +1 -0
- package/dist/vyayam/tool-fault-proxy.d.ts +95 -0
- package/dist/vyayam/tool-fault-proxy.d.ts.map +1 -0
- package/dist/vyayam/tool-fault-proxy.js +170 -0
- package/dist/vyayam/tool-fault-proxy.js.map +1 -0
- package/docs/ARCHITECTURE.md +162 -0
- package/docs/BACKLOG.md +342 -0
- package/docs/CONFIGURATION.md +305 -0
- package/docs/EVIDENCE.md +232 -0
- package/docs/EVIDENCE_MATRIX.md +293 -0
- package/docs/KNOWN_FAILURES.md +367 -0
- package/docs/MCP.md +614 -0
- package/docs/MODULES.md +368 -0
- package/docs/SECURITY.md +251 -0
- package/docs/TRUST.md +88 -0
- package/docs/assets/ojas-hero.png +0 -0
- package/package.json +101 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Ojas Agni (ओजस अग्नि) — AI Cognitive Metabolism System
|
|
4
|
+
*
|
|
5
|
+
* Regulates token budgets, tool economy, latency, and reasoning effort.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.Agni = exports.charBasedTokenEstimator = void 0;
|
|
9
|
+
const types_1 = require("../types");
|
|
10
|
+
const model_router_1 = require("./model-router");
|
|
11
|
+
const response_distiller_1 = require("./response-distiller");
|
|
12
|
+
/**
|
|
13
|
+
* Default token estimator: `Math.ceil(text.length / 4)`. Conservative,
|
|
14
|
+
* platform-stable, no external dependency. Off by up to ~25% from real
|
|
15
|
+
* tokenizers (`cl100k_base`, `o200k_base`) on natural-language English,
|
|
16
|
+
* and worse on code, JSON, and non-English text. The number is
|
|
17
|
+
* *directionally* correct but not a model-billing prediction.
|
|
18
|
+
*
|
|
19
|
+
* Plug in a real tokenizer via `new Agni({}, { tokenEstimator: ... })`.
|
|
20
|
+
* The optional `createTiktokenEstimator()` adapter in
|
|
21
|
+
* `src/agni/tiktoken-adapter.ts` wraps OpenAI's `tiktoken` if installed.
|
|
22
|
+
*/
|
|
23
|
+
exports.charBasedTokenEstimator = {
|
|
24
|
+
name: 'char/4',
|
|
25
|
+
estimate(text) {
|
|
26
|
+
if (typeof text !== 'string' || text.length === 0)
|
|
27
|
+
return 0;
|
|
28
|
+
return Math.ceil(text.length / 4);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
function now() {
|
|
32
|
+
return new Date().toISOString();
|
|
33
|
+
}
|
|
34
|
+
function clamp(v, min = 0, max = 1) {
|
|
35
|
+
return Math.max(min, Math.min(max, v));
|
|
36
|
+
}
|
|
37
|
+
function healthScore(value, source) {
|
|
38
|
+
return { value: clamp(value), timestamp: now(), source };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Serialize a value to a string for size estimation, gracefully handling
|
|
42
|
+
* circular references. A single bad trace must not crash health assessment.
|
|
43
|
+
*/
|
|
44
|
+
function safeStringify(value) {
|
|
45
|
+
if (value === null || value === undefined)
|
|
46
|
+
return '';
|
|
47
|
+
try {
|
|
48
|
+
return JSON.stringify(value) ?? '';
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
try {
|
|
52
|
+
return String(value);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return '[unserializable]';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
class Agni {
|
|
60
|
+
policy;
|
|
61
|
+
traces = [];
|
|
62
|
+
tokenEstimator;
|
|
63
|
+
modelRouter;
|
|
64
|
+
responseDistiller;
|
|
65
|
+
/**
|
|
66
|
+
* Running sum of estimated tokens removed by `distillResponse`.
|
|
67
|
+
* Used by the token-negative learning-budget invariant in
|
|
68
|
+
* `lifetimeOutputTokensSaved()`.
|
|
69
|
+
*/
|
|
70
|
+
outputTokensSaved = 0;
|
|
71
|
+
constructor(policy = {}, options = {}) {
|
|
72
|
+
this.policy = this.validatePolicy({ ...types_1.DEFAULT_METABOLISM_POLICY, ...policy });
|
|
73
|
+
this.tokenEstimator = options.tokenEstimator ?? exports.charBasedTokenEstimator;
|
|
74
|
+
this.modelRouter = options.modelRouter ?? new model_router_1.ConfidenceRoutingTable();
|
|
75
|
+
this.responseDistiller = options.responseDistiller ?? response_distiller_1.defaultResponseDistiller;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Identifier of the token estimator Agni is using. Useful for stamping on
|
|
79
|
+
* reports / benchmarks so the reader knows whether numbers are char/4 or
|
|
80
|
+
* a real tokenizer. Stable across calls.
|
|
81
|
+
*/
|
|
82
|
+
getTokenEstimatorName() {
|
|
83
|
+
return this.tokenEstimator.name;
|
|
84
|
+
}
|
|
85
|
+
/** Identifier of the model router currently wired in. */
|
|
86
|
+
getModelRouterName() {
|
|
87
|
+
return this.modelRouter.name;
|
|
88
|
+
}
|
|
89
|
+
/** Identifier of the response distiller currently wired in. */
|
|
90
|
+
getResponseDistillerName() {
|
|
91
|
+
return this.responseDistiller.name;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Record an observed pass/fail outcome for a task class so the model
|
|
95
|
+
* router can build a confidence interval. Delegates to the configured
|
|
96
|
+
* `ModelRouter` — see `ConfidenceRoutingTable` for the default.
|
|
97
|
+
*/
|
|
98
|
+
recordTaskOutcome(taskClass, succeeded) {
|
|
99
|
+
this.modelRouter.recordOutcome(taskClass, succeeded);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Recommend a routing decision (`'cheap'` vs `'flagship'`) for a task
|
|
103
|
+
* class. The router never calls an LLM itself — the caller wires the
|
|
104
|
+
* decision to their own provider gateway. Fail-closed: on insufficient
|
|
105
|
+
* data, low CI lower bound, or a configured safety class, returns
|
|
106
|
+
* `flagship`.
|
|
107
|
+
*/
|
|
108
|
+
recommendRoute(taskClass) {
|
|
109
|
+
return this.modelRouter.recommend(taskClass);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Snapshot of what the router has learned, sorted by observation
|
|
113
|
+
* count (most-observed task classes first). Useful for debugging or
|
|
114
|
+
* for an operator dashboard.
|
|
115
|
+
*/
|
|
116
|
+
getRouterReport() {
|
|
117
|
+
return this.modelRouter.report();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Distill an agent **output** to remove non-load-bearing filler
|
|
121
|
+
* (preserves code blocks). Updates the lifetime
|
|
122
|
+
* `outputTokensSaved` counter so callers can audit the
|
|
123
|
+
* token-negative invariant.
|
|
124
|
+
*/
|
|
125
|
+
distillResponse(text) {
|
|
126
|
+
const result = this.responseDistiller.distill(text);
|
|
127
|
+
this.outputTokensSaved += result.tokensRemoved;
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Lifetime estimated tokens saved by `distillResponse` since this
|
|
132
|
+
* Agni was constructed. Used by callers (or downstream tooling) to
|
|
133
|
+
* enforce a token-negative learning-budget invariant — i.e. a
|
|
134
|
+
* self-improvement loop should never spend more than a small fraction
|
|
135
|
+
* of lifetime savings on its own learning.
|
|
136
|
+
*/
|
|
137
|
+
lifetimeOutputTokensSaved() {
|
|
138
|
+
return this.outputTokensSaved;
|
|
139
|
+
}
|
|
140
|
+
validatePolicy(policy) {
|
|
141
|
+
const finite = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
142
|
+
if (!finite(policy.targetTokensPerTask) || policy.targetTokensPerTask <= 0) {
|
|
143
|
+
throw new Error('Agni: targetTokensPerTask must be a positive finite number');
|
|
144
|
+
}
|
|
145
|
+
if (!finite(policy.maxLatencyMs) || policy.maxLatencyMs <= 0) {
|
|
146
|
+
throw new Error('Agni: maxLatencyMs must be a positive finite number');
|
|
147
|
+
}
|
|
148
|
+
if (!Number.isInteger(policy.maxToolCallsPerTask) || policy.maxToolCallsPerTask <= 0) {
|
|
149
|
+
throw new Error('Agni: maxToolCallsPerTask must be a positive integer');
|
|
150
|
+
}
|
|
151
|
+
if (!finite(policy.highRiskReasoningBoost) || policy.highRiskReasoningBoost < 0 || policy.highRiskReasoningBoost > 1) {
|
|
152
|
+
throw new Error('Agni: highRiskReasoningBoost must be a finite number in [0,1]');
|
|
153
|
+
}
|
|
154
|
+
if (policy.maxTraces !== undefined && (!Number.isInteger(policy.maxTraces) || policy.maxTraces < 0)) {
|
|
155
|
+
throw new Error('Agni: maxTraces must be a non-negative integer if set');
|
|
156
|
+
}
|
|
157
|
+
if (policy.targetCostUsdPerTask !== undefined && (!finite(policy.targetCostUsdPerTask) || policy.targetCostUsdPerTask <= 0)) {
|
|
158
|
+
throw new Error('Agni: targetCostUsdPerTask must be a positive finite number if set');
|
|
159
|
+
}
|
|
160
|
+
return policy;
|
|
161
|
+
}
|
|
162
|
+
enforceTraceLimit() {
|
|
163
|
+
const cap = this.policy.maxTraces ?? 0;
|
|
164
|
+
if (cap > 0 && this.traces.length > cap) {
|
|
165
|
+
this.traces.splice(0, this.traces.length - cap);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
recordTrace(trace) {
|
|
169
|
+
this.traces.push(trace);
|
|
170
|
+
this.enforceTraceLimit();
|
|
171
|
+
}
|
|
172
|
+
estimateReasoningEffort(riskScore, ambiguityScore) {
|
|
173
|
+
const pressure = clamp((riskScore * 0.6) + (ambiguityScore * 0.4) + this.policy.highRiskReasoningBoost);
|
|
174
|
+
if (pressure >= 0.75)
|
|
175
|
+
return 'deep';
|
|
176
|
+
if (pressure >= 0.4)
|
|
177
|
+
return 'standard';
|
|
178
|
+
return 'light';
|
|
179
|
+
}
|
|
180
|
+
assess(traces = this.traces) {
|
|
181
|
+
if (traces.length === 0) {
|
|
182
|
+
return {
|
|
183
|
+
tokenEfficiency: healthScore(0.5, 'agni.tokenEfficiency'),
|
|
184
|
+
toolEconomy: healthScore(0.5, 'agni.toolEconomy'),
|
|
185
|
+
reasoningEfficiency: healthScore(0.5, 'agni.reasoningEfficiency'),
|
|
186
|
+
latencyEfficiency: healthScore(0.5, 'agni.latencyEfficiency'),
|
|
187
|
+
costPressure: 0,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const avgLatency = traces.reduce((sum, trace) => sum + trace.durationMs, 0) / traces.length;
|
|
191
|
+
const failureRate = traces.filter((trace) => !trace.success).length / traces.length;
|
|
192
|
+
const reasoningWaste = traces.filter((trace) => (trace.reasoning?.length ?? 0) > 4000 && !trace.success).length / traces.length;
|
|
193
|
+
// Prefer explicit telemetry. Fall back to input+output token components,
|
|
194
|
+
// then finally to the configured `tokenEstimator` over the serialized
|
|
195
|
+
// payload + reasoning text. The estimator is `charBasedTokenEstimator`
|
|
196
|
+
// by default; pass a real tokenizer via `new Agni({}, {tokenEstimator})`
|
|
197
|
+
// (e.g. `createTiktokenEstimator('cl100k_base')`) for production-grade
|
|
198
|
+
// cost claims.
|
|
199
|
+
const tokensPerTrace = traces.map((trace) => {
|
|
200
|
+
if (typeof trace.tokensUsed === 'number' && Number.isFinite(trace.tokensUsed) && trace.tokensUsed >= 0) {
|
|
201
|
+
return trace.tokensUsed;
|
|
202
|
+
}
|
|
203
|
+
const componentTokens = (trace.inputTokens ?? 0) + (trace.outputTokens ?? 0);
|
|
204
|
+
if (componentTokens > 0 && Number.isFinite(componentTokens))
|
|
205
|
+
return componentTokens;
|
|
206
|
+
const inputStr = typeof trace.input === 'string' ? trace.input : safeStringify(trace.input);
|
|
207
|
+
const outputStr = typeof trace.output === 'string' ? trace.output : safeStringify(trace.output);
|
|
208
|
+
const reasoningStr = trace.reasoning ?? '';
|
|
209
|
+
// Use the configured estimator. We sum independently so the estimator
|
|
210
|
+
// sees natural sub-strings rather than one concatenated blob — most
|
|
211
|
+
// tokenizers are sensitive to whitespace and joining can over-count.
|
|
212
|
+
let est = 0;
|
|
213
|
+
try {
|
|
214
|
+
est = this.tokenEstimator.estimate(inputStr)
|
|
215
|
+
+ this.tokenEstimator.estimate(outputStr)
|
|
216
|
+
+ this.tokenEstimator.estimate(reasoningStr);
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
// Contract says estimators must not throw; if one does, fall back to
|
|
220
|
+
// char/4 so a single bad estimator can't crash health assessment.
|
|
221
|
+
est = exports.charBasedTokenEstimator.estimate(inputStr + outputStr + reasoningStr);
|
|
222
|
+
}
|
|
223
|
+
return est;
|
|
224
|
+
});
|
|
225
|
+
const avgTokens = tokensPerTrace.reduce((s, n) => s + n, 0) / tokensPerTrace.length;
|
|
226
|
+
const avgToolCalls = traces.reduce((sum, trace) => {
|
|
227
|
+
const n = trace.toolCalls;
|
|
228
|
+
return sum + (typeof n === 'number' && Number.isFinite(n) && n >= 0 ? n : 0);
|
|
229
|
+
}, 0) / traces.length;
|
|
230
|
+
const avgCostUsd = traces.reduce((sum, trace) => {
|
|
231
|
+
const n = trace.costUsd;
|
|
232
|
+
return sum + (typeof n === 'number' && Number.isFinite(n) && n >= 0 ? n : 0);
|
|
233
|
+
}, 0) / traces.length;
|
|
234
|
+
const tokenEfficiency = 1 - Math.max(0, avgTokens - this.policy.targetTokensPerTask) / this.policy.targetTokensPerTask;
|
|
235
|
+
const latencyEfficiency = 1 - Math.max(0, avgLatency - this.policy.maxLatencyMs) / this.policy.maxLatencyMs;
|
|
236
|
+
const toolCallEfficiency = 1 - Math.max(0, avgToolCalls - this.policy.maxToolCallsPerTask) / this.policy.maxToolCallsPerTask;
|
|
237
|
+
const toolEconomy = Math.min(1 - failureRate, toolCallEfficiency);
|
|
238
|
+
const reasoningEfficiency = 1 - reasoningWaste;
|
|
239
|
+
const costComponent = this.policy.targetCostUsdPerTask
|
|
240
|
+
? Math.min(1, avgCostUsd / this.policy.targetCostUsdPerTask)
|
|
241
|
+
: 0;
|
|
242
|
+
const costPressure = clamp((avgTokens / this.policy.targetTokensPerTask) * 0.4 +
|
|
243
|
+
(avgLatency / this.policy.maxLatencyMs) * 0.25 +
|
|
244
|
+
(avgToolCalls / this.policy.maxToolCallsPerTask) * 0.15 +
|
|
245
|
+
failureRate * 0.15 +
|
|
246
|
+
costComponent * 0.05);
|
|
247
|
+
return {
|
|
248
|
+
tokenEfficiency: healthScore(tokenEfficiency, 'agni.tokenEfficiency'),
|
|
249
|
+
toolEconomy: healthScore(toolEconomy, 'agni.toolEconomy'),
|
|
250
|
+
reasoningEfficiency: healthScore(reasoningEfficiency, 'agni.reasoningEfficiency'),
|
|
251
|
+
latencyEfficiency: healthScore(latencyEfficiency, 'agni.latencyEfficiency'),
|
|
252
|
+
costPressure,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
recommend(traces = this.traces) {
|
|
256
|
+
const health = this.assess(traces);
|
|
257
|
+
const recs = [];
|
|
258
|
+
if (health.tokenEfficiency.value < 0.6) {
|
|
259
|
+
recs.push({
|
|
260
|
+
module: 'agni',
|
|
261
|
+
severity: 'warning',
|
|
262
|
+
message: 'Token metabolism is inefficient.',
|
|
263
|
+
action: 'Compress context, reduce retrieval volume, and summarize verbose tool outputs.',
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
if (health.latencyEfficiency.value < 0.6) {
|
|
267
|
+
recs.push({
|
|
268
|
+
module: 'agni',
|
|
269
|
+
severity: 'warning',
|
|
270
|
+
message: 'Latency metabolism is degraded.',
|
|
271
|
+
action: 'Reduce tool fan-out and prefer cached or lower-latency sources.',
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
if (health.costPressure > 0.85) {
|
|
275
|
+
recs.push({
|
|
276
|
+
module: 'agni',
|
|
277
|
+
severity: 'critical',
|
|
278
|
+
message: 'Cognitive cost pressure is critical.',
|
|
279
|
+
action: 'Switch to conservative mode and cap reasoning depth.',
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
if (recs.length === 0) {
|
|
283
|
+
recs.push({ module: 'agni', severity: 'info', message: 'Cognitive metabolism is efficient.' });
|
|
284
|
+
}
|
|
285
|
+
return recs;
|
|
286
|
+
}
|
|
287
|
+
getPolicy() {
|
|
288
|
+
return { ...this.policy };
|
|
289
|
+
}
|
|
290
|
+
/** Defensive copy of retained traces. Useful for introspecting retention. */
|
|
291
|
+
getTraces() {
|
|
292
|
+
return this.traces.map((t) => ({
|
|
293
|
+
...t,
|
|
294
|
+
failures: t.failures?.map((f) => ({ ...f, metadata: f.metadata ? { ...f.metadata } : undefined })),
|
|
295
|
+
}));
|
|
296
|
+
}
|
|
297
|
+
exportState() {
|
|
298
|
+
return {
|
|
299
|
+
traces: [...this.getTraces()],
|
|
300
|
+
outputTokensSaved: this.outputTokensSaved,
|
|
301
|
+
routerReport: this.getRouterReport().map((r) => ({
|
|
302
|
+
taskClass: r.taskClass,
|
|
303
|
+
n: r.n,
|
|
304
|
+
successes: r.successes,
|
|
305
|
+
})),
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
importState(snapshot) {
|
|
309
|
+
if (!snapshot)
|
|
310
|
+
return;
|
|
311
|
+
this.traces = (snapshot.traces ?? []).map((t) => ({
|
|
312
|
+
...t,
|
|
313
|
+
failures: t.failures?.map((f) => ({ ...f, metadata: f.metadata ? { ...f.metadata } : undefined })),
|
|
314
|
+
}));
|
|
315
|
+
this.outputTokensSaved = snapshot.outputTokensSaved ?? 0;
|
|
316
|
+
for (const row of snapshot.routerReport ?? []) {
|
|
317
|
+
for (let i = 0; i < row.n; i += 1) {
|
|
318
|
+
this.modelRouter.recordOutcome(row.taskClass, i < row.successes);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
updatePolicy(updates) {
|
|
323
|
+
this.policy = this.validatePolicy({ ...this.policy, ...updates });
|
|
324
|
+
this.enforceTraceLimit();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
exports.Agni = Agni;
|
|
328
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agni/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ConfidenceRoutingTable` — default `ModelRouter` implementation.
|
|
3
|
+
*
|
|
4
|
+
* The idea: many tasks are routinely simple (running tests, formatting
|
|
5
|
+
* code, looking up a config) and don't need a flagship model. The
|
|
6
|
+
* router watches honest pass/fail outcomes per task class, computes a
|
|
7
|
+
* Wilson 95% CI on the success rate, and only recommends routing to
|
|
8
|
+
* the cheap model when the *lower bound* of the CI exceeds a
|
|
9
|
+
* configured threshold. That's "fail-closed": if data is sparse, the
|
|
10
|
+
* task class stays on the flagship model.
|
|
11
|
+
*
|
|
12
|
+
* Why Wilson instead of bootstrap (which we use elsewhere in
|
|
13
|
+
* benchmarks): the routing decision is a real-time per-task call, so
|
|
14
|
+
* an analytic CI is preferred over a 1000-resample bootstrap. Wilson
|
|
15
|
+
* has good coverage even at small n (≥ 10), which matters when a task
|
|
16
|
+
* class has just been observed for the first time.
|
|
17
|
+
*
|
|
18
|
+
* **Hard-coded safety classes**: certain task classes are never routed
|
|
19
|
+
* to cheap regardless of observed success rate. By default these are
|
|
20
|
+
* `'security'` and `'auth'`. The caller can override the list via the
|
|
21
|
+
* policy.
|
|
22
|
+
*
|
|
23
|
+
* The router itself never calls an LLM. It returns a *recommendation*;
|
|
24
|
+
* wiring it to your provider gateway is the caller's job.
|
|
25
|
+
*/
|
|
26
|
+
import type { ModelRouter, ModelRouterDecision, ModelRouterTaskReport } from '../types';
|
|
27
|
+
export interface ConfidenceRoutingTablePolicy {
|
|
28
|
+
/**
|
|
29
|
+
* Lower-bound success-rate threshold below which cheap routing is
|
|
30
|
+
* not recommended. Default 0.80. Tighten this if a quality regression
|
|
31
|
+
* is more expensive than a few extra dollars of token spend.
|
|
32
|
+
*/
|
|
33
|
+
successRateThreshold?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Minimum observation count before *any* cheap routing is allowed.
|
|
36
|
+
* Default 10. Below this, every recommendation falls back to
|
|
37
|
+
* `flagship` with reason `insufficient_data`.
|
|
38
|
+
*/
|
|
39
|
+
minObservations?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Task classes that must always route to flagship regardless of
|
|
42
|
+
* observed success. Default `['security', 'auth']`. Matched
|
|
43
|
+
* case-insensitively as a prefix of the supplied taskClass.
|
|
44
|
+
*/
|
|
45
|
+
safetyClasses?: string[];
|
|
46
|
+
/**
|
|
47
|
+
* CI coverage level. Default 0.95. Reduce for a looser bound (more
|
|
48
|
+
* cheap routing); raise for a tighter bound (more conservative).
|
|
49
|
+
*/
|
|
50
|
+
ciLevel?: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Wilson score interval for a binomial proportion.
|
|
54
|
+
*
|
|
55
|
+
* Given `k` successes out of `n` trials, returns the [lo, hi] bounds at
|
|
56
|
+
* coverage `level` (default 0.95). For `n === 0` returns `null`.
|
|
57
|
+
*
|
|
58
|
+
* We use the standard form (Wilson 1927) — Agresti–Coull is the other
|
|
59
|
+
* popular choice but Wilson is more conservative at low n, which is
|
|
60
|
+
* what we want for fail-closed routing.
|
|
61
|
+
*/
|
|
62
|
+
export declare function wilsonInterval(successes: number, n: number, level?: number): {
|
|
63
|
+
lo: number;
|
|
64
|
+
hi: number;
|
|
65
|
+
} | null;
|
|
66
|
+
export declare class ConfidenceRoutingTable implements ModelRouter {
|
|
67
|
+
readonly name = "confidence-routing-table/wilson";
|
|
68
|
+
private readonly policy;
|
|
69
|
+
private readonly buckets;
|
|
70
|
+
constructor(policy?: ConfidenceRoutingTablePolicy);
|
|
71
|
+
recordOutcome(taskClass: string, succeeded: boolean): void;
|
|
72
|
+
recommend(taskClass: string): ModelRouterDecision;
|
|
73
|
+
report(): ReadonlyArray<ModelRouterTaskReport>;
|
|
74
|
+
private successCI;
|
|
75
|
+
private isSafetyClass;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=model-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-router.d.ts","sourceRoot":"","sources":["../../src/agni/model-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAOD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,CAAC,EAAE,MAAM,EACT,KAAK,SAAO,GACX;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAenC;AAED,qBAAa,sBAAuB,YAAW,WAAW;IACxD,QAAQ,CAAC,IAAI,qCAAqC;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;gBAE7C,MAAM,GAAE,4BAAiC;IASrD,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI;IAS1D,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB;IAkDjD,MAAM,IAAI,aAAa,CAAC,qBAAqB,CAAC;IAiB9C,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,aAAa;CAMtB"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `ConfidenceRoutingTable` — default `ModelRouter` implementation.
|
|
4
|
+
*
|
|
5
|
+
* The idea: many tasks are routinely simple (running tests, formatting
|
|
6
|
+
* code, looking up a config) and don't need a flagship model. The
|
|
7
|
+
* router watches honest pass/fail outcomes per task class, computes a
|
|
8
|
+
* Wilson 95% CI on the success rate, and only recommends routing to
|
|
9
|
+
* the cheap model when the *lower bound* of the CI exceeds a
|
|
10
|
+
* configured threshold. That's "fail-closed": if data is sparse, the
|
|
11
|
+
* task class stays on the flagship model.
|
|
12
|
+
*
|
|
13
|
+
* Why Wilson instead of bootstrap (which we use elsewhere in
|
|
14
|
+
* benchmarks): the routing decision is a real-time per-task call, so
|
|
15
|
+
* an analytic CI is preferred over a 1000-resample bootstrap. Wilson
|
|
16
|
+
* has good coverage even at small n (≥ 10), which matters when a task
|
|
17
|
+
* class has just been observed for the first time.
|
|
18
|
+
*
|
|
19
|
+
* **Hard-coded safety classes**: certain task classes are never routed
|
|
20
|
+
* to cheap regardless of observed success rate. By default these are
|
|
21
|
+
* `'security'` and `'auth'`. The caller can override the list via the
|
|
22
|
+
* policy.
|
|
23
|
+
*
|
|
24
|
+
* The router itself never calls an LLM. It returns a *recommendation*;
|
|
25
|
+
* wiring it to your provider gateway is the caller's job.
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.ConfidenceRoutingTable = void 0;
|
|
29
|
+
exports.wilsonInterval = wilsonInterval;
|
|
30
|
+
/**
|
|
31
|
+
* Wilson score interval for a binomial proportion.
|
|
32
|
+
*
|
|
33
|
+
* Given `k` successes out of `n` trials, returns the [lo, hi] bounds at
|
|
34
|
+
* coverage `level` (default 0.95). For `n === 0` returns `null`.
|
|
35
|
+
*
|
|
36
|
+
* We use the standard form (Wilson 1927) — Agresti–Coull is the other
|
|
37
|
+
* popular choice but Wilson is more conservative at low n, which is
|
|
38
|
+
* what we want for fail-closed routing.
|
|
39
|
+
*/
|
|
40
|
+
function wilsonInterval(successes, n, level = 0.95) {
|
|
41
|
+
if (n <= 0)
|
|
42
|
+
return null;
|
|
43
|
+
// z = inverse normal CDF at (1 + level) / 2. We hard-code the
|
|
44
|
+
// common values to avoid pulling in a stats library.
|
|
45
|
+
const z = level === 0.95 ? 1.959963984540054 : level === 0.99 ? 2.5758293035489004 : 1.959963984540054;
|
|
46
|
+
const p = successes / n;
|
|
47
|
+
const denom = 1 + (z * z) / n;
|
|
48
|
+
const centre = p + (z * z) / (2 * n);
|
|
49
|
+
const margin = z * Math.sqrt((p * (1 - p)) / n + (z * z) / (4 * n * n));
|
|
50
|
+
const lo = (centre - margin) / denom;
|
|
51
|
+
const hi = (centre + margin) / denom;
|
|
52
|
+
return {
|
|
53
|
+
lo: Math.max(0, Math.min(1, lo)),
|
|
54
|
+
hi: Math.max(0, Math.min(1, hi)),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
class ConfidenceRoutingTable {
|
|
58
|
+
name = 'confidence-routing-table/wilson';
|
|
59
|
+
policy;
|
|
60
|
+
buckets = new Map();
|
|
61
|
+
constructor(policy = {}) {
|
|
62
|
+
this.policy = {
|
|
63
|
+
successRateThreshold: clamp01(policy.successRateThreshold ?? 0.8),
|
|
64
|
+
minObservations: Math.max(1, Math.floor(policy.minObservations ?? 10)),
|
|
65
|
+
safetyClasses: policy.safetyClasses ?? ['security', 'auth'],
|
|
66
|
+
ciLevel: clamp01(policy.ciLevel ?? 0.95),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
recordOutcome(taskClass, succeeded) {
|
|
70
|
+
const key = normaliseTaskClass(taskClass);
|
|
71
|
+
if (key === '')
|
|
72
|
+
return;
|
|
73
|
+
const bucket = this.buckets.get(key) ?? { n: 0, successes: 0 };
|
|
74
|
+
bucket.n += 1;
|
|
75
|
+
if (succeeded)
|
|
76
|
+
bucket.successes += 1;
|
|
77
|
+
this.buckets.set(key, bucket);
|
|
78
|
+
}
|
|
79
|
+
recommend(taskClass) {
|
|
80
|
+
const key = normaliseTaskClass(taskClass);
|
|
81
|
+
// Safety classes never route cheap, no matter how good the stats are.
|
|
82
|
+
if (this.isSafetyClass(key)) {
|
|
83
|
+
return {
|
|
84
|
+
route: 'flagship',
|
|
85
|
+
reason: `safety_class:${key}`,
|
|
86
|
+
n: this.buckets.get(key)?.n ?? 0,
|
|
87
|
+
successCI: this.successCI(key),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const bucket = this.buckets.get(key);
|
|
91
|
+
if (!bucket || bucket.n < this.policy.minObservations) {
|
|
92
|
+
return {
|
|
93
|
+
route: 'flagship',
|
|
94
|
+
reason: `insufficient_data:${bucket?.n ?? 0}_of_${this.policy.minObservations}`,
|
|
95
|
+
n: bucket?.n ?? 0,
|
|
96
|
+
successCI: bucket ? wilsonInterval(bucket.successes, bucket.n, this.policy.ciLevel) : null,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const ci = wilsonInterval(bucket.successes, bucket.n, this.policy.ciLevel);
|
|
100
|
+
if (!ci) {
|
|
101
|
+
// Defensive: should be impossible given `n >= minObservations >= 1`.
|
|
102
|
+
return {
|
|
103
|
+
route: 'flagship',
|
|
104
|
+
reason: 'ci_unavailable',
|
|
105
|
+
n: bucket.n,
|
|
106
|
+
successCI: null,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (ci.lo >= this.policy.successRateThreshold) {
|
|
110
|
+
return {
|
|
111
|
+
route: 'cheap',
|
|
112
|
+
reason: `wilson_lo=${ci.lo.toFixed(3)}>=${this.policy.successRateThreshold.toFixed(2)}`,
|
|
113
|
+
n: bucket.n,
|
|
114
|
+
successCI: ci,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
route: 'flagship',
|
|
119
|
+
reason: `wilson_lo=${ci.lo.toFixed(3)}<${this.policy.successRateThreshold.toFixed(2)}`,
|
|
120
|
+
n: bucket.n,
|
|
121
|
+
successCI: ci,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
report() {
|
|
125
|
+
const out = [];
|
|
126
|
+
for (const [taskClass, b] of this.buckets) {
|
|
127
|
+
const ci = wilsonInterval(b.successes, b.n, this.policy.ciLevel);
|
|
128
|
+
const decision = this.recommend(taskClass);
|
|
129
|
+
out.push({
|
|
130
|
+
taskClass,
|
|
131
|
+
n: b.n,
|
|
132
|
+
successes: b.successes,
|
|
133
|
+
successRate: b.n === 0 ? 0 : b.successes / b.n,
|
|
134
|
+
successCI: ci,
|
|
135
|
+
currentRoute: decision.route,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return out.sort((a, b) => b.n - a.n);
|
|
139
|
+
}
|
|
140
|
+
successCI(key) {
|
|
141
|
+
const b = this.buckets.get(key);
|
|
142
|
+
if (!b)
|
|
143
|
+
return null;
|
|
144
|
+
return wilsonInterval(b.successes, b.n, this.policy.ciLevel);
|
|
145
|
+
}
|
|
146
|
+
isSafetyClass(key) {
|
|
147
|
+
for (const safe of this.policy.safetyClasses) {
|
|
148
|
+
if (key.startsWith(safe.toLowerCase()))
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.ConfidenceRoutingTable = ConfidenceRoutingTable;
|
|
155
|
+
function clamp01(v) {
|
|
156
|
+
if (!Number.isFinite(v))
|
|
157
|
+
return 0;
|
|
158
|
+
return Math.max(0, Math.min(1, v));
|
|
159
|
+
}
|
|
160
|
+
function normaliseTaskClass(taskClass) {
|
|
161
|
+
return (taskClass ?? '').toLowerCase().trim();
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=model-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-router.js","sourceRoot":"","sources":["../../src/agni/model-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defaultResponseDistiller` — rule-based filler stripper for agent
|
|
3
|
+
* output.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: LLM responses routinely contain ~30-40% filler — "Sure,
|
|
6
|
+
* I'd be happy to help!", "Hope this helps!", chain-of-thought
|
|
7
|
+
* meta-commentary, repeated preambles. None of it is load-bearing
|
|
8
|
+
* for the caller. Stripping it
|
|
9
|
+
* saves tokens on the output side without touching what actually
|
|
10
|
+
* matters.
|
|
11
|
+
*
|
|
12
|
+
* **Code blocks are sacrosanct.** Anything between fenced code fences
|
|
13
|
+
* (``` … ```) is preserved verbatim, byte-for-byte. We also preserve
|
|
14
|
+
* indented code blocks (4-space indent) and inline single-backtick
|
|
15
|
+
* spans.
|
|
16
|
+
*
|
|
17
|
+
* Three intensity levels:
|
|
18
|
+
* - **`lite`**: strip only the lowest-risk preamble/closer phrases
|
|
19
|
+
* (e.g. "Sure!", "Hope this helps!"). Won't touch substance.
|
|
20
|
+
* - **`full`** (default): adds hedging (`I think`, `It seems`),
|
|
21
|
+
* filler intros ("Let me take a look", "Here's what I found"), and
|
|
22
|
+
* repeated "in summary" / "to conclude" closers.
|
|
23
|
+
* - **`ultra`**: also collapses repeated empty lines, strips
|
|
24
|
+
* standalone Markdown emphasis on filler phrases, and removes
|
|
25
|
+
* "Note:" / "FYI:" prefixes from individual sentences.
|
|
26
|
+
*
|
|
27
|
+
* False-positive guard: every pattern is anchored to either start-of-
|
|
28
|
+
* string, start-of-line, end-of-string, or a sentence boundary. We
|
|
29
|
+
* never strip mid-sentence content unless it's a standalone hedge
|
|
30
|
+
* (`, I think,`) — and even then only at intensity `full`+.
|
|
31
|
+
*/
|
|
32
|
+
import type { ResponseDistiller } from '../types';
|
|
33
|
+
export type DistillerIntensity = 'lite' | 'full' | 'ultra';
|
|
34
|
+
export declare function createResponseDistiller(intensity?: DistillerIntensity): ResponseDistiller;
|
|
35
|
+
/** Default `ResponseDistiller` at `full` intensity. Re-export for convenience. */
|
|
36
|
+
export declare const defaultResponseDistiller: ResponseDistiller;
|
|
37
|
+
//# sourceMappingURL=response-distiller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-distiller.d.ts","sourceRoot":"","sources":["../../src/agni/response-distiller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAyB,MAAM,UAAU,CAAC;AAEzE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AA0I3D,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,kBAA2B,GAAG,iBAAiB,CA+CjG;AAED,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,EAAE,iBAAmD,CAAC"}
|