@oh-my-pi/pi-coding-agent 15.12.2 → 15.12.4
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 +49 -1
- package/dist/cli.js +1121 -871
- package/dist/types/autoresearch/tools/init-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/log-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/run-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/update-notes.d.ts +1 -1
- package/dist/types/cli/args.d.ts +0 -1
- package/dist/types/cli/models-cli.d.ts +49 -0
- package/dist/types/commands/launch.d.ts +0 -3
- package/dist/types/commands/models.d.ts +33 -0
- package/dist/types/commands/token.d.ts +25 -0
- package/dist/types/commit/agentic/tools/analyze-file.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-file-diff.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-hunk.d.ts +1 -1
- package/dist/types/commit/agentic/tools/git-overview.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-changelog.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +1 -1
- package/dist/types/commit/agentic/tools/recent-commits.d.ts +1 -1
- package/dist/types/commit/agentic/tools/schemas.d.ts +1 -1
- package/dist/types/commit/agentic/tools/split-commit.d.ts +1 -1
- package/dist/types/commit/changelog/generate.d.ts +1 -1
- package/dist/types/commit/shared-llm.d.ts +1 -1
- package/dist/types/config/model-registry.d.ts +7 -0
- package/dist/types/config/models-config-schema.d.ts +1 -1
- package/dist/types/config/settings-schema.d.ts +21 -1
- package/dist/types/edit/hashline/params.d.ts +1 -1
- package/dist/types/edit/modes/apply-patch.d.ts +1 -1
- package/dist/types/edit/modes/patch.d.ts +1 -1
- package/dist/types/edit/modes/replace.d.ts +1 -1
- package/dist/types/extensibility/custom-commands/types.d.ts +2 -2
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
- package/dist/types/extensibility/extensions/types.d.ts +2 -2
- package/dist/types/extensibility/hooks/types.d.ts +2 -2
- package/dist/types/goals/tools/goal-tool.d.ts +1 -1
- package/dist/types/lsp/types.d.ts +1 -1
- package/dist/types/mcp/manager.d.ts +8 -0
- package/dist/types/mnemopi/config.d.ts +28 -0
- package/dist/types/modes/acp/acp-agent.d.ts +1 -2
- package/dist/types/modes/components/index.d.ts +1 -0
- package/dist/types/modes/components/logout-account-selector.d.ts +8 -0
- package/dist/types/modes/components/status-line/component.d.ts +9 -5
- package/dist/types/modes/components/status-line/types.d.ts +2 -1
- package/dist/types/modes/controllers/event-controller.d.ts +0 -17
- package/dist/types/modes/interactive-mode.d.ts +0 -3
- package/dist/types/modes/types.d.ts +0 -5
- package/dist/types/session/agent-session.d.ts +14 -33
- package/dist/types/session/agent-storage.d.ts +2 -1
- package/dist/types/session/indexed-session-storage.d.ts +1 -0
- package/dist/types/session/messages.d.ts +8 -10
- package/dist/types/session/session-manager.d.ts +15 -0
- package/dist/types/session/session-storage.d.ts +5 -0
- package/dist/types/slash-commands/helpers/logout.d.ts +15 -0
- package/dist/types/task/types.d.ts +1 -1
- package/dist/types/tools/ask.d.ts +1 -1
- package/dist/types/tools/ast-edit.d.ts +1 -1
- package/dist/types/tools/ast-grep.d.ts +1 -1
- package/dist/types/tools/bash.d.ts +1 -1
- package/dist/types/tools/browser/cmux/cmux-tab.d.ts +202 -0
- package/dist/types/tools/browser/cmux/rpc.d.ts +70 -0
- package/dist/types/tools/browser/cmux/socket-client.d.ts +19 -0
- package/dist/types/tools/browser/registry.d.ts +16 -3
- package/dist/types/tools/browser/render.d.ts +2 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +2 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +16 -4
- package/dist/types/tools/browser.d.ts +3 -1
- package/dist/types/tools/checkpoint.d.ts +1 -1
- package/dist/types/tools/debug.d.ts +1 -1
- package/dist/types/tools/eval.d.ts +1 -1
- package/dist/types/tools/find.d.ts +1 -1
- package/dist/types/tools/gh.d.ts +1 -1
- package/dist/types/tools/image-gen.d.ts +1 -1
- package/dist/types/tools/index.d.ts +3 -1
- package/dist/types/tools/inspect-image.d.ts +1 -1
- package/dist/types/tools/irc.d.ts +1 -1
- package/dist/types/tools/job.d.ts +1 -1
- package/dist/types/tools/memory-edit.d.ts +1 -1
- package/dist/types/tools/memory-recall.d.ts +1 -1
- package/dist/types/tools/memory-reflect.d.ts +1 -1
- package/dist/types/tools/memory-retain.d.ts +1 -1
- package/dist/types/tools/read.d.ts +1 -1
- package/dist/types/tools/render-mermaid.d.ts +1 -1
- package/dist/types/tools/resolve.d.ts +1 -1
- package/dist/types/tools/review.d.ts +1 -1
- package/dist/types/tools/search-tool-bm25.d.ts +1 -1
- package/dist/types/tools/search.d.ts +1 -1
- package/dist/types/tools/ssh.d.ts +1 -1
- package/dist/types/tools/todo.d.ts +1 -1
- package/dist/types/tools/tts.d.ts +1 -1
- package/dist/types/tools/write.d.ts +1 -1
- package/dist/types/utils/clipboard.d.ts +4 -3
- package/dist/types/utils/image-loading.d.ts +18 -1
- package/dist/types/utils/thinking-display.d.ts +17 -0
- package/dist/types/web/search/index.d.ts +1 -1
- package/package.json +14 -14
- package/src/autoresearch/storage.ts +2 -1
- package/src/autoresearch/tools/init-experiment.ts +1 -1
- package/src/autoresearch/tools/log-experiment.ts +1 -1
- package/src/autoresearch/tools/run-experiment.ts +1 -1
- package/src/autoresearch/tools/update-notes.ts +1 -1
- package/src/cli/args.ts +0 -8
- package/src/cli/auth-gateway-cli.ts +1 -1
- package/src/cli/bench-cli.ts +1 -1
- package/src/cli/dry-balance-cli.ts +1 -1
- package/src/cli/models-cli.ts +427 -0
- package/src/cli-commands.ts +2 -0
- package/src/collab/host.ts +9 -12
- package/src/commands/launch.ts +0 -3
- package/src/commands/models.ts +61 -0
- package/src/commands/token.ts +89 -0
- package/src/commit/agentic/tools/analyze-file.ts +1 -1
- package/src/commit/agentic/tools/git-file-diff.ts +1 -1
- package/src/commit/agentic/tools/git-hunk.ts +1 -1
- package/src/commit/agentic/tools/git-overview.ts +1 -1
- package/src/commit/agentic/tools/propose-changelog.ts +1 -1
- package/src/commit/agentic/tools/propose-commit.ts +1 -1
- package/src/commit/agentic/tools/recent-commits.ts +1 -1
- package/src/commit/agentic/tools/schemas.ts +1 -1
- package/src/commit/agentic/tools/split-commit.ts +1 -1
- package/src/commit/analysis/summary.ts +1 -1
- package/src/commit/changelog/generate.ts +1 -1
- package/src/commit/shared-llm.ts +1 -1
- package/src/config/model-registry.ts +15 -12
- package/src/config/model-resolver.ts +2 -2
- package/src/config/models-config-schema.ts +1 -1
- package/src/config/settings-schema.ts +19 -1
- package/src/edit/hashline/params.ts +1 -1
- package/src/edit/modes/apply-patch.ts +1 -1
- package/src/edit/modes/patch.ts +1 -1
- package/src/edit/modes/replace.ts +1 -1
- package/src/eval/agent-bridge.ts +1 -1
- package/src/eval/completion-bridge.ts +1 -1
- package/src/export/html/template.js +24 -2
- package/src/export/html/tool-views.generated.js +2 -2
- package/src/extensibility/custom-commands/loader.ts +1 -1
- package/src/extensibility/custom-commands/types.ts +2 -2
- package/src/extensibility/custom-tools/loader.ts +1 -1
- package/src/extensibility/custom-tools/types.ts +2 -2
- package/src/extensibility/extensions/loader.ts +2 -2
- package/src/extensibility/extensions/types.ts +2 -2
- package/src/extensibility/hooks/loader.ts +1 -1
- package/src/extensibility/hooks/types.ts +2 -2
- package/src/extensibility/skills.ts +18 -3
- package/src/goals/tools/goal-tool.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +6 -3
- package/src/lsp/types.ts +1 -1
- package/src/main.ts +0 -25
- package/src/mcp/config-writer.ts +7 -3
- package/src/mcp/manager.ts +11 -0
- package/src/memories/index.ts +3 -1
- package/src/memories/storage.ts +2 -1
- package/src/mnemopi/config.ts +95 -11
- package/src/modes/acp/acp-agent.ts +5 -48
- package/src/modes/acp/acp-event-mapper.ts +5 -1
- package/src/modes/components/agent-hub.ts +2 -1
- package/src/modes/components/assistant-message.ts +8 -7
- package/src/modes/components/index.ts +1 -0
- package/src/modes/components/logout-account-selector.ts +130 -0
- package/src/modes/components/mcp-add-wizard.ts +1 -1
- package/src/modes/components/model-selector.ts +2 -2
- package/src/modes/components/status-line/component.ts +54 -157
- package/src/modes/components/status-line/segments.ts +1 -1
- package/src/modes/components/status-line/types.ts +2 -1
- package/src/modes/controllers/command-controller.ts +0 -12
- package/src/modes/controllers/event-controller.ts +23 -62
- package/src/modes/controllers/input-controller.ts +60 -31
- package/src/modes/controllers/mcp-command-controller.ts +44 -3
- package/src/modes/controllers/selector-controller.ts +56 -10
- package/src/modes/controllers/streaming-reveal.ts +4 -3
- package/src/modes/interactive-mode.ts +2 -8
- package/src/modes/theme/theme.ts +1 -1
- package/src/modes/types.ts +0 -5
- package/src/modes/utils/ui-helpers.ts +2 -1
- package/src/prompts/system/empty-stop-retry.md +4 -6
- package/src/sdk.ts +15 -19
- package/src/session/agent-session.ts +125 -234
- package/src/session/agent-storage.ts +18 -9
- package/src/session/history-storage.ts +2 -1
- package/src/session/indexed-session-storage.ts +7 -0
- package/src/session/messages.ts +9 -11
- package/src/session/session-dump-format.ts +4 -2
- package/src/session/session-manager.ts +116 -0
- package/src/session/session-storage.ts +20 -0
- package/src/slash-commands/builtin-registry.ts +15 -1
- package/src/slash-commands/helpers/logout.ts +88 -0
- package/src/task/types.ts +1 -1
- package/src/tools/ask.ts +1 -1
- package/src/tools/ast-edit.ts +13 -4
- package/src/tools/ast-grep.ts +1 -1
- package/src/tools/bash.ts +1 -1
- package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
- package/src/tools/browser/cmux/rpc.ts +156 -0
- package/src/tools/browser/cmux/socket-client.ts +309 -0
- package/src/tools/browser/registry.ts +37 -3
- package/src/tools/browser/render.ts +6 -1
- package/src/tools/browser/tab-protocol.ts +2 -0
- package/src/tools/browser/tab-supervisor.ts +189 -18
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/browser.ts +16 -1
- package/src/tools/checkpoint.ts +1 -1
- package/src/tools/debug.ts +1 -1
- package/src/tools/eval.ts +11 -6
- package/src/tools/fetch.ts +13 -2
- package/src/tools/find.ts +1 -1
- package/src/tools/gh.ts +1 -1
- package/src/tools/github-cache.ts +2 -1
- package/src/tools/image-gen.ts +1 -1
- package/src/tools/index.ts +3 -1
- package/src/tools/inspect-image.ts +3 -1
- package/src/tools/irc.ts +1 -1
- package/src/tools/job.ts +1 -1
- package/src/tools/memory-edit.ts +1 -1
- package/src/tools/memory-recall.ts +1 -1
- package/src/tools/memory-reflect.ts +1 -1
- package/src/tools/memory-retain.ts +1 -1
- package/src/tools/read.ts +8 -2
- package/src/tools/render-mermaid.ts +1 -1
- package/src/tools/report-tool-issue.ts +3 -2
- package/src/tools/resolve.ts +1 -1
- package/src/tools/review.ts +1 -1
- package/src/tools/search-tool-bm25.ts +1 -1
- package/src/tools/search.ts +1 -1
- package/src/tools/ssh.ts +1 -1
- package/src/tools/todo.ts +1 -1
- package/src/tools/tts.ts +1 -1
- package/src/tools/write.ts +1 -1
- package/src/utils/clipboard.ts +35 -18
- package/src/utils/image-loading.ts +35 -4
- package/src/utils/thinking-display.ts +37 -0
- package/src/web/search/index.ts +1 -1
- package/dist/types/cli/list-models.d.ts +0 -30
- package/src/cli/list-models.ts +0 -194
package/src/tools/read.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
9
9
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
10
10
|
import { getRemoteDir, logger, prompt, readImageMetadata, untilAborted } from "@oh-my-pi/pi-utils";
|
|
11
11
|
import { LRUCache } from "lru-cache/raw";
|
|
12
|
-
import
|
|
12
|
+
import { z } from "zod/v4";
|
|
13
13
|
import {
|
|
14
14
|
canonicalSnapshotKey,
|
|
15
15
|
getFileSnapshotStore,
|
|
@@ -38,7 +38,12 @@ import { fileHyperlink, renderCodeCell, renderMarkdownCell, renderStatusLine, tr
|
|
|
38
38
|
import { CachedOutputBlock, markFramedBlockComponent } from "../tui/output-block";
|
|
39
39
|
import { buildLineEntriesWithBlockContext, type LineEntry, lineEntriesToPlainText } from "../utils/block-context";
|
|
40
40
|
import { resolveFileDisplayMode } from "../utils/file-display-mode";
|
|
41
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
ImageInputTooLargeError,
|
|
43
|
+
loadImageInput,
|
|
44
|
+
MAX_IMAGE_INPUT_BYTES,
|
|
45
|
+
webpExclusionForModel,
|
|
46
|
+
} from "../utils/image-loading";
|
|
42
47
|
import { convertFileWithMarkit } from "../utils/markit";
|
|
43
48
|
import { buildDirectoryTree, type DirectoryTree } from "../workspace-tree";
|
|
44
49
|
import { type ArchiveReader, formatArchiveEntryLines, openArchive, parseArchivePathCandidates } from "./archive-reader";
|
|
@@ -1974,6 +1979,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1974
1979
|
maxBytes: MAX_IMAGE_SIZE,
|
|
1975
1980
|
resolvedPath: absolutePath,
|
|
1976
1981
|
detectedMimeType: mimeType,
|
|
1982
|
+
excludeWebP: webpExclusionForModel(this.session.getActiveModel?.()),
|
|
1977
1983
|
});
|
|
1978
1984
|
if (!imageInput) {
|
|
1979
1985
|
throw new ToolError(`Read image file [${mimeType}] failed: unsupported image format.`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import { type MermaidAsciiRenderOptions, prompt, renderMermaidAscii } from "@oh-my-pi/pi-utils";
|
|
3
|
-
import
|
|
3
|
+
import { z } from "zod/v4";
|
|
4
4
|
import renderMermaidDescription from "../prompts/tools/render-mermaid.md" with { type: "text" };
|
|
5
5
|
import type { ToolSession } from "./index";
|
|
6
6
|
|
|
@@ -24,7 +24,7 @@ import path from "node:path";
|
|
|
24
24
|
import type { AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
25
25
|
import type { FetchImpl } from "@oh-my-pi/pi-ai";
|
|
26
26
|
import { $env, $flag, getAgentDir, getInstallId, logger, VERSION } from "@oh-my-pi/pi-utils";
|
|
27
|
-
import
|
|
27
|
+
import { z } from "zod/v4";
|
|
28
28
|
import type { Settings } from "..";
|
|
29
29
|
import type { ToolSession } from "./index";
|
|
30
30
|
|
|
@@ -206,10 +206,11 @@ export function openAutoQaDb(): Database | null {
|
|
|
206
206
|
if (cachedDb) return cachedDb;
|
|
207
207
|
try {
|
|
208
208
|
const db = new Database(getAutoQaDbPath());
|
|
209
|
+
// Install the busy handler BEFORE any lock-taking statement. See #2421.
|
|
210
|
+
db.run("PRAGMA busy_timeout = 5000");
|
|
209
211
|
db.run(`
|
|
210
212
|
PRAGMA journal_mode=WAL;
|
|
211
213
|
PRAGMA synchronous=NORMAL;
|
|
212
|
-
PRAGMA busy_timeout=5000;
|
|
213
214
|
CREATE TABLE IF NOT EXISTS grievances (
|
|
214
215
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
215
216
|
model TEXT NOT NULL,
|
package/src/tools/resolve.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
|
|
|
2
2
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
3
3
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
|
|
5
|
-
import
|
|
5
|
+
import { z } from "zod/v4";
|
|
6
6
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
7
7
|
import type { Theme } from "../modes/theme/theme";
|
|
8
8
|
import resolveDescription from "../prompts/tools/resolve.md" with { type: "text" };
|
package/src/tools/review.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type { AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
|
12
12
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
13
13
|
import { Container, Text } from "@oh-my-pi/pi-tui";
|
|
14
14
|
import { isRecord } from "@oh-my-pi/pi-utils";
|
|
15
|
-
import
|
|
15
|
+
import { z } from "zod/v4";
|
|
16
16
|
import type { Theme, ThemeColor } from "../modes/theme/theme";
|
|
17
17
|
import { subprocessToolRegistry } from "../task/subprocess-tool-registry";
|
|
18
18
|
import type { ReviewFinding } from "../task/types";
|
|
@@ -2,7 +2,7 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
|
|
|
2
2
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
3
3
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import { prompt } from "@oh-my-pi/pi-utils";
|
|
5
|
-
import
|
|
5
|
+
import { z } from "zod/v4";
|
|
6
6
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
7
7
|
import type { Theme } from "../modes/theme/theme";
|
|
8
8
|
import searchToolBm25Description from "../prompts/tools/search-tool-bm25.md" with { type: "text" };
|
package/src/tools/search.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { type GrepMatch, GrepOutputMode, type GrepResult, grep } from "@oh-my-pi
|
|
|
7
7
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
8
8
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
9
9
|
import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
|
|
10
|
-
import
|
|
10
|
+
import { z } from "zod/v4";
|
|
11
11
|
import { recordFileSnapshot } from "../edit/file-snapshot-store";
|
|
12
12
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
13
13
|
import type { LocalProtocolOptions } from "../internal-urls/local-protocol";
|
package/src/tools/ssh.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
3
3
|
import { prompt } from "@oh-my-pi/pi-utils";
|
|
4
|
-
import
|
|
4
|
+
import { z } from "zod/v4";
|
|
5
5
|
import type { SSHHost } from "../capability/ssh";
|
|
6
6
|
import { sshCapability } from "../capability/ssh";
|
|
7
7
|
import { loadCapability } from "../discovery";
|
package/src/tools/todo.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
3
3
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import { prompt } from "@oh-my-pi/pi-utils";
|
|
5
5
|
import chalk from "chalk";
|
|
6
|
-
import
|
|
6
|
+
import { z } from "zod/v4";
|
|
7
7
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
8
8
|
import type { Theme } from "../modes/theme/theme";
|
|
9
9
|
import todoDescription from "../prompts/tools/todo.md" with { type: "text" };
|
package/src/tools/tts.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
4
4
|
import { type ApiKey, ProviderHttpError, withAuth } from "@oh-my-pi/pi-ai";
|
|
5
|
-
import
|
|
5
|
+
import { z } from "zod/v4";
|
|
6
6
|
import type { CustomTool, CustomToolContext } from "../extensibility/custom-tools/types";
|
|
7
7
|
import { ohMyPiXAIUserAgent, resolveXAIHttpCredentials } from "../lib/xai-http";
|
|
8
8
|
import { formatPathRelativeToCwd, resolveToCwd } from "./path-utils";
|
package/src/tools/write.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { formatHashlineHeader, stripHashlinePrefixes } from "@oh-my-pi/hashline"
|
|
|
6
6
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
7
7
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
8
8
|
import { isEnoent, isRecord, prompt, untilAborted } from "@oh-my-pi/pi-utils";
|
|
9
|
-
import
|
|
9
|
+
import { z } from "zod/v4";
|
|
10
10
|
|
|
11
11
|
import { canonicalSnapshotKey, getFileSnapshotStore } from "../edit/file-snapshot-store";
|
|
12
12
|
import { normalizeToLF } from "../edit/normalize";
|
package/src/utils/clipboard.ts
CHANGED
|
@@ -66,9 +66,10 @@ export async function copyToClipboard(text: string): Promise<void> {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
// PowerShell one-liner that emits the clipboard image as base64-encoded
|
|
70
|
-
// stdout, or nothing when the clipboard does not hold image data. Used
|
|
71
|
-
//
|
|
69
|
+
// PowerShell one-liner that emits the Windows clipboard image as base64-encoded
|
|
70
|
+
// PNG on stdout, or nothing when the clipboard does not hold image data. Used
|
|
71
|
+
// for native Windows fallback and WSL interop because arboard can miss host
|
|
72
|
+
// clipboard image payloads in those terminal paths.
|
|
72
73
|
const POWERSHELL_IMAGE_SCRIPT = `
|
|
73
74
|
$ErrorActionPreference = 'Stop'
|
|
74
75
|
Add-Type -AssemblyName System.Windows.Forms
|
|
@@ -84,31 +85,36 @@ if ($img -ne $null) {
|
|
|
84
85
|
const POWERSHELL_TIMEOUT_MS = 8000;
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
|
-
* Read
|
|
88
|
+
* Read an image through the Windows host's PowerShell.
|
|
88
89
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
90
|
+
* Native Windows uses this as a fallback when arboard reports no image or
|
|
91
|
+
* cannot access the clipboard. WSLg exposes a Wayland socket but no native
|
|
92
|
+
* clipboard image transport, so arboard returns `ContentNotAvailable` there;
|
|
93
|
+
* PowerShell, reached via WSL interop, can read the Windows clipboard directly
|
|
94
|
+
* and round-trip the bitmap as PNG.
|
|
92
95
|
*
|
|
93
96
|
* Returns null when no image is on the clipboard, the host PowerShell is
|
|
94
97
|
* missing, or the bridge times out.
|
|
95
98
|
*/
|
|
96
99
|
async function readImageViaPowerShell(): Promise<ClipboardImage | null> {
|
|
97
100
|
try {
|
|
98
|
-
const proc = Bun.spawn(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
const proc = Bun.spawn(
|
|
102
|
+
["powershell.exe", "-NoProfile", "-NonInteractive", "-Sta", "-Command", POWERSHELL_IMAGE_SCRIPT],
|
|
103
|
+
{
|
|
104
|
+
stdout: "pipe",
|
|
105
|
+
stderr: "ignore",
|
|
106
|
+
stdin: "ignore",
|
|
107
|
+
},
|
|
108
|
+
);
|
|
103
109
|
const timer = setTimeout(() => proc.kill(), POWERSHELL_TIMEOUT_MS);
|
|
104
110
|
let stdout = "";
|
|
105
111
|
try {
|
|
106
112
|
stdout = await new Response(proc.stdout).text();
|
|
107
113
|
await proc.exited;
|
|
108
114
|
} catch (err) {
|
|
109
|
-
// powershell.exe
|
|
110
|
-
// doesn't reap cleanly,
|
|
111
|
-
//
|
|
115
|
+
// powershell.exe can be a Windows process reached either natively or
|
|
116
|
+
// over WSL interop; if it doesn't reap cleanly, report no image instead
|
|
117
|
+
// of surfacing an opaque bridge failure to the prompt.
|
|
112
118
|
logger.warn("clipboard: powershell read failed", { error: String(err) });
|
|
113
119
|
return null;
|
|
114
120
|
} finally {
|
|
@@ -179,9 +185,10 @@ async function readTextViaPowerShell(): Promise<string | null> {
|
|
|
179
185
|
* Read an image from the system clipboard.
|
|
180
186
|
*
|
|
181
187
|
* Returns null on Termux (no image clipboard support) or when no display
|
|
182
|
-
* server is available (headless/SSH without forwarding). Under
|
|
183
|
-
* Windows clipboard is reached through `powershell.exe
|
|
184
|
-
*
|
|
188
|
+
* server is available (headless/SSH without forwarding). Under native Windows
|
|
189
|
+
* and WSL, the Windows clipboard is also reached through `powershell.exe`
|
|
190
|
+
* because terminal clipboard paths can leave image payloads invisible to the
|
|
191
|
+
* native bridge.
|
|
185
192
|
*
|
|
186
193
|
* @returns PNG payload or null when no image is available.
|
|
187
194
|
*/
|
|
@@ -198,6 +205,16 @@ export async function readImageFromClipboard(): Promise<ClipboardImage | null> {
|
|
|
198
205
|
// no display, so arboard would reject anyway.
|
|
199
206
|
}
|
|
200
207
|
|
|
208
|
+
if (process.platform === "win32") {
|
|
209
|
+
try {
|
|
210
|
+
const image = await native.readImageFromClipboard();
|
|
211
|
+
if (image) return image;
|
|
212
|
+
} catch (err) {
|
|
213
|
+
logger.warn("clipboard: native Windows image read failed", { error: String(err) });
|
|
214
|
+
}
|
|
215
|
+
return await readImageViaPowerShell();
|
|
216
|
+
}
|
|
217
|
+
|
|
201
218
|
if (!hasDisplay()) {
|
|
202
219
|
return null;
|
|
203
220
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
|
-
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { ImageContent, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import { formatBytes, readImageMetadata, SUPPORTED_IMAGE_MIME_TYPES } from "@oh-my-pi/pi-utils";
|
|
4
4
|
import { resolveReadPath } from "../tools/path-utils";
|
|
5
5
|
import { formatDimensionNote, type ImageResizeOptions, resizeImage } from "./image-resize";
|
|
@@ -7,6 +7,26 @@ import { formatDimensionNote, type ImageResizeOptions, resizeImage } from "./ima
|
|
|
7
7
|
export const MAX_IMAGE_INPUT_BYTES = 20 * 1024 * 1024;
|
|
8
8
|
export const SUPPORTED_INPUT_IMAGE_MIME_TYPES = SUPPORTED_IMAGE_MIME_TYPES;
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Ollama and its local-backend family decode image input through llama.cpp /
|
|
12
|
+
* `stb_image`, which is compiled without WebP support, so a WebP upload fails
|
|
13
|
+
* with an opaque HTTP 400. Detect those models so the resize pipeline encodes
|
|
14
|
+
* to PNG/JPEG instead — the automatic equivalent of `OMP_NO_WEBP=1`.
|
|
15
|
+
*/
|
|
16
|
+
export function modelLacksWebpSupport(model: Pick<Model, "provider" | "api"> | undefined): boolean {
|
|
17
|
+
if (!model) return false;
|
|
18
|
+
return model.provider === "ollama" || model.provider === "ollama-cloud" || model.api === "ollama-chat";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* `true` when `model` cannot decode WebP, otherwise `undefined` so the
|
|
23
|
+
* `OMP_NO_WEBP` env fallback in {@link resizeImage} still applies. Feed straight
|
|
24
|
+
* into {@link ImageResizeOptions.excludeWebP}.
|
|
25
|
+
*/
|
|
26
|
+
export function webpExclusionForModel(model: Pick<Model, "provider" | "api"> | undefined): true | undefined {
|
|
27
|
+
return modelLacksWebpSupport(model) ? true : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
10
30
|
export interface LoadImageInputOptions {
|
|
11
31
|
path: string;
|
|
12
32
|
cwd: string;
|
|
@@ -14,6 +34,8 @@ export interface LoadImageInputOptions {
|
|
|
14
34
|
maxBytes?: number;
|
|
15
35
|
resolvedPath?: string;
|
|
16
36
|
detectedMimeType?: string;
|
|
37
|
+
/** Force non-WebP output (e.g. for Ollama). Leave unset to honor `OMP_NO_WEBP`. */
|
|
38
|
+
excludeWebP?: boolean;
|
|
17
39
|
}
|
|
18
40
|
|
|
19
41
|
export interface LoadedImageInput {
|
|
@@ -51,6 +73,8 @@ export async function ensureSupportedImageInput(image: ImageContent): Promise<Im
|
|
|
51
73
|
}
|
|
52
74
|
|
|
53
75
|
export interface NormalizeModelContextImagesOptions {
|
|
76
|
+
/** Model the images are bound for; used to derive encoder constraints (WebP exclusion for Ollama). */
|
|
77
|
+
model?: Model;
|
|
54
78
|
resize?: ImageResizeOptions;
|
|
55
79
|
}
|
|
56
80
|
|
|
@@ -66,10 +90,13 @@ export async function normalizeModelContextImages(
|
|
|
66
90
|
options?: NormalizeModelContextImagesOptions,
|
|
67
91
|
): Promise<ImageContent[] | undefined> {
|
|
68
92
|
if (!images || images.length === 0) return undefined;
|
|
93
|
+
const resize: ImageResizeOptions | undefined = modelLacksWebpSupport(options?.model)
|
|
94
|
+
? { ...options?.resize, excludeWebP: true }
|
|
95
|
+
: options?.resize;
|
|
69
96
|
const normalized: ImageContent[] = [];
|
|
70
97
|
for (const image of images) {
|
|
71
98
|
try {
|
|
72
|
-
const resized = await resizeImage(image,
|
|
99
|
+
const resized = await resizeImage(image, resize);
|
|
73
100
|
normalized.push({ type: "image", data: resized.data, mimeType: resized.mimeType });
|
|
74
101
|
} catch {
|
|
75
102
|
// Preserve existing caller behavior for decode/resize failures: keep the
|
|
@@ -104,9 +131,13 @@ export async function loadImageInput(options: LoadImageInputOptions): Promise<Lo
|
|
|
104
131
|
let outputBytes = inputBuffer.byteLength;
|
|
105
132
|
let dimensionNote: string | undefined;
|
|
106
133
|
|
|
107
|
-
|
|
134
|
+
const shouldReencodeWebP = options.excludeWebP === true && mimeType === "image/webp";
|
|
135
|
+
if (options.autoResize || shouldReencodeWebP) {
|
|
108
136
|
try {
|
|
109
|
-
const resized = await resizeImage(
|
|
137
|
+
const resized = await resizeImage(
|
|
138
|
+
{ type: "image", data: outputData, mimeType },
|
|
139
|
+
{ excludeWebP: options.excludeWebP },
|
|
140
|
+
);
|
|
110
141
|
outputData = resized.data;
|
|
111
142
|
outputMimeType = resized.mimeType;
|
|
112
143
|
outputBytes = resized.buffer.byteLength;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
2
|
+
|
|
3
|
+
type AssistantContentBlock = AssistantMessage["content"][number];
|
|
4
|
+
type ThinkingBlock = Extract<AssistantContentBlock, { type: "thinking" }>;
|
|
5
|
+
|
|
6
|
+
function isDotOnlyThinking(text: string): boolean {
|
|
7
|
+
let sawDot = false;
|
|
8
|
+
for (let i = 0; i < text.length; i++) {
|
|
9
|
+
const code = text.charCodeAt(i);
|
|
10
|
+
if (code === 0x2e || code === 0x2026) {
|
|
11
|
+
sawDot = true;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (code === 0x20 || code === 0x09 || code === 0x0a || code === 0x0d) continue;
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return sawDot;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns the operator-visible thinking text for a block.
|
|
22
|
+
*
|
|
23
|
+
* Some OpenAI-compatible reasoning gateways require a non-empty
|
|
24
|
+
* `reasoning_content` field on historical assistant tool-call turns even when
|
|
25
|
+
* the model did not emit any reasoning. The provider adapter uses a single dot
|
|
26
|
+
* as the wire-only placeholder those gateways accept; if that value is later
|
|
27
|
+
* replayed or echoed as a thinking block, it should not render as model thought.
|
|
28
|
+
*/
|
|
29
|
+
export function getVisibleThinkingText(block: ThinkingBlock): string {
|
|
30
|
+
const text = block.thinking.trim();
|
|
31
|
+
if (text.length === 0) return "";
|
|
32
|
+
return isDotOnlyThinking(text) ? "" : text;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function hasVisibleThinking(block: ThinkingBlock): boolean {
|
|
36
|
+
return getVisibleThinkingText(block).length > 0;
|
|
37
|
+
}
|
package/src/web/search/index.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
8
8
|
import type { AuthStorage } from "@oh-my-pi/pi-ai";
|
|
9
9
|
import { prompt } from "@oh-my-pi/pi-utils";
|
|
10
|
-
import
|
|
10
|
+
import { z } from "zod/v4";
|
|
11
11
|
import type { CustomTool, CustomToolContext, RenderResultOptions } from "../../extensibility/custom-tools/types";
|
|
12
12
|
import type { Theme } from "../../modes/theme/theme";
|
|
13
13
|
import webSearchSystemPrompt from "../../prompts/system/web-search.md" with { type: "text" };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { ModelRegistry } from "../config/model-registry";
|
|
2
|
-
/**
|
|
3
|
-
* List available models, optionally filtered by search pattern
|
|
4
|
-
*/
|
|
5
|
-
export declare function listModels(modelRegistry: ModelRegistry, searchPattern?: string): Promise<void>;
|
|
6
|
-
/**
|
|
7
|
-
* Options for the `--list-models` command entry point.
|
|
8
|
-
*/
|
|
9
|
-
export interface RunListModelsOptions {
|
|
10
|
-
modelRegistry: ModelRegistry;
|
|
11
|
-
cwd: string;
|
|
12
|
-
/** CLI-supplied extension paths (e.g. from `-e <path>`). */
|
|
13
|
-
additionalExtensionPaths?: string[];
|
|
14
|
-
/** Extension paths configured under `extensions:` in user settings. */
|
|
15
|
-
settingsExtensions?: string[];
|
|
16
|
-
/** Disabled extension ids from settings (`disabledExtensions`). */
|
|
17
|
-
disabledExtensionIds?: string[];
|
|
18
|
-
/** When true, skip discovery and only load `additionalExtensionPaths`. */
|
|
19
|
-
disableExtensionDiscovery?: boolean;
|
|
20
|
-
searchPattern?: string;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Loads extensions (CLI `-e` paths and `settings.extensions`) and surfaces
|
|
24
|
-
* any provider/model registrations on the supplied `modelRegistry` before
|
|
25
|
-
* delegating to {@link listModels}. This is the single entry point used by
|
|
26
|
-
* `--list-models` and exists to ensure extension-contributed providers are
|
|
27
|
-
* visible in the listing (issue #905). The load is intentionally narrow:
|
|
28
|
-
* no agent loop, no MCP servers, no custom-tool registration.
|
|
29
|
-
*/
|
|
30
|
-
export declare function runListModelsCommand(options: RunListModelsOptions): Promise<void>;
|
package/src/cli/list-models.ts
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* List available models with optional fuzzy search
|
|
3
|
-
*/
|
|
4
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
5
|
-
import { getSupportedEfforts } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
6
|
-
import { fuzzyFilter } from "@oh-my-pi/pi-tui";
|
|
7
|
-
import { formatNumber } from "@oh-my-pi/pi-utils";
|
|
8
|
-
import type { ModelRegistry } from "../config/model-registry";
|
|
9
|
-
import { discoverAndLoadExtensions, loadExtensions } from "../extensibility/extensions";
|
|
10
|
-
import { EventBus } from "../utils/event-bus";
|
|
11
|
-
|
|
12
|
-
interface ProviderRow {
|
|
13
|
-
provider: string;
|
|
14
|
-
model: string;
|
|
15
|
-
context: string;
|
|
16
|
-
maxOut: string;
|
|
17
|
-
thinking: string;
|
|
18
|
-
images: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface CanonicalRow {
|
|
22
|
-
canonical: string;
|
|
23
|
-
selected: string;
|
|
24
|
-
variants: string;
|
|
25
|
-
context: string;
|
|
26
|
-
maxOut: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function writeLine(line = ""): void {
|
|
30
|
-
process.stdout.write(`${line}\n`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function renderTable<T extends Record<string, string>>(rows: T[], headers: T): void {
|
|
34
|
-
const widths = Object.fromEntries(
|
|
35
|
-
Object.keys(headers).map(key => [key, Math.max(headers[key]!.length, ...rows.map(row => row[key]!.length))]),
|
|
36
|
-
) as Record<keyof T, number>;
|
|
37
|
-
|
|
38
|
-
const headerLine = Object.keys(headers)
|
|
39
|
-
.map(key => headers[key as keyof T]!.padEnd(widths[key as keyof T]))
|
|
40
|
-
.join(" ");
|
|
41
|
-
writeLine(headerLine);
|
|
42
|
-
|
|
43
|
-
for (const row of rows) {
|
|
44
|
-
const line = Object.keys(headers)
|
|
45
|
-
.map(key => row[key as keyof T]!.padEnd(widths[key as keyof T]))
|
|
46
|
-
.join(" ");
|
|
47
|
-
writeLine(line);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* List available models, optionally filtered by search pattern
|
|
53
|
-
*/
|
|
54
|
-
export async function listModels(modelRegistry: ModelRegistry, searchPattern?: string): Promise<void> {
|
|
55
|
-
const models = modelRegistry.getAvailable();
|
|
56
|
-
|
|
57
|
-
if (models.length === 0) {
|
|
58
|
-
writeLine("No models available. Set API keys in environment variables.");
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
let filteredModels: Model<Api>[] = models;
|
|
63
|
-
if (searchPattern) {
|
|
64
|
-
filteredModels = fuzzyFilter(models, searchPattern, model => `${model.provider} ${model.id}`);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const filteredCanonical = modelRegistry
|
|
68
|
-
.getCanonicalModelSelections({ availableOnly: true, candidates: filteredModels })
|
|
69
|
-
.map(
|
|
70
|
-
({ record, model: selected }): CanonicalRow => ({
|
|
71
|
-
canonical: record.id,
|
|
72
|
-
selected: `${selected.provider}/${selected.id}`,
|
|
73
|
-
variants: String(record.variants.length),
|
|
74
|
-
context: formatNumber(selected.contextWindow),
|
|
75
|
-
maxOut: formatNumber(selected.maxTokens),
|
|
76
|
-
}),
|
|
77
|
-
)
|
|
78
|
-
.sort((left, right) => left.canonical.localeCompare(right.canonical));
|
|
79
|
-
|
|
80
|
-
if (filteredModels.length === 0 && filteredCanonical.length === 0) {
|
|
81
|
-
writeLine(`No models matching "${searchPattern}"`);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
filteredModels.sort((left, right) => {
|
|
86
|
-
const providerCmp = left.provider.localeCompare(right.provider);
|
|
87
|
-
if (providerCmp !== 0) return providerCmp;
|
|
88
|
-
return left.id.localeCompare(right.id);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const providerRows = filteredModels.map(model => ({
|
|
92
|
-
provider: model.provider,
|
|
93
|
-
model: model.id,
|
|
94
|
-
context: formatNumber(model.contextWindow),
|
|
95
|
-
maxOut: formatNumber(model.maxTokens),
|
|
96
|
-
thinking: model.thinking ? getSupportedEfforts(model).join(",") : model.reasoning ? "yes" : "-",
|
|
97
|
-
images: model.input.includes("image") ? "yes" : "no",
|
|
98
|
-
})) satisfies ProviderRow[];
|
|
99
|
-
|
|
100
|
-
if (filteredCanonical.length > 0) {
|
|
101
|
-
writeLine("Canonical models");
|
|
102
|
-
renderTable(filteredCanonical, {
|
|
103
|
-
canonical: "canonical",
|
|
104
|
-
selected: "selected",
|
|
105
|
-
variants: "variants",
|
|
106
|
-
context: "context",
|
|
107
|
-
maxOut: "max-out",
|
|
108
|
-
});
|
|
109
|
-
if (providerRows.length > 0) {
|
|
110
|
-
writeLine();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (providerRows.length > 0) {
|
|
115
|
-
writeLine("Provider models");
|
|
116
|
-
renderTable(providerRows, {
|
|
117
|
-
provider: "provider",
|
|
118
|
-
model: "model",
|
|
119
|
-
context: "context",
|
|
120
|
-
maxOut: "max-out",
|
|
121
|
-
thinking: "thinking",
|
|
122
|
-
images: "images",
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Options for the `--list-models` command entry point.
|
|
129
|
-
*/
|
|
130
|
-
export interface RunListModelsOptions {
|
|
131
|
-
modelRegistry: ModelRegistry;
|
|
132
|
-
cwd: string;
|
|
133
|
-
/** CLI-supplied extension paths (e.g. from `-e <path>`). */
|
|
134
|
-
additionalExtensionPaths?: string[];
|
|
135
|
-
/** Extension paths configured under `extensions:` in user settings. */
|
|
136
|
-
settingsExtensions?: string[];
|
|
137
|
-
/** Disabled extension ids from settings (`disabledExtensions`). */
|
|
138
|
-
disabledExtensionIds?: string[];
|
|
139
|
-
/** When true, skip discovery and only load `additionalExtensionPaths`. */
|
|
140
|
-
disableExtensionDiscovery?: boolean;
|
|
141
|
-
searchPattern?: string;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Loads extensions (CLI `-e` paths and `settings.extensions`) and surfaces
|
|
146
|
-
* any provider/model registrations on the supplied `modelRegistry` before
|
|
147
|
-
* delegating to {@link listModels}. This is the single entry point used by
|
|
148
|
-
* `--list-models` and exists to ensure extension-contributed providers are
|
|
149
|
-
* visible in the listing (issue #905). The load is intentionally narrow:
|
|
150
|
-
* no agent loop, no MCP servers, no custom-tool registration.
|
|
151
|
-
*/
|
|
152
|
-
export async function runListModelsCommand(options: RunListModelsOptions): Promise<void> {
|
|
153
|
-
const {
|
|
154
|
-
modelRegistry,
|
|
155
|
-
cwd,
|
|
156
|
-
additionalExtensionPaths = [],
|
|
157
|
-
settingsExtensions = [],
|
|
158
|
-
disabledExtensionIds = [],
|
|
159
|
-
disableExtensionDiscovery = false,
|
|
160
|
-
searchPattern,
|
|
161
|
-
} = options;
|
|
162
|
-
|
|
163
|
-
const eventBus = new EventBus();
|
|
164
|
-
const extensionsResult = disableExtensionDiscovery
|
|
165
|
-
? await loadExtensions(additionalExtensionPaths, cwd, eventBus)
|
|
166
|
-
: await discoverAndLoadExtensions(
|
|
167
|
-
[...additionalExtensionPaths, ...settingsExtensions],
|
|
168
|
-
cwd,
|
|
169
|
-
eventBus,
|
|
170
|
-
disabledExtensionIds,
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
for (const { path: extPath, error } of extensionsResult.errors) {
|
|
174
|
-
process.stderr.write(`Failed to load extension: ${extPath}: ${error}\n`);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Mirror sdk.ts: drain pending provider registrations into the registry.
|
|
178
|
-
const activeSources = extensionsResult.extensions.map(extension => extension.path);
|
|
179
|
-
modelRegistry.syncExtensionSources(activeSources);
|
|
180
|
-
for (const sourceId of new Set(activeSources)) {
|
|
181
|
-
modelRegistry.clearSourceRegistrations(sourceId);
|
|
182
|
-
}
|
|
183
|
-
for (const { name, config, sourceId } of extensionsResult.runtime.pendingProviderRegistrations) {
|
|
184
|
-
modelRegistry.registerProvider(name, config, sourceId);
|
|
185
|
-
}
|
|
186
|
-
extensionsResult.runtime.pendingProviderRegistrations = [];
|
|
187
|
-
// Discover runtime (extension) provider catalogs now that they are registered.
|
|
188
|
-
// The full refresh in main.ts ran before extensions loaded, so this is the only
|
|
189
|
-
// point where extension-contributed dynamic providers get discovered. Cache-aware
|
|
190
|
-
// so it reuses the shared 24 h model cache instead of refetching every invocation.
|
|
191
|
-
await modelRegistry.refreshRuntimeProviders("online-if-uncached");
|
|
192
|
-
|
|
193
|
-
await listModels(modelRegistry, searchPattern);
|
|
194
|
-
}
|