pi-rtk-optimizer 0.7.0 → 0.7.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.
- package/CHANGELOG.md +16 -1
- package/README.md +8 -5
- package/package.json +11 -8
- package/src/additional-coverage-test.ts +116 -57
- package/src/command-rewriter-test.ts +187 -118
- package/src/command-rewriter.ts +5 -2
- package/src/config-modal-test.ts +95 -29
- package/src/config-modal.ts +13 -3
- package/src/index-test.ts +196 -1
- package/src/index.ts +48 -4
- package/src/output-compactor.ts +22 -15
- package/src/rewrite-pipeline-safety.ts +203 -178
- package/src/rtk-command-environment.ts +73 -69
- package/src/rtk-executable-resolver.ts +97 -0
- package/src/rtk-rewrite-provider.ts +39 -3
- package/src/shell-env-prefix.ts +5 -1
- package/src/test-helpers.ts +23 -10
- package/src/tool-execution-sanitizer.ts +80 -69
- package/src/types.ts +4 -0
- package/src/windows-command-helpers.ts +92 -16
- package/src/zellij-modal.ts +1 -1
package/src/index-test.ts
CHANGED
|
@@ -28,9 +28,33 @@ mock.module("@mariozechner/pi-tui", () => ({
|
|
|
28
28
|
visibleWidth: (text: string) => text.length,
|
|
29
29
|
}));
|
|
30
30
|
|
|
31
|
-
const
|
|
31
|
+
const indexModule = await import("./index.ts");
|
|
32
|
+
const { createBoundedNoticeTracker, shouldInjectSourceFilterTroubleshootingNote } = indexModule;
|
|
33
|
+
const rtkIntegrationExtension = indexModule.default;
|
|
32
34
|
const { DEFAULT_RTK_INTEGRATION_CONFIG } = await import("./types.ts");
|
|
33
35
|
|
|
36
|
+
type Notification = { message: string; level: "info" | "warning" | "error" };
|
|
37
|
+
type ExtensionHandler = (event: Record<string, unknown>, ctx: Record<string, unknown>) => Promise<Record<string, unknown> | void>;
|
|
38
|
+
|
|
39
|
+
function createNotificationContext(notifications: Notification[]): Record<string, unknown> {
|
|
40
|
+
return {
|
|
41
|
+
hasUI: true,
|
|
42
|
+
ui: {
|
|
43
|
+
notify(message: string, level: "info" | "warning" | "error") {
|
|
44
|
+
notifications.push({ message, level });
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function firstText(content: unknown): string {
|
|
51
|
+
if (!Array.isArray(content) || content.length === 0) {
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
54
|
+
const block = content[0] as { type?: string; text?: string };
|
|
55
|
+
return block.type === "text" && typeof block.text === "string" ? block.text : "";
|
|
56
|
+
}
|
|
57
|
+
|
|
34
58
|
function configWith(overrides: {
|
|
35
59
|
enabled?: boolean;
|
|
36
60
|
compactionEnabled?: boolean;
|
|
@@ -160,4 +184,175 @@ runTest("source-filter note skipped when all read filtering safeguards are disab
|
|
|
160
184
|
);
|
|
161
185
|
});
|
|
162
186
|
|
|
187
|
+
await runTest("session_start refreshes RTK provenance and runtime guard skips missing rewrites", async () => {
|
|
188
|
+
const handlers: Record<string, ExtensionHandler> = {};
|
|
189
|
+
const notifications: Notification[] = [];
|
|
190
|
+
const execCommands: string[] = [];
|
|
191
|
+
let rtkAvailable = false;
|
|
192
|
+
let rewriteCalls = 0;
|
|
193
|
+
|
|
194
|
+
rtkIntegrationExtension({
|
|
195
|
+
exec: async (command: string, args: string[]) => {
|
|
196
|
+
execCommands.push(command);
|
|
197
|
+
if (command === "which" || command === "where") {
|
|
198
|
+
return { code: 0, stdout: "/opt/rtk/bin/rtk\n", stderr: "" };
|
|
199
|
+
}
|
|
200
|
+
if (args[0] === "--version") {
|
|
201
|
+
return rtkAvailable
|
|
202
|
+
? { code: 0, stdout: "rtk 1.0.0", stderr: "" }
|
|
203
|
+
: { code: 1, stdout: "", stderr: "missing rtk" };
|
|
204
|
+
}
|
|
205
|
+
if (args[0] === "rewrite") {
|
|
206
|
+
rewriteCalls += 1;
|
|
207
|
+
return { code: 3, stdout: "rtk git status", stderr: "" };
|
|
208
|
+
}
|
|
209
|
+
return { code: 1, stdout: "", stderr: "unexpected" };
|
|
210
|
+
},
|
|
211
|
+
on(eventName: string, handler: ExtensionHandler) {
|
|
212
|
+
handlers[eventName] = handler;
|
|
213
|
+
},
|
|
214
|
+
registerCommand() {},
|
|
215
|
+
} as never);
|
|
216
|
+
|
|
217
|
+
const sessionStartHandler = handlers.session_start;
|
|
218
|
+
const toolCallHandler = handlers.tool_call;
|
|
219
|
+
assert.ok(sessionStartHandler);
|
|
220
|
+
assert.ok(toolCallHandler);
|
|
221
|
+
|
|
222
|
+
await sessionStartHandler({}, createNotificationContext(notifications));
|
|
223
|
+
const skippedEvent = { toolName: "bash", input: { command: "git status" } };
|
|
224
|
+
await toolCallHandler(skippedEvent, createNotificationContext(notifications));
|
|
225
|
+
|
|
226
|
+
assert.equal((skippedEvent.input as { command: string }).command, "git status");
|
|
227
|
+
assert.equal(rewriteCalls, 0);
|
|
228
|
+
assert.ok(notifications.some((notice) => notice.message.includes("rtk binary unavailable")));
|
|
229
|
+
|
|
230
|
+
rtkAvailable = true;
|
|
231
|
+
await sessionStartHandler({}, createNotificationContext(notifications));
|
|
232
|
+
const rewrittenEvent = { toolName: "bash", input: { command: "git status" } };
|
|
233
|
+
await toolCallHandler(rewrittenEvent, createNotificationContext(notifications));
|
|
234
|
+
|
|
235
|
+
assert.equal(rewriteCalls, 1);
|
|
236
|
+
assert.ok((rewrittenEvent.input as { command: string }).command.includes("rtk git status"));
|
|
237
|
+
assert.ok(execCommands.includes("/opt/rtk/bin/rtk"));
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
await runTest("tool execution lifecycle sanitizes streamed bash output", async () => {
|
|
241
|
+
const handlers: Record<string, ExtensionHandler> = {};
|
|
242
|
+
|
|
243
|
+
rtkIntegrationExtension({
|
|
244
|
+
exec: async () => ({ code: 0, stdout: "rtk 1.0.0", stderr: "" }),
|
|
245
|
+
on(eventName: string, handler: ExtensionHandler) {
|
|
246
|
+
handlers[eventName] = handler;
|
|
247
|
+
},
|
|
248
|
+
registerCommand() {},
|
|
249
|
+
} as never);
|
|
250
|
+
|
|
251
|
+
const startHandler = handlers.tool_execution_start;
|
|
252
|
+
const updateHandler = handlers.tool_execution_update;
|
|
253
|
+
const endHandler = handlers.tool_execution_end;
|
|
254
|
+
assert.ok(startHandler);
|
|
255
|
+
assert.ok(updateHandler);
|
|
256
|
+
assert.ok(endHandler);
|
|
257
|
+
|
|
258
|
+
await startHandler(
|
|
259
|
+
{ toolName: "bash", toolCallId: "bash-1", args: { command: "rtk git status" } },
|
|
260
|
+
{},
|
|
261
|
+
);
|
|
262
|
+
const updateEvent = {
|
|
263
|
+
toolName: "bash",
|
|
264
|
+
toolCallId: "bash-1",
|
|
265
|
+
args: { command: "rtk git status" },
|
|
266
|
+
partialResult: {
|
|
267
|
+
content: [
|
|
268
|
+
{
|
|
269
|
+
type: "text",
|
|
270
|
+
text: "[rtk] /!\\ No hook installed — run `rtk init -g` for automatic token savings\n\nworking tree clean\n",
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
await updateHandler(updateEvent, {});
|
|
276
|
+
assert.equal(firstText(updateEvent.partialResult.content), "working tree clean\n");
|
|
277
|
+
|
|
278
|
+
const endEvent = {
|
|
279
|
+
toolName: "bash",
|
|
280
|
+
toolCallId: "bash-1",
|
|
281
|
+
result: { content: [{ type: "text", text: "📄 src/file.ts\n✅ Files are identical\n" }] },
|
|
282
|
+
};
|
|
283
|
+
await endHandler(endEvent, {});
|
|
284
|
+
assert.equal(firstText(endEvent.result.content), "> src/file.ts\n[OK] Files are identical\n");
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
await runTest("tool_result lifecycle merges compaction metadata with existing details", async () => {
|
|
288
|
+
const handlers: Record<string, ExtensionHandler> = {};
|
|
289
|
+
const notifications: Notification[] = [];
|
|
290
|
+
|
|
291
|
+
rtkIntegrationExtension({
|
|
292
|
+
exec: async () => ({ code: 0, stdout: "rtk 1.0.0", stderr: "" }),
|
|
293
|
+
on(eventName: string, handler: ExtensionHandler) {
|
|
294
|
+
handlers[eventName] = handler;
|
|
295
|
+
},
|
|
296
|
+
registerCommand() {},
|
|
297
|
+
} as never);
|
|
298
|
+
|
|
299
|
+
const toolResultHandler = handlers.tool_result;
|
|
300
|
+
assert.ok(toolResultHandler);
|
|
301
|
+
const result = await toolResultHandler(
|
|
302
|
+
{
|
|
303
|
+
toolName: "grep",
|
|
304
|
+
input: { pattern: "TODO" },
|
|
305
|
+
content: [{ type: "text", text: "src/a.ts:1:TODO\nsrc/b.ts:2:TODO\n" }],
|
|
306
|
+
details: { metadata: { requestId: "abc" }, traceId: "trace-1" },
|
|
307
|
+
},
|
|
308
|
+
createNotificationContext(notifications),
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
assert.ok(result);
|
|
312
|
+
assert.ok(firstText(result.content).startsWith("2 matches in 2 files:"));
|
|
313
|
+
assert.equal((result.details as { traceId?: string }).traceId, "trace-1");
|
|
314
|
+
const details = result.details as { rtkCompaction?: { applied: boolean }; metadata?: Record<string, unknown> };
|
|
315
|
+
assert.equal(details.rtkCompaction?.applied, true);
|
|
316
|
+
assert.deepEqual(details.metadata?.requestId, "abc");
|
|
317
|
+
assert.equal((details.metadata?.rtkCompaction as { applied?: boolean } | undefined)?.applied, true);
|
|
318
|
+
assert.equal(notifications.length, 0);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
await runTest("tool_call surfaces RTK rewrite errors through existing UI warning path", async () => {
|
|
322
|
+
const handlers: Record<string, (event: Record<string, unknown>, ctx: Record<string, unknown>) => Promise<Record<string, unknown> | void>> = {};
|
|
323
|
+
const notifications: Notification[] = [];
|
|
324
|
+
|
|
325
|
+
rtkIntegrationExtension({
|
|
326
|
+
exec: async (_command: string, args: string[]) => {
|
|
327
|
+
if (args[0] === "--version") {
|
|
328
|
+
return { code: 0, stdout: "rtk 1.0.0", stderr: "" };
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return { code: 2, stdout: "", stderr: "denied unsafe rewrite" };
|
|
332
|
+
},
|
|
333
|
+
on(eventName: string, handler: (event: Record<string, unknown>, ctx: Record<string, unknown>) => Promise<Record<string, unknown> | void>) {
|
|
334
|
+
handlers[eventName] = handler;
|
|
335
|
+
},
|
|
336
|
+
registerCommand() {},
|
|
337
|
+
} as never);
|
|
338
|
+
|
|
339
|
+
const toolCallHandler = handlers.tool_call;
|
|
340
|
+
assert.ok(toolCallHandler);
|
|
341
|
+
const event = { toolName: "bash", input: { command: "git status" } };
|
|
342
|
+
await toolCallHandler(event, {
|
|
343
|
+
hasUI: true,
|
|
344
|
+
ui: {
|
|
345
|
+
notify(message: string, level: "info" | "warning" | "error") {
|
|
346
|
+
notifications.push({ message, level });
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
assert.equal((event.input as { command: string }).command, "git status");
|
|
352
|
+
assert.equal(notifications.length, 1);
|
|
353
|
+
assert.equal(notifications[0]?.level, "warning");
|
|
354
|
+
assert.ok(notifications[0]?.message.includes("rtk rewrite skipped"));
|
|
355
|
+
assert.ok(notifications[0]?.message.includes("denied unsafe rewrite"));
|
|
356
|
+
});
|
|
357
|
+
|
|
163
358
|
console.log("All index tests passed.");
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { clearOutputMetrics, getOutputMetricsSummary } from "./output-metrics.js
|
|
|
13
13
|
import { compactToolResult, type ToolResultCompactionMetadata } from "./output-compactor.js";
|
|
14
14
|
import { toRecord } from "./record-utils.js";
|
|
15
15
|
import { applyRtkCommandEnvironment } from "./rtk-command-environment.js";
|
|
16
|
+
import { resolveRtkExecutable, type RtkExecutableResolution } from "./rtk-executable-resolver.js";
|
|
16
17
|
import { applyRewrittenCommandShellSafetyFixups } from "./rewrite-pipeline-safety.js";
|
|
17
18
|
import { shouldRequireRtkAvailabilityForCommandHandling, shouldSkipCommandHandlingWhenRtkMissing } from "./runtime-guard.js";
|
|
18
19
|
import { sanitizeStreamingBashExecutionResult } from "./tool-execution-sanitizer.js";
|
|
@@ -115,6 +116,12 @@ export default function rtkIntegrationExtension(pi: ExtensionAPI): void {
|
|
|
115
116
|
return `RTK rewrite: ${original} -> ${rewritten}`;
|
|
116
117
|
};
|
|
117
118
|
|
|
119
|
+
const formatRewriteWarning = (command: string, warning: string): string => {
|
|
120
|
+
const target = trimMessage(command, 100);
|
|
121
|
+
const detail = trimMessage(warning, 120);
|
|
122
|
+
return `${EXTENSION_NAME}: rtk rewrite skipped for '${target}' (${detail}).`;
|
|
123
|
+
};
|
|
124
|
+
|
|
118
125
|
const warnOnce = (
|
|
119
126
|
ctx: ExtensionContext | ExtensionCommandContext,
|
|
120
127
|
message: string,
|
|
@@ -190,12 +197,18 @@ export default function rtkIntegrationExtension(pi: ExtensionAPI): void {
|
|
|
190
197
|
};
|
|
191
198
|
|
|
192
199
|
const refreshRuntimeStatus = async (): Promise<RuntimeStatus> => {
|
|
200
|
+
let executableResolution: RtkExecutableResolution | undefined;
|
|
193
201
|
try {
|
|
194
|
-
|
|
202
|
+
executableResolution = await resolveRtkExecutable(pi);
|
|
203
|
+
const result = await pi.exec(executableResolution.command, ["--version"], { timeout: 5000 });
|
|
195
204
|
if (result.code === 0) {
|
|
196
205
|
runtimeStatus = {
|
|
197
206
|
rtkAvailable: true,
|
|
198
207
|
lastCheckedAt: Date.now(),
|
|
208
|
+
rtkExecutablePath: executableResolution.resolvedPath,
|
|
209
|
+
rtkExecutableCommand: executableResolution.command,
|
|
210
|
+
rtkExecutableResolver: executableResolution.resolver,
|
|
211
|
+
rtkExecutableResolutionWarning: executableResolution.warning,
|
|
199
212
|
};
|
|
200
213
|
missingRtkWarningShown = false;
|
|
201
214
|
return runtimeStatus;
|
|
@@ -208,6 +221,10 @@ export default function rtkIntegrationExtension(pi: ExtensionAPI): void {
|
|
|
208
221
|
rtkAvailable: false,
|
|
209
222
|
lastCheckedAt: Date.now(),
|
|
210
223
|
lastError: detail || `exit ${result.code}`,
|
|
224
|
+
rtkExecutablePath: executableResolution.resolvedPath,
|
|
225
|
+
rtkExecutableCommand: executableResolution.command,
|
|
226
|
+
rtkExecutableResolver: executableResolution.resolver,
|
|
227
|
+
rtkExecutableResolutionWarning: executableResolution.warning,
|
|
211
228
|
};
|
|
212
229
|
return runtimeStatus;
|
|
213
230
|
} catch (error) {
|
|
@@ -216,6 +233,10 @@ export default function rtkIntegrationExtension(pi: ExtensionAPI): void {
|
|
|
216
233
|
rtkAvailable: false,
|
|
217
234
|
lastCheckedAt: Date.now(),
|
|
218
235
|
lastError: trimMessage(message),
|
|
236
|
+
rtkExecutablePath: executableResolution?.resolvedPath,
|
|
237
|
+
rtkExecutableCommand: executableResolution?.command,
|
|
238
|
+
rtkExecutableResolver: executableResolution?.resolver,
|
|
239
|
+
rtkExecutableResolutionWarning: executableResolution?.warning,
|
|
219
240
|
};
|
|
220
241
|
return runtimeStatus;
|
|
221
242
|
}
|
|
@@ -303,10 +324,13 @@ export default function rtkIntegrationExtension(pi: ExtensionAPI): void {
|
|
|
303
324
|
}
|
|
304
325
|
|
|
305
326
|
trackBashCommand(eventRecord.toolCallId, eventRecord.args);
|
|
306
|
-
sanitizeStreamingBashExecutionResult(
|
|
327
|
+
const sanitization = sanitizeStreamingBashExecutionResult(
|
|
307
328
|
eventRecord.partialResult,
|
|
308
329
|
getTrackedBashCommand(eventRecord.toolCallId),
|
|
309
330
|
);
|
|
331
|
+
if (sanitization.changed) {
|
|
332
|
+
eventRecord.partialResult = sanitization.result;
|
|
333
|
+
}
|
|
310
334
|
});
|
|
311
335
|
|
|
312
336
|
pi.on("tool_execution_end", async (event) => {
|
|
@@ -317,7 +341,13 @@ export default function rtkIntegrationExtension(pi: ExtensionAPI): void {
|
|
|
317
341
|
|
|
318
342
|
try {
|
|
319
343
|
if (config.enabled && config.outputCompaction.enabled) {
|
|
320
|
-
sanitizeStreamingBashExecutionResult(
|
|
344
|
+
const sanitization = sanitizeStreamingBashExecutionResult(
|
|
345
|
+
eventRecord.result,
|
|
346
|
+
getTrackedBashCommand(eventRecord.toolCallId),
|
|
347
|
+
);
|
|
348
|
+
if (sanitization.changed) {
|
|
349
|
+
eventRecord.result = sanitization.result;
|
|
350
|
+
}
|
|
321
351
|
}
|
|
322
352
|
} finally {
|
|
323
353
|
forgetTrackedBashCommand(eventRecord.toolCallId);
|
|
@@ -362,8 +392,22 @@ export default function rtkIntegrationExtension(pi: ExtensionAPI): void {
|
|
|
362
392
|
return {};
|
|
363
393
|
}
|
|
364
394
|
|
|
365
|
-
|
|
395
|
+
let executableResolution: RtkExecutableResolution | undefined;
|
|
396
|
+
if (runtimeStatus.rtkExecutableCommand) {
|
|
397
|
+
const resolver: RtkExecutableResolution["resolver"] =
|
|
398
|
+
runtimeStatus.rtkExecutableResolver === "where" ? "where" : "which";
|
|
399
|
+
executableResolution = {
|
|
400
|
+
command: runtimeStatus.rtkExecutableCommand,
|
|
401
|
+
resolvedPath: runtimeStatus.rtkExecutablePath,
|
|
402
|
+
resolver,
|
|
403
|
+
warning: runtimeStatus.rtkExecutableResolutionWarning,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
const decision = await computeRewriteDecision(event.input.command, config, pi, { executableResolution });
|
|
366
407
|
if (!decision.changed) {
|
|
408
|
+
if (decision.warning) {
|
|
409
|
+
warnOnce(ctx, formatRewriteWarning(decision.originalCommand, decision.warning));
|
|
410
|
+
}
|
|
367
411
|
return {};
|
|
368
412
|
}
|
|
369
413
|
|
package/src/output-compactor.ts
CHANGED
|
@@ -190,6 +190,10 @@ function hasLossyCompaction(techniques: string[]): boolean {
|
|
|
190
190
|
);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
function normalizeTechniqueResult(result: string | null, currentText: string): string {
|
|
194
|
+
return result === null ? currentText : result;
|
|
195
|
+
}
|
|
196
|
+
|
|
193
197
|
function compactBashText(
|
|
194
198
|
text: string,
|
|
195
199
|
command: string | undefined,
|
|
@@ -207,45 +211,45 @@ function compactBashText(
|
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
|
|
210
|
-
const withoutRtkHookWarnings = stripRtkHookWarnings(nextText, command);
|
|
211
|
-
if (withoutRtkHookWarnings !==
|
|
214
|
+
const withoutRtkHookWarnings = normalizeTechniqueResult(stripRtkHookWarnings(nextText, command), nextText);
|
|
215
|
+
if (withoutRtkHookWarnings !== nextText) {
|
|
212
216
|
nextText = withoutRtkHookWarnings;
|
|
213
217
|
techniques.push("rtk-hook-warning");
|
|
214
218
|
}
|
|
215
219
|
|
|
216
|
-
const withoutRtkEmoji = sanitizeRtkEmojiOutput(nextText, command);
|
|
217
|
-
if (withoutRtkEmoji !==
|
|
220
|
+
const withoutRtkEmoji = normalizeTechniqueResult(sanitizeRtkEmojiOutput(nextText, command), nextText);
|
|
221
|
+
if (withoutRtkEmoji !== nextText) {
|
|
218
222
|
nextText = withoutRtkEmoji;
|
|
219
223
|
techniques.push("rtk-emoji");
|
|
220
224
|
}
|
|
221
225
|
|
|
222
226
|
if (compaction.filterBuildOutput) {
|
|
223
|
-
const compacted = filterBuildOutput(nextText, command);
|
|
224
|
-
if (compacted !==
|
|
227
|
+
const compacted = normalizeTechniqueResult(filterBuildOutput(nextText, command), nextText);
|
|
228
|
+
if (compacted !== nextText) {
|
|
225
229
|
nextText = compacted;
|
|
226
230
|
techniques.push("build");
|
|
227
231
|
}
|
|
228
232
|
}
|
|
229
233
|
|
|
230
234
|
if (compaction.aggregateTestOutput) {
|
|
231
|
-
const compacted = aggregateTestOutput(nextText, command);
|
|
232
|
-
if (compacted !==
|
|
235
|
+
const compacted = normalizeTechniqueResult(aggregateTestOutput(nextText, command), nextText);
|
|
236
|
+
if (compacted !== nextText) {
|
|
233
237
|
nextText = compacted;
|
|
234
238
|
techniques.push("test");
|
|
235
239
|
}
|
|
236
240
|
}
|
|
237
241
|
|
|
238
242
|
if (compaction.compactGitOutput) {
|
|
239
|
-
const compacted = compactGitOutput(nextText, command);
|
|
240
|
-
if (compacted !==
|
|
243
|
+
const compacted = normalizeTechniqueResult(compactGitOutput(nextText, command), nextText);
|
|
244
|
+
if (compacted !== nextText) {
|
|
241
245
|
nextText = compacted;
|
|
242
246
|
techniques.push("git");
|
|
243
247
|
}
|
|
244
248
|
}
|
|
245
249
|
|
|
246
250
|
if (compaction.aggregateLinterOutput) {
|
|
247
|
-
const compacted = aggregateLinterOutput(nextText, command);
|
|
248
|
-
if (compacted !==
|
|
251
|
+
const compacted = normalizeTechniqueResult(aggregateLinterOutput(nextText, command), nextText);
|
|
252
|
+
if (compacted !== nextText) {
|
|
249
253
|
nextText = compacted;
|
|
250
254
|
techniques.push("linter");
|
|
251
255
|
}
|
|
@@ -288,7 +292,10 @@ function compactReadText(
|
|
|
288
292
|
compaction.sourceCodeFiltering !== "none" &&
|
|
289
293
|
shouldApplyReadSourceFiltering(text, config)
|
|
290
294
|
) {
|
|
291
|
-
const filtered =
|
|
295
|
+
const filtered = normalizeTechniqueResult(
|
|
296
|
+
filterSourceCode(nextText, language, compaction.sourceCodeFiltering),
|
|
297
|
+
nextText,
|
|
298
|
+
);
|
|
292
299
|
if (filtered !== nextText) {
|
|
293
300
|
nextText = filtered;
|
|
294
301
|
techniques.push(`source:${compaction.sourceCodeFiltering}`);
|
|
@@ -332,8 +339,8 @@ function compactGrepText(text: string, config: RtkIntegrationConfig): { text: st
|
|
|
332
339
|
}
|
|
333
340
|
|
|
334
341
|
if (compaction.groupSearchOutput) {
|
|
335
|
-
const grouped = groupSearchResults(nextText);
|
|
336
|
-
if (grouped !==
|
|
342
|
+
const grouped = normalizeTechniqueResult(groupSearchResults(nextText), nextText);
|
|
343
|
+
if (grouped !== nextText) {
|
|
337
344
|
nextText = grouped;
|
|
338
345
|
techniques.push("search");
|
|
339
346
|
}
|