🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@iinm/plain-agent

Package Overview
Dependencies
Maintainers
1
Versions
120
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@iinm/plain-agent - npm Package Compare versions

Comparing version
1.14.4
to
1.14.5
+1
-1
package.json
{
"name": "@iinm/plain-agent",
"version": "1.14.4",
"version": "1.14.5",
"description": "A lightweight terminal-based coding agent focused on safety and low token cost",

@@ -5,0 +5,0 @@ "license": "MIT",

# Plain Agent
[![CodeQL](https://github.com/iinm/plain-agent/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/iinm/plain-agent/actions/workflows/github-code-scanning/codeql)
[![Socket Badge](https://badge.socket.dev/npm/package/@iinm/plain-agent/1.14.4)](https://socket.dev/npm/package/@iinm/plain-agent)
[![Socket Badge](https://badge.socket.dev/npm/package/@iinm/plain-agent/1.14.5)](https://socket.dev/npm/package/@iinm/plain-agent)
[![install size](https://packagephobia.com/badge?p=@iinm/plain-agent)](https://packagephobia.com/result?p=@iinm/plain-agent)

@@ -6,0 +6,0 @@

@@ -14,4 +14,3 @@ /**

import { styleText } from "node:util";
import { parseBlocks } from "../tools/patchFile.mjs";
import { diffLines } from "../utils/diffLines.mjs";
import { parseBlocks, renderPatchBlock } from "../tools/patchFile.mjs";
import { noThrow } from "../utils/noThrow.mjs";

@@ -867,3 +866,9 @@

return blocks
.map((block) => renderPatchBlock(block, originalLines, nonce))
.map((block) =>
renderPatchBlock(block, originalLines, nonce, {
header: (text) => styleText("cyan", text),
del: (text) => styleText("magenta", text),
add: (text) => styleText("green", text),
}),
)
.join("\n\n");

@@ -873,53 +878,2 @@ }

/**
* @param {PatchBlock} block
* @param {string[] | null} originalLines
* @param {string} nonce
* @returns {string}
*/
function renderPatchBlock(block, originalLines, nonce) {
/** @type {string[]} */
const out = [];
if (block.op === "replace") {
out.push(
styleText(
"cyan",
`REPLACE ${nonce} ${block.start}:${block.startHash}-${block.end}:${block.endHash}`,
),
);
if (originalLines) {
const safeStart = Math.max(1, block.start);
const safeEnd = Math.min(originalLines.length, block.end);
const oldSlice = originalLines.slice(safeStart - 1, safeEnd);
// Use a real line diff so unchanged lines render as context
// (no color, " " prefix) instead of being shown as both "- " and
// "+ ".
for (const op of diffLines(oldSlice, block.body)) {
if (op.type === "-") {
out.push(styleText("magenta", `- ${op.line}`));
} else if (op.type === "+") {
out.push(styleText("green", `+ ${op.line}`));
} else {
out.push(` ${op.line}`);
}
}
} else {
// No file context available — fall back to listing the body as
// additions so the user can still see the new content.
for (const line of block.body) {
out.push(styleText("green", `+ ${line}`));
}
}
} else {
const afterSuffix = block.afterHash ? `:${block.afterHash}` : "";
out.push(
styleText("cyan", `INSERT_AFTER ${nonce} ${block.after}${afterSuffix}`),
);
for (const line of block.body) {
out.push(styleText("green", `+ ${line}`));
}
}
return out.join("\n");
}
/**
* Verbatim highlighter used as fallback when block-aware rendering is not

@@ -926,0 +880,0 @@ * possible (parse error, missing nonce, etc.).

@@ -7,2 +7,3 @@ /**

import fs from "node:fs/promises";
import { diffLines } from "../utils/diffLines.mjs";
import { lineHash } from "../utils/lineHash.mjs";

@@ -70,5 +71,10 @@ import { noThrow } from "../utils/noThrow.mjs";

const original = await fs.readFile(filePath, "utf8");
const originalLines = splitLines(original);
const newContent = applyBlocks(original, blocks);
await fs.writeFile(filePath, newContent);
return `Patched file: ${filePath}`;
const diff = blocks
.map((block) => renderPatchBlock(block, originalLines, nonce))
.join("\n\n");
return `Patched file: ${filePath}\n${diff}`;
}),

@@ -240,2 +246,67 @@

/**
* @typedef {(text: string) => string} DiffStyler
*/
/**
* Render a single patch block as a unified-style diff of the change against
* the original file: the block header, then removed lines ("- "), added lines
* ("+ "), and unchanged context (" ") for its range only.
*
* The optional `style` callbacks colorize the header and change lines; they
* default to identity so the output is plain text suitable for tool results,
* while the CLI passes styleText-based stylers for colored display.
*
* @param {PatchBlock} block
* @param {string[] | null} originalLines
* @param {string} nonce
* @param {{ header?: DiffStyler, del?: DiffStyler, add?: DiffStyler }} [style]
* @returns {string}
*/
export function renderPatchBlock(block, originalLines, nonce, style = {}) {
const header = style.header ?? ((text) => text);
const del = style.del ?? ((text) => text);
const add = style.add ?? ((text) => text);
/** @type {string[]} */
const out = [];
if (block.op === "replace") {
out.push(
header(
`REPLACE ${nonce} ${block.start}:${block.startHash}-${block.end}:${block.endHash}`,
),
);
if (originalLines) {
const safeStart = Math.max(1, block.start);
const safeEnd = Math.min(originalLines.length, block.end);
const oldSlice = originalLines.slice(safeStart - 1, safeEnd);
// Use a real line diff so unchanged lines render as context
// (no color, " " prefix) instead of being shown as both "- " and
// "+ ".
for (const op of diffLines(oldSlice, block.body)) {
if (op.type === "-") {
out.push(del(`- ${op.line}`));
} else if (op.type === "+") {
out.push(add(`+ ${op.line}`));
} else {
out.push(` ${op.line}`);
}
}
} else {
// No file context available — fall back to listing the body as
// additions so the new content is still visible.
for (const line of block.body) {
out.push(add(`+ ${line}`));
}
}
} else {
const afterSuffix = block.afterHash ? `:${block.afterHash}` : "";
out.push(header(`INSERT_AFTER ${nonce} ${block.after}${afterSuffix}`));
for (const line of block.body) {
out.push(add(`+ ${line}`));
}
}
return out.join("\n");
}
/**
* @param {string} headerArgs

@@ -380,1 +451,16 @@ * @param {"replace" | "insert"} op

}
/**
* Split file content into lines the same way applyBlocks does: drop the
* trailing empty element produced by split() when the content ends with a
* newline (or is empty), so line numbers match read_file.
* @param {string} content
* @returns {string[]}
*/
function splitLines(content) {
const lines = content.split("\n");
if (lines.length > 0 && lines[lines.length - 1] === "") {
lines.pop();
}
return lines;
}