pi-readseek 0.4.30 → 0.5.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.
@@ -1,25 +1,15 @@
1
+ import { resolveReadSeekSyntaxValidation } from "./readseek-settings.js";
2
+
1
3
  export type SyntaxValidateMode = "warn" | "block" | "off";
2
4
 
3
5
  export interface SyntaxValidateOptions {
4
6
  syntaxValidate?: SyntaxValidateMode;
5
7
  }
6
8
 
7
- const VALID = new Set<SyntaxValidateMode>(["warn", "block", "off"]);
8
9
  const DEFAULT: SyntaxValidateMode = "warn";
9
10
 
10
- function coerce(value: unknown): SyntaxValidateMode | undefined {
11
- if (typeof value !== "string") return undefined;
12
- return VALID.has(value as SyntaxValidateMode)
13
- ? (value as SyntaxValidateMode)
14
- : undefined;
15
- }
16
-
17
11
  export function resolveSyntaxValidateMode(
18
12
  opts: SyntaxValidateOptions,
19
13
  ): SyntaxValidateMode {
20
- const fromOpt = coerce(opts.syntaxValidate);
21
- if (fromOpt) return fromOpt;
22
- const fromEnv = coerce(process.env.READSEEK_SYNTAX_VALIDATE);
23
- if (fromEnv) return fromEnv;
24
- return DEFAULT;
14
+ return opts.syntaxValidate ?? resolveReadSeekSyntaxValidation() ?? DEFAULT;
25
15
  }
@@ -3,8 +3,8 @@ import { readFileSync } from "node:fs";
3
3
  import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "@earendil-works/pi-coding-agent";
4
4
 
5
5
  const COMPACT_DESCRIPTIONS: Record<string, string> = {
6
- "read.md": "Read text files/images by path; text has LINE:HASH anchors, images return the attachment plus OCR-extracted text.",
7
- "edit.md": "Edit existing text files using fresh LINE:HASH anchors from read, grep, search, or write.",
6
+ "read.md": "Read text files/images by path; text has LINE:HASH anchors, images return the attachment plus OCR text, a caption, and detected objects.",
7
+ "edit.md": "Edit existing text files using fresh LINE:HASH anchors from readSeek_read, readSeek_grep, readSeek_search, or readSeek_write.",
8
8
  "grep.md": "Search file contents; non-summary results include LINE:HASH anchors for edits.",
9
9
 
10
10
  "write.md": "Create or overwrite a complete file and return anchors.",
@@ -14,30 +14,30 @@ const COMPACT_DESCRIPTIONS: Record<string, string> = {
14
14
 
15
15
  const COMPACT_GUIDELINES: Record<string, string[]> = {
16
16
  "read.md": [
17
- "Use read for file contents, images/screenshots, ranges, symbols, and edit anchors.",
17
+ "Use readSeek_read for file contents, images/screenshots, ranges, symbols, and edit anchors.",
18
18
  "Use map or symbol mode before pulling large code files into context.",
19
- "Use read for images; it returns the image attachment plus OCR-extracted text, so you don't need separate OCR tools.",
19
+ "Use readSeek_read for images; it returns the image attachment plus OCR text, a caption, and detected objects, so you don't need separate OCR tools.",
20
20
  ],
21
21
  "edit.md": [
22
- "Use edit with fresh LINE:HASH anchors for existing files.",
22
+ "Use readSeek_edit with fresh LINE:HASH anchors for existing files.",
23
23
  "Prefer set_line, replace_lines, and insert_after; use replace only when anchors are impractical.",
24
24
  ],
25
25
  "grep.md": [
26
- "Use grep for text search and edit-ready matching anchors.",
27
- "Use grep summary mode for broad count/file discovery before narrowing.",
26
+ "Use readSeek_grep for text search and edit-ready matching anchors.",
27
+ "Use readSeek_grep summary mode for broad count/file discovery before narrowing.",
28
28
  ],
29
29
 
30
30
  "write.md": [
31
- "Use write to create files or intentionally overwrite whole files.",
32
- "Use edit rather than write for small changes or appends to existing files.",
31
+ "Use readSeek_write to create files or intentionally overwrite whole files.",
32
+ "Use readSeek_edit rather than readSeek_write for small changes or appends to existing files.",
33
33
  ],
34
34
  "sg.md": [
35
- "Use search for AST-shaped code patterns.",
36
- "Use grep instead of search for plain text.",
35
+ "Use readSeek_search for AST-shaped code patterns.",
36
+ "Use readSeek_grep instead of readSeek_search for plain text.",
37
37
  ],
38
38
  "refs.md": [
39
- "Use refs to find every usage of an identifier before renaming or deleting it.",
40
- "Use refs with scope plus line/column to follow a specific binding instead of every same-named identifier.",
39
+ "Use readSeek_refs to find every usage of an identifier before renaming or deleting it.",
40
+ "Use readSeek_refs with scope plus line/column to follow a specific binding instead of every same-named identifier.",
41
41
  ],
42
42
  };
43
43
 
@@ -238,10 +238,10 @@ export function renderAnchoredFilesResult(
238
238
  const textContent = content?.type === "text" ? content.text : "";
239
239
  if (isError || result.isError) return renderErrorResult(textContent, { expanded, width });
240
240
 
241
- const readseekValue = (result.details as any)?.readseekValue as
241
+ const readSeekValue = (result.details as any)?.readSeekValue as
242
242
  | { files: Array<{ path: string; lines: any[] }> }
243
243
  | undefined;
244
- const files = readseekValue?.files ?? [];
244
+ const files = readSeekValue?.files ?? [];
245
245
  if (files.length === 0) return new Text(summaryLine(labels.emptyLabel), 0, 0);
246
246
 
247
247
  const fileCount = files.length;
package/src/write.ts CHANGED
@@ -80,7 +80,7 @@ export interface WriteResult extends WriteDiffFields {
80
80
  text: string;
81
81
  warnings: string[];
82
82
  writeState?: "created" | "overwritten";
83
- readseekValue: {
83
+ readSeekValue: {
84
84
  tool: "write";
85
85
  path: string;
86
86
  lines: ReadSeekLine[];
@@ -143,24 +143,24 @@ export async function executeWrite(opts: {
143
143
 
144
144
  const { path: filePath, content, map: requestMap, cwd } = opts;
145
145
  const warnings: string[] = [];
146
- const readseekWarnings: ReadSeekWarning[] = [];
146
+ const readSeekWarnings: ReadSeekWarning[] = [];
147
147
 
148
148
  if (hasBareCarriageReturn(content)) {
149
- const message = "File content contains bare CR (\\r) line endings; write refuses to emit anchors that read/edit would normalize differently.";
149
+ const message = "File content contains bare CR (\\r) line endings; readSeek_write refuses to emit anchors that readSeek_read/readSeek_edit would normalize differently.";
150
150
  warnings.push(message);
151
- readseekWarnings.push(buildReadSeekWarning("bare-cr", message));
151
+ readSeekWarnings.push(buildReadSeekWarning("bare-cr", message));
152
152
  return buildToolErrorResult("write", "bare-cr", `Cannot write ${filePath}\n⚠️ ${message}`, {
153
153
  path: filePath,
154
- extra: { lines: [], warnings: readseekWarnings },
154
+ extra: { lines: [], warnings: readSeekWarnings },
155
155
  });
156
156
  }
157
157
  if (looksLikeBinary(Buffer.from(content, "utf-8"))) {
158
158
  const message = "File content appears to be binary.";
159
159
  warnings.push(message);
160
- readseekWarnings.push(buildReadSeekWarning("binary-content", message));
160
+ readSeekWarnings.push(buildReadSeekWarning("binary-content", message));
161
161
  return buildToolErrorResult("write", "binary-content", `Cannot write ${filePath}\n⚠️ ${message} — refusing to write.`, {
162
162
  path: filePath,
163
- extra: { lines: [], warnings: readseekWarnings },
163
+ extra: { lines: [], warnings: readSeekWarnings },
164
164
  });
165
165
  }
166
166
 
@@ -173,13 +173,13 @@ export async function executeWrite(opts: {
173
173
  await writeFile(filePath, content, "utf-8");
174
174
  // Compute hashlines
175
175
  const rawLines = content.split("\n");
176
- const readseekLines: ReadSeekLine[] = [];
176
+ const readSeekLines: ReadSeekLine[] = [];
177
177
  const displayLines: string[] = [];
178
178
 
179
179
  for (let i = 0; i < rawLines.length; i++) {
180
180
  const lineNum = i + 1;
181
- const readseekLine = buildReadSeekLine(lineNum, rawLines[i]);
182
- readseekLines.push(readseekLine);
181
+ const readSeekLine = buildReadSeekLine(lineNum, rawLines[i]);
182
+ readSeekLines.push(readSeekLine);
183
183
  displayLines.push(formatHashlineDisplay(lineNum, rawLines[i]));
184
184
  }
185
185
 
@@ -188,9 +188,9 @@ export async function executeWrite(opts: {
188
188
  let text = truncated.content;
189
189
  if (truncated.truncated) {
190
190
  if (truncated.truncatedBy === "lines") {
191
- text += `\n[… ${truncated.totalLines - truncated.outputLines} more lines not shown — full anchors in readseekValue]`;
191
+ text += `\n[… ${truncated.totalLines - truncated.outputLines} more lines not shown — full anchors in readSeekValue]`;
192
192
  } else {
193
- text += "\n[… output truncated at 50 KB — full anchors in readseekValue]";
193
+ text += "\n[… output truncated at 50 KB — full anchors in readSeekValue]";
194
194
  }
195
195
  }
196
196
 
@@ -228,11 +228,11 @@ export async function executeWrite(opts: {
228
228
  writeState: existedBeforeWrite ? "overwritten" : "created",
229
229
  diff: diffResult.diff,
230
230
  diffData,
231
- readseekValue: {
231
+ readSeekValue: {
232
232
  tool: "write",
233
233
  path: displayPath,
234
- lines: readseekLines,
235
- warnings: readseekWarnings,
234
+ lines: readSeekLines,
235
+ warnings: readSeekWarnings,
236
236
  diff: diffResult.diff,
237
237
  diffData,
238
238
  ...(requestMap ? { map: { appended: mapAppended } } : {}),
@@ -242,11 +242,7 @@ export async function executeWrite(opts: {
242
242
 
243
243
  export function registerWriteTool(pi: ExtensionAPI, options: WriteToolOptions = {}) {
244
244
  const tool = registerReadSeekTool(pi, {
245
- policy: "mutating",
246
- pythonName: "write",
247
- defaultExposure: "not-safe-by-default",
248
- }, {
249
- name: "write",
245
+ name: "readSeek_write",
250
246
  label: "write",
251
247
  description: WRITE_PROMPT_METADATA.description,
252
248
  promptSnippet: WRITE_PROMPT_METADATA.promptSnippet,
@@ -275,7 +271,7 @@ export function registerWriteTool(pi: ExtensionAPI, options: WriteToolOptions =
275
271
 
276
272
  if (isToolErrorResult(result)) return result;
277
273
 
278
- if (result.readseekValue.lines.length > 0) {
274
+ if (result.readSeekValue.lines.length > 0) {
279
275
  options.onFileAnchored?.(absolutePath);
280
276
  }
281
277
 
@@ -285,7 +281,7 @@ export function registerWriteTool(pi: ExtensionAPI, options: WriteToolOptions =
285
281
  ...(result.diff !== undefined ? { diff: result.diff } : {}),
286
282
  ...(result.diffData !== undefined ? { diffData: result.diffData } : {}),
287
283
  ...(result.writeState ? { writeState: result.writeState } : {}),
288
- readseekValue: result.readseekValue,
284
+ readSeekValue: result.readSeekValue,
289
285
  warnings: result.warnings,
290
286
  },
291
287
  };
@@ -326,7 +322,7 @@ export function registerWriteTool(pi: ExtensionAPI, options: WriteToolOptions =
326
322
  if (isPartial) return renderPendingResult("pending write", width);
327
323
  const details = result.details ?? {};
328
324
  const output = result.content?.[0]?.type === "text" ? result.content[0].text : "";
329
- if (result.isError || details.readseekValue?.ok === false) {
325
+ if (result.isError || details.readSeekValue?.ok === false) {
330
326
  return renderErrorResult(output, { expanded, width, fallback: "write failed" });
331
327
  }
332
328
  const diffData = details.diffData;
@@ -335,12 +331,12 @@ export function registerWriteTool(pi: ExtensionAPI, options: WriteToolOptions =
335
331
  // instead of a diff body — every line is an add, so the gutter, line
336
332
  // numbers, and red/green tinting are noise.
337
333
  if (state === "created") {
338
- const readseekLines = (details.readseekValue?.lines ?? []) as Array<{ raw: string }>;
339
- const hasContent = readseekLines.length > 0;
334
+ const readSeekLines = (details.readSeekValue?.lines ?? []) as Array<{ raw: string }>;
335
+ const hasContent = readSeekLines.length > 0;
340
336
  const header = summaryLine(state, { hidden: hasContent && !expanded });
341
337
  const lines = header.split("\n");
342
338
  if (expanded && hasContent) {
343
- const content = readseekLines.map((l) => l.raw).join("\n");
339
+ const content = readSeekLines.map((l) => l.raw).join("\n");
344
340
  lines.push(...formatContentPreviewLines(content, theme));
345
341
  }
346
342
  return new Text(clampLinesToWidth(lines, width).join("\n"), 0, 0);