@felan-ai/ext-rtk-optimizer 0.1.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,64 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { joinRuntimePath } from './runtime-path.js';
3
+ const RECOVERY_DIRECTORY = 'rtk-optimizer/recovery';
4
+ const RECOVERY_FILE_PATTERN = /^\d{13}-[0-9a-f-]{36}\.txt$/u;
5
+ const MAX_RECOVERY_BYTES = 2 * 1024 * 1024;
6
+ const MAX_RECOVERY_FILES = 64;
7
+ const MAX_RECOVERY_TOTAL_BYTES = 16 * 1024 * 1024;
8
+ const encoder = new TextEncoder();
9
+ /**
10
+ * Stores the exact pre-compaction text in session storage and returns a path
11
+ * readable through the same runtime namespace. A failed or oversized write is
12
+ * reported as undefined so callers can fail open instead of showing a lossy
13
+ * result with no recovery path.
14
+ */
15
+ export async function persistRecoveryArtifact(runtime, text) {
16
+ const bytes = encoder.encode(text);
17
+ if (bytes.byteLength > MAX_RECOVERY_BYTES)
18
+ return undefined;
19
+ const storage = runtime.storage('session');
20
+ const directory = joinRuntimePath(storage.root, RECOVERY_DIRECTORY);
21
+ const fileName = `${Date.now()}-${randomUUID()}.txt`;
22
+ const relativePath = joinRuntimePath(RECOVERY_DIRECTORY, fileName);
23
+ const absolutePath = joinRuntimePath(storage.root, relativePath);
24
+ try {
25
+ await storage.mkdir(RECOVERY_DIRECTORY, { recursive: true });
26
+ await pruneRecoveryArtifacts(runtime, directory);
27
+ await storage.writeFile(relativePath, bytes);
28
+ return absolutePath;
29
+ }
30
+ catch {
31
+ await storage.remove(relativePath).catch(() => { });
32
+ return undefined;
33
+ }
34
+ }
35
+ async function pruneRecoveryArtifacts(runtime, directory) {
36
+ const storage = runtime.storage('session');
37
+ const entries = await storage.listFiles(directory, { limit: MAX_RECOVERY_FILES + 1 });
38
+ const candidates = entries
39
+ .filter((entry) => RECOVERY_FILE_PATTERN.test(fileName(entry)))
40
+ .sort();
41
+ const sizes = [];
42
+ for (const entry of candidates) {
43
+ const path = joinRuntimePath(RECOVERY_DIRECTORY, fileName(entry));
44
+ try {
45
+ sizes.push({ path, bytes: (await storage.readFile(path)).byteLength });
46
+ }
47
+ catch {
48
+ await storage.remove(path).catch(() => { });
49
+ }
50
+ }
51
+ let total = sizes.reduce((sum, entry) => sum + entry.bytes, 0);
52
+ while (sizes.length >= MAX_RECOVERY_FILES || total > MAX_RECOVERY_TOTAL_BYTES) {
53
+ const oldest = sizes.shift();
54
+ if (!oldest)
55
+ break;
56
+ total -= oldest.bytes;
57
+ await storage.remove(oldest.path).catch(() => { });
58
+ }
59
+ }
60
+ function fileName(path) {
61
+ const normalized = path.replaceAll('\\', '/');
62
+ return normalized.slice(normalized.lastIndexOf('/') + 1);
63
+ }
64
+ //# sourceMappingURL=recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.js","sourceRoot":"","sources":["../src/recovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { AgentRuntime, SavingsModelReference } from '@felan-ai/agent-core';
2
+ export interface RtkGainTotals {
3
+ readonly calls: number;
4
+ readonly inputTokens: number;
5
+ readonly outputTokens: number;
6
+ }
7
+ export interface RtkGainSegment {
8
+ readonly key: string;
9
+ readonly relativeDatabasePath: string;
10
+ readonly databasePath: string;
11
+ readonly relativeManifestPath: string;
12
+ readonly model: SavingsModelReference | undefined;
13
+ }
14
+ interface SegmentOptions {
15
+ readonly now?: () => number;
16
+ }
17
+ export declare function createRtkGainSegment(runtime: AgentRuntime, model: SavingsModelReference | undefined, options?: SegmentOptions): Promise<RtkGainSegment | undefined>;
18
+ export declare function discoverRtkGainSegments(runtime: AgentRuntime): Promise<RtkGainSegment[]>;
19
+ export declare function readRtkGainSegment(runtime: AgentRuntime, executable: string, segment: RtkGainSegment): Promise<RtkGainTotals | undefined>;
20
+ export declare function discardRtkGainSegment(runtime: AgentRuntime, segment: RtkGainSegment): Promise<void>;
21
+ export declare function wrapCommandWithRtkGain(command: string, capture: RtkGainSegment): string;
22
+ export declare function parseRtkGainSummary(value: string): RtkGainTotals | undefined;
23
+ export {};
24
+ //# sourceMappingURL=rtk-gain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rtk-gain.d.ts","sourceRoot":"","sources":["../src/rtk-gain.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAgBhF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,CAAC;CACnD;AASD,UAAU,cAAc;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,qBAAqB,GAAG,SAAS,EACxC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAqBrC;AAED,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAuD9F;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAEpC;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAEvF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAkB5E"}
@@ -0,0 +1,259 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { isWindowsRuntimePath, joinRuntimePath } from './runtime-path.js';
3
+ const GAIN_DIRECTORY = 'rtk-optimizer/gain';
4
+ const CAPTURE_PATTERN = /^(\d{13})-[0-9a-f-]{36}\.db(?:-(?:wal|shm|journal))?$/u;
5
+ const SEGMENT_MANIFEST_PATTERN = /^([0-9a-f]{64})\.json$/u;
6
+ const SEGMENT_DATABASE_PATTERN = /^([0-9a-f]{64})\.db(?:-(?:wal|shm|journal))?$/u;
7
+ const MAX_CAPTURE_AGE_MS = 24 * 60 * 60 * 1_000;
8
+ const MAX_GAIN_FILES = 512;
9
+ const MAX_GAIN_SEGMENTS = 64;
10
+ const MAX_GAIN_OUTPUT_BYTES = 64 * 1_024;
11
+ const MAX_MANIFEST_BYTES = 1_024;
12
+ const GAIN_TIMEOUT_MS = 5_000;
13
+ const encoder = new TextEncoder();
14
+ const decoder = new TextDecoder();
15
+ export async function createRtkGainSegment(runtime, model, options = {}) {
16
+ const storage = runtime.storage('session');
17
+ if (isWindowsRuntimePath(storage.root) || !isValidModel(model))
18
+ return undefined;
19
+ const segment = segmentFor(storage.root, model);
20
+ const manifest = {
21
+ version: 1,
22
+ updatedAt: options.now?.() ?? Date.now(),
23
+ ...(model === undefined ? {} : { provider: model.provider, model: model.id }),
24
+ };
25
+ const bytes = encoder.encode(JSON.stringify(manifest));
26
+ if (bytes.byteLength > MAX_MANIFEST_BYTES)
27
+ return undefined;
28
+ try {
29
+ await storage.mkdir(GAIN_DIRECTORY, { recursive: true });
30
+ await pruneStaleRtkGainCaptures(runtime, options.now?.() ?? Date.now()).catch(() => { });
31
+ await storage.writeFile(segment.relativeManifestPath, bytes);
32
+ return segment;
33
+ }
34
+ catch {
35
+ return undefined;
36
+ }
37
+ }
38
+ export async function discoverRtkGainSegments(runtime) {
39
+ const storage = runtime.storage('session');
40
+ if (isWindowsRuntimePath(storage.root))
41
+ return [];
42
+ let entries;
43
+ try {
44
+ entries = await storage.listFiles(GAIN_DIRECTORY, { limit: MAX_GAIN_FILES });
45
+ }
46
+ catch {
47
+ return [];
48
+ }
49
+ const names = entries.map(fileName);
50
+ const databaseKeys = new Set(names.flatMap((name) => {
51
+ const match = SEGMENT_DATABASE_PATTERN.exec(name);
52
+ return match ? [match[1]] : [];
53
+ }));
54
+ const retainedKeys = new Set();
55
+ const segments = [];
56
+ for (const name of names) {
57
+ const match = SEGMENT_MANIFEST_PATTERN.exec(name);
58
+ if (!match)
59
+ continue;
60
+ const key = match[1];
61
+ const relativeManifestPath = joinRuntimePath(GAIN_DIRECTORY, name);
62
+ let manifest;
63
+ try {
64
+ const bytes = await storage.readFile(relativeManifestPath, { maxBytes: MAX_MANIFEST_BYTES });
65
+ manifest = parseSegmentManifest(decoder.decode(bytes));
66
+ }
67
+ catch {
68
+ await discardSegmentKey(runtime, key);
69
+ continue;
70
+ }
71
+ const model = modelFromManifest(manifest);
72
+ if (!manifest || !isValidModel(model) || segmentKey(model) !== key) {
73
+ await discardSegmentKey(runtime, key);
74
+ continue;
75
+ }
76
+ if (Date.now() - manifest.updatedAt > MAX_CAPTURE_AGE_MS) {
77
+ await discardSegmentKey(runtime, key);
78
+ continue;
79
+ }
80
+ retainedKeys.add(key);
81
+ if (segments.length >= MAX_GAIN_SEGMENTS) {
82
+ await discardSegmentKey(runtime, key);
83
+ retainedKeys.delete(key);
84
+ continue;
85
+ }
86
+ segments.push(segmentFor(storage.root, model));
87
+ }
88
+ await Promise.allSettled([...databaseKeys]
89
+ .filter((key) => !retainedKeys.has(key))
90
+ .map((key) => discardSegmentKey(runtime, key)));
91
+ return segments;
92
+ }
93
+ export async function readRtkGainSegment(runtime, executable, segment) {
94
+ return readRtkGainDatabase(runtime, executable, segment.databasePath);
95
+ }
96
+ export async function discardRtkGainSegment(runtime, segment) {
97
+ await discardSegmentKey(runtime, segment.key);
98
+ }
99
+ export function wrapCommandWithRtkGain(command, capture) {
100
+ return `(RTK_DB_PATH=${quotePosixShellArgument(capture.databasePath)}; export RTK_DB_PATH; ${command}\n\n)`;
101
+ }
102
+ export function parseRtkGainSummary(value) {
103
+ let parsed;
104
+ try {
105
+ parsed = JSON.parse(value);
106
+ }
107
+ catch {
108
+ return undefined;
109
+ }
110
+ const summary = record(record(parsed).summary);
111
+ const calls = safeCounter(summary.total_commands);
112
+ const inputTokens = safeCounter(summary.total_input);
113
+ const outputTokens = safeCounter(summary.total_output);
114
+ const savedTokens = safeCounter(summary.total_saved);
115
+ if (calls === undefined || inputTokens === undefined || outputTokens === undefined || savedTokens === undefined) {
116
+ return undefined;
117
+ }
118
+ if (savedTokens !== Math.max(0, inputTokens - outputTokens))
119
+ return undefined;
120
+ if (calls === 0 && (inputTokens !== 0 || outputTokens !== 0))
121
+ return undefined;
122
+ return { calls, inputTokens, outputTokens };
123
+ }
124
+ async function pruneStaleCaptures(runtime, now) {
125
+ const storage = runtime.storage('session');
126
+ const entries = await storage.listFiles(GAIN_DIRECTORY, { limit: 512 });
127
+ await Promise.allSettled(entries.flatMap((entry) => {
128
+ const name = fileName(entry);
129
+ const match = CAPTURE_PATTERN.exec(name);
130
+ if (!match)
131
+ return [];
132
+ const createdAt = Number.parseInt(match[1], 10);
133
+ if (!Number.isSafeInteger(createdAt) || now - createdAt <= MAX_CAPTURE_AGE_MS)
134
+ return [];
135
+ return [storage.remove(joinRuntimePath(GAIN_DIRECTORY, name))];
136
+ }));
137
+ }
138
+ async function pruneStaleRtkGainCaptures(runtime, now) {
139
+ await pruneStaleCaptures(runtime, now);
140
+ const storage = runtime.storage('session');
141
+ let entries;
142
+ try {
143
+ entries = await storage.listFiles(GAIN_DIRECTORY, { limit: MAX_GAIN_FILES });
144
+ }
145
+ catch {
146
+ return;
147
+ }
148
+ await Promise.allSettled(entries.map(async (entry) => {
149
+ const match = SEGMENT_MANIFEST_PATTERN.exec(fileName(entry));
150
+ if (!match)
151
+ return;
152
+ try {
153
+ const manifest = parseSegmentManifest(decoder.decode(await storage.readFile(entry, { maxBytes: MAX_MANIFEST_BYTES })));
154
+ if (!manifest || now - manifest.updatedAt > MAX_CAPTURE_AGE_MS)
155
+ await discardSegmentKey(runtime, match[1]);
156
+ }
157
+ catch {
158
+ await discardSegmentKey(runtime, match[1]);
159
+ }
160
+ }));
161
+ }
162
+ function segmentFor(storageRoot, model) {
163
+ const key = segmentKey(model);
164
+ const relativeDatabasePath = joinRuntimePath(GAIN_DIRECTORY, `${key}.db`);
165
+ return {
166
+ key,
167
+ relativeDatabasePath,
168
+ databasePath: joinRuntimePath(storageRoot, relativeDatabasePath),
169
+ relativeManifestPath: joinRuntimePath(GAIN_DIRECTORY, `${key}.json`),
170
+ model,
171
+ };
172
+ }
173
+ function segmentKey(model) {
174
+ return createHash('sha256')
175
+ .update(model === undefined ? 'unknown' : `${model.provider}\0${model.id}`, 'utf8')
176
+ .digest('hex');
177
+ }
178
+ function modelFromManifest(manifest) {
179
+ if (!manifest || manifest.provider === undefined || manifest.model === undefined)
180
+ return undefined;
181
+ return { provider: manifest.provider, id: manifest.model };
182
+ }
183
+ function parseSegmentManifest(value) {
184
+ try {
185
+ const parsed = record(JSON.parse(value));
186
+ if (parsed.version !== 1)
187
+ return undefined;
188
+ if (!safeTimestamp(parsed.updatedAt))
189
+ return undefined;
190
+ const provider = parsed.provider;
191
+ const model = parsed.model;
192
+ if (provider !== undefined && typeof provider !== 'string')
193
+ return undefined;
194
+ if (model !== undefined && typeof model !== 'string')
195
+ return undefined;
196
+ if ((provider === undefined) !== (model === undefined))
197
+ return undefined;
198
+ return {
199
+ version: 1,
200
+ updatedAt: parsed.updatedAt,
201
+ ...(provider === undefined ? {} : { provider, model: model }),
202
+ };
203
+ }
204
+ catch {
205
+ return undefined;
206
+ }
207
+ }
208
+ function isValidModel(model) {
209
+ return model === undefined
210
+ || (isBoundedLabel(model.provider, 64) && isBoundedLabel(model.id, 128));
211
+ }
212
+ function isBoundedLabel(value, maximum) {
213
+ return value.length > 0 && value.length <= maximum && !/[\u0000\r\n]/u.test(value);
214
+ }
215
+ function safeTimestamp(value) {
216
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
217
+ }
218
+ async function readRtkGainDatabase(runtime, executable, databasePath) {
219
+ try {
220
+ const result = await runtime.exec('/usr/bin/env', [
221
+ `RTK_DB_PATH=${databasePath}`,
222
+ executable,
223
+ 'gain',
224
+ '--format',
225
+ 'json',
226
+ ], {
227
+ timeout: GAIN_TIMEOUT_MS,
228
+ maxOutputBytes: MAX_GAIN_OUTPUT_BYTES,
229
+ });
230
+ if (result.killed || result.code !== 0 || result.truncated)
231
+ return undefined;
232
+ return parseRtkGainSummary(result.stdout);
233
+ }
234
+ catch {
235
+ return undefined;
236
+ }
237
+ }
238
+ async function discardSegmentKey(runtime, key) {
239
+ const storage = runtime.storage('session');
240
+ await Promise.allSettled(['', '-wal', '-shm', '-journal', '.json'].map((suffix) => storage.remove(suffix === '.json'
241
+ ? joinRuntimePath(GAIN_DIRECTORY, `${key}.json`)
242
+ : joinRuntimePath(GAIN_DIRECTORY, `${key}.db${suffix}`))));
243
+ }
244
+ function quotePosixShellArgument(value) {
245
+ return `'${value.replace(/'/gu, `'\\''`)}'`;
246
+ }
247
+ function safeCounter(value) {
248
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
249
+ }
250
+ function record(value) {
251
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
252
+ ? value
253
+ : {};
254
+ }
255
+ function fileName(path) {
256
+ const normalized = path.replaceAll('\\', '/');
257
+ return normalized.slice(normalized.lastIndexOf('/') + 1);
258
+ }
259
+ //# sourceMappingURL=rtk-gain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rtk-gain.js","sourceRoot":"","sources":["../src/rtk-gain.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,11 @@
1
+ export interface HeadTailTruncationOptions {
2
+ readonly tailRatio?: number;
3
+ readonly marker?: (omittedCharacters: number) => string;
4
+ }
5
+ export interface HeadTailTruncationResult {
6
+ readonly text: string;
7
+ readonly omittedCharacters: number;
8
+ }
9
+ export declare function truncateHeadTail(text: string, maxLength: number, options?: HeadTailTruncationOptions): HeadTailTruncationResult;
1
10
  export declare function truncate(text: string, maxLength: number): string;
2
11
  //# sourceMappingURL=truncate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../src/techniques/truncate.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAUhE"}
1
+ {"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../src/techniques/truncate.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,MAAM,CAAC;CACzD;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAID,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,yBAA8B,GACtC,wBAAwB,CAwC1B;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhE"}
@@ -1,10 +1,81 @@
1
- export function truncate(text, maxLength) {
2
- if (text.length <= maxLength) {
3
- return text;
1
+ const DEFAULT_TAIL_RATIO = 1 / 3;
2
+ export function truncateHeadTail(text, maxLength, options = {}) {
3
+ const limit = Math.max(0, Math.floor(maxLength));
4
+ if (text.length <= limit) {
5
+ return { text, omittedCharacters: 0 };
6
+ }
7
+ if (limit === 0) {
8
+ return { text: '', omittedCharacters: text.length };
4
9
  }
5
- if (maxLength < 3) {
6
- return '...';
10
+ const markerFor = options.marker ?? (() => '...');
11
+ const tailRatio = clampRatio(options.tailRatio ?? DEFAULT_TAIL_RATIO);
12
+ let omittedCharacters = text.length;
13
+ for (let attempt = 0; attempt < 4; attempt += 1) {
14
+ const marker = markerFor(omittedCharacters);
15
+ if (marker.length >= limit) {
16
+ return {
17
+ text: safeSliceEnd(marker, limit),
18
+ omittedCharacters: text.length,
19
+ };
20
+ }
21
+ const available = limit - marker.length;
22
+ const tailTarget = Math.floor(available * tailRatio);
23
+ const headTarget = available - tailTarget;
24
+ const headEnd = lineSafeHeadEnd(text, headTarget);
25
+ const tailStart = lineSafeTailStart(text, text.length - tailTarget, headEnd);
26
+ const nextOmitted = Math.max(0, tailStart - headEnd);
27
+ const output = `${safeSliceEnd(text, headEnd)}${marker}${safeSliceStart(text, tailStart)}`;
28
+ if (nextOmitted === omittedCharacters || attempt === 3) {
29
+ return {
30
+ text: output.length <= limit ? output : safeSliceEnd(output, limit),
31
+ omittedCharacters: nextOmitted,
32
+ };
33
+ }
34
+ omittedCharacters = nextOmitted;
7
35
  }
8
- return `${text.slice(0, maxLength - 3)}...`;
36
+ return { text: safeSliceEnd(text, limit), omittedCharacters: text.length - limit };
37
+ }
38
+ export function truncate(text, maxLength) {
39
+ return truncateHeadTail(text, maxLength).text;
40
+ }
41
+ function clampRatio(value) {
42
+ if (!Number.isFinite(value))
43
+ return DEFAULT_TAIL_RATIO;
44
+ return Math.min(0.9, Math.max(0.1, value));
45
+ }
46
+ function lineSafeHeadEnd(text, target) {
47
+ if (target <= 0)
48
+ return 0;
49
+ if (target >= text.length)
50
+ return text.length;
51
+ const newline = text.lastIndexOf('\n', target - 1);
52
+ return newline >= Math.floor(target / 2) ? newline + 1 : target;
53
+ }
54
+ function lineSafeTailStart(text, target, minimum) {
55
+ if (target <= minimum)
56
+ return minimum;
57
+ if (target >= text.length)
58
+ return text.length;
59
+ const newline = text.indexOf('\n', target);
60
+ const maximumSearch = target + Math.floor((text.length - target) / 2);
61
+ return newline !== -1 && newline <= maximumSearch ? newline + 1 : target;
62
+ }
63
+ function safeSliceEnd(text, end) {
64
+ let safeEnd = Math.min(text.length, Math.max(0, end));
65
+ if (safeEnd > 0 && isHighSurrogate(text.charCodeAt(safeEnd - 1)))
66
+ safeEnd -= 1;
67
+ return text.slice(0, safeEnd);
68
+ }
69
+ function safeSliceStart(text, start) {
70
+ let safeStart = Math.min(text.length, Math.max(0, start));
71
+ if (safeStart < text.length && isLowSurrogate(text.charCodeAt(safeStart)))
72
+ safeStart += 1;
73
+ return text.slice(safeStart);
74
+ }
75
+ function isHighSurrogate(code) {
76
+ return code >= 0xd800 && code <= 0xdbff;
77
+ }
78
+ function isLowSurrogate(code) {
79
+ return code >= 0xdc00 && code <= 0xdfff;
9
80
  }
10
81
  //# sourceMappingURL=truncate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../src/techniques/truncate.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,SAAiB;IACtD,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../src/techniques/truncate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@felan-ai/ext-rtk-optimizer",
3
- "version": "0.1.1",
3
+ "version": "0.4.1",
4
4
  "description": "RTK command rewriting and tool-output compaction for Felan",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,10 +25,10 @@
25
25
  }
26
26
  },
27
27
  "peerDependencies": {
28
- "@felan-ai/agent-core": "^0.4.3"
28
+ "@felan-ai/agent-core": "^0.5.0"
29
29
  },
30
30
  "devDependencies": {
31
- "@felan-ai/agent-core": "0.4.9"
31
+ "@felan-ai/agent-core": "0.5.2"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public",
@@ -1,15 +0,0 @@
1
- export interface OutputMetricRecord {
2
- readonly timestamp: string;
3
- readonly tool: string;
4
- readonly techniques: string;
5
- readonly originalChars: number;
6
- readonly filteredChars: number;
7
- readonly savingsPercent: number;
8
- }
9
- export declare class OutputMetrics {
10
- #private;
11
- track(original: string, filtered: string, tool: string, techniques: readonly string[]): OutputMetricRecord;
12
- clear(): void;
13
- summary(): string;
14
- }
15
- //# sourceMappingURL=output-metrics.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"output-metrics.d.ts","sourceRoot":"","sources":["../src/output-metrics.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,qBAAa,aAAa;;IAGxB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB;IAiB1G,KAAK,IAAI,IAAI;IAIb,OAAO,IAAI,MAAM;CA2BlB"}
@@ -1,50 +0,0 @@
1
- export class OutputMetrics {
2
- #records = [];
3
- track(original, filtered, tool, techniques) {
4
- const originalChars = original.length;
5
- const filteredChars = filtered.length;
6
- const savingsPercent = originalChars === 0 ? 0 : Math.round(((originalChars - filteredChars) / originalChars) * 10_000) / 100;
7
- const record = {
8
- timestamp: new Date().toISOString(),
9
- tool,
10
- techniques: techniques.join(',') || 'none',
11
- originalChars,
12
- filteredChars,
13
- savingsPercent,
14
- };
15
- this.#records.push(record);
16
- return record;
17
- }
18
- clear() {
19
- this.#records.length = 0;
20
- }
21
- summary() {
22
- if (this.#records.length === 0)
23
- return 'RTK output compaction metrics: no data yet.';
24
- const totalOriginal = sum(this.#records, (record) => record.originalChars);
25
- const totalFiltered = sum(this.#records, (record) => record.filteredChars);
26
- const totalSaved = totalOriginal - totalFiltered;
27
- const savingsPercent = totalOriginal === 0 ? 0 : (totalSaved / totalOriginal) * 100;
28
- const byTool = new Map();
29
- for (const record of this.#records) {
30
- const current = byTool.get(record.tool) ?? { count: 0, original: 0, filtered: 0 };
31
- current.count += 1;
32
- current.original += record.originalChars;
33
- current.filtered += record.filteredChars;
34
- byTool.set(record.tool, current);
35
- }
36
- return [
37
- 'RTK output compaction metrics',
38
- `calls=${this.#records.length}, saved=${totalSaved.toLocaleString()} chars (${savingsPercent.toFixed(1)}%)`,
39
- ...[...byTool].map(([tool, current]) => {
40
- const saved = current.original - current.filtered;
41
- const percent = current.original === 0 ? 0 : (saved / current.original) * 100;
42
- return `- ${tool}: ${current.count} calls, saved ${saved.toLocaleString()} chars (${percent.toFixed(1)}%)`;
43
- }),
44
- ].join('\n');
45
- }
46
- }
47
- function sum(values, select) {
48
- return values.reduce((total, value) => total + select(value), 0);
49
- }
50
- //# sourceMappingURL=output-metrics.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"output-metrics.js","sourceRoot":"","sources":["../src/output-metrics.ts"],"names":[],"mappings":"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"}