@oh-my-pi/pi-coding-agent 14.5.12 → 14.5.14
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 +45 -0
- package/package.json +18 -10
- package/src/cli/jupyter-cli.ts +1 -1
- package/src/commit/pipeline.ts +4 -3
- package/src/config/model-equivalence.ts +49 -16
- package/src/config/model-registry.ts +100 -25
- package/src/config/model-resolver.ts +29 -15
- package/src/config/settings-schema.ts +20 -6
- package/src/config/settings.ts +9 -8
- package/src/config.ts +18 -6
- package/src/eval/backend.ts +43 -0
- package/src/eval/eval.lark +43 -0
- package/src/eval/index.ts +5 -0
- package/src/eval/js/context-manager.ts +717 -0
- package/src/eval/js/executor.ts +131 -0
- package/src/eval/js/index.ts +46 -0
- package/src/eval/js/prelude.ts +2 -0
- package/src/eval/js/prelude.txt +84 -0
- package/src/eval/js/tool-bridge.ts +124 -0
- package/src/eval/parse.ts +337 -0
- package/src/{ipy → eval/py}/executor.ts +2 -180
- package/src/{ipy → eval/py}/gateway-coordinator.ts +2 -2
- package/src/eval/py/index.ts +58 -0
- package/src/{ipy → eval/py}/kernel.ts +9 -45
- package/src/{ipy → eval/py}/prelude.py +39 -227
- package/src/eval/types.ts +48 -0
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +8 -10
- package/src/extensibility/extensions/types.ts +2 -3
- package/src/internal-urls/docs-index.generated.ts +5 -5
- package/src/lsp/client.ts +9 -0
- package/src/lsp/index.ts +395 -0
- package/src/lsp/types.ts +15 -4
- package/src/main.ts +35 -14
- package/src/mcp/manager.ts +22 -0
- package/src/mcp/oauth-flow.ts +1 -1
- package/src/memories/index.ts +1 -1
- package/src/modes/acp/acp-event-mapper.ts +1 -1
- package/src/modes/components/{python-execution.ts → eval-execution.ts} +11 -4
- package/src/modes/components/login-dialog.ts +1 -1
- package/src/modes/components/oauth-selector.ts +2 -1
- package/src/modes/components/tool-execution.ts +3 -4
- package/src/modes/controllers/command-controller.ts +28 -8
- package/src/modes/controllers/input-controller.ts +4 -4
- package/src/modes/controllers/selector-controller.ts +2 -1
- package/src/modes/interactive-mode.ts +4 -5
- package/src/modes/rpc/rpc-client.ts +9 -0
- package/src/modes/rpc/rpc-mode.ts +6 -0
- package/src/modes/rpc/rpc-types.ts +9 -0
- package/src/modes/types.ts +3 -3
- package/src/modes/utils/ui-helpers.ts +2 -2
- package/src/prompts/system/system-prompt.md +3 -3
- package/src/prompts/tools/eval.md +92 -0
- package/src/prompts/tools/lsp.md +7 -3
- package/src/sdk.ts +64 -35
- package/src/session/agent-session.ts +152 -46
- package/src/session/messages.ts +1 -1
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/system-prompt.ts +34 -66
- package/src/task/agents.ts +4 -5
- package/src/task/executor.ts +5 -9
- package/src/tools/archive-reader.ts +9 -3
- package/src/tools/browser/launch.ts +22 -0
- package/src/tools/browser/readable.ts +11 -6
- package/src/tools/browser/registry.ts +25 -244
- package/src/tools/browser/render.ts +1 -1
- package/src/tools/browser/tab-protocol.ts +101 -0
- package/src/tools/browser/tab-supervisor.ts +429 -0
- package/src/tools/browser/tab-worker-entry.ts +21 -0
- package/src/tools/browser/tab-worker.ts +1006 -0
- package/src/tools/browser.ts +17 -32
- package/src/tools/checkpoint.ts +2 -2
- package/src/tools/{python.ts → eval.ts} +324 -315
- package/src/tools/exit-plan-mode.ts +1 -1
- package/src/tools/image-gen.ts +2 -2
- package/src/tools/index.ts +62 -100
- package/src/tools/read.ts +0 -6
- package/src/tools/recipe/runners/pkg.ts +34 -32
- package/src/tools/renderers.ts +2 -2
- package/src/tools/resolve.ts +7 -2
- package/src/tools/todo-write.ts +0 -1
- package/src/tools/tool-timeouts.ts +2 -2
- package/src/tools/write.ts +8 -1
- package/src/utils/markit.ts +15 -7
- package/src/utils/tools-manager.ts +5 -5
- package/src/web/scrapers/crossref.ts +3 -3
- package/src/web/scrapers/devto.ts +1 -1
- package/src/web/scrapers/discourse.ts +5 -5
- package/src/web/scrapers/firefox-addons.ts +1 -1
- package/src/web/scrapers/flathub.ts +2 -2
- package/src/web/scrapers/gitlab.ts +1 -1
- package/src/web/scrapers/go-pkg.ts +2 -2
- package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
- package/src/web/scrapers/mastodon.ts +9 -9
- package/src/web/scrapers/mdn.ts +11 -7
- package/src/web/scrapers/pub-dev.ts +1 -1
- package/src/web/scrapers/rawg.ts +3 -3
- package/src/web/scrapers/readthedocs.ts +1 -1
- package/src/web/scrapers/spdx.ts +1 -1
- package/src/web/scrapers/stackoverflow.ts +2 -2
- package/src/web/scrapers/types.ts +53 -39
- package/src/web/scrapers/w3c.ts +1 -1
- package/src/web/search/index.ts +5 -5
- package/src/web/search/provider.ts +121 -39
- package/src/web/search/providers/gemini.ts +4 -4
- package/src/web/search/render.ts +2 -2
- package/src/ipy/modules.ts +0 -144
- package/src/prompts/tools/python.md +0 -57
- package/src/tools/browser/vm.ts +0 -792
- /package/src/{ipy → eval/py}/cancellation.ts +0 -0
- /package/src/{ipy → eval/py}/prelude.ts +0 -0
- /package/src/{ipy → eval/py}/runtime.ts +0 -0
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
import {
|
|
9
9
|
ANTIGRAVITY_SYSTEM_INSTRUCTION,
|
|
10
10
|
extractRetryDelay,
|
|
11
|
-
|
|
11
|
+
getAntigravityUserAgent,
|
|
12
12
|
getGeminiCliHeaders,
|
|
13
|
-
refreshAntigravityToken,
|
|
14
|
-
refreshGoogleCloudToken,
|
|
15
13
|
} from "@oh-my-pi/pi-ai";
|
|
14
|
+
import { refreshAntigravityToken } from "@oh-my-pi/pi-ai/utils/oauth/google-antigravity";
|
|
15
|
+
import { refreshGoogleCloudToken } from "@oh-my-pi/pi-ai/utils/oauth/google-gemini-cli";
|
|
16
16
|
import { getAgentDbPath } from "@oh-my-pi/pi-utils";
|
|
17
17
|
import { AgentStorage } from "../../../session/agent-storage";
|
|
18
18
|
import type { SearchCitation, SearchResponse, SearchSource } from "../../../web/search/types";
|
|
@@ -248,7 +248,7 @@ async function callGeminiSearch(
|
|
|
248
248
|
usage?: { inputTokens: number; outputTokens: number; totalTokens: number };
|
|
249
249
|
}> {
|
|
250
250
|
const endpoints = auth.isAntigravity ? ANTIGRAVITY_ENDPOINT_FALLBACKS : [DEFAULT_ENDPOINT];
|
|
251
|
-
const headers = auth.isAntigravity ?
|
|
251
|
+
const headers = auth.isAntigravity ? { "User-Agent": getAntigravityUserAgent() } : getGeminiCliHeaders();
|
|
252
252
|
|
|
253
253
|
const requestMetadata = auth.isAntigravity
|
|
254
254
|
? {
|
package/src/web/search/render.ts
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from "../../tools/render-utils";
|
|
23
23
|
import { renderStatusLine, renderTreeList } from "../../tui";
|
|
24
24
|
import { CachedOutputBlock } from "../../tui/output-block";
|
|
25
|
-
import {
|
|
25
|
+
import { getSearchProviderLabel } from "./provider";
|
|
26
26
|
import type { SearchResponse } from "./types";
|
|
27
27
|
|
|
28
28
|
const MAX_COLLAPSED_ANSWER_LINES = PREVIEW_LIMITS.COLLAPSED_LINES;
|
|
@@ -112,7 +112,7 @@ export function renderSearchResult(
|
|
|
112
112
|
: [];
|
|
113
113
|
const totalAnswerLines = answerLines.length;
|
|
114
114
|
|
|
115
|
-
const providerLabel = provider !== "none" ?
|
|
115
|
+
const providerLabel = provider !== "none" ? getSearchProviderLabel(provider) : "None";
|
|
116
116
|
const queryPreview = args?.query
|
|
117
117
|
? truncateToWidth(args.query, 80)
|
|
118
118
|
: searchQueries[0]
|
package/src/ipy/modules.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs/promises";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import { getAgentModulesDir, getProjectDir, getProjectModulesDir } from "@oh-my-pi/pi-utils";
|
|
4
|
-
import { getExecutionCancellationError } from "./cancellation";
|
|
5
|
-
|
|
6
|
-
export type PythonModuleSource = "user" | "project";
|
|
7
|
-
|
|
8
|
-
export interface PythonModuleEntry {
|
|
9
|
-
path: string;
|
|
10
|
-
content: string;
|
|
11
|
-
source: PythonModuleSource;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface PythonModuleExecuteResult {
|
|
15
|
-
status: "ok" | "error";
|
|
16
|
-
cancelled: boolean;
|
|
17
|
-
timedOut?: boolean;
|
|
18
|
-
error?: { name: string; value: string; traceback: string[] };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface PythonModuleExecutor {
|
|
22
|
-
execute: (
|
|
23
|
-
code: string,
|
|
24
|
-
options?: { signal?: AbortSignal; timeoutMs?: number; silent?: boolean; storeHistory?: boolean },
|
|
25
|
-
) => Promise<PythonModuleExecuteResult>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface DiscoverPythonModulesOptions {
|
|
29
|
-
/** Working directory for project-level modules. Default: getProjectDir() */
|
|
30
|
-
cwd?: string;
|
|
31
|
-
/** Agent directory for user-level modules. Default: from getAgentDir() */
|
|
32
|
-
agentDir?: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface LoadPythonModulesOptions extends DiscoverPythonModulesOptions {
|
|
36
|
-
signal?: AbortSignal;
|
|
37
|
-
timeoutMs?: number;
|
|
38
|
-
deadlineMs?: number;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface ModuleCandidate {
|
|
42
|
-
name: string;
|
|
43
|
-
path: string;
|
|
44
|
-
source: PythonModuleSource;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function listModuleCandidates(dir: string, source: PythonModuleSource): Promise<ModuleCandidate[]> {
|
|
48
|
-
try {
|
|
49
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
50
|
-
return entries
|
|
51
|
-
.filter(entry => entry.isFile() && entry.name.endsWith(".py"))
|
|
52
|
-
.map(entry => ({
|
|
53
|
-
name: entry.name,
|
|
54
|
-
path: path.resolve(dir, entry.name),
|
|
55
|
-
source,
|
|
56
|
-
}));
|
|
57
|
-
} catch {
|
|
58
|
-
return [];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async function readModuleContent(candidate: ModuleCandidate): Promise<PythonModuleEntry> {
|
|
63
|
-
try {
|
|
64
|
-
const content = await Bun.file(candidate.path).text();
|
|
65
|
-
return { path: candidate.path, content, source: candidate.source };
|
|
66
|
-
} catch (err) {
|
|
67
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
68
|
-
throw new Error(`Failed to read Python module ${candidate.path}: ${message}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function createTimeoutError(message: string): Error {
|
|
73
|
-
const error = new Error(message);
|
|
74
|
-
error.name = "TimeoutError";
|
|
75
|
-
return error;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function requireModuleExecutionTimeoutMs(options: LoadPythonModulesOptions): number | undefined {
|
|
79
|
-
if (options.deadlineMs === undefined) {
|
|
80
|
-
return options.timeoutMs;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const remainingMs = options.deadlineMs - Date.now();
|
|
84
|
-
if (remainingMs <= 0) {
|
|
85
|
-
throw createTimeoutError("Python module loading timed out");
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return remainingMs;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Discover Python prelude extension modules from user and project directories.
|
|
93
|
-
*/
|
|
94
|
-
export async function discoverPythonModules(options: DiscoverPythonModulesOptions = {}): Promise<PythonModuleEntry[]> {
|
|
95
|
-
const cwd = options.cwd ?? getProjectDir();
|
|
96
|
-
|
|
97
|
-
const userDir = getAgentModulesDir(options.agentDir);
|
|
98
|
-
const projectDir = getProjectModulesDir(cwd);
|
|
99
|
-
|
|
100
|
-
const userCandidates = await listModuleCandidates(userDir, "user");
|
|
101
|
-
const projectCandidates = await listModuleCandidates(projectDir, "project");
|
|
102
|
-
|
|
103
|
-
const byName = new Map<string, ModuleCandidate>();
|
|
104
|
-
for (const candidate of userCandidates) {
|
|
105
|
-
if (!byName.has(candidate.name)) {
|
|
106
|
-
byName.set(candidate.name, candidate);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
for (const candidate of projectCandidates) {
|
|
110
|
-
const existing = byName.get(candidate.name);
|
|
111
|
-
if (!existing || existing.source === "user") {
|
|
112
|
-
byName.set(candidate.name, candidate);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const sorted = Array.from(byName.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
117
|
-
return Promise.all(sorted.map(candidate => readModuleContent(candidate)));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Load Python prelude extension modules into an active kernel.
|
|
122
|
-
*/
|
|
123
|
-
export async function loadPythonModules(
|
|
124
|
-
executor: PythonModuleExecutor,
|
|
125
|
-
options: LoadPythonModulesOptions = {},
|
|
126
|
-
): Promise<PythonModuleEntry[]> {
|
|
127
|
-
const modules = await discoverPythonModules(options);
|
|
128
|
-
for (const module of modules) {
|
|
129
|
-
const result = await executor.execute(module.content, {
|
|
130
|
-
signal: options.signal,
|
|
131
|
-
timeoutMs: requireModuleExecutionTimeoutMs(options),
|
|
132
|
-
silent: true,
|
|
133
|
-
storeHistory: false,
|
|
134
|
-
});
|
|
135
|
-
if (result.cancelled) {
|
|
136
|
-
throw getExecutionCancellationError(result, options.signal, `Failed to load Python module ${module.path}`);
|
|
137
|
-
}
|
|
138
|
-
if (result.status === "error") {
|
|
139
|
-
const details = result.error ? `${result.error.name}: ${result.error.value}` : "unknown error";
|
|
140
|
-
throw new Error(`Failed to load Python module ${module.path}: ${details}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return modules;
|
|
144
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
Runs Python cells sequentially in persistent IPython kernel.
|
|
2
|
-
|
|
3
|
-
<instruction>
|
|
4
|
-
Kernel persists across calls and cells; **imports, variables, and functions survive — use this.**
|
|
5
|
-
|
|
6
|
-
**Work incrementally:** one logical step per cell (imports, define, test, use). Pass multiple small cells in one call. Define small reusable functions you can debug individually. You **MUST** put workflow explanations in the assistant message or cell title — never inside cell code.
|
|
7
|
-
|
|
8
|
-
**On failure:** errors identify the failing cell (e.g., "Cell 3 failed"). Resubmit only the fixed cell (or fixed cell + remaining cells).
|
|
9
|
-
</instruction>
|
|
10
|
-
|
|
11
|
-
{{#if categories.length}}
|
|
12
|
-
<prelude>
|
|
13
|
-
All helpers auto-print results and return values for chaining.
|
|
14
|
-
|
|
15
|
-
{{#each categories}}
|
|
16
|
-
### {{name}}
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
{{#each functions}}
|
|
20
|
-
{{name}}{{signature}}
|
|
21
|
-
{{docstring}}
|
|
22
|
-
{{/each}}
|
|
23
|
-
```
|
|
24
|
-
{{/each}}
|
|
25
|
-
</prelude>
|
|
26
|
-
{{/if}}
|
|
27
|
-
|
|
28
|
-
<output>
|
|
29
|
-
User sees output like Jupyter notebook; rich displays render fully:
|
|
30
|
-
- `display(JSON(data))` → interactive JSON tree
|
|
31
|
-
- `display(HTML(…))` → rendered HTML
|
|
32
|
-
- `display(Markdown(…))` → formatted markdown
|
|
33
|
-
- `plt.show()` → inline figures
|
|
34
|
-
|
|
35
|
-
**You will see object repr** (e.g., `<IPython.core.display.JSON object>`). Trust `display()`; you **MUST NOT** assume the user sees only the repr.
|
|
36
|
-
</output>
|
|
37
|
-
|
|
38
|
-
<caution>
|
|
39
|
-
- Per-call mode uses a fresh kernel each call
|
|
40
|
-
- You **MUST** use `reset: true` to clear state when session mode is active
|
|
41
|
-
</caution>
|
|
42
|
-
|
|
43
|
-
<critical>
|
|
44
|
-
- You **MUST** use `run()` for shell commands; you **MUST NOT** use raw `subprocess`
|
|
45
|
-
</critical>
|
|
46
|
-
|
|
47
|
-
<examples>
|
|
48
|
-
# Multiple small cells
|
|
49
|
-
```python
|
|
50
|
-
cells: [
|
|
51
|
-
{"title": "imports", "code": "import json\nfrom pathlib import Path"},
|
|
52
|
-
{"title": "parse helper", "code": "def parse_config(path):\n return json.loads(Path(path).read_text())"},
|
|
53
|
-
{"title": "test helper", "code": "parse_config('config.json')"},
|
|
54
|
-
{"title": "use helper", "code": "configs = [parse_config(p) for p in Path('.').glob('*.json')]"}
|
|
55
|
-
]
|
|
56
|
-
```
|
|
57
|
-
</examples>
|