@oh-my-pi/pi-coding-agent 2.3.1337 → 3.1.1337
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 +72 -34
- package/README.md +100 -100
- package/docs/compaction.md +8 -8
- package/docs/config-usage.md +113 -0
- package/docs/custom-tools.md +8 -8
- package/docs/extension-loading.md +58 -58
- package/docs/hooks.md +11 -11
- package/docs/rpc.md +4 -4
- package/docs/sdk.md +14 -14
- package/docs/session-tree-plan.md +1 -1
- package/docs/session.md +2 -2
- package/docs/skills.md +16 -16
- package/docs/theme.md +9 -9
- package/docs/tui.md +1 -1
- package/examples/README.md +1 -1
- package/examples/custom-tools/README.md +4 -4
- package/examples/custom-tools/subagent/README.md +13 -13
- package/examples/custom-tools/subagent/agents.ts +2 -2
- package/examples/custom-tools/subagent/index.ts +5 -5
- package/examples/hooks/README.md +3 -3
- package/examples/hooks/auto-commit-on-exit.ts +1 -1
- package/examples/hooks/custom-compaction.ts +1 -1
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/examples/sdk/05-tools.ts +1 -1
- package/examples/sdk/08-slash-commands.ts +1 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
- package/examples/sdk/README.md +2 -2
- package/package.json +13 -11
- package/src/capability/context-file.ts +40 -0
- package/src/capability/extension.ts +48 -0
- package/src/capability/hook.ts +40 -0
- package/src/capability/index.ts +616 -0
- package/src/capability/instruction.ts +37 -0
- package/src/capability/mcp.ts +52 -0
- package/src/capability/prompt.ts +35 -0
- package/src/capability/rule.ts +52 -0
- package/src/capability/settings.ts +35 -0
- package/src/capability/skill.ts +49 -0
- package/src/capability/slash-command.ts +40 -0
- package/src/capability/system-prompt.ts +35 -0
- package/src/capability/tool.ts +38 -0
- package/src/capability/types.ts +166 -0
- package/src/cli/args.ts +2 -2
- package/src/cli/plugin-cli.ts +24 -19
- package/src/cli/update-cli.ts +10 -10
- package/src/config.ts +290 -6
- package/src/core/auth-storage.ts +32 -9
- package/src/core/bash-executor.ts +1 -1
- package/src/core/custom-commands/loader.ts +44 -50
- package/src/core/custom-tools/index.ts +1 -0
- package/src/core/custom-tools/loader.ts +67 -69
- package/src/core/custom-tools/types.ts +10 -1
- package/src/core/hooks/loader.ts +13 -42
- package/src/core/index.ts +0 -1
- package/src/core/logger.ts +7 -7
- package/src/core/mcp/client.ts +1 -1
- package/src/core/mcp/config.ts +94 -146
- package/src/core/mcp/index.ts +0 -4
- package/src/core/mcp/loader.ts +26 -22
- package/src/core/mcp/manager.ts +18 -23
- package/src/core/mcp/tool-bridge.ts +9 -1
- package/src/core/mcp/types.ts +2 -0
- package/src/core/model-registry.ts +25 -8
- package/src/core/plugins/installer.ts +1 -1
- package/src/core/plugins/loader.ts +17 -11
- package/src/core/plugins/manager.ts +2 -2
- package/src/core/plugins/paths.ts +12 -7
- package/src/core/plugins/types.ts +3 -3
- package/src/core/sdk.ts +48 -27
- package/src/core/session-manager.ts +4 -4
- package/src/core/settings-manager.ts +45 -21
- package/src/core/skills.ts +208 -293
- package/src/core/slash-commands.ts +34 -165
- package/src/core/system-prompt.ts +58 -65
- package/src/core/timings.ts +2 -2
- package/src/core/tools/lsp/config.ts +38 -17
- package/src/core/tools/task/agents.ts +21 -0
- package/src/core/tools/task/artifacts.ts +1 -1
- package/src/core/tools/task/bundled-agents/reviewer.md +2 -1
- package/src/core/tools/task/bundled-agents/task.md +1 -0
- package/src/core/tools/task/commands.ts +30 -107
- package/src/core/tools/task/discovery.ts +75 -66
- package/src/core/tools/task/executor.ts +25 -10
- package/src/core/tools/task/index.ts +35 -10
- package/src/core/tools/task/model-resolver.ts +27 -25
- package/src/core/tools/task/types.ts +6 -2
- package/src/core/tools/web-fetch.ts +3 -3
- package/src/core/tools/web-search/auth.ts +40 -34
- package/src/core/tools/web-search/index.ts +1 -1
- package/src/core/tools/web-search/providers/anthropic.ts +1 -1
- package/src/discovery/agents-md.ts +75 -0
- package/src/discovery/builtin.ts +646 -0
- package/src/discovery/claude.ts +623 -0
- package/src/discovery/cline.ts +102 -0
- package/src/discovery/codex.ts +571 -0
- package/src/discovery/cursor.ts +264 -0
- package/src/discovery/gemini.ts +368 -0
- package/src/discovery/github.ts +120 -0
- package/src/discovery/helpers.test.ts +127 -0
- package/src/discovery/helpers.ts +249 -0
- package/src/discovery/index.ts +84 -0
- package/src/discovery/mcp-json.ts +127 -0
- package/src/discovery/vscode.ts +99 -0
- package/src/discovery/windsurf.ts +216 -0
- package/src/main.ts +14 -13
- package/src/migrations.ts +24 -3
- package/src/modes/interactive/components/hook-editor.ts +1 -1
- package/src/modes/interactive/components/plugin-settings.ts +1 -1
- package/src/modes/interactive/components/settings-defs.ts +38 -2
- package/src/modes/interactive/components/settings-selector.ts +1 -0
- package/src/modes/interactive/components/welcome.ts +2 -2
- package/src/modes/interactive/interactive-mode.ts +233 -16
- package/src/modes/interactive/theme/theme-schema.json +1 -1
- package/src/utils/clipboard.ts +1 -1
- package/src/utils/shell-snapshot.ts +2 -2
- package/src/utils/shell.ts +7 -7
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
+
import { basename } from "node:path";
|
|
9
10
|
import type { AgentMessage, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
10
11
|
import type { AssistantMessage, ImageContent, Message, OAuthProvider } from "@oh-my-pi/pi-ai";
|
|
11
12
|
import type { SlashCommand } from "@oh-my-pi/pi-tui";
|
|
@@ -23,6 +24,10 @@ import {
|
|
|
23
24
|
TUI,
|
|
24
25
|
visibleWidth,
|
|
25
26
|
} from "@oh-my-pi/pi-tui";
|
|
27
|
+
import { contextFileCapability } from "../../capability/context-file";
|
|
28
|
+
import { instructionCapability } from "../../capability/instruction";
|
|
29
|
+
import { promptCapability } from "../../capability/prompt";
|
|
30
|
+
import { ruleCapability } from "../../capability/rule";
|
|
26
31
|
import { getAuthPath, getDebugLogPath } from "../../config";
|
|
27
32
|
import type { AgentSession, AgentSessionEvent } from "../../core/agent-session";
|
|
28
33
|
import type { CustomToolSessionEvent, LoadedCustomTool } from "../../core/custom-tools/index";
|
|
@@ -30,9 +35,17 @@ import type { HookUIContext } from "../../core/hooks/index";
|
|
|
30
35
|
import { createCompactionSummaryMessage } from "../../core/messages";
|
|
31
36
|
import { getRecentSessions, type SessionContext, SessionManager } from "../../core/session-manager";
|
|
32
37
|
import { loadSkills } from "../../core/skills";
|
|
33
|
-
import { loadProjectContextFiles } from "../../core/system-prompt";
|
|
34
38
|
import { generateSessionTitle, setTerminalTitle } from "../../core/title-generator";
|
|
35
39
|
import type { TruncationResult } from "../../core/tools/truncate";
|
|
40
|
+
import {
|
|
41
|
+
type ContextFile,
|
|
42
|
+
disableProvider,
|
|
43
|
+
enableProvider,
|
|
44
|
+
type Instruction,
|
|
45
|
+
loadSync,
|
|
46
|
+
type Prompt,
|
|
47
|
+
type Rule,
|
|
48
|
+
} from "../../discovery";
|
|
36
49
|
import { getChangelogPath, parseChangelog } from "../../utils/changelog";
|
|
37
50
|
import { copyToClipboard, readImageFromClipboard } from "../../utils/clipboard";
|
|
38
51
|
import { ArminComponent } from "./components/armin";
|
|
@@ -1535,7 +1548,7 @@ export class InteractiveMode {
|
|
|
1535
1548
|
}
|
|
1536
1549
|
|
|
1537
1550
|
const currentText = this.editor.getText();
|
|
1538
|
-
const tmpFile = path.join(os.tmpdir(), `
|
|
1551
|
+
const tmpFile = path.join(os.tmpdir(), `omp-editor-${Date.now()}.omp.md`);
|
|
1539
1552
|
|
|
1540
1553
|
try {
|
|
1541
1554
|
// Write current content to temp file
|
|
@@ -1729,6 +1742,17 @@ export class InteractiveMode {
|
|
|
1729
1742
|
* This handles side effects and session-specific settings.
|
|
1730
1743
|
*/
|
|
1731
1744
|
private handleSettingChange(id: string, value: string | boolean): void {
|
|
1745
|
+
// Discovery provider toggles
|
|
1746
|
+
if (id.startsWith("discovery.")) {
|
|
1747
|
+
const providerId = id.replace("discovery.", "");
|
|
1748
|
+
if (value) {
|
|
1749
|
+
enableProvider(providerId);
|
|
1750
|
+
} else {
|
|
1751
|
+
disableProvider(providerId);
|
|
1752
|
+
}
|
|
1753
|
+
return;
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1732
1756
|
switch (id) {
|
|
1733
1757
|
// Session-managed settings (not in SettingsManager)
|
|
1734
1758
|
case "autoCompact":
|
|
@@ -2369,13 +2393,113 @@ export class InteractiveMode {
|
|
|
2369
2393
|
private handleStatusCommand(): void {
|
|
2370
2394
|
const sections: string[] = [];
|
|
2371
2395
|
|
|
2396
|
+
type StatusSource =
|
|
2397
|
+
| { provider: string; level: string }
|
|
2398
|
+
| { mcpServer: string; provider?: string }
|
|
2399
|
+
| "builtin"
|
|
2400
|
+
| "unknown";
|
|
2401
|
+
|
|
2402
|
+
const capitalize = (value: string): string => value.charAt(0).toUpperCase() + value.slice(1);
|
|
2403
|
+
|
|
2404
|
+
const resolveSourceText = (source: StatusSource): string => {
|
|
2405
|
+
if (source === "builtin") return "builtin";
|
|
2406
|
+
if (source === "unknown") return "unknown";
|
|
2407
|
+
if ("mcpServer" in source) {
|
|
2408
|
+
if (!source.provider) return `mcp:${source.mcpServer}`;
|
|
2409
|
+
return `${source.mcpServer} via ${source.provider}`;
|
|
2410
|
+
}
|
|
2411
|
+
const levelLabel = capitalize(source.level);
|
|
2412
|
+
return `via ${source.provider} (${levelLabel})`;
|
|
2413
|
+
};
|
|
2414
|
+
|
|
2415
|
+
const renderSourceText = (text: string): string => text.replace(/\bvia\b/, theme.italic("via"));
|
|
2416
|
+
|
|
2417
|
+
const truncateText = (text: string, maxWidth: number): string => {
|
|
2418
|
+
const textWidth = visibleWidth(text);
|
|
2419
|
+
if (textWidth <= maxWidth) return text;
|
|
2420
|
+
if (maxWidth <= 3) {
|
|
2421
|
+
let acc = "";
|
|
2422
|
+
let width = 0;
|
|
2423
|
+
for (const char of text) {
|
|
2424
|
+
const charWidth = visibleWidth(char);
|
|
2425
|
+
if (width + charWidth > maxWidth) break;
|
|
2426
|
+
width += charWidth;
|
|
2427
|
+
acc += char;
|
|
2428
|
+
}
|
|
2429
|
+
return acc;
|
|
2430
|
+
}
|
|
2431
|
+
const targetWidth = maxWidth - 3;
|
|
2432
|
+
let acc = "";
|
|
2433
|
+
let width = 0;
|
|
2434
|
+
for (const char of text) {
|
|
2435
|
+
const charWidth = visibleWidth(char);
|
|
2436
|
+
if (width + charWidth > targetWidth) break;
|
|
2437
|
+
width += charWidth;
|
|
2438
|
+
acc += char;
|
|
2439
|
+
}
|
|
2440
|
+
return `${acc}...`;
|
|
2441
|
+
};
|
|
2442
|
+
|
|
2443
|
+
// Helper to format a section with consistent column alignment
|
|
2444
|
+
const formatSection = <T>(
|
|
2445
|
+
title: string,
|
|
2446
|
+
items: readonly T[],
|
|
2447
|
+
getName: (item: T) => string,
|
|
2448
|
+
getDesc: (item: T) => string | undefined,
|
|
2449
|
+
getSource: (item: T) => StatusSource,
|
|
2450
|
+
): string => {
|
|
2451
|
+
if (items.length === 0) return "";
|
|
2452
|
+
|
|
2453
|
+
const lineItems = items.map((item) => {
|
|
2454
|
+
const name = getName(item);
|
|
2455
|
+
const desc = getDesc(item);
|
|
2456
|
+
const sourceText = resolveSourceText(getSource(item));
|
|
2457
|
+
const nameWithSource = sourceText ? `${name} ${sourceText}` : name;
|
|
2458
|
+
return { name, sourceText, nameWithSource, desc };
|
|
2459
|
+
});
|
|
2460
|
+
|
|
2461
|
+
const maxNameWidth = Math.min(
|
|
2462
|
+
60,
|
|
2463
|
+
Math.max(...lineItems.map((line) => visibleWidth(line.nameWithSource))),
|
|
2464
|
+
);
|
|
2465
|
+
const formattedLines = lineItems.map((line) => {
|
|
2466
|
+
let nameText = line.name;
|
|
2467
|
+
let sourceText = line.sourceText;
|
|
2468
|
+
|
|
2469
|
+
if (sourceText) {
|
|
2470
|
+
const maxSourceWidth = Math.max(0, maxNameWidth - 2);
|
|
2471
|
+
sourceText = truncateText(sourceText, maxSourceWidth);
|
|
2472
|
+
}
|
|
2473
|
+
const sourceWidth = sourceText ? visibleWidth(sourceText) : 0;
|
|
2474
|
+
const availableForName = sourceText
|
|
2475
|
+
? Math.max(1, maxNameWidth - sourceWidth - 1)
|
|
2476
|
+
: maxNameWidth;
|
|
2477
|
+
nameText = truncateText(nameText, availableForName);
|
|
2478
|
+
|
|
2479
|
+
const nameWithSourcePlain = sourceText ? `${nameText} ${sourceText}` : nameText;
|
|
2480
|
+
const sourceRendered = sourceText ? renderSourceText(sourceText) : "";
|
|
2481
|
+
const nameRendered = sourceText ? `${theme.bold(nameText)} ${sourceRendered}` : theme.bold(nameText);
|
|
2482
|
+
const pad = Math.max(0, maxNameWidth - visibleWidth(nameWithSourcePlain));
|
|
2483
|
+
const desc = line.desc?.trim();
|
|
2484
|
+
const descPart = desc ? ` ${theme.fg("dim", desc.slice(0, 50) + (desc.length > 50 ? "..." : ""))}` : "";
|
|
2485
|
+
return ` ${nameRendered}${" ".repeat(pad)}${descPart}`;
|
|
2486
|
+
});
|
|
2487
|
+
|
|
2488
|
+
return `${theme.bold(theme.fg("accent", title))}\n${formattedLines.join("\n")}`;
|
|
2489
|
+
};
|
|
2490
|
+
|
|
2372
2491
|
// Loaded context files
|
|
2373
|
-
const
|
|
2492
|
+
const contextFilesResult = loadSync(contextFileCapability.id, { cwd: process.cwd() });
|
|
2493
|
+
const contextFiles = contextFilesResult.items as ContextFile[];
|
|
2374
2494
|
if (contextFiles.length > 0) {
|
|
2375
2495
|
sections.push(
|
|
2376
|
-
|
|
2377
|
-
"
|
|
2378
|
-
contextFiles
|
|
2496
|
+
formatSection(
|
|
2497
|
+
"Context Files",
|
|
2498
|
+
contextFiles,
|
|
2499
|
+
(f) => basename(f.path),
|
|
2500
|
+
() => undefined,
|
|
2501
|
+
(f) => ({ provider: f._source.providerName, level: f.level }),
|
|
2502
|
+
),
|
|
2379
2503
|
);
|
|
2380
2504
|
}
|
|
2381
2505
|
|
|
@@ -2385,9 +2509,13 @@ export class InteractiveMode {
|
|
|
2385
2509
|
const { skills, warnings: skillWarnings } = loadSkills(skillsSettings ?? {});
|
|
2386
2510
|
if (skills.length > 0) {
|
|
2387
2511
|
sections.push(
|
|
2388
|
-
|
|
2389
|
-
"
|
|
2390
|
-
skills
|
|
2512
|
+
formatSection(
|
|
2513
|
+
"Skills",
|
|
2514
|
+
skills,
|
|
2515
|
+
(s) => s.name,
|
|
2516
|
+
(s) => s.description,
|
|
2517
|
+
(s) => (s._source ? { provider: s._source.providerName, level: s._source.level } : "unknown"),
|
|
2518
|
+
),
|
|
2391
2519
|
);
|
|
2392
2520
|
}
|
|
2393
2521
|
if (skillWarnings.length > 0) {
|
|
@@ -2399,14 +2527,103 @@ export class InteractiveMode {
|
|
|
2399
2527
|
}
|
|
2400
2528
|
}
|
|
2401
2529
|
|
|
2402
|
-
// Loaded
|
|
2530
|
+
// Loaded rules
|
|
2531
|
+
const rulesResult = loadSync<Rule>(ruleCapability.id, { cwd: process.cwd() });
|
|
2532
|
+
if (rulesResult.items.length > 0) {
|
|
2533
|
+
sections.push(
|
|
2534
|
+
formatSection(
|
|
2535
|
+
"Rules",
|
|
2536
|
+
rulesResult.items,
|
|
2537
|
+
(r) => r.name,
|
|
2538
|
+
(r) => r.description,
|
|
2539
|
+
(r) => ({ provider: r._source.providerName, level: r._source.level }),
|
|
2540
|
+
),
|
|
2541
|
+
);
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
// Loaded prompts
|
|
2545
|
+
const promptsResult = loadSync<Prompt>(promptCapability.id, { cwd: process.cwd() });
|
|
2546
|
+
if (promptsResult.items.length > 0) {
|
|
2547
|
+
sections.push(
|
|
2548
|
+
formatSection(
|
|
2549
|
+
"Prompts",
|
|
2550
|
+
promptsResult.items,
|
|
2551
|
+
(p) => p.name,
|
|
2552
|
+
() => undefined,
|
|
2553
|
+
(p) => ({ provider: p._source.providerName, level: p._source.level }),
|
|
2554
|
+
),
|
|
2555
|
+
);
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
// Loaded instructions
|
|
2559
|
+
const instructionsResult = loadSync<Instruction>(instructionCapability.id, { cwd: process.cwd() });
|
|
2560
|
+
if (instructionsResult.items.length > 0) {
|
|
2561
|
+
sections.push(
|
|
2562
|
+
formatSection(
|
|
2563
|
+
"Instructions",
|
|
2564
|
+
instructionsResult.items,
|
|
2565
|
+
(i) => i.name,
|
|
2566
|
+
(i) => (i.applyTo ? `applies to: ${i.applyTo}` : undefined),
|
|
2567
|
+
(i) => ({ provider: i._source.providerName, level: i._source.level }),
|
|
2568
|
+
),
|
|
2569
|
+
);
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
// Loaded custom tools - split MCP from non-MCP
|
|
2403
2573
|
if (this.customTools.size > 0) {
|
|
2574
|
+
const allTools = Array.from(this.customTools.values());
|
|
2575
|
+
const mcpTools = allTools.filter((ct) => ct.path.startsWith("mcp:"));
|
|
2576
|
+
const customTools = allTools.filter((ct) => !ct.path.startsWith("mcp:"));
|
|
2577
|
+
|
|
2578
|
+
// MCP Tools section
|
|
2579
|
+
if (mcpTools.length > 0) {
|
|
2580
|
+
sections.push(
|
|
2581
|
+
formatSection(
|
|
2582
|
+
"MCP Tools",
|
|
2583
|
+
mcpTools,
|
|
2584
|
+
(ct) => ct.tool.label || ct.tool.name,
|
|
2585
|
+
() => undefined,
|
|
2586
|
+
(ct) => {
|
|
2587
|
+
const match = ct.path.match(/^mcp:(.+?) via (.+)$/);
|
|
2588
|
+
if (match) {
|
|
2589
|
+
const [, serverName, providerName] = match;
|
|
2590
|
+
return { mcpServer: serverName, provider: providerName };
|
|
2591
|
+
}
|
|
2592
|
+
return ct.path.startsWith("mcp:") ? { mcpServer: ct.path.slice(4) } : "unknown";
|
|
2593
|
+
},
|
|
2594
|
+
),
|
|
2595
|
+
);
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
// Custom Tools section
|
|
2599
|
+
if (customTools.length > 0) {
|
|
2600
|
+
sections.push(
|
|
2601
|
+
formatSection(
|
|
2602
|
+
"Custom Tools",
|
|
2603
|
+
customTools,
|
|
2604
|
+
(ct) => ct.tool.label || ct.tool.name,
|
|
2605
|
+
(ct) => ct.tool.description,
|
|
2606
|
+
(ct) => {
|
|
2607
|
+
if (ct.source?.provider === "builtin") return "builtin";
|
|
2608
|
+
if (ct.path === "<exa>") return "builtin";
|
|
2609
|
+
return ct.source ? { provider: ct.source.providerName, level: ct.source.level } : "unknown";
|
|
2610
|
+
},
|
|
2611
|
+
),
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
// Loaded slash commands (file-based)
|
|
2617
|
+
const fileCommands = this.session.fileCommands;
|
|
2618
|
+
if (fileCommands.length > 0) {
|
|
2404
2619
|
sections.push(
|
|
2405
|
-
|
|
2406
|
-
"
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2620
|
+
formatSection(
|
|
2621
|
+
"Slash Commands",
|
|
2622
|
+
fileCommands,
|
|
2623
|
+
(cmd) => `/${cmd.name}`,
|
|
2624
|
+
(cmd) => cmd.description,
|
|
2625
|
+
(cmd) => (cmd._source ? { provider: cmd._source.providerName, level: cmd._source.level } : "unknown"),
|
|
2626
|
+
),
|
|
2410
2627
|
);
|
|
2411
2628
|
}
|
|
2412
2629
|
|
|
@@ -2416,7 +2633,7 @@ export class InteractiveMode {
|
|
|
2416
2633
|
const hookPaths = hookRunner.getHookPaths();
|
|
2417
2634
|
if (hookPaths.length > 0) {
|
|
2418
2635
|
sections.push(
|
|
2419
|
-
`${theme.bold(theme.fg("accent", "Hooks"))}\n${hookPaths.map((p) => theme.fg("dim",
|
|
2636
|
+
`${theme.bold(theme.fg("accent", "Hooks"))}\n${hookPaths.map((p) => ` ${theme.bold(basename(p))} ${theme.fg("dim", "hook")}`).join("\n")}`,
|
|
2420
2637
|
);
|
|
2421
2638
|
}
|
|
2422
2639
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"title": "Pi Coding Agent Theme",
|
|
4
|
-
"description": "Theme schema for
|
|
4
|
+
"description": "Theme schema for OMP coding agent",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": ["name", "colors"],
|
|
7
7
|
"properties": {
|
package/src/utils/clipboard.ts
CHANGED
|
@@ -199,7 +199,7 @@ async function readImageMacOS(timeout: number): Promise<ClipboardImage | null> {
|
|
|
199
199
|
|
|
200
200
|
// Read the actual image data using a temp file approach
|
|
201
201
|
// osascript can't output binary directly, so we write to a temp file
|
|
202
|
-
const tempFile = `/tmp/
|
|
202
|
+
const tempFile = `/tmp/omp-clipboard-${Date.now()}.${imageType === "png" ? "png" : "jpg"}`;
|
|
203
203
|
const clipboardClass = imageType === "png" ? "«class PNGf»" : "«class JPEG»";
|
|
204
204
|
|
|
205
205
|
const readScript = `
|
|
@@ -77,7 +77,7 @@ SNAPSHOT_FILE='${escapedPath}'
|
|
|
77
77
|
${hasRcFile ? `source "${rcFile}" < /dev/null 2>/dev/null` : "# No user config file to source"}
|
|
78
78
|
|
|
79
79
|
# Create/clear the snapshot file
|
|
80
|
-
echo "# Shell snapshot - generated by
|
|
80
|
+
echo "# Shell snapshot - generated by omp agent" >| "$SNAPSHOT_FILE"
|
|
81
81
|
|
|
82
82
|
# Unalias everything first to avoid conflicts when sourced
|
|
83
83
|
echo "unalias -a 2>/dev/null || true" >> "$SNAPSHOT_FILE"
|
|
@@ -127,7 +127,7 @@ export async function getOrCreateSnapshot(
|
|
|
127
127
|
const rcFile = getShellConfigFile(shell);
|
|
128
128
|
|
|
129
129
|
// Create snapshot directory
|
|
130
|
-
const snapshotDir = join(tmpdir(), "
|
|
130
|
+
const snapshotDir = join(tmpdir(), "omp-shell-snapshots");
|
|
131
131
|
try {
|
|
132
132
|
mkdirSync(snapshotDir, { recursive: true });
|
|
133
133
|
} catch {
|
package/src/utils/shell.ts
CHANGED
|
@@ -26,13 +26,13 @@ function isExecutable(path: string): boolean {
|
|
|
26
26
|
* Build the spawn environment (cached).
|
|
27
27
|
*/
|
|
28
28
|
function buildSpawnEnv(shell: string): Record<string, string | undefined> {
|
|
29
|
-
const noCI = process.env.
|
|
29
|
+
const noCI = process.env.OMP_BASH_NO_CI || process.env.CLAUDE_BASH_NO_CI;
|
|
30
30
|
return {
|
|
31
31
|
...process.env,
|
|
32
32
|
SHELL: shell,
|
|
33
33
|
GIT_EDITOR: "true",
|
|
34
34
|
GPG_TTY: "not a tty",
|
|
35
|
-
|
|
35
|
+
OMPCODE: "1",
|
|
36
36
|
CLAUDECODE: "1",
|
|
37
37
|
...(noCI ? {} : { CI: "true" }),
|
|
38
38
|
};
|
|
@@ -40,10 +40,10 @@ function buildSpawnEnv(shell: string): Record<string, string | undefined> {
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Get shell args, optionally including login shell flag.
|
|
43
|
-
* Supports
|
|
43
|
+
* Supports OMP_BASH_NO_LOGIN and CLAUDE_BASH_NO_LOGIN to skip -l.
|
|
44
44
|
*/
|
|
45
45
|
function getShellArgs(): string[] {
|
|
46
|
-
const noLogin = process.env.
|
|
46
|
+
const noLogin = process.env.OMP_BASH_NO_LOGIN || process.env.CLAUDE_BASH_NO_LOGIN;
|
|
47
47
|
return noLogin ? ["-c"] : ["-l", "-c"];
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -51,7 +51,7 @@ function getShellArgs(): string[] {
|
|
|
51
51
|
* Get shell prefix for wrapping commands (profilers, strace, etc.).
|
|
52
52
|
*/
|
|
53
53
|
function getShellPrefix(): string | undefined {
|
|
54
|
-
return process.env.
|
|
54
|
+
return process.env.OMP_SHELL_PREFIX || process.env.CLAUDE_CODE_SHELL_PREFIX;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
@@ -107,7 +107,7 @@ export function getShellConfig(): ShellConfig {
|
|
|
107
107
|
return cachedShellConfig;
|
|
108
108
|
}
|
|
109
109
|
throw new Error(
|
|
110
|
-
`Custom shell path not found: ${customShellPath}\nPlease update shellPath in ~/.
|
|
110
|
+
`Custom shell path not found: ${customShellPath}\nPlease update shellPath in ~/.omp/agent/settings.json`,
|
|
111
111
|
);
|
|
112
112
|
}
|
|
113
113
|
|
|
@@ -141,7 +141,7 @@ export function getShellConfig(): ShellConfig {
|
|
|
141
141
|
`No bash shell found. Options:\n` +
|
|
142
142
|
` 1. Install Git for Windows: https://git-scm.com/download/win\n` +
|
|
143
143
|
` 2. Add your bash to PATH (Cygwin, MSYS2, etc.)\n` +
|
|
144
|
-
` 3. Set shellPath in ~/.
|
|
144
|
+
` 3. Set shellPath in ~/.omp/agent/settings.json\n\n` +
|
|
145
145
|
`Searched Git Bash in:\n${paths.map((p) => ` ${p}`).join("\n")}`,
|
|
146
146
|
);
|
|
147
147
|
}
|