@oh-my-pi/pi-coding-agent 15.10.9 → 15.10.11
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 +117 -0
- package/dist/cli.js +23087 -0
- package/dist/tokenizers.linux-x64-gnu-xcjh3jwk.node +0 -0
- package/dist/types/async/job-manager.d.ts +18 -0
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/cli/dry-balance-cli.d.ts +1 -1
- package/dist/types/cli/gallery-cli.d.ts +1 -1
- package/dist/types/cli/gallery-fixtures/types.d.ts +1 -1
- package/dist/types/cli/usage-cli.d.ts +72 -0
- package/dist/types/commands/launch.d.ts +1 -1
- package/dist/types/commands/read.d.ts +1 -1
- package/dist/types/commands/usage.d.ts +25 -0
- package/dist/types/config/append-only-context-mode.d.ts +2 -1
- package/dist/types/config/model-discovery.d.ts +55 -0
- package/dist/types/config/model-registry.d.ts +20 -219
- package/dist/types/config/model-resolver.d.ts +16 -10
- package/dist/types/config/model-roles.d.ts +28 -0
- package/dist/types/config/models-config-schema.d.ts +523 -42
- package/dist/types/config/models-config.d.ts +385 -0
- package/dist/types/config/settings-schema.d.ts +12 -16
- package/dist/types/config/settings.d.ts +1 -1
- package/dist/types/debug/log-viewer.d.ts +1 -1
- package/dist/types/debug/raw-sse.d.ts +1 -1
- package/dist/types/debug/terminal-info.d.ts +0 -1
- package/dist/types/eval/backend.d.ts +0 -2
- package/dist/types/eval/idle-timeout.d.ts +0 -4
- package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/extensions/types.d.ts +3 -3
- package/dist/types/hindsight/mental-models.d.ts +17 -8
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/lsp/edits.d.ts +9 -0
- package/dist/types/lsp/index.d.ts +2 -2
- package/dist/types/lsp/types.d.ts +2 -0
- package/dist/types/lsp/utils.d.ts +3 -0
- package/dist/types/mcp/json-rpc.d.ts +5 -0
- package/dist/types/mnemopi/state.d.ts +11 -1
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/bash-execution.d.ts +1 -1
- package/dist/types/modes/components/copy-selector.d.ts +1 -1
- package/dist/types/modes/components/dynamic-border.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
- package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
- package/dist/types/modes/components/footer.d.ts +1 -1
- package/dist/types/modes/components/hook-editor.d.ts +5 -0
- package/dist/types/modes/components/hook-input.d.ts +4 -0
- package/dist/types/modes/components/hook-selector.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +1 -1
- package/dist/types/modes/components/plan-review-overlay.d.ts +1 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +1 -1
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/component.d.ts +1 -1
- package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
- package/dist/types/modes/components/transcript-container.d.ts +31 -26
- package/dist/types/modes/components/tree-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message.d.ts +2 -1
- package/dist/types/modes/components/visual-truncate.d.ts +1 -1
- package/dist/types/modes/components/welcome.d.ts +19 -3
- package/dist/types/modes/controllers/mcp-command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/streaming-reveal.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/types.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
- package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
- package/dist/types/modes/types.d.ts +2 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/auth-broker-config.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +1 -1
- package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
- package/dist/types/ssh/connection-manager.d.ts +8 -0
- package/dist/types/task/discovery.d.ts +1 -2
- package/dist/types/task/parallel.d.ts +2 -2
- package/dist/types/task/worktree.d.ts +2 -0
- package/dist/types/tiny/title-client.d.ts +1 -1
- package/dist/types/tools/ask.d.ts +4 -0
- package/dist/types/tools/conflict-detect.d.ts +16 -0
- package/dist/types/tools/github-cache.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +3 -0
- package/dist/types/tools/todo.d.ts +2 -0
- package/dist/types/tui/output-block.d.ts +3 -3
- package/dist/types/utils/changelog.d.ts +8 -0
- package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
- package/dist/types/web/scrapers/types.d.ts +12 -0
- package/dist/types/web/search/providers/codex.d.ts +1 -1
- package/dist/types/web/search/providers/gemini.d.ts +1 -1
- package/examples/extensions/tools.ts +5 -4
- package/package.json +14 -11
- package/scripts/build-binary.ts +18 -23
- package/scripts/bundle-dist.ts +81 -0
- package/scripts/{dev-launch → omp} +1 -1
- package/scripts/{dev-launch-preload.ts → omp.ts} +1 -1
- package/src/async/job-manager.ts +57 -3
- package/src/autoresearch/dashboard.ts +1 -1
- package/src/autoresearch/prompt-setup.md +6 -6
- package/src/autoresearch/prompt.md +6 -6
- package/src/capability/fs.ts +10 -0
- package/src/cli/args.ts +1 -1
- package/src/cli/auth-gateway-cli.ts +1 -3
- package/src/cli/dry-balance-cli.ts +1 -1
- package/src/cli/gallery-cli.ts +1 -1
- package/src/cli/gallery-fixtures/fs.ts +1 -1
- package/src/cli/gallery-fixtures/types.ts +5 -1
- package/src/cli/list-models.ts +7 -12
- package/src/cli/usage-cli.ts +603 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +69 -5
- package/src/commands/complete.ts +1 -1
- package/src/commands/launch.ts +1 -1
- package/src/commands/read.ts +6 -3
- package/src/commands/usage.ts +35 -0
- package/src/commit/agentic/agent.ts +1 -1
- package/src/commit/model-selection.ts +1 -1
- package/src/config/append-only-context-mode.ts +6 -12
- package/src/config/model-discovery.ts +554 -0
- package/src/config/model-registry.ts +308 -1025
- package/src/config/model-resolver.ts +113 -156
- package/src/config/model-roles.ts +74 -0
- package/src/config/models-config-schema.ts +57 -8
- package/src/config/models-config.ts +129 -0
- package/src/config/settings-schema.ts +18 -14
- package/src/config/settings.ts +37 -1
- package/src/dap/client.ts +124 -37
- package/src/dap/session.ts +259 -158
- package/src/debug/log-viewer.ts +1 -1
- package/src/debug/raw-sse.ts +1 -1
- package/src/debug/terminal-info.ts +0 -3
- package/src/edit/diff.ts +95 -18
- package/src/edit/hashline/block-resolver.ts +20 -1
- package/src/edit/hashline/diff.ts +36 -1
- package/src/edit/hashline/execute.ts +8 -2
- package/src/edit/index.ts +16 -1
- package/src/edit/modes/patch.ts +52 -0
- package/src/edit/modes/replace.ts +56 -22
- package/src/edit/notebook.ts +22 -2
- package/src/edit/renderer.ts +36 -10
- package/src/eval/__tests__/completion-bridge.test.ts +1 -1
- package/src/eval/backend.ts +0 -2
- package/src/eval/completion-bridge.ts +2 -1
- package/src/eval/idle-timeout.ts +2 -9
- package/src/eval/js/context-manager.ts +6 -8
- package/src/eval/js/executor.ts +6 -2
- package/src/eval/js/index.ts +0 -2
- package/src/eval/js/shared/helpers.ts +5 -6
- package/src/eval/js/shared/local-module-loader.ts +1 -1
- package/src/eval/js/shared/prelude.txt +62 -1
- package/src/eval/js/shared/rewrite-imports.ts +49 -23
- package/src/eval/js/shared/runtime.ts +1 -1
- package/src/eval/py/index.ts +0 -2
- package/src/eval/py/kernel.ts +19 -0
- package/src/eval/py/runner.py +107 -3
- package/src/exec/bash-executor.ts +3 -1
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +3 -1
- package/src/extensibility/extensions/types.ts +3 -2
- package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
- package/src/hindsight/mental-models.ts +59 -12
- package/src/hindsight/state.ts +6 -1
- package/src/internal-urls/artifact-protocol.ts +11 -2
- package/src/internal-urls/docs-index.generated.ts +10 -10
- package/src/internal-urls/issue-pr-protocol.ts +12 -5
- package/src/internal-urls/router.ts +1 -1
- package/src/internal-urls/types.ts +1 -1
- package/src/lib/xai-http.ts +1 -1
- package/src/lsp/client.ts +118 -38
- package/src/lsp/clients/biome-client.ts +101 -39
- package/src/lsp/edits.ts +143 -95
- package/src/lsp/index.ts +31 -22
- package/src/lsp/render.ts +1 -1
- package/src/lsp/types.ts +2 -0
- package/src/lsp/utils.ts +28 -10
- package/src/main.ts +165 -17
- package/src/mcp/json-rpc.ts +35 -5
- package/src/mcp/transports/stdio.ts +7 -1
- package/src/memories/index.ts +2 -1
- package/src/mnemopi/backend.ts +25 -3
- package/src/mnemopi/state.ts +38 -2
- package/src/modes/components/agent-dashboard.ts +10 -7
- package/src/modes/components/assistant-message.ts +19 -13
- package/src/modes/components/bash-execution.ts +1 -1
- package/src/modes/components/copy-selector.ts +1 -1
- package/src/modes/components/diff.ts +13 -2
- package/src/modes/components/dynamic-border.ts +12 -3
- package/src/modes/components/extensions/extension-dashboard.ts +8 -5
- package/src/modes/components/extensions/extension-list.ts +1 -1
- package/src/modes/components/extensions/inspector-panel.ts +1 -1
- package/src/modes/components/footer.ts +1 -1
- package/src/modes/components/history-search.ts +1 -1
- package/src/modes/components/hook-editor.ts +8 -0
- package/src/modes/components/hook-input.ts +8 -0
- package/src/modes/components/hook-selector.ts +2 -2
- package/src/modes/components/model-selector.ts +66 -54
- package/src/modes/components/plan-review-overlay.ts +1 -1
- package/src/modes/components/session-observer-overlay.ts +2 -2
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-selector.ts +5 -1
- package/src/modes/components/status-line/component.ts +1 -1
- package/src/modes/components/tiny-title-download-progress.ts +1 -1
- package/src/modes/components/transcript-container.ts +373 -141
- package/src/modes/components/tree-selector.ts +3 -3
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +17 -5
- package/src/modes/components/visual-truncate.ts +1 -1
- package/src/modes/components/welcome.ts +108 -26
- package/src/modes/controllers/command-controller.ts +10 -3
- package/src/modes/controllers/event-controller.ts +73 -49
- package/src/modes/controllers/input-controller.ts +5 -5
- package/src/modes/controllers/mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +1 -5
- package/src/modes/controllers/streaming-reveal.ts +85 -18
- package/src/modes/interactive-mode.ts +5 -19
- package/src/modes/setup-wizard/scenes/glyph.ts +1 -1
- package/src/modes/setup-wizard/scenes/providers.ts +1 -1
- package/src/modes/setup-wizard/scenes/sign-in.ts +1 -1
- package/src/modes/setup-wizard/scenes/theme.ts +1 -1
- package/src/modes/setup-wizard/scenes/types.ts +1 -1
- package/src/modes/setup-wizard/scenes/web-search.ts +1 -1
- package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/types.ts +2 -1
- package/src/prompts/agents/explore.md +2 -2
- package/src/prompts/agents/librarian.md +1 -2
- package/src/prompts/agents/oracle.md +1 -1
- package/src/prompts/agents/plan.md +5 -5
- package/src/prompts/agents/task.md +5 -5
- package/src/prompts/ci-green-request.md +5 -7
- package/src/prompts/goals/goal-budget-limit.md +2 -2
- package/src/prompts/goals/goal-continuation.md +4 -4
- package/src/prompts/goals/goal-mode-active.md +1 -1
- package/src/prompts/memories/read-path.md +1 -1
- package/src/prompts/memories/stage_one_system.md +2 -2
- package/src/prompts/review-custom-request.md +1 -1
- package/src/prompts/system/agent-creation-architect.md +2 -2
- package/src/prompts/system/auto-continue.md +1 -1
- package/src/prompts/system/background-tan-dispatch.md +1 -1
- package/src/prompts/system/btw-user.md +2 -2
- package/src/prompts/system/commit-message-system.md +13 -1
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/eager-todo.md +2 -2
- package/src/prompts/system/irc-incoming.md +1 -1
- package/src/prompts/system/manual-continue.md +1 -1
- package/src/prompts/system/omfg-user.md +3 -4
- package/src/prompts/system/orchestrate-notice.md +9 -9
- package/src/prompts/system/plan-mode-active.md +4 -4
- package/src/prompts/system/plan-mode-subagent.md +4 -5
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
- package/src/prompts/system/project-prompt.md +2 -2
- package/src/prompts/system/subagent-system-prompt.md +4 -4
- package/src/prompts/system/system-prompt.md +15 -26
- package/src/prompts/system/title-system.md +2 -2
- package/src/prompts/system/ttsr-tool-reminder.md +1 -1
- package/src/prompts/system/workflow-notice.md +1 -1
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/prompts/tools/ast-grep.md +2 -2
- package/src/prompts/tools/bash.md +8 -10
- package/src/prompts/tools/browser.md +7 -7
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/eval.md +3 -3
- package/src/prompts/tools/find.md +0 -1
- package/src/prompts/tools/github.md +8 -7
- package/src/prompts/tools/goal.md +1 -1
- package/src/prompts/tools/image-gen.md +1 -1
- package/src/prompts/tools/inspect-image-system.md +1 -1
- package/src/prompts/tools/irc.md +15 -15
- package/src/prompts/tools/lsp.md +2 -2
- package/src/prompts/tools/patch.md +2 -2
- package/src/prompts/tools/read.md +3 -4
- package/src/prompts/tools/recall.md +1 -1
- package/src/prompts/tools/reflect.md +1 -1
- package/src/prompts/tools/render-mermaid.md +2 -2
- package/src/prompts/tools/replace.md +4 -10
- package/src/prompts/tools/rewind.md +2 -2
- package/src/prompts/tools/search-tool-bm25.md +1 -9
- package/src/prompts/tools/search.md +0 -1
- package/src/prompts/tools/ssh.md +0 -4
- package/src/prompts/tools/task.md +2 -3
- package/src/prompts/tools/todo.md +6 -2
- package/src/sdk.ts +23 -10
- package/src/session/agent-session.ts +44 -10
- package/src/session/auth-broker-config.ts +30 -1
- package/src/session/session-manager.ts +2 -2
- package/src/session/streaming-output.ts +23 -2
- package/src/slash-commands/builtin-registry.ts +20 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/ssh/connection-manager.ts +27 -0
- package/src/task/commands.ts +2 -1
- package/src/task/discovery.ts +17 -24
- package/src/task/executor.ts +61 -53
- package/src/task/index.ts +137 -60
- package/src/task/parallel.ts +3 -3
- package/src/task/render.ts +2 -2
- package/src/task/worktree.ts +64 -56
- package/src/thinking.ts +2 -1
- package/src/tiny/title-client.ts +32 -14
- package/src/tools/archive-reader.ts +30 -2
- package/src/tools/ask.ts +104 -21
- package/src/tools/ast-edit.ts +25 -5
- package/src/tools/auto-generated-guard.ts +20 -3
- package/src/tools/bash-interactive.ts +27 -7
- package/src/tools/bash.ts +54 -13
- package/src/tools/browser/launch.ts +11 -2
- package/src/tools/browser/readable.ts +19 -2
- package/src/tools/browser/registry.ts +4 -1
- package/src/tools/browser/render.ts +2 -2
- package/src/tools/browser/tab-supervisor.ts +55 -16
- package/src/tools/conflict-detect.ts +50 -4
- package/src/tools/debug.ts +1 -1
- package/src/tools/eval-render.ts +5 -5
- package/src/tools/eval.ts +0 -2
- package/src/tools/fetch.ts +33 -10
- package/src/tools/gh-cache-invalidation.ts +63 -8
- package/src/tools/gh-renderer.ts +1 -1
- package/src/tools/gh.ts +172 -29
- package/src/tools/github-cache.ts +70 -6
- package/src/tools/image-gen.ts +3 -9
- package/src/tools/irc.ts +5 -1
- package/src/tools/job.ts +1 -1
- package/src/tools/read.ts +202 -61
- package/src/tools/render-utils.ts +3 -3
- package/src/tools/resolve.ts +1 -1
- package/src/tools/search.ts +92 -29
- package/src/tools/sqlite-reader.ts +17 -5
- package/src/tools/ssh.ts +8 -8
- package/src/tools/todo.ts +51 -12
- package/src/tools/write.ts +118 -18
- package/src/tui/output-block.ts +4 -4
- package/src/utils/changelog.ts +27 -1
- package/src/utils/file-mentions.ts +2 -1
- package/src/web/scrapers/arxiv.ts +1 -1
- package/src/web/scrapers/go-pkg.ts +1 -1
- package/src/web/scrapers/iacr.ts +1 -1
- package/src/web/scrapers/readthedocs.ts +1 -1
- package/src/web/scrapers/twitter.ts +2 -1
- package/src/web/scrapers/types.ts +87 -8
- package/src/web/scrapers/wikipedia.ts +1 -1
- package/src/web/scrapers/youtube.ts +6 -1
- package/src/web/search/index.ts +1 -1
- package/src/web/search/providers/anthropic.ts +8 -2
- package/src/web/search/providers/codex.ts +2 -1
- package/src/web/search/providers/gemini.ts +2 -3
- package/src/web/search/render.ts +8 -6
- package/dist/types/config/model-equivalence.d.ts +0 -24
- package/dist/types/config/model-id-affixes.d.ts +0 -12
- package/dist/types/config/model-provider-priority.d.ts +0 -1
- package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
- package/src/config/model-equivalence.ts +0 -875
- package/src/config/model-id-affixes.ts +0 -81
- package/src/config/model-provider-priority.ts +0 -56
- package/src/exec/idle-timeout-watchdog.ts +0 -126
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* models.json config file handle and provider configuration validation.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Api, ModelSpec } from "@oh-my-pi/pi-ai/types";
|
|
6
|
+
import { ConfigFile } from "./config-file";
|
|
7
|
+
import {
|
|
8
|
+
type ModelsConfig,
|
|
9
|
+
ModelsConfigSchema,
|
|
10
|
+
type ProviderAuthMode,
|
|
11
|
+
type ProviderDiscovery,
|
|
12
|
+
} from "./models-config-schema";
|
|
13
|
+
|
|
14
|
+
export type ProviderValidationMode = "models-config" | "runtime-register";
|
|
15
|
+
|
|
16
|
+
export interface ProviderValidationModel {
|
|
17
|
+
id: string;
|
|
18
|
+
api?: Api;
|
|
19
|
+
contextWindow?: number;
|
|
20
|
+
maxTokens?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ProviderValidationConfig {
|
|
24
|
+
baseUrl?: string;
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
apiKey?: string;
|
|
27
|
+
api?: Api;
|
|
28
|
+
auth?: ProviderAuthMode;
|
|
29
|
+
oauthConfigured?: boolean;
|
|
30
|
+
discovery?: ProviderDiscovery;
|
|
31
|
+
compat?: ModelSpec<Api>["compat"];
|
|
32
|
+
disableStrictTools?: boolean;
|
|
33
|
+
modelOverrides?: Record<string, unknown>;
|
|
34
|
+
models: ProviderValidationModel[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function validateProviderConfiguration(
|
|
38
|
+
providerName: string,
|
|
39
|
+
config: ProviderValidationConfig,
|
|
40
|
+
mode: ProviderValidationMode,
|
|
41
|
+
): void {
|
|
42
|
+
const hasProviderApi = !!config.api;
|
|
43
|
+
const models = config.models;
|
|
44
|
+
|
|
45
|
+
if (models.length === 0) {
|
|
46
|
+
if (mode === "models-config") {
|
|
47
|
+
const hasModelOverrides = config.modelOverrides && Object.keys(config.modelOverrides).length > 0;
|
|
48
|
+
if (
|
|
49
|
+
!config.baseUrl &&
|
|
50
|
+
!config.headers &&
|
|
51
|
+
!config.compat &&
|
|
52
|
+
!config.apiKey &&
|
|
53
|
+
!config.disableStrictTools &&
|
|
54
|
+
!hasModelOverrides &&
|
|
55
|
+
!config.discovery
|
|
56
|
+
) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`Provider ${providerName}: must specify "baseUrl", "headers", "apiKey", "compat", "disableStrictTools", "modelOverrides", "discovery", or "models"`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
if (!config.baseUrl) {
|
|
64
|
+
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining custom models.`);
|
|
65
|
+
}
|
|
66
|
+
const requiresAuth =
|
|
67
|
+
mode === "runtime-register"
|
|
68
|
+
? !config.apiKey && !config.oauthConfigured
|
|
69
|
+
: !config.apiKey && (config.auth ?? "apiKey") !== "none";
|
|
70
|
+
if (requiresAuth) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
mode === "runtime-register"
|
|
73
|
+
? `Provider ${providerName}: "apiKey" or "oauth" is required when defining models.`
|
|
74
|
+
: `Provider ${providerName}: "apiKey" is required when defining custom models unless auth is "none".`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (mode === "models-config" && config.discovery && !config.api && config.discovery.type !== "proxy") {
|
|
80
|
+
throw new Error(`Provider ${providerName}: "api" is required when discovery is enabled at provider level.`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (const modelDef of models) {
|
|
84
|
+
if (!hasProviderApi && !modelDef.api) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
mode === "runtime-register"
|
|
87
|
+
? `Provider ${providerName}, model ${modelDef.id}: no "api" specified.`
|
|
88
|
+
: `Provider ${providerName}, model ${modelDef.id}: no "api" specified. Set at provider or model level.`,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (!modelDef.id) {
|
|
92
|
+
throw new Error(`Provider ${providerName}: model missing "id"`);
|
|
93
|
+
}
|
|
94
|
+
if (mode === "models-config") {
|
|
95
|
+
if (modelDef.contextWindow !== undefined && modelDef.contextWindow <= 0) {
|
|
96
|
+
throw new Error(`Provider ${providerName}, model ${modelDef.id}: invalid contextWindow`);
|
|
97
|
+
}
|
|
98
|
+
if (modelDef.maxTokens !== undefined && modelDef.maxTokens <= 0) {
|
|
99
|
+
throw new Error(`Provider ${providerName}, model ${modelDef.id}: invalid maxTokens`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const ModelsConfigFile = new ConfigFile<ModelsConfig>("models", ModelsConfigSchema).withValidation(
|
|
106
|
+
"models",
|
|
107
|
+
config => {
|
|
108
|
+
const providers = config.providers ?? {};
|
|
109
|
+
for (const providerName in providers) {
|
|
110
|
+
const providerConfig = providers[providerName];
|
|
111
|
+
validateProviderConfiguration(
|
|
112
|
+
providerName,
|
|
113
|
+
{
|
|
114
|
+
baseUrl: providerConfig.baseUrl,
|
|
115
|
+
headers: providerConfig.headers,
|
|
116
|
+
apiKey: providerConfig.apiKey,
|
|
117
|
+
api: providerConfig.api as Api | undefined,
|
|
118
|
+
auth: (providerConfig.auth ?? "apiKey") as ProviderAuthMode,
|
|
119
|
+
discovery: providerConfig.discovery as ProviderDiscovery | undefined,
|
|
120
|
+
compat: providerConfig.compat,
|
|
121
|
+
disableStrictTools: providerConfig.disableStrictTools,
|
|
122
|
+
modelOverrides: providerConfig.modelOverrides,
|
|
123
|
+
models: (providerConfig.models ?? []) as ProviderValidationModel[],
|
|
124
|
+
},
|
|
125
|
+
"models-config",
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
);
|
|
@@ -246,7 +246,11 @@ export const DEFAULT_BASH_INTERCEPTOR_RULES: BashInterceptorRule[] = [
|
|
|
246
246
|
message: "Use the `edit` tool instead of awk -i inplace. It provides diff preview and fuzzy matching.",
|
|
247
247
|
},
|
|
248
248
|
{
|
|
249
|
-
|
|
249
|
+
// `>` must sit outside quoted regions (so `echo "a -> b"` passes) and be
|
|
250
|
+
// followed by a plausible filename — including `$VAR` targets; `>|`
|
|
251
|
+
// (clobber) counts as a redirect; `>&2`/`2>&1` style fd duplication is
|
|
252
|
+
// not matched.
|
|
253
|
+
pattern: "^\\s*(echo|printf|cat\\s*<<)\\s+(?:[^\"'>]|\"[^\"]*\"|'[^']*')*(?<!\\|)>{1,2}\\|?\\s*[$\\w./~\"'-]",
|
|
250
254
|
tool: "write",
|
|
251
255
|
message: "Use the `write` tool instead of echo/cat redirection. It handles encoding and provides confirmation.",
|
|
252
256
|
},
|
|
@@ -256,7 +260,6 @@ export const SETTINGS_SCHEMA = {
|
|
|
256
260
|
// ────────────────────────────────────────────────────────────────────────
|
|
257
261
|
// General settings (no UI)
|
|
258
262
|
// ────────────────────────────────────────────────────────────────────────
|
|
259
|
-
lastChangelogVersion: { type: "string", default: undefined },
|
|
260
263
|
setupVersion: { type: "number", default: 0 },
|
|
261
264
|
|
|
262
265
|
// Auth broker — credentials proxied through a remote `omp auth-broker serve`
|
|
@@ -686,16 +689,6 @@ export const SETTINGS_SCHEMA = {
|
|
|
686
689
|
ui: { tab: "appearance", label: "Show Hardware Cursor", description: "Show terminal cursor for IME support" },
|
|
687
690
|
},
|
|
688
691
|
|
|
689
|
-
clearOnShrink: {
|
|
690
|
-
type: "boolean",
|
|
691
|
-
default: false,
|
|
692
|
-
ui: {
|
|
693
|
-
tab: "appearance",
|
|
694
|
-
label: "Clear on Shrink",
|
|
695
|
-
description: "Clear empty rows when content shrinks (may cause flicker)",
|
|
696
|
-
},
|
|
697
|
-
},
|
|
698
|
-
|
|
699
692
|
// ────────────────────────────────────────────────────────────────────────
|
|
700
693
|
// Model
|
|
701
694
|
// ────────────────────────────────────────────────────────────────────────
|
|
@@ -886,7 +879,7 @@ export const SETTINGS_SCHEMA = {
|
|
|
886
879
|
|
|
887
880
|
"retry.maxRetries": {
|
|
888
881
|
type: "number",
|
|
889
|
-
default:
|
|
882
|
+
default: 10,
|
|
890
883
|
ui: {
|
|
891
884
|
tab: "model",
|
|
892
885
|
label: "Retry Attempts",
|
|
@@ -901,7 +894,7 @@ export const SETTINGS_SCHEMA = {
|
|
|
901
894
|
},
|
|
902
895
|
},
|
|
903
896
|
|
|
904
|
-
"retry.baseDelayMs": { type: "number", default:
|
|
897
|
+
"retry.baseDelayMs": { type: "number", default: 500 },
|
|
905
898
|
"retry.maxDelayMs": {
|
|
906
899
|
type: "number",
|
|
907
900
|
default: 5 * 60 * 1000,
|
|
@@ -1984,6 +1977,17 @@ export const SETTINGS_SCHEMA = {
|
|
|
1984
1977
|
ui: { tab: "editing", label: "LSP", description: "Enable the lsp tool for language server protocol" },
|
|
1985
1978
|
},
|
|
1986
1979
|
|
|
1980
|
+
"lsp.lazy": {
|
|
1981
|
+
type: "boolean",
|
|
1982
|
+
default: true,
|
|
1983
|
+
ui: {
|
|
1984
|
+
tab: "editing",
|
|
1985
|
+
label: "Lazy LSP Startup",
|
|
1986
|
+
description:
|
|
1987
|
+
"Start language servers on first use (lsp tool or editing a matching file type) instead of at session startup",
|
|
1988
|
+
},
|
|
1989
|
+
},
|
|
1990
|
+
|
|
1987
1991
|
"lsp.formatOnWrite": {
|
|
1988
1992
|
type: "boolean",
|
|
1989
1993
|
default: false,
|
package/src/config/settings.ts
CHANGED
|
@@ -17,6 +17,7 @@ import * as path from "node:path";
|
|
|
17
17
|
import {
|
|
18
18
|
getAgentDbPath,
|
|
19
19
|
getAgentDir,
|
|
20
|
+
getLastChangelogVersionPath,
|
|
20
21
|
getProjectDir,
|
|
21
22
|
isEnoent,
|
|
22
23
|
logger,
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
} from "@oh-my-pi/pi-utils";
|
|
26
27
|
import { YAML } from "bun";
|
|
27
28
|
import { type Settings as SettingsCapabilityItem, settingsCapability } from "../capability/settings";
|
|
28
|
-
import type { ModelRole } from "../config/model-
|
|
29
|
+
import type { ModelRole } from "../config/model-roles";
|
|
29
30
|
import { loadCapability } from "../discovery";
|
|
30
31
|
import { isLightTheme, setAutoThemeMapping, setColorBlindMode, setSymbolPreset } from "../modes/theme/theme";
|
|
31
32
|
import { AgentStorage } from "../session/agent-storage";
|
|
@@ -206,6 +207,9 @@ export class Settings {
|
|
|
206
207
|
/** Paths modified during this session (for partial save) */
|
|
207
208
|
#modified = new Set<string>();
|
|
208
209
|
|
|
210
|
+
/** Legacy `lastChangelogVersion` captured from config.yml during migration (now a marker file). */
|
|
211
|
+
#legacyLastChangelogVersion?: string;
|
|
212
|
+
|
|
209
213
|
/** Pending save (debounced) */
|
|
210
214
|
#saveTimer?: NodeJS.Timeout;
|
|
211
215
|
#savePromise?: Promise<void>;
|
|
@@ -549,6 +553,7 @@ export class Settings {
|
|
|
549
553
|
this.#storage = await AgentStorage.open(getAgentDbPath(this.#agentDir));
|
|
550
554
|
await this.#migrateFromLegacy();
|
|
551
555
|
this.#global = await this.#loadYaml(this.#configPath!);
|
|
556
|
+
await this.#seedLastChangelogVersionMarker();
|
|
552
557
|
}
|
|
553
558
|
|
|
554
559
|
this.#project = await projectPromise;
|
|
@@ -642,6 +647,16 @@ export class Settings {
|
|
|
642
647
|
delete raw.queueMode;
|
|
643
648
|
}
|
|
644
649
|
|
|
650
|
+
// lastChangelogVersion moved out of config.yml into the
|
|
651
|
+
// <agentDir>/last-changelog-version marker file so version bumps no
|
|
652
|
+
// longer dirty user-tracked configs. Capture for marker seeding (see
|
|
653
|
+
// #seedLastChangelogVersionMarker), then strip the key — the next
|
|
654
|
+
// config save drops it from disk.
|
|
655
|
+
if (typeof raw.lastChangelogVersion === "string") {
|
|
656
|
+
this.#legacyLastChangelogVersion ??= raw.lastChangelogVersion;
|
|
657
|
+
}
|
|
658
|
+
delete raw.lastChangelogVersion;
|
|
659
|
+
|
|
645
660
|
// ask.timeout: ms -> seconds (if value > 1000, it's old ms format)
|
|
646
661
|
if (raw.ask && typeof (raw.ask as Record<string, unknown>).timeout === "number") {
|
|
647
662
|
const oldValue = (raw.ask as Record<string, unknown>).timeout as number;
|
|
@@ -803,6 +818,27 @@ export class Settings {
|
|
|
803
818
|
return raw;
|
|
804
819
|
}
|
|
805
820
|
|
|
821
|
+
/**
|
|
822
|
+
* One-time migration: seed the last-changelog-version marker file from the
|
|
823
|
+
* legacy config.yml key. An existing marker always wins — it is the newer
|
|
824
|
+
* source of truth.
|
|
825
|
+
*/
|
|
826
|
+
async #seedLastChangelogVersionMarker(): Promise<void> {
|
|
827
|
+
const legacy = this.#legacyLastChangelogVersion;
|
|
828
|
+
if (!legacy) return;
|
|
829
|
+
const markerPath = getLastChangelogVersionPath(this.#agentDir);
|
|
830
|
+
try {
|
|
831
|
+
if ((await Bun.file(markerPath).text()).trim()) return;
|
|
832
|
+
} catch (error) {
|
|
833
|
+
if (!isEnoent(error)) return;
|
|
834
|
+
}
|
|
835
|
+
try {
|
|
836
|
+
await Bun.write(markerPath, legacy);
|
|
837
|
+
} catch (error) {
|
|
838
|
+
logger.warn("Settings: failed to seed last-changelog-version marker", { error: String(error) });
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
806
842
|
// ─────────────────────────────────────────────────────────────────────────
|
|
807
843
|
// Saving
|
|
808
844
|
// ─────────────────────────────────────────────────────────────────────────
|
package/src/dap/client.ts
CHANGED
|
@@ -29,32 +29,67 @@ type DapReverseRequestHandler = (args: unknown) => unknown | Promise<unknown>;
|
|
|
29
29
|
|
|
30
30
|
const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
// Reused for all full decodes; each decode() resets state, so a single
|
|
33
|
+
// instance is safe and avoids per-message TextDecoder allocation.
|
|
34
|
+
const MESSAGE_DECODER = new TextDecoder("utf-8");
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Locate the `\r\n\r\n` header terminator across the pending chunk list.
|
|
38
|
+
* Returns the absolute byte index of the first `\r`, or -1 when not present.
|
|
39
|
+
* Equivalent to scanning the contiguous concatenation of the chunks.
|
|
40
|
+
*/
|
|
41
|
+
function findHeaderEndInChunks(chunks: Buffer[]): number {
|
|
42
|
+
let global = 0;
|
|
43
|
+
let b0 = -1;
|
|
44
|
+
let b1 = -1;
|
|
45
|
+
let b2 = -1;
|
|
46
|
+
for (const chunk of chunks) {
|
|
47
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
48
|
+
const b3 = chunk[i];
|
|
49
|
+
if (b0 === 13 && b1 === 10 && b2 === 13 && b3 === 10) {
|
|
50
|
+
return global - 3;
|
|
51
|
+
}
|
|
52
|
+
b0 = b1;
|
|
53
|
+
b1 = b2;
|
|
54
|
+
b2 = b3;
|
|
55
|
+
global++;
|
|
36
56
|
}
|
|
37
57
|
}
|
|
38
58
|
return -1;
|
|
39
59
|
}
|
|
40
60
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
/** Copy the byte range [from, to) out of the pending chunk list into one Buffer. */
|
|
62
|
+
function copyChunkRange(chunks: Buffer[], from: number, to: number): Buffer {
|
|
63
|
+
const out = Buffer.allocUnsafe(to - from);
|
|
64
|
+
let global = 0;
|
|
65
|
+
let written = 0;
|
|
66
|
+
for (const chunk of chunks) {
|
|
67
|
+
const chunkEnd = global + chunk.length;
|
|
68
|
+
if (chunkEnd > from && global < to) {
|
|
69
|
+
const start = Math.max(from, global) - global;
|
|
70
|
+
const end = Math.min(to, chunkEnd) - global;
|
|
71
|
+
chunk.copy(out, written, start, end);
|
|
72
|
+
written += end - start;
|
|
73
|
+
}
|
|
74
|
+
global = chunkEnd;
|
|
75
|
+
if (global >= to) break;
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Drop the first `count` bytes from the pending chunk list in place. */
|
|
81
|
+
function dropChunkFront(chunks: Buffer[], count: number): void {
|
|
82
|
+
let removed = 0;
|
|
83
|
+
while (chunks.length > 0) {
|
|
84
|
+
const head = chunks[0];
|
|
85
|
+
if (removed + head.length <= count) {
|
|
86
|
+
removed += head.length;
|
|
87
|
+
chunks.shift();
|
|
88
|
+
} else {
|
|
89
|
+
chunks[0] = head.subarray(count - removed);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
58
93
|
}
|
|
59
94
|
|
|
60
95
|
async function writeMessage(sink: DapWriteSink, message: DapRequestMessage | DapResponseMessage): Promise<void> {
|
|
@@ -81,7 +116,7 @@ export class DapClient {
|
|
|
81
116
|
readonly #socket?: { end(): void };
|
|
82
117
|
#requestSeq = 0;
|
|
83
118
|
#pendingRequests = new Map<number, DapPendingRequest>();
|
|
84
|
-
#messageBuffer = Buffer.alloc(0);
|
|
119
|
+
#messageBuffer: Buffer = Buffer.alloc(0);
|
|
85
120
|
#isReading = false;
|
|
86
121
|
#disposed = false;
|
|
87
122
|
#lastActivity = Date.now();
|
|
@@ -416,32 +451,84 @@ export class DapClient {
|
|
|
416
451
|
if (this.#isReading) return;
|
|
417
452
|
this.#isReading = true;
|
|
418
453
|
const reader = this.#readable.getReader();
|
|
454
|
+
|
|
455
|
+
// Incoming bytes are buffered as a list of chunks and only joined when a
|
|
456
|
+
// full message is framed (mirrors the LSP reader) — concatenating the
|
|
457
|
+
// accumulator on every read is O(n^2) for messages spanning many reads.
|
|
458
|
+
const pendingChunks: Buffer[] = [];
|
|
459
|
+
let pendingLen = 0;
|
|
460
|
+
if (this.#messageBuffer.length > 0) {
|
|
461
|
+
pendingChunks.push(this.#messageBuffer);
|
|
462
|
+
pendingLen = this.#messageBuffer.length;
|
|
463
|
+
}
|
|
464
|
+
|
|
419
465
|
try {
|
|
420
466
|
while (true) {
|
|
421
467
|
const { done, value } = await reader.read();
|
|
422
468
|
if (done) break;
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
469
|
+
|
|
470
|
+
pendingChunks.push(Buffer.from(value));
|
|
471
|
+
pendingLen += value.length;
|
|
472
|
+
|
|
473
|
+
// Drain every complete message currently buffered.
|
|
474
|
+
while (true) {
|
|
475
|
+
const headerEnd = findHeaderEndInChunks(pendingChunks);
|
|
476
|
+
if (headerEnd === -1) break;
|
|
477
|
+
|
|
478
|
+
const headerText = MESSAGE_DECODER.decode(copyChunkRange(pendingChunks, 0, headerEnd));
|
|
479
|
+
const contentLengthMatch = headerText.match(/Content-Length: (\d+)/i);
|
|
480
|
+
if (!contentLengthMatch) {
|
|
481
|
+
// Non-protocol bytes (e.g. an adapter printing to stdout).
|
|
482
|
+
// Drop past the bogus terminator and resync instead of
|
|
483
|
+
// stalling on the same junk header forever.
|
|
484
|
+
logger.warn("DAP framing resync: header block without Content-Length", {
|
|
485
|
+
adapter: this.adapter.name,
|
|
486
|
+
header: headerText.slice(0, 200),
|
|
487
|
+
});
|
|
488
|
+
dropChunkFront(pendingChunks, headerEnd + 4);
|
|
489
|
+
pendingLen -= headerEnd + 4;
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const contentLength = Number.parseInt(contentLengthMatch[1], 10);
|
|
494
|
+
const messageStart = headerEnd + 4; // Skip \r\n\r\n
|
|
495
|
+
const messageEnd = messageStart + contentLength;
|
|
496
|
+
if (pendingLen < messageEnd) break;
|
|
497
|
+
|
|
498
|
+
const messageText = MESSAGE_DECODER.decode(copyChunkRange(pendingChunks, messageStart, messageEnd));
|
|
499
|
+
dropChunkFront(pendingChunks, messageEnd);
|
|
500
|
+
pendingLen -= messageEnd;
|
|
430
501
|
this.#lastActivity = Date.now();
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
502
|
+
|
|
503
|
+
// A malformed message must not kill the reader — later
|
|
504
|
+
// messages are still well-framed.
|
|
505
|
+
try {
|
|
506
|
+
const message = JSON.parse(messageText) as DapResponseMessage | DapEventMessage | DapRequestMessage;
|
|
507
|
+
if (message.type === "response") {
|
|
508
|
+
this.#handleResponse(message);
|
|
509
|
+
} else if (message.type === "event") {
|
|
510
|
+
await this.#dispatchEvent(message);
|
|
511
|
+
} else {
|
|
512
|
+
await this.#handleAdapterRequest(message);
|
|
513
|
+
}
|
|
514
|
+
} catch (error) {
|
|
515
|
+
logger.warn("DAP message handling failed", {
|
|
516
|
+
adapter: this.adapter.name,
|
|
517
|
+
error: toErrorMessage(error),
|
|
518
|
+
});
|
|
437
519
|
}
|
|
438
|
-
parsed = parseMessage(workingBuffer);
|
|
439
520
|
}
|
|
440
|
-
this.#messageBuffer = workingBuffer;
|
|
441
521
|
}
|
|
442
522
|
} catch (error) {
|
|
443
523
|
this.#rejectPendingRequests(new Error(`DAP connection closed: ${toErrorMessage(error)}`));
|
|
444
524
|
} finally {
|
|
525
|
+
// Persist any unparsed remainder so a restarted reader resumes mid-message.
|
|
526
|
+
this.#messageBuffer =
|
|
527
|
+
pendingChunks.length === 0
|
|
528
|
+
? Buffer.alloc(0)
|
|
529
|
+
: pendingChunks.length === 1
|
|
530
|
+
? pendingChunks[0]
|
|
531
|
+
: Buffer.concat(pendingChunks, pendingLen);
|
|
445
532
|
reader.releaseLock();
|
|
446
533
|
this.#isReading = false;
|
|
447
534
|
}
|