@oh-my-pi/pi-coding-agent 9.0.0 → 9.1.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.1.1",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"ompConfig": {
|
|
@@ -79,12 +79,12 @@
|
|
|
79
79
|
"test": "bun test"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"@oh-my-pi/omp-stats": "9.
|
|
83
|
-
"@oh-my-pi/pi-agent-core": "9.
|
|
84
|
-
"@oh-my-pi/pi-ai": "9.
|
|
85
|
-
"@oh-my-pi/pi-natives": "9.
|
|
86
|
-
"@oh-my-pi/pi-tui": "9.
|
|
87
|
-
"@oh-my-pi/pi-utils": "9.
|
|
82
|
+
"@oh-my-pi/omp-stats": "9.1.1",
|
|
83
|
+
"@oh-my-pi/pi-agent-core": "9.1.1",
|
|
84
|
+
"@oh-my-pi/pi-ai": "9.1.1",
|
|
85
|
+
"@oh-my-pi/pi-natives": "9.1.1",
|
|
86
|
+
"@oh-my-pi/pi-tui": "9.1.1",
|
|
87
|
+
"@oh-my-pi/pi-utils": "9.1.1",
|
|
88
88
|
"@openai/agents": "^0.4.4",
|
|
89
89
|
"@sinclair/typebox": "^0.34.48",
|
|
90
90
|
"ajv": "^8.17.1",
|
|
@@ -5,6 +5,7 @@ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
|
5
5
|
import { type Api, type KnownProvider, type Model, modelsAreEqual } from "@oh-my-pi/pi-ai";
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
import { isValidThinkingLevel } from "../cli/args";
|
|
8
|
+
import { fuzzyMatch } from "../utils/fuzzy";
|
|
8
9
|
import type { ModelRegistry } from "./model-registry";
|
|
9
10
|
|
|
10
11
|
/** Default model IDs for each known provider */
|
|
@@ -163,6 +164,32 @@ function tryMatchModel(
|
|
|
163
164
|
if (providerMatch) {
|
|
164
165
|
return providerMatch;
|
|
165
166
|
}
|
|
167
|
+
|
|
168
|
+
const providerModels = availableModels.filter(m => m.provider.toLowerCase() === provider.toLowerCase());
|
|
169
|
+
if (providerModels.length > 0) {
|
|
170
|
+
const scored = providerModels
|
|
171
|
+
.map(model => ({ model, match: fuzzyMatch(modelId, model.id) }))
|
|
172
|
+
.filter(entry => entry.match.matches);
|
|
173
|
+
if (scored.length > 0) {
|
|
174
|
+
scored.sort((a, b) => {
|
|
175
|
+
if (a.match.score !== b.match.score) return a.match.score - b.match.score;
|
|
176
|
+
const aKey = formatModelString(a.model);
|
|
177
|
+
const bKey = formatModelString(b.model);
|
|
178
|
+
const aUsage = context.modelUsageRank.get(aKey) ?? Number.POSITIVE_INFINITY;
|
|
179
|
+
const bUsage = context.modelUsageRank.get(bKey) ?? Number.POSITIVE_INFINITY;
|
|
180
|
+
if (aUsage !== bUsage) return aUsage - bUsage;
|
|
181
|
+
|
|
182
|
+
const aProviderUsage = context.providerUsageRank.get(a.model.provider) ?? Number.POSITIVE_INFINITY;
|
|
183
|
+
const bProviderUsage = context.providerUsageRank.get(b.model.provider) ?? Number.POSITIVE_INFINITY;
|
|
184
|
+
if (aProviderUsage !== bProviderUsage) return aProviderUsage - bProviderUsage;
|
|
185
|
+
|
|
186
|
+
const aOrder = context.modelOrder.get(aKey) ?? 0;
|
|
187
|
+
const bOrder = context.modelOrder.get(bKey) ?? 0;
|
|
188
|
+
return aOrder - bOrder;
|
|
189
|
+
});
|
|
190
|
+
return scored[0]?.model;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
166
193
|
// No exact provider/model match - fall through to other matching
|
|
167
194
|
}
|
|
168
195
|
|
package/src/debug/index.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides tools for debugging, bug report generation, and system diagnostics.
|
|
5
5
|
*/
|
|
6
|
+
import * as fs from "node:fs/promises";
|
|
6
7
|
import { Container, Loader, type SelectItem, SelectList, Spacer, Text } from "@oh-my-pi/pi-tui";
|
|
7
8
|
import { getSessionsDir } from "../config";
|
|
8
9
|
import { DynamicBorder } from "../modes/components/dynamic-border";
|
|
@@ -14,6 +15,7 @@ import { collectSystemInfo, formatSystemInfo } from "./system-info";
|
|
|
14
15
|
|
|
15
16
|
/** Debug menu options */
|
|
16
17
|
const DEBUG_MENU_ITEMS: SelectItem[] = [
|
|
18
|
+
{ value: "open-artifacts", label: "Open: artifact folder", description: "Open session artifacts in file manager" },
|
|
17
19
|
{ value: "performance", label: "Report: performance issue", description: "Profile CPU, reproduce, then bundle" },
|
|
18
20
|
{ value: "dump", label: "Report: dump session", description: "Create report bundle immediately" },
|
|
19
21
|
{ value: "memory", label: "Report: memory issue", description: "Heap snapshot + bundle" },
|
|
@@ -40,7 +42,7 @@ export class DebugSelectorComponent extends Container {
|
|
|
40
42
|
this.addChild(new Spacer(1));
|
|
41
43
|
|
|
42
44
|
// Select list
|
|
43
|
-
this.selectList = new SelectList(DEBUG_MENU_ITEMS,
|
|
45
|
+
this.selectList = new SelectList(DEBUG_MENU_ITEMS, 7, getSelectListTheme());
|
|
44
46
|
|
|
45
47
|
this.selectList.onSelect = item => {
|
|
46
48
|
onDone();
|
|
@@ -61,6 +63,9 @@ export class DebugSelectorComponent extends Container {
|
|
|
61
63
|
|
|
62
64
|
private async handleSelection(value: string): Promise<void> {
|
|
63
65
|
switch (value) {
|
|
66
|
+
case "open-artifacts":
|
|
67
|
+
await this.handleOpenArtifacts();
|
|
68
|
+
break;
|
|
64
69
|
case "performance":
|
|
65
70
|
await this.handlePerformanceReport();
|
|
66
71
|
break;
|
|
@@ -276,6 +281,42 @@ export class DebugSelectorComponent extends Container {
|
|
|
276
281
|
this.ctx.ui.requestRender();
|
|
277
282
|
}
|
|
278
283
|
|
|
284
|
+
private async handleOpenArtifacts(): Promise<void> {
|
|
285
|
+
const sessionFile = this.ctx.sessionManager.getSessionFile();
|
|
286
|
+
if (!sessionFile) {
|
|
287
|
+
this.ctx.showWarning("No active session file.");
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const artifactsDir = sessionFile.slice(0, -6);
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
const stat = await fs.stat(artifactsDir);
|
|
295
|
+
if (!stat.isDirectory()) {
|
|
296
|
+
this.ctx.showWarning("Artifact folder does not exist yet.");
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
} catch {
|
|
300
|
+
this.ctx.showWarning("Artifact folder does not exist yet.");
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const openArgs =
|
|
305
|
+
process.platform === "darwin"
|
|
306
|
+
? ["open", artifactsDir]
|
|
307
|
+
: process.platform === "win32"
|
|
308
|
+
? ["cmd", "/c", "start", "", artifactsDir]
|
|
309
|
+
: ["xdg-open", artifactsDir];
|
|
310
|
+
const [cmd, ...args] = openArgs;
|
|
311
|
+
|
|
312
|
+
try {
|
|
313
|
+
Bun.spawn([cmd, ...args], { stdout: "ignore", stderr: "ignore" }).unref();
|
|
314
|
+
this.ctx.showStatus(`Opened: ${artifactsDir}`);
|
|
315
|
+
} catch (err) {
|
|
316
|
+
this.ctx.showError(`Failed to open artifact folder: ${err instanceof Error ? err.message : String(err)}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
279
320
|
private async handleClearCache(): Promise<void> {
|
|
280
321
|
const sessionsDir = getSessionsDir();
|
|
281
322
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
2
|
-
import { Container,
|
|
2
|
+
import { Container, Markdown, Spacer, TERMINAL_INFO, Text } from "@oh-my-pi/pi-tui";
|
|
3
3
|
import { hasPendingMermaid, prerenderMermaid } from "../../modes/theme/mermaid-cache";
|
|
4
4
|
import { getMarkdownTheme, theme } from "../../modes/theme/theme";
|
|
5
5
|
|
|
@@ -38,8 +38,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
private triggerMermaidPrerender(message: AssistantMessage): void {
|
|
41
|
-
|
|
42
|
-
if (!caps.images || this.prerenderInFlight) return;
|
|
41
|
+
if (!TERMINAL_INFO.imageProtocol || this.prerenderInFlight) return;
|
|
43
42
|
|
|
44
43
|
// Check if any text content has pending mermaid blocks
|
|
45
44
|
const hasPending = message.content.some(c => c.type === "text" && c.text.trim() && hasPendingMermaid(c.text));
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 3. Add the handler in interactive-mode.ts settingsHandlers
|
|
9
9
|
*/
|
|
10
10
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
11
|
-
import {
|
|
11
|
+
import { TERMINAL_INFO } from "@oh-my-pi/pi-tui";
|
|
12
12
|
import type {
|
|
13
13
|
ImageProviderOption,
|
|
14
14
|
NotificationMethod,
|
|
@@ -485,7 +485,7 @@ export const SETTINGS_DEFS: SettingDef[] = [
|
|
|
485
485
|
description: "Render images inline in terminal",
|
|
486
486
|
get: sm => sm.getShowImages(),
|
|
487
487
|
set: (sm, v) => sm.setShowImages(v),
|
|
488
|
-
condition: () => !!
|
|
488
|
+
condition: () => !!TERMINAL_INFO.imageProtocol,
|
|
489
489
|
},
|
|
490
490
|
{
|
|
491
491
|
id: "autoResizeImages",
|
|
@@ -3,14 +3,15 @@ import {
|
|
|
3
3
|
Box,
|
|
4
4
|
type Component,
|
|
5
5
|
Container,
|
|
6
|
-
getCapabilities,
|
|
7
6
|
getImageDimensions,
|
|
8
7
|
Image,
|
|
9
8
|
imageFallback,
|
|
10
9
|
Spacer,
|
|
10
|
+
TERMINAL_INFO,
|
|
11
11
|
Text,
|
|
12
12
|
type TUI,
|
|
13
13
|
} from "@oh-my-pi/pi-tui";
|
|
14
|
+
import { ImageProtocol } from "@oh-my-pi/pi-tui/terminal-image";
|
|
14
15
|
import { sanitizeText } from "@oh-my-pi/pi-utils";
|
|
15
16
|
import type { Theme } from "../../modes/theme/theme";
|
|
16
17
|
import { theme } from "../../modes/theme/theme";
|
|
@@ -288,9 +289,8 @@ export class ToolExecutionComponent extends Container {
|
|
|
288
289
|
* Kitty requires PNG format (f=100), so JPEG/GIF/WebP won't display.
|
|
289
290
|
*/
|
|
290
291
|
private maybeConvertImagesForKitty(): void {
|
|
291
|
-
const caps = getCapabilities();
|
|
292
292
|
// Only needed for Kitty protocol
|
|
293
|
-
if (
|
|
293
|
+
if (TERMINAL_INFO.imageProtocol !== ImageProtocol.Kitty) return;
|
|
294
294
|
if (!this.result) return;
|
|
295
295
|
|
|
296
296
|
const imageBlocks = this.getAllImageBlocks();
|
|
@@ -520,18 +520,17 @@ export class ToolExecutionComponent extends Container {
|
|
|
520
520
|
|
|
521
521
|
if (this.result) {
|
|
522
522
|
const imageBlocks = this.getAllImageBlocks();
|
|
523
|
-
const caps = getCapabilities();
|
|
524
523
|
|
|
525
524
|
for (let i = 0; i < imageBlocks.length; i++) {
|
|
526
525
|
const img = imageBlocks[i];
|
|
527
|
-
if (
|
|
526
|
+
if (TERMINAL_INFO.imageProtocol && this.showImages && img.data && img.mimeType) {
|
|
528
527
|
// Use converted PNG for Kitty protocol if available
|
|
529
528
|
const converted = this.convertedImages.get(i);
|
|
530
529
|
const imageData = converted?.data ?? img.data;
|
|
531
530
|
const imageMimeType = converted?.mimeType ?? img.mimeType;
|
|
532
531
|
|
|
533
532
|
// For Kitty, skip non-PNG images that haven't been converted yet
|
|
534
|
-
if (
|
|
533
|
+
if (TERMINAL_INFO.imageProtocol === ImageProtocol.Kitty && imageMimeType !== "image/png") {
|
|
535
534
|
continue;
|
|
536
535
|
}
|
|
537
536
|
|
|
@@ -595,8 +594,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
595
594
|
})
|
|
596
595
|
.join("\n");
|
|
597
596
|
|
|
598
|
-
|
|
599
|
-
if (imageBlocks.length > 0 && (!caps.images || !this.showImages)) {
|
|
597
|
+
if (imageBlocks.length > 0 && (!TERMINAL_INFO.imageProtocol || !this.showImages)) {
|
|
600
598
|
const imageIndicators = imageBlocks
|
|
601
599
|
.map((img: any) => {
|
|
602
600
|
const dims = img.data ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;
|