@oh-my-pi/pi-coding-agent 17.1.2 → 17.1.3
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 +9 -0
- package/dist/cli.js +3395 -3395
- package/dist/types/tools/auto-generated-guard.d.ts +5 -2
- package/dist/types/tools/memory-render.d.ts +1 -4
- package/package.json +12 -12
- package/src/edit/hashline/filesystem.ts +1 -1
- package/src/edit/modes/patch.ts +1 -1
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/session/stream-guards.ts +1 -1
- package/src/tools/auto-generated-guard.ts +18 -5
- package/src/tools/memory-render.ts +11 -2
- package/src/tools/render-utils.ts +8 -3
- package/src/tools/write.ts +1 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import { type Settings } from "../config/settings.js";
|
|
1
2
|
/**
|
|
2
3
|
* Check if a file is auto-generated by examining its content.
|
|
3
4
|
* Throws ToolError if the file appears to be auto-generated.
|
|
4
5
|
*
|
|
5
6
|
* @param absolutePath - Absolute path to the file
|
|
6
7
|
* @param displayPath - Path to show in error messages (relative or as provided)
|
|
8
|
+
* @param activeSettings - Session settings; falls back to global settings or the schema default
|
|
7
9
|
*/
|
|
8
|
-
export declare function assertEditableFile(absolutePath: string, displayPath?: string): Promise<void>;
|
|
10
|
+
export declare function assertEditableFile(absolutePath: string, displayPath?: string, activeSettings?: Settings): Promise<void>;
|
|
9
11
|
/**
|
|
10
12
|
* Check if file content is auto-generated.
|
|
11
13
|
* Uses only the first CHECK_BYTE_COUNT characters of the content.
|
|
@@ -13,5 +15,6 @@ export declare function assertEditableFile(absolutePath: string, displayPath?: s
|
|
|
13
15
|
*
|
|
14
16
|
* @param content - File content to check (can be full content or prefix)
|
|
15
17
|
* @param displayPath - Path to show in error messages
|
|
18
|
+
* @param activeSettings - Session settings; falls back to global settings or the schema default
|
|
16
19
|
*/
|
|
17
|
-
export declare function assertEditableFileContent(content: string, displayPath: string): void;
|
|
20
|
+
export declare function assertEditableFileContent(content: string, displayPath: string, activeSettings?: Settings): void;
|
|
@@ -13,10 +13,7 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
13
13
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types.js";
|
|
14
14
|
import type { Theme } from "../modes/theme/theme.js";
|
|
15
15
|
interface RetainRenderArgs {
|
|
16
|
-
items?:
|
|
17
|
-
content?: string;
|
|
18
|
-
context?: string;
|
|
19
|
-
}>;
|
|
16
|
+
items?: unknown;
|
|
20
17
|
}
|
|
21
18
|
interface QueryRenderArgs {
|
|
22
19
|
query?: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
4
|
-
"version": "17.1.
|
|
4
|
+
"version": "17.1.3",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -53,17 +53,17 @@
|
|
|
53
53
|
"@babel/parser": "^7.29.7",
|
|
54
54
|
"@babel/traverse": "^7.29.7",
|
|
55
55
|
"@mozilla/readability": "^0.6.0",
|
|
56
|
-
"@oh-my-pi/hashline": "17.1.
|
|
57
|
-
"@oh-my-pi/omp-stats": "17.1.
|
|
58
|
-
"@oh-my-pi/pi-agent-core": "17.1.
|
|
59
|
-
"@oh-my-pi/pi-ai": "17.1.
|
|
60
|
-
"@oh-my-pi/pi-catalog": "17.1.
|
|
61
|
-
"@oh-my-pi/pi-mnemopi": "17.1.
|
|
62
|
-
"@oh-my-pi/pi-natives": "17.1.
|
|
63
|
-
"@oh-my-pi/pi-tui": "17.1.
|
|
64
|
-
"@oh-my-pi/pi-utils": "17.1.
|
|
65
|
-
"@oh-my-pi/pi-wire": "17.1.
|
|
66
|
-
"@oh-my-pi/snapcompact": "17.1.
|
|
56
|
+
"@oh-my-pi/hashline": "17.1.3",
|
|
57
|
+
"@oh-my-pi/omp-stats": "17.1.3",
|
|
58
|
+
"@oh-my-pi/pi-agent-core": "17.1.3",
|
|
59
|
+
"@oh-my-pi/pi-ai": "17.1.3",
|
|
60
|
+
"@oh-my-pi/pi-catalog": "17.1.3",
|
|
61
|
+
"@oh-my-pi/pi-mnemopi": "17.1.3",
|
|
62
|
+
"@oh-my-pi/pi-natives": "17.1.3",
|
|
63
|
+
"@oh-my-pi/pi-tui": "17.1.3",
|
|
64
|
+
"@oh-my-pi/pi-utils": "17.1.3",
|
|
65
|
+
"@oh-my-pi/pi-wire": "17.1.3",
|
|
66
|
+
"@oh-my-pi/snapcompact": "17.1.3",
|
|
67
67
|
"@opentelemetry/api": "^1.9.1",
|
|
68
68
|
"@opentelemetry/api-logs": "^0.220.0",
|
|
69
69
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
@@ -121,7 +121,7 @@ export class HashlineFilesystem extends Filesystem {
|
|
|
121
121
|
throw error;
|
|
122
122
|
}
|
|
123
123
|
// Refuse edits against generated files (lockfiles, models.json, …).
|
|
124
|
-
assertEditableFileContent(content, relativePath);
|
|
124
|
+
assertEditableFileContent(content, relativePath, this.session.settings);
|
|
125
125
|
return content;
|
|
126
126
|
}
|
|
127
127
|
|
package/src/edit/modes/patch.ts
CHANGED
|
@@ -1816,7 +1816,7 @@ export async function executePatchSingle(
|
|
|
1816
1816
|
const resolvedPath = resolvePlanPath(session, path);
|
|
1817
1817
|
const resolvedRename = rename ? resolvePlanPath(session, rename) : undefined;
|
|
1818
1818
|
|
|
1819
|
-
await assertEditableFile(resolvedPath, path);
|
|
1819
|
+
await assertEditableFile(resolvedPath, path, session.settings);
|
|
1820
1820
|
|
|
1821
1821
|
// Capture pre-edit content so we can verify the write actually hit disk.
|
|
1822
1822
|
// `LspFileSystem.writeFile` delegates to a writethrough callback that, in
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Structural AST-aware rewrites via ast-grep. Use for codemods where text replace is unsafe.
|
|
1
|
+
Structural AST-aware rewrites via ast-grep. Use for codemods where text replace is unsafe. Mixed-language paths are fine: each file is parsed in its own language, and a pattern only rewrites files it parses in.
|
|
2
2
|
|
|
3
3
|
- Metavariables in `pat` (`$A`, `$$$ARGS`) substitute into `out`.
|
|
4
4
|
- **Patterns match AST structure, not text.** `$NAME` = one node; `$_` = unbound; `$$$NAME` = zero-or-more.
|
|
@@ -185,7 +185,7 @@ export class StreamingEditGuard {
|
|
|
185
185
|
#abortForAutoGeneratedPath(toolCall: ToolCall, filePath: string, resolvedPath: string): void {
|
|
186
186
|
if (this.#lastToolCallId === toolCall.id) return;
|
|
187
187
|
this.#lastToolCallId = toolCall.id;
|
|
188
|
-
void assertEditableFile(resolvedPath, filePath).catch(error => {
|
|
188
|
+
void assertEditableFile(resolvedPath, filePath, this.#host.settings).catch(error => {
|
|
189
189
|
if (!(error instanceof ToolError) || this.#lastToolCallId !== toolCall.id) return;
|
|
190
190
|
if (!this.#abortTriggered) {
|
|
191
191
|
this.#abortTriggered = true;
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import { isEnoent, peekFile } from "@oh-my-pi/pi-utils";
|
|
9
9
|
import { LRUCache } from "lru-cache/raw";
|
|
10
|
-
import { settings } from "../config/settings";
|
|
10
|
+
import { settings as globalSettings, isSettingsInitialized, type Settings } from "../config/settings";
|
|
11
|
+
import { getDefault } from "../config/settings-schema";
|
|
11
12
|
import { ToolError } from "./tool-errors";
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -283,15 +284,26 @@ async function getAutoGeneratedMarker(filePath: string): Promise<string | undefi
|
|
|
283
284
|
return marker;
|
|
284
285
|
}
|
|
285
286
|
|
|
287
|
+
function shouldBlockAutoGeneratedFiles(activeSettings?: Settings): boolean {
|
|
288
|
+
if (activeSettings) return activeSettings.get("edit.blockAutoGenerated");
|
|
289
|
+
if (isSettingsInitialized()) return globalSettings.get("edit.blockAutoGenerated");
|
|
290
|
+
return getDefault("edit.blockAutoGenerated");
|
|
291
|
+
}
|
|
292
|
+
|
|
286
293
|
/**
|
|
287
294
|
* Check if a file is auto-generated by examining its content.
|
|
288
295
|
* Throws ToolError if the file appears to be auto-generated.
|
|
289
296
|
*
|
|
290
297
|
* @param absolutePath - Absolute path to the file
|
|
291
298
|
* @param displayPath - Path to show in error messages (relative or as provided)
|
|
299
|
+
* @param activeSettings - Session settings; falls back to global settings or the schema default
|
|
292
300
|
*/
|
|
293
|
-
export async function assertEditableFile(
|
|
294
|
-
|
|
301
|
+
export async function assertEditableFile(
|
|
302
|
+
absolutePath: string,
|
|
303
|
+
displayPath?: string,
|
|
304
|
+
activeSettings?: Settings,
|
|
305
|
+
): Promise<void> {
|
|
306
|
+
if (!shouldBlockAutoGeneratedFiles(activeSettings)) {
|
|
295
307
|
return;
|
|
296
308
|
}
|
|
297
309
|
const pathForDisplay = displayPath ?? absolutePath;
|
|
@@ -308,9 +320,10 @@ export async function assertEditableFile(absolutePath: string, displayPath?: str
|
|
|
308
320
|
*
|
|
309
321
|
* @param content - File content to check (can be full content or prefix)
|
|
310
322
|
* @param displayPath - Path to show in error messages
|
|
323
|
+
* @param activeSettings - Session settings; falls back to global settings or the schema default
|
|
311
324
|
*/
|
|
312
|
-
export function assertEditableFileContent(content: string, displayPath: string): void {
|
|
313
|
-
if (!
|
|
325
|
+
export function assertEditableFileContent(content: string, displayPath: string, activeSettings?: Settings): void {
|
|
326
|
+
if (!shouldBlockAutoGeneratedFiles(activeSettings)) {
|
|
314
327
|
return;
|
|
315
328
|
}
|
|
316
329
|
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
// from the active theme (`•` by default, a nerd-font dot under nerd themes).
|
|
28
28
|
|
|
29
29
|
interface RetainRenderArgs {
|
|
30
|
-
items?:
|
|
30
|
+
items?: unknown;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
interface QueryRenderArgs {
|
|
@@ -35,7 +35,16 @@ interface QueryRenderArgs {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function retainContents(args: RetainRenderArgs | undefined): string[] {
|
|
38
|
-
|
|
38
|
+
const items = args?.items;
|
|
39
|
+
if (!Array.isArray(items)) return [];
|
|
40
|
+
|
|
41
|
+
const contents: string[] = [];
|
|
42
|
+
for (const item of items) {
|
|
43
|
+
if (!item || typeof item !== "object" || !("content" in item) || typeof item.content !== "string") continue;
|
|
44
|
+
const content = replaceTabs(item.content.trim());
|
|
45
|
+
if (content.length > 0) contents.push(content);
|
|
46
|
+
}
|
|
47
|
+
return contents;
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
function resultText(result: { content?: Array<{ type: string; text?: string }> }): string {
|
|
@@ -13,7 +13,8 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
13
13
|
import { getKeybindings, replaceTabs, truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
14
14
|
import { pluralize } from "@oh-my-pi/pi-utils";
|
|
15
15
|
import { formatKeyHints, type KeyId } from "../config/keybindings";
|
|
16
|
-
import { settings } from "../config/settings";
|
|
16
|
+
import { isSettingsInitialized, settings } from "../config/settings";
|
|
17
|
+
import { getDefault } from "../config/settings-schema";
|
|
17
18
|
import type { Theme } from "../modes/theme/theme";
|
|
18
19
|
import { Hasher } from "../tui/utils";
|
|
19
20
|
import { formatDimensionNote, type ResizedImage } from "../utils/image-resize";
|
|
@@ -27,8 +28,12 @@ export { replaceTabs, truncateToWidth, wrapTextWithAnsi } from "@oh-my-pi/pi-tui
|
|
|
27
28
|
|
|
28
29
|
/** Resolve inline image dimension caps from settings and viewport. */
|
|
29
30
|
export function resolveImageOptions(): { maxWidthCells: number; maxHeightCells?: number } {
|
|
30
|
-
const
|
|
31
|
-
const
|
|
31
|
+
const activeSettings = isSettingsInitialized() ? settings : undefined;
|
|
32
|
+
const maxWidthCells = activeSettings?.get("tui.maxInlineImageColumns") ?? getDefault("tui.maxInlineImageColumns");
|
|
33
|
+
const rowSetting = Math.max(
|
|
34
|
+
0,
|
|
35
|
+
activeSettings?.get("tui.maxInlineImageRows") ?? getDefault("tui.maxInlineImageRows"),
|
|
36
|
+
);
|
|
32
37
|
const viewportRows = process.stdout.rows;
|
|
33
38
|
const viewportFraction = viewportRows ? Math.floor(viewportRows * 0.6) : 0;
|
|
34
39
|
let maxHeightCells: number | undefined;
|
package/src/tools/write.ts
CHANGED
|
@@ -1215,7 +1215,7 @@ export class WriteTool implements AgentTool<typeof writeSchema, WriteToolDetails
|
|
|
1215
1215
|
|
|
1216
1216
|
// Check if file exists and is auto-generated before overwriting
|
|
1217
1217
|
if (await fs.exists(absolutePath)) {
|
|
1218
|
-
await assertEditableFile(absolutePath, path);
|
|
1218
|
+
await assertEditableFile(absolutePath, path, this.session.settings);
|
|
1219
1219
|
}
|
|
1220
1220
|
|
|
1221
1221
|
const displayPath = formatPathRelativeToCwd(absolutePath, this.session.cwd);
|