@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
|
@@ -309,7 +309,7 @@ function convertWithMarkitdown(
|
|
|
309
309
|
|
|
310
310
|
// Write to temp file with extension hint
|
|
311
311
|
const ext = extensionHint || ".bin";
|
|
312
|
-
const tmpFile = path.join(os.tmpdir(), `
|
|
312
|
+
const tmpFile = path.join(os.tmpdir(), `omp-convert-${Date.now()}${ext}`);
|
|
313
313
|
|
|
314
314
|
try {
|
|
315
315
|
fs.writeFileSync(tmpFile, content);
|
|
@@ -531,7 +531,7 @@ function parseFeedToMarkdown(content: string, maxItems = 10): string {
|
|
|
531
531
|
* Render HTML to text using lynx
|
|
532
532
|
*/
|
|
533
533
|
function renderWithLynx(html: string, timeout: number): { content: string; ok: boolean } {
|
|
534
|
-
const tmpFile = path.join(os.tmpdir(), `
|
|
534
|
+
const tmpFile = path.join(os.tmpdir(), `omp-render-${Date.now()}.html`);
|
|
535
535
|
try {
|
|
536
536
|
fs.writeFileSync(tmpFile, html);
|
|
537
537
|
// Convert path to file URL (handles Windows paths correctly)
|
|
@@ -712,7 +712,7 @@ async function fetchGitHubApi(endpoint: string, timeout: number): Promise<{ data
|
|
|
712
712
|
|
|
713
713
|
const headers: Record<string, string> = {
|
|
714
714
|
Accept: "application/vnd.github.v3+json",
|
|
715
|
-
"User-Agent": "
|
|
715
|
+
"User-Agent": "omp-web-fetch/1.0",
|
|
716
716
|
};
|
|
717
717
|
|
|
718
718
|
// Use GITHUB_TOKEN if available
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 4-tier auth resolution:
|
|
5
5
|
* 1. ANTHROPIC_SEARCH_API_KEY / ANTHROPIC_SEARCH_BASE_URL env vars
|
|
6
|
-
* 2. Provider with api="anthropic-messages" in ~/.
|
|
7
|
-
* 3. OAuth credentials in ~/.
|
|
6
|
+
* 2. Provider with api="anthropic-messages" in ~/.omp/agent/models.json
|
|
7
|
+
* 3. OAuth credentials in ~/.omp/agent/auth.json (with expiry check)
|
|
8
8
|
* 4. ANTHROPIC_API_KEY / ANTHROPIC_BASE_URL fallback
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import * as os from "node:os";
|
|
12
12
|
import * as path from "node:path";
|
|
13
|
+
import { getConfigDirPaths } from "../../../config";
|
|
13
14
|
import type { AnthropicAuthConfig, AuthJson, ModelsJson } from "./types";
|
|
14
15
|
|
|
15
16
|
const DEFAULT_BASE_URL = "https://api.anthropic.com";
|
|
@@ -83,7 +84,8 @@ export function isOAuthToken(apiKey: string): boolean {
|
|
|
83
84
|
* 4. ANTHROPIC_API_KEY / ANTHROPIC_BASE_URL fallback
|
|
84
85
|
*/
|
|
85
86
|
export async function findAnthropicAuth(): Promise<AnthropicAuthConfig | null> {
|
|
86
|
-
|
|
87
|
+
// Get all config directories (user-level only) for fallback support
|
|
88
|
+
const configDirs = getConfigDirPaths("", { project: false });
|
|
87
89
|
|
|
88
90
|
// 1. Explicit search-specific env vars
|
|
89
91
|
const searchApiKey = await getEnv("ANTHROPIC_SEARCH_API_KEY");
|
|
@@ -96,41 +98,45 @@ export async function findAnthropicAuth(): Promise<AnthropicAuthConfig | null> {
|
|
|
96
98
|
};
|
|
97
99
|
}
|
|
98
100
|
|
|
99
|
-
// 2. Provider with api="anthropic-messages" in models.json
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
101
|
+
// 2. Provider with api="anthropic-messages" in models.json (check all config dirs)
|
|
102
|
+
for (const configDir of configDirs) {
|
|
103
|
+
const modelsJson = await readJson<ModelsJson>(path.join(configDir, "models.json"));
|
|
104
|
+
if (modelsJson?.providers) {
|
|
105
|
+
// First pass: look for providers with actual API keys
|
|
106
|
+
for (const [_name, provider] of Object.entries(modelsJson.providers)) {
|
|
107
|
+
if (provider.api === "anthropic-messages" && provider.apiKey && provider.apiKey !== "none") {
|
|
108
|
+
return {
|
|
109
|
+
apiKey: provider.apiKey,
|
|
110
|
+
baseUrl: provider.baseUrl ?? DEFAULT_BASE_URL,
|
|
111
|
+
isOAuth: isOAuthToken(provider.apiKey),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
110
114
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
115
|
+
// Second pass: check for proxy mode (baseUrl but apiKey="none")
|
|
116
|
+
for (const [_name, provider] of Object.entries(modelsJson.providers)) {
|
|
117
|
+
if (provider.api === "anthropic-messages" && provider.baseUrl) {
|
|
118
|
+
return {
|
|
119
|
+
apiKey: provider.apiKey ?? "",
|
|
120
|
+
baseUrl: provider.baseUrl,
|
|
121
|
+
isOAuth: false,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
}
|
|
123
127
|
|
|
124
|
-
// 3. OAuth credentials in auth.json (with 5-minute expiry buffer)
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
// 3. OAuth credentials in auth.json (with 5-minute expiry buffer, check all config dirs)
|
|
129
|
+
for (const configDir of configDirs) {
|
|
130
|
+
const authJson = await readJson<AuthJson>(path.join(configDir, "auth.json"));
|
|
131
|
+
if (authJson?.anthropic?.type === "oauth" && authJson.anthropic.access) {
|
|
132
|
+
const expiryBuffer = 5 * 60 * 1000; // 5 minutes
|
|
133
|
+
if (authJson.anthropic.expires > Date.now() + expiryBuffer) {
|
|
134
|
+
return {
|
|
135
|
+
apiKey: authJson.anthropic.access,
|
|
136
|
+
baseUrl: DEFAULT_BASE_URL,
|
|
137
|
+
isOAuth: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
134
140
|
}
|
|
135
141
|
}
|
|
136
142
|
|
|
@@ -163,7 +169,7 @@ export function buildAnthropicHeaders(auth: AnthropicAuthConfig): Record<string,
|
|
|
163
169
|
"content-type": "application/json",
|
|
164
170
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
165
171
|
"anthropic-beta": betas.join(","),
|
|
166
|
-
"user-agent": "
|
|
172
|
+
"user-agent": "claude-code/2.0.20",
|
|
167
173
|
"x-app": "cli",
|
|
168
174
|
// Stainless SDK telemetry headers (required for OAuth)
|
|
169
175
|
"x-stainless-arch": process.arch,
|
|
@@ -186,7 +186,7 @@ async function executeWebSearch(
|
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
const WEB_SEARCH_DESCRIPTION = `Allows
|
|
189
|
+
const WEB_SEARCH_DESCRIPTION = `Allows OMP to search the web and use the results to inform responses
|
|
190
190
|
- Provides up-to-date information for current events and recent data
|
|
191
191
|
- Returns search result information formatted as search result blocks, including links as markdown hyperlinks
|
|
192
192
|
- Use this tool for accessing information beyond Claude's knowledge cutoff
|
|
@@ -180,7 +180,7 @@ export async function searchAnthropic(params: AnthropicSearchParams): Promise<We
|
|
|
180
180
|
const auth = await findAnthropicAuth();
|
|
181
181
|
if (!auth) {
|
|
182
182
|
throw new Error(
|
|
183
|
-
"No Anthropic credentials found. Set ANTHROPIC_API_KEY or configure OAuth in ~/.
|
|
183
|
+
"No Anthropic credentials found. Set ANTHROPIC_API_KEY or configure OAuth in ~/.omp/agent/auth.json",
|
|
184
184
|
);
|
|
185
185
|
}
|
|
186
186
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AGENTS.md Provider
|
|
3
|
+
*
|
|
4
|
+
* Discovers standalone AGENTS.md files by walking up from cwd.
|
|
5
|
+
* This handles AGENTS.md files that live in project root (not in config directories
|
|
6
|
+
* like .codex/ or .gemini/, which are handled by their respective providers).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { dirname, join, sep } from "node:path";
|
|
10
|
+
import { type ContextFile, contextFileCapability } from "../capability/context-file";
|
|
11
|
+
import { registerProvider } from "../capability/index";
|
|
12
|
+
import type { LoadContext, LoadResult } from "../capability/types";
|
|
13
|
+
import { calculateDepth, createSourceMeta } from "./helpers";
|
|
14
|
+
|
|
15
|
+
const PROVIDER_ID = "agents-md";
|
|
16
|
+
const DISPLAY_NAME = "AGENTS.md";
|
|
17
|
+
const MAX_DEPTH = 20; // Prevent walking up excessively far from cwd
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Load standalone AGENTS.md files.
|
|
21
|
+
*/
|
|
22
|
+
function loadAgentsMd(ctx: LoadContext): LoadResult<ContextFile> {
|
|
23
|
+
const items: ContextFile[] = [];
|
|
24
|
+
const warnings: string[] = [];
|
|
25
|
+
|
|
26
|
+
// Walk up from cwd looking for AGENTS.md files
|
|
27
|
+
let current = ctx.cwd;
|
|
28
|
+
let depth = 0;
|
|
29
|
+
|
|
30
|
+
while (depth < MAX_DEPTH) {
|
|
31
|
+
const candidate = join(current, "AGENTS.md");
|
|
32
|
+
|
|
33
|
+
if (ctx.fs.isFile(candidate)) {
|
|
34
|
+
// Skip if it's inside a config directory (handled by other providers)
|
|
35
|
+
const parent = dirname(candidate);
|
|
36
|
+
const baseName = parent.split(sep).pop() ?? "";
|
|
37
|
+
|
|
38
|
+
// Skip if inside .codex, .gemini, or other config dirs
|
|
39
|
+
if (!baseName.startsWith(".")) {
|
|
40
|
+
const content = ctx.fs.readFile(candidate);
|
|
41
|
+
|
|
42
|
+
if (content === null) {
|
|
43
|
+
warnings.push(`Failed to read: ${candidate}`);
|
|
44
|
+
} else {
|
|
45
|
+
const fileDir = dirname(candidate);
|
|
46
|
+
const calculatedDepth = calculateDepth(ctx.cwd, fileDir, sep);
|
|
47
|
+
|
|
48
|
+
items.push({
|
|
49
|
+
path: candidate,
|
|
50
|
+
content,
|
|
51
|
+
level: "project",
|
|
52
|
+
depth: calculatedDepth,
|
|
53
|
+
_source: createSourceMeta(PROVIDER_ID, candidate, "project"),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Move to parent directory
|
|
60
|
+
const parent = dirname(current);
|
|
61
|
+
if (parent === current) break; // Reached filesystem root
|
|
62
|
+
current = parent;
|
|
63
|
+
depth++;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return { items, warnings };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
registerProvider(contextFileCapability.id, {
|
|
70
|
+
id: PROVIDER_ID,
|
|
71
|
+
displayName: DISPLAY_NAME,
|
|
72
|
+
description: "Standalone AGENTS.md files (Codex/Gemini style)",
|
|
73
|
+
priority: 10,
|
|
74
|
+
load: loadAgentsMd,
|
|
75
|
+
});
|