@oh-my-pi/pi-coding-agent 8.0.20 → 8.2.0
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 +125 -0
- package/docs/session.md +111 -46
- package/examples/custom-tools/hello/index.ts +1 -1
- package/examples/custom-tools/todo/index.ts +3 -4
- package/examples/extensions/api-demo.ts +0 -1
- package/examples/extensions/chalk-logger.ts +2 -3
- package/examples/extensions/hello.ts +0 -1
- package/examples/extensions/pirate.ts +0 -1
- package/examples/extensions/plan-mode.ts +15 -16
- package/examples/extensions/todo.ts +3 -4
- package/examples/extensions/tools.ts +1 -2
- package/examples/extensions/with-deps/index.ts +0 -1
- package/examples/hooks/auto-commit-on-exit.ts +1 -2
- package/examples/hooks/confirm-destructive.ts +0 -1
- package/examples/hooks/custom-compaction.ts +1 -2
- package/examples/hooks/dirty-repo-guard.ts +0 -1
- package/examples/hooks/file-trigger.ts +3 -4
- package/examples/hooks/git-checkpoint.ts +0 -1
- package/examples/hooks/handoff.ts +3 -4
- package/examples/hooks/permission-gate.ts +1 -2
- package/examples/hooks/protected-paths.ts +1 -2
- package/examples/hooks/qna.ts +2 -3
- package/examples/hooks/snake.ts +4 -5
- package/examples/hooks/status-line.ts +0 -1
- package/examples/sdk/01-minimal.ts +2 -3
- package/examples/sdk/02-custom-model.ts +2 -3
- package/examples/sdk/03-custom-prompt.ts +3 -4
- package/examples/sdk/04-skills.ts +2 -3
- package/examples/sdk/06-extensions.ts +1 -2
- package/examples/sdk/06-hooks.ts +6 -7
- package/examples/sdk/07-context-files.ts +0 -1
- package/examples/sdk/08-prompt-templates.ts +0 -1
- package/examples/sdk/08-slash-commands.ts +0 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +0 -1
- package/examples/sdk/10-settings.ts +0 -1
- package/examples/sdk/11-sessions.ts +0 -1
- package/package.json +54 -23
- package/scripts/format-prompts.ts +0 -1
- package/src/capability/context-file.ts +3 -4
- package/src/capability/extension-module.ts +3 -4
- package/src/capability/extension.ts +3 -4
- package/src/capability/fs.ts +20 -21
- package/src/capability/hook.ts +3 -4
- package/src/capability/index.ts +15 -16
- package/src/capability/instruction.ts +3 -4
- package/src/capability/mcp.ts +3 -4
- package/src/capability/prompt.ts +3 -4
- package/src/capability/rule.ts +3 -4
- package/src/capability/settings.ts +2 -3
- package/src/capability/skill.ts +3 -4
- package/src/capability/slash-command.ts +3 -4
- package/src/capability/ssh.ts +3 -4
- package/src/capability/system-prompt.ts +3 -4
- package/src/capability/tool.ts +3 -4
- package/src/cli/args.ts +5 -6
- package/src/cli/config-cli.ts +6 -7
- package/src/cli/file-processor.ts +19 -17
- package/src/cli/jupyter-cli.ts +105 -0
- package/src/cli/list-models.ts +10 -11
- package/src/cli/plugin-cli.ts +20 -25
- package/src/cli/session-picker.ts +2 -3
- package/src/cli/setup-cli.ts +2 -3
- package/src/cli/stats-cli.ts +2 -3
- package/src/cli/update-cli.ts +25 -22
- package/src/commit/agentic/agent.ts +307 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +351 -0
- package/src/commit/agentic/prompts/analyze-file.md +22 -0
- package/src/commit/agentic/prompts/session-user.md +26 -0
- package/src/commit/agentic/prompts/split-confirm.md +1 -0
- package/src/commit/agentic/prompts/system.md +40 -0
- package/src/commit/agentic/state.ts +69 -0
- package/src/commit/agentic/tools/analyze-file.ts +131 -0
- package/src/commit/agentic/tools/git-file-diff.ts +194 -0
- package/src/commit/agentic/tools/git-hunk.ts +50 -0
- package/src/commit/agentic/tools/git-overview.ts +84 -0
- package/src/commit/agentic/tools/index.ts +56 -0
- package/src/commit/agentic/tools/propose-changelog.ts +128 -0
- package/src/commit/agentic/tools/propose-commit.ts +154 -0
- package/src/commit/agentic/tools/recent-commits.ts +81 -0
- package/src/commit/agentic/tools/split-commit.ts +280 -0
- package/src/commit/agentic/topo-sort.ts +44 -0
- package/src/commit/agentic/trivial.ts +51 -0
- package/src/commit/agentic/validation.ts +200 -0
- package/src/commit/analysis/conventional.ts +165 -0
- package/src/commit/analysis/index.ts +4 -0
- package/src/commit/analysis/scope.ts +242 -0
- package/src/commit/analysis/summary.ts +112 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +36 -0
- package/src/commit/changelog/generate.ts +110 -0
- package/src/commit/changelog/index.ts +233 -0
- package/src/commit/changelog/parse.ts +44 -0
- package/src/commit/cli.ts +93 -0
- package/src/commit/git/diff.ts +148 -0
- package/src/commit/git/errors.ts +11 -0
- package/src/commit/git/index.ts +212 -0
- package/src/commit/git/operations.ts +53 -0
- package/src/commit/index.ts +5 -0
- package/src/commit/map-reduce/index.ts +63 -0
- package/src/commit/map-reduce/map-phase.ts +178 -0
- package/src/commit/map-reduce/reduce-phase.ts +145 -0
- package/src/commit/map-reduce/utils.ts +9 -0
- package/src/commit/message.ts +11 -0
- package/src/commit/model-selection.ts +80 -0
- package/src/commit/pipeline.ts +240 -0
- package/src/commit/prompts/analysis-system.md +155 -0
- package/src/commit/prompts/analysis-user.md +41 -0
- package/src/commit/prompts/changelog-system.md +56 -0
- package/src/commit/prompts/changelog-user.md +19 -0
- package/src/commit/prompts/file-observer-system.md +26 -0
- package/src/commit/prompts/file-observer-user.md +9 -0
- package/src/commit/prompts/reduce-system.md +60 -0
- package/src/commit/prompts/reduce-user.md +17 -0
- package/src/commit/prompts/summary-retry.md +4 -0
- package/src/commit/prompts/summary-system.md +52 -0
- package/src/commit/prompts/summary-user.md +13 -0
- package/src/commit/prompts/types-description.md +2 -0
- package/src/commit/types.ts +109 -0
- package/src/commit/utils/exclusions.ts +42 -0
- package/src/config/file-lock.ts +121 -0
- package/src/config/keybindings.ts +6 -8
- package/src/config/model-registry.ts +65 -38
- package/src/config/model-resolver.ts +18 -19
- package/src/config/prompt-templates.ts +11 -11
- package/src/config/settings-manager.ts +141 -50
- package/src/config.ts +64 -66
- package/src/cursor.ts +11 -9
- package/src/discovery/agents-md.ts +11 -12
- package/src/discovery/builtin.ts +68 -73
- package/src/discovery/claude.ts +41 -42
- package/src/discovery/cline.ts +11 -12
- package/src/discovery/codex.ts +52 -53
- package/src/discovery/cursor.ts +9 -10
- package/src/discovery/gemini.ts +17 -22
- package/src/discovery/github.ts +13 -14
- package/src/discovery/helpers.ts +35 -34
- package/src/discovery/index.ts +22 -24
- package/src/discovery/mcp-json.ts +8 -9
- package/src/discovery/ssh.ts +8 -9
- package/src/discovery/vscode.ts +4 -5
- package/src/discovery/windsurf.ts +6 -7
- package/src/exa/company.ts +1 -2
- package/src/exa/index.ts +2 -3
- package/src/exa/linkedin.ts +1 -2
- package/src/exa/mcp-client.ts +14 -16
- package/src/exa/render.ts +10 -11
- package/src/exa/researcher.ts +1 -2
- package/src/exa/search.ts +1 -2
- package/src/exa/types.ts +0 -1
- package/src/exa/websets.ts +1 -2
- package/src/exec/bash-executor.ts +3 -4
- package/src/exec/exec.ts +0 -1
- package/src/export/custom-share.ts +5 -6
- package/src/export/html/index.ts +24 -21
- package/src/export/ttsr.ts +2 -3
- package/src/extensibility/custom-commands/bundled/review/index.ts +7 -8
- package/src/extensibility/custom-commands/loader.ts +18 -15
- package/src/extensibility/custom-commands/types.ts +2 -3
- package/src/extensibility/custom-tools/loader.ts +11 -12
- package/src/extensibility/custom-tools/types.ts +7 -8
- package/src/extensibility/custom-tools/wrapper.ts +2 -3
- package/src/extensibility/extensions/loader.ts +76 -54
- package/src/extensibility/extensions/runner.ts +11 -12
- package/src/extensibility/extensions/types.ts +20 -27
- package/src/extensibility/extensions/wrapper.ts +3 -4
- package/src/extensibility/hooks/index.ts +1 -1
- package/src/extensibility/hooks/loader.ts +9 -10
- package/src/extensibility/hooks/runner.ts +7 -8
- package/src/extensibility/hooks/tool-wrapper.ts +0 -1
- package/src/extensibility/hooks/types.ts +11 -18
- package/src/extensibility/plugins/doctor.ts +3 -3
- package/src/extensibility/plugins/installer.ts +27 -27
- package/src/extensibility/plugins/loader.ts +59 -56
- package/src/extensibility/plugins/manager.ts +211 -171
- package/src/extensibility/plugins/parser.ts +1 -1
- package/src/extensibility/plugins/paths.ts +8 -8
- package/src/extensibility/skills.ts +63 -60
- package/src/extensibility/slash-commands.ts +10 -10
- package/src/index.ts +54 -54
- package/src/internal-urls/agent-protocol.ts +21 -11
- package/src/internal-urls/artifact-protocol.ts +17 -13
- package/src/internal-urls/router.ts +1 -2
- package/src/internal-urls/rule-protocol.ts +3 -4
- package/src/internal-urls/skill-protocol.ts +3 -4
- package/src/ipy/executor.ts +109 -9
- package/src/ipy/gateway-coordinator.ts +79 -90
- package/src/ipy/kernel.ts +32 -30
- package/src/ipy/modules.ts +13 -13
- package/src/lsp/client.ts +21 -10
- package/src/lsp/clients/biome-client.ts +1 -2
- package/src/lsp/clients/index.ts +3 -3
- package/src/lsp/clients/lsp-linter-client.ts +4 -5
- package/src/lsp/config.ts +15 -15
- package/src/lsp/edits.ts +4 -5
- package/src/lsp/index.ts +43 -44
- package/src/lsp/lspmux.ts +8 -8
- package/src/lsp/render.ts +99 -61
- package/src/lsp/utils.ts +3 -3
- package/src/main.ts +71 -37
- package/src/mcp/client.ts +2 -3
- package/src/mcp/config.ts +5 -6
- package/src/mcp/json-rpc.ts +0 -1
- package/src/mcp/loader.ts +6 -7
- package/src/mcp/manager.ts +17 -18
- package/src/mcp/tool-bridge.ts +4 -9
- package/src/mcp/tool-cache.ts +2 -3
- package/src/mcp/transports/http.ts +2 -4
- package/src/mcp/transports/stdio.ts +1 -2
- package/src/migrations.ts +63 -52
- package/src/modes/components/armin.ts +4 -5
- package/src/modes/components/assistant-message.ts +33 -5
- package/src/modes/components/bash-execution.ts +7 -8
- package/src/modes/components/bordered-loader.ts +3 -3
- package/src/modes/components/branch-summary-message.ts +3 -3
- package/src/modes/components/compaction-summary-message.ts +3 -3
- package/src/modes/components/countdown-timer.ts +0 -1
- package/src/modes/components/custom-message.ts +5 -5
- package/src/modes/components/diff.ts +1 -1
- package/src/modes/components/dynamic-border.ts +2 -2
- package/src/modes/components/extensions/extension-dashboard.ts +6 -7
- package/src/modes/components/extensions/extension-list.ts +2 -3
- package/src/modes/components/extensions/inspector-panel.ts +3 -4
- package/src/modes/components/extensions/state-manager.ts +25 -26
- package/src/modes/components/extensions/types.ts +1 -2
- package/src/modes/components/footer.ts +47 -43
- package/src/modes/components/history-search.ts +2 -2
- package/src/modes/components/hook-editor.ts +3 -4
- package/src/modes/components/hook-input.ts +2 -3
- package/src/modes/components/hook-message.ts +5 -5
- package/src/modes/components/hook-selector.ts +2 -3
- package/src/modes/components/keybinding-hints.ts +2 -3
- package/src/modes/components/login-dialog.ts +2 -2
- package/src/modes/components/model-selector.ts +12 -12
- package/src/modes/components/oauth-selector.ts +2 -2
- package/src/modes/components/plugin-settings.ts +20 -20
- package/src/modes/components/python-execution.ts +7 -8
- package/src/modes/components/queue-mode-selector.ts +3 -3
- package/src/modes/components/read-tool-group.ts +2 -2
- package/src/modes/components/session-selector.ts +4 -4
- package/src/modes/components/settings-defs.ts +77 -69
- package/src/modes/components/settings-selector.ts +16 -16
- package/src/modes/components/show-images-selector.ts +2 -2
- package/src/modes/components/status-line/segments.ts +4 -4
- package/src/modes/components/status-line/separators.ts +1 -1
- package/src/modes/components/status-line/types.ts +2 -2
- package/src/modes/components/status-line-segment-editor.ts +7 -8
- package/src/modes/components/status-line.ts +12 -12
- package/src/modes/components/theme-selector.ts +8 -7
- package/src/modes/components/thinking-selector.ts +4 -4
- package/src/modes/components/todo-display.ts +2 -2
- package/src/modes/components/todo-reminder.ts +4 -4
- package/src/modes/components/tool-execution.ts +16 -19
- package/src/modes/components/tree-selector.ts +12 -12
- package/src/modes/components/ttsr-notification.ts +5 -5
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +1 -1
- package/src/modes/components/visual-truncate.ts +0 -1
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +46 -47
- package/src/modes/controllers/event-controller.ts +16 -20
- package/src/modes/controllers/extension-ui-controller.ts +40 -46
- package/src/modes/controllers/input-controller.ts +17 -18
- package/src/modes/controllers/selector-controller.ts +103 -91
- package/src/modes/index.ts +3 -3
- package/src/modes/interactive-mode.ts +31 -31
- package/src/modes/print-mode.ts +12 -13
- package/src/modes/rpc/rpc-client.ts +7 -8
- package/src/modes/rpc/rpc-mode.ts +24 -28
- package/src/modes/rpc/rpc-types.ts +3 -4
- package/src/modes/theme/mermaid-cache.ts +89 -0
- package/src/modes/theme/theme.ts +130 -53
- package/src/modes/types.ts +10 -10
- package/src/modes/utils/ui-helpers.ts +17 -17
- package/src/patch/applicator.ts +18 -19
- package/src/patch/diff.ts +1 -2
- package/src/patch/fuzzy.ts +1 -2
- package/src/patch/index.ts +11 -18
- package/src/patch/normalize.ts +4 -4
- package/src/patch/normative.ts +1 -2
- package/src/patch/parser.ts +8 -9
- package/src/patch/shared.ts +43 -16
- package/src/prompts/tools/task.md +2 -0
- package/src/sdk.ts +100 -65
- package/src/session/agent-session.ts +84 -85
- package/src/session/agent-storage.ts +43 -39
- package/src/session/artifacts.ts +32 -10
- package/src/session/auth-storage.ts +50 -39
- package/src/session/compaction/branch-summarization.ts +7 -10
- package/src/session/compaction/compaction.ts +8 -19
- package/src/session/compaction/utils.ts +6 -9
- package/src/session/history-storage.ts +10 -10
- package/src/session/messages.ts +4 -5
- package/src/session/session-manager.ts +76 -65
- package/src/session/session-storage.ts +57 -69
- package/src/session/storage-migration.ts +14 -56
- package/src/session/streaming-output.ts +2 -2
- package/src/ssh/connection-manager.ts +43 -50
- package/src/ssh/ssh-executor.ts +2 -2
- package/src/ssh/sshfs-mount.ts +11 -18
- package/src/system-prompt.ts +28 -35
- package/src/task/agents.ts +45 -30
- package/src/task/commands.ts +6 -7
- package/src/task/discovery.ts +39 -76
- package/src/task/executor.ts +14 -15
- package/src/task/index.ts +40 -34
- package/src/task/output-manager.ts +93 -0
- package/src/task/parallel.ts +0 -1
- package/src/task/render.ts +24 -30
- package/src/task/subprocess-tool-registry.ts +1 -2
- package/src/task/worker-protocol.ts +3 -3
- package/src/task/worker.ts +33 -39
- package/src/task/worktree.ts +19 -19
- package/src/tools/ask.ts +41 -20
- package/src/tools/bash-interceptor.ts +1 -5
- package/src/tools/bash.ts +91 -97
- package/src/tools/calculator.ts +49 -47
- package/src/tools/complete.ts +4 -5
- package/src/tools/context.ts +2 -2
- package/src/tools/fetch.ts +84 -124
- package/src/tools/find.ts +94 -98
- package/src/tools/gemini-image.ts +14 -14
- package/src/tools/grep.ts +100 -116
- package/src/tools/index.ts +80 -55
- package/src/tools/list-limit.ts +1 -1
- package/src/tools/ls.ts +44 -70
- package/src/tools/notebook.ts +51 -67
- package/src/tools/output-meta.ts +3 -4
- package/src/tools/output-utils.ts +2 -2
- package/src/tools/path-utils.ts +5 -5
- package/src/tools/python.ts +104 -217
- package/src/tools/read.ts +92 -33
- package/src/tools/render-utils.ts +8 -23
- package/src/tools/renderers.ts +6 -7
- package/src/tools/review.ts +8 -11
- package/src/tools/ssh.ts +69 -49
- package/src/tools/todo-write.ts +37 -25
- package/src/tools/tool-errors.ts +3 -3
- package/src/tools/tool-result.ts +3 -8
- package/src/tools/write.ts +99 -75
- package/src/tui/code-cell.ts +109 -0
- package/src/tui/file-list.ts +47 -0
- package/src/tui/index.ts +11 -0
- package/src/tui/output-block.ts +72 -0
- package/src/tui/status-line.ts +39 -0
- package/src/tui/tree-list.ts +55 -0
- package/src/tui/types.ts +16 -0
- package/src/tui/utils.ts +48 -0
- package/src/utils/changelog.ts +9 -10
- package/src/utils/clipboard.ts +11 -11
- package/src/utils/file-mentions.ts +4 -10
- package/src/utils/frontmatter.ts +6 -3
- package/src/utils/fuzzy.ts +2 -2
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +1 -1
- package/src/utils/mime.ts +2 -2
- package/src/utils/shell-snapshot.ts +11 -13
- package/src/utils/shell.ts +4 -5
- package/src/utils/title-generator.ts +8 -9
- package/src/utils/tools-manager.ts +23 -23
- package/src/vendor/photon/index.js +1099 -1059
- package/src/vendor/photon/photon_rs_bg.wasm +0 -0
- package/src/web/scrapers/artifacthub.ts +1 -1
- package/src/web/scrapers/arxiv.ts +2 -2
- package/src/web/scrapers/bluesky.ts +2 -2
- package/src/web/scrapers/cheatsh.ts +1 -1
- package/src/web/scrapers/chocolatey.ts +2 -2
- package/src/web/scrapers/choosealicense.ts +5 -5
- package/src/web/scrapers/cisa-kev.ts +1 -1
- package/src/web/scrapers/crossref.ts +2 -2
- package/src/web/scrapers/devto.ts +3 -3
- package/src/web/scrapers/discogs.ts +3 -4
- package/src/web/scrapers/discourse.ts +1 -1
- package/src/web/scrapers/dockerhub.ts +1 -1
- package/src/web/scrapers/fdroid.ts +2 -2
- package/src/web/scrapers/firefox-addons.ts +3 -3
- package/src/web/scrapers/flathub.ts +1 -1
- package/src/web/scrapers/github.ts +3 -3
- package/src/web/scrapers/gitlab.ts +4 -4
- package/src/web/scrapers/hackernews.ts +2 -2
- package/src/web/scrapers/huggingface.ts +1 -1
- package/src/web/scrapers/iacr.ts +2 -2
- package/src/web/scrapers/index.ts +0 -1
- package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
- package/src/web/scrapers/lemmy.ts +2 -2
- package/src/web/scrapers/maven.ts +2 -2
- package/src/web/scrapers/mdn.ts +2 -4
- package/src/web/scrapers/metacpan.ts +2 -2
- package/src/web/scrapers/musicbrainz.ts +1 -2
- package/src/web/scrapers/npm.ts +1 -1
- package/src/web/scrapers/nuget.ts +2 -2
- package/src/web/scrapers/nvd.ts +3 -3
- package/src/web/scrapers/ollama.ts +7 -9
- package/src/web/scrapers/opencorporates.ts +2 -2
- package/src/web/scrapers/openlibrary.ts +6 -6
- package/src/web/scrapers/orcid.ts +0 -1
- package/src/web/scrapers/osv.ts +2 -2
- package/src/web/scrapers/packagist.ts +1 -1
- package/src/web/scrapers/pubmed.ts +1 -2
- package/src/web/scrapers/rawg.ts +2 -2
- package/src/web/scrapers/readthedocs.ts +1 -2
- package/src/web/scrapers/repology.ts +2 -2
- package/src/web/scrapers/rfc.ts +1 -1
- package/src/web/scrapers/searchcode.ts +2 -2
- package/src/web/scrapers/semantic-scholar.ts +1 -1
- package/src/web/scrapers/snapcraft.ts +2 -2
- package/src/web/scrapers/sourcegraph.ts +1 -1
- package/src/web/scrapers/spdx.ts +3 -3
- package/src/web/scrapers/spotify.ts +0 -1
- package/src/web/scrapers/twitter.ts +1 -1
- package/src/web/scrapers/types.ts +1 -2
- package/src/web/scrapers/utils.ts +5 -5
- package/src/web/scrapers/wikidata.ts +3 -3
- package/src/web/scrapers/youtube.ts +9 -14
- package/src/web/search/auth.ts +5 -10
- package/src/web/search/index.ts +11 -21
- package/src/web/search/providers/anthropic.ts +3 -9
- package/src/web/search/providers/exa.ts +6 -10
- package/src/web/search/providers/perplexity.ts +5 -5
- package/src/web/search/render.ts +129 -175
- package/tsconfig.json +0 -42
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{{#if types_description}}
|
|
2
|
+
<type_definitions>
|
|
3
|
+
{{ types_description }}
|
|
4
|
+
</type_definitions>
|
|
5
|
+
{{/if}}
|
|
6
|
+
|
|
7
|
+
<observations>
|
|
8
|
+
{{ observations }}
|
|
9
|
+
</observations>
|
|
10
|
+
|
|
11
|
+
<diff_statistics>
|
|
12
|
+
{{ stat }}
|
|
13
|
+
</diff_statistics>
|
|
14
|
+
|
|
15
|
+
<scope_candidates>
|
|
16
|
+
{{ scope_candidates }}
|
|
17
|
+
</scope_candidates>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
You are a commit message specialist generating precise, informative descriptions.
|
|
2
|
+
|
|
3
|
+
<context>
|
|
4
|
+
Output: ONLY the description after "{{ commit_type }}{{ scope_prefix }}:".
|
|
5
|
+
Constraint: {{ chars }} characters max, no trailing period, no type prefix in output.
|
|
6
|
+
</context>
|
|
7
|
+
|
|
8
|
+
<instructions>
|
|
9
|
+
1. Start with lowercase past-tense verb (must differ from "{{ commit_type }}")
|
|
10
|
+
2. Name the specific subsystem/component affected
|
|
11
|
+
3. Include WHY when it clarifies intent
|
|
12
|
+
4. One focused concept per message
|
|
13
|
+
|
|
14
|
+
Get this right.
|
|
15
|
+
</instructions>
|
|
16
|
+
|
|
17
|
+
<verb_reference>
|
|
18
|
+
| Type | Use instead |
|
|
19
|
+
|----------|-------------------------------------------------|
|
|
20
|
+
| feat | added, introduced, implemented, enabled |
|
|
21
|
+
| fix | corrected, resolved, patched, addressed |
|
|
22
|
+
| refactor | restructured, reorganized, migrated, simplified |
|
|
23
|
+
| perf | optimized, reduced, eliminated, accelerated |
|
|
24
|
+
| docs | documented, clarified, expanded |
|
|
25
|
+
| build | upgraded, pinned, configured |
|
|
26
|
+
| chore | cleaned, removed, renamed, organized |
|
|
27
|
+
</verb_reference>
|
|
28
|
+
|
|
29
|
+
<examples>
|
|
30
|
+
feat | TLS encryption added to HTTP client for MITM prevention
|
|
31
|
+
-> added TLS support to prevent man-in-the-middle attacks
|
|
32
|
+
|
|
33
|
+
refactor | Consolidated HTTP transport into unified builder pattern
|
|
34
|
+
-> migrated HTTP transport to unified builder API
|
|
35
|
+
|
|
36
|
+
fix | Race condition in connection pool causing exhaustion under load
|
|
37
|
+
-> corrected race condition causing connection pool exhaustion
|
|
38
|
+
|
|
39
|
+
perf | Batch processing optimized to reduce memory allocations
|
|
40
|
+
-> eliminated allocation overhead in batch processing
|
|
41
|
+
|
|
42
|
+
build | Updated serde to fix CVE-2024-1234
|
|
43
|
+
-> upgraded serde to 1.0.200 for CVE-2024-1234
|
|
44
|
+
</examples>
|
|
45
|
+
|
|
46
|
+
<banned_words>
|
|
47
|
+
comprehensive, various, several, improved, enhanced, quickly, simply, basically, this change, this commit, now
|
|
48
|
+
</banned_words>
|
|
49
|
+
|
|
50
|
+
<output_format>
|
|
51
|
+
Output the description text only. Include motivation, name specifics, stay focused.
|
|
52
|
+
</output_format>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the omp commit pipeline.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type CommitType =
|
|
6
|
+
| "feat"
|
|
7
|
+
| "fix"
|
|
8
|
+
| "refactor"
|
|
9
|
+
| "perf"
|
|
10
|
+
| "docs"
|
|
11
|
+
| "test"
|
|
12
|
+
| "build"
|
|
13
|
+
| "ci"
|
|
14
|
+
| "chore"
|
|
15
|
+
| "style"
|
|
16
|
+
| "revert";
|
|
17
|
+
|
|
18
|
+
export type ChangelogCategory =
|
|
19
|
+
| "Breaking Changes"
|
|
20
|
+
| "Added"
|
|
21
|
+
| "Changed"
|
|
22
|
+
| "Deprecated"
|
|
23
|
+
| "Removed"
|
|
24
|
+
| "Fixed"
|
|
25
|
+
| "Security";
|
|
26
|
+
|
|
27
|
+
export interface CommitCommandArgs {
|
|
28
|
+
/** Push after commit */
|
|
29
|
+
push: boolean;
|
|
30
|
+
/** Preview without committing */
|
|
31
|
+
dryRun: boolean;
|
|
32
|
+
/** Skip changelog updates */
|
|
33
|
+
noChangelog: boolean;
|
|
34
|
+
/** Use legacy deterministic pipeline */
|
|
35
|
+
legacy?: boolean;
|
|
36
|
+
/** Additional user context for the model */
|
|
37
|
+
context?: string;
|
|
38
|
+
/** Override the model selection */
|
|
39
|
+
model?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface NumstatEntry {
|
|
43
|
+
path: string;
|
|
44
|
+
additions: number;
|
|
45
|
+
deletions: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ConventionalDetail {
|
|
49
|
+
text: string;
|
|
50
|
+
changelogCategory?: ChangelogCategory;
|
|
51
|
+
userVisible: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ConventionalAnalysis {
|
|
55
|
+
type: CommitType;
|
|
56
|
+
scope: string | null;
|
|
57
|
+
details: ConventionalDetail[];
|
|
58
|
+
issueRefs: string[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface CommitSummary {
|
|
62
|
+
summary: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface FileObservation {
|
|
66
|
+
file: string;
|
|
67
|
+
observations: string[];
|
|
68
|
+
additions: number;
|
|
69
|
+
deletions: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface FileDiff {
|
|
73
|
+
filename: string;
|
|
74
|
+
content: string;
|
|
75
|
+
additions: number;
|
|
76
|
+
deletions: number;
|
|
77
|
+
isBinary: boolean;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface DiffHunk {
|
|
81
|
+
index: number;
|
|
82
|
+
header: string;
|
|
83
|
+
oldStart: number;
|
|
84
|
+
oldLines: number;
|
|
85
|
+
newStart: number;
|
|
86
|
+
newLines: number;
|
|
87
|
+
content: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface FileHunks {
|
|
91
|
+
filename: string;
|
|
92
|
+
isBinary: boolean;
|
|
93
|
+
hunks: DiffHunk[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface ChangelogBoundary {
|
|
97
|
+
changelogPath: string;
|
|
98
|
+
files: string[];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface UnreleasedSection {
|
|
102
|
+
startLine: number;
|
|
103
|
+
endLine: number;
|
|
104
|
+
entries: Record<string, string[]>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface ChangelogGenerationResult {
|
|
108
|
+
entries: Record<string, string[]>;
|
|
109
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const EXCLUDED_FILES = [
|
|
2
|
+
"Cargo.lock",
|
|
3
|
+
"package-lock.json",
|
|
4
|
+
"npm-shrinkwrap.json",
|
|
5
|
+
"yarn.lock",
|
|
6
|
+
"pnpm-lock.yaml",
|
|
7
|
+
"shrinkwrap.yaml",
|
|
8
|
+
"bun.lock",
|
|
9
|
+
"bun.lockb",
|
|
10
|
+
"deno.lock",
|
|
11
|
+
"composer.lock",
|
|
12
|
+
"Gemfile.lock",
|
|
13
|
+
"poetry.lock",
|
|
14
|
+
"Pipfile.lock",
|
|
15
|
+
"pdm.lock",
|
|
16
|
+
"uv.lock",
|
|
17
|
+
"go.sum",
|
|
18
|
+
"flake.lock",
|
|
19
|
+
"pubspec.lock",
|
|
20
|
+
"Podfile.lock",
|
|
21
|
+
"Packages.resolved",
|
|
22
|
+
"mix.lock",
|
|
23
|
+
"packages.lock.json",
|
|
24
|
+
"config.yml.lock",
|
|
25
|
+
"config.yaml.lock",
|
|
26
|
+
"settings.yml.lock",
|
|
27
|
+
"settings.yaml.lock",
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const EXCLUDED_SUFFIXES = [".lock.yml", ".lock.yaml", "-lock.yml", "-lock.yaml"];
|
|
31
|
+
|
|
32
|
+
export function isExcludedFile(path: string): boolean {
|
|
33
|
+
const lower = path.toLowerCase();
|
|
34
|
+
if (EXCLUDED_FILES.some(name => lower.endsWith(name.toLowerCase()))) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return EXCLUDED_SUFFIXES.some(suffix => lower.endsWith(suffix));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function filterExcludedFiles<T extends { filename: string }>(files: T[]): T[] {
|
|
41
|
+
return files.filter(file => !isExcludedFile(file.filename));
|
|
42
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import { isEnoent } from "@oh-my-pi/pi-utils";
|
|
3
|
+
|
|
4
|
+
export interface FileLockOptions {
|
|
5
|
+
staleMs?: number;
|
|
6
|
+
retries?: number;
|
|
7
|
+
retryDelayMs?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const DEFAULT_OPTIONS: Required<FileLockOptions> = {
|
|
11
|
+
staleMs: 10_000,
|
|
12
|
+
retries: 50,
|
|
13
|
+
retryDelayMs: 100,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
interface LockInfo {
|
|
17
|
+
pid: number;
|
|
18
|
+
timestamp: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getLockPath(filePath: string): string {
|
|
22
|
+
return `${filePath}.lock`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function writeLockInfo(lockPath: string): Promise<void> {
|
|
26
|
+
const info: LockInfo = { pid: process.pid, timestamp: Date.now() };
|
|
27
|
+
await Bun.write(`${lockPath}/info`, JSON.stringify(info));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function readLockInfo(lockPath: string): Promise<LockInfo | null> {
|
|
31
|
+
try {
|
|
32
|
+
const content = await fs.readFile(`${lockPath}/info`, "utf-8");
|
|
33
|
+
return JSON.parse(content) as LockInfo;
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isProcessAlive(pid: number): boolean {
|
|
40
|
+
try {
|
|
41
|
+
process.kill(pid, 0);
|
|
42
|
+
return true;
|
|
43
|
+
} catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function isLockStale(lockPath: string, staleMs: number): Promise<boolean> {
|
|
49
|
+
const info = await readLockInfo(lockPath);
|
|
50
|
+
if (!info) return true;
|
|
51
|
+
|
|
52
|
+
if (!isProcessAlive(info.pid)) return true;
|
|
53
|
+
|
|
54
|
+
if (Date.now() - info.timestamp > staleMs) return true;
|
|
55
|
+
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function tryAcquireLock(lockPath: string): Promise<boolean> {
|
|
60
|
+
try {
|
|
61
|
+
await fs.mkdir(lockPath);
|
|
62
|
+
await writeLockInfo(lockPath);
|
|
63
|
+
return true;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if ((error as NodeJS.ErrnoException).code === "EEXIST") {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function releaseLock(lockPath: string): Promise<void> {
|
|
73
|
+
try {
|
|
74
|
+
await fs.rm(lockPath, { recursive: true });
|
|
75
|
+
} catch {
|
|
76
|
+
// Ignore errors on release
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function lockExists(lockPath: string): Promise<boolean> {
|
|
81
|
+
try {
|
|
82
|
+
await fs.stat(lockPath);
|
|
83
|
+
return true;
|
|
84
|
+
} catch (err) {
|
|
85
|
+
if (isEnoent(err)) return false;
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function acquireLock(filePath: string, options: FileLockOptions = {}): Promise<() => Promise<void>> {
|
|
91
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
92
|
+
const lockPath = getLockPath(filePath);
|
|
93
|
+
|
|
94
|
+
for (let attempt = 0; attempt < opts.retries; attempt++) {
|
|
95
|
+
if (await tryAcquireLock(lockPath)) {
|
|
96
|
+
return () => releaseLock(lockPath);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if ((await lockExists(lockPath)) && (await isLockStale(lockPath, opts.staleMs))) {
|
|
100
|
+
await releaseLock(lockPath);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await new Promise(resolve => setTimeout(resolve, opts.retryDelayMs));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
throw new Error(`Failed to acquire lock for ${filePath} after ${opts.retries} attempts`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function withFileLock<T>(
|
|
111
|
+
filePath: string,
|
|
112
|
+
fn: () => Promise<T>,
|
|
113
|
+
options: FileLockOptions = {},
|
|
114
|
+
): Promise<T> {
|
|
115
|
+
const release = await acquireLock(filePath, options);
|
|
116
|
+
try {
|
|
117
|
+
return await fn();
|
|
118
|
+
} finally {
|
|
119
|
+
await release();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { getAgentDir } from "@oh-my-pi/pi-coding-agent/config";
|
|
1
|
+
import * as path from "node:path";
|
|
4
2
|
import {
|
|
5
3
|
DEFAULT_EDITOR_KEYBINDINGS,
|
|
6
4
|
type EditorAction,
|
|
@@ -11,6 +9,7 @@ import {
|
|
|
11
9
|
setEditorKeybindings,
|
|
12
10
|
} from "@oh-my-pi/pi-tui";
|
|
13
11
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
12
|
+
import { getAgentDir } from "../config";
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
15
|
* Application-level actions (coding agent specific).
|
|
@@ -162,7 +161,7 @@ export class KeybindingsManager {
|
|
|
162
161
|
* Create from config file and set up editor keybindings.
|
|
163
162
|
*/
|
|
164
163
|
static async create(agentDir: string = getAgentDir()): Promise<KeybindingsManager> {
|
|
165
|
-
const configPath = join(agentDir, "keybindings.json");
|
|
164
|
+
const configPath = path.join(agentDir, "keybindings.json");
|
|
166
165
|
const config = await KeybindingsManager.loadFromFile(configPath);
|
|
167
166
|
const manager = new KeybindingsManager(config);
|
|
168
167
|
|
|
@@ -186,9 +185,8 @@ export class KeybindingsManager {
|
|
|
186
185
|
}
|
|
187
186
|
|
|
188
187
|
private static async loadFromFile(path: string): Promise<KeybindingsConfig> {
|
|
189
|
-
if (!existsSync(path)) return {};
|
|
190
188
|
try {
|
|
191
|
-
return
|
|
189
|
+
return await Bun.file(path).json();
|
|
192
190
|
} catch (error) {
|
|
193
191
|
logger.warn("Failed to parse keybindings config", { path, error: String(error) });
|
|
194
192
|
return {};
|
|
@@ -203,7 +201,7 @@ export class KeybindingsManager {
|
|
|
203
201
|
const keyArray = Array.isArray(keys) ? keys : [keys];
|
|
204
202
|
this.appActionToKeys.set(
|
|
205
203
|
action as AppAction,
|
|
206
|
-
keyArray.map(
|
|
204
|
+
keyArray.map(key => normalizeKeyId(key as KeyId)),
|
|
207
205
|
);
|
|
208
206
|
}
|
|
209
207
|
|
|
@@ -213,7 +211,7 @@ export class KeybindingsManager {
|
|
|
213
211
|
const keyArray = Array.isArray(keys) ? keys : [keys];
|
|
214
212
|
this.appActionToKeys.set(
|
|
215
213
|
action,
|
|
216
|
-
keyArray.map(
|
|
214
|
+
keyArray.map(key => normalizeKeyId(key as KeyId)),
|
|
217
215
|
);
|
|
218
216
|
}
|
|
219
217
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Model registry - manages built-in and custom models, provides API key resolution.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import
|
|
4
|
+
import * as fs from "node:fs";
|
|
5
|
+
import * as path from "node:path";
|
|
6
6
|
import {
|
|
7
7
|
type Api,
|
|
8
8
|
getGitHubCopilotBaseUrl,
|
|
@@ -11,10 +11,11 @@ import {
|
|
|
11
11
|
type Model,
|
|
12
12
|
normalizeDomain,
|
|
13
13
|
} from "@oh-my-pi/pi-ai";
|
|
14
|
-
import
|
|
15
|
-
import { logger } from "@oh-my-pi/pi-utils";
|
|
14
|
+
import { isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
16
15
|
import { type Static, Type } from "@sinclair/typebox";
|
|
17
16
|
import AjvModule from "ajv";
|
|
17
|
+
import { YAML } from "bun";
|
|
18
|
+
import type { AuthStorage } from "../session/auth-storage";
|
|
18
19
|
|
|
19
20
|
const Ajv = (AjvModule as any).default || AjvModule;
|
|
20
21
|
|
|
@@ -102,10 +103,12 @@ interface CustomModelsResult {
|
|
|
102
103
|
/** Providers with only baseUrl/headers override (no custom models) */
|
|
103
104
|
overrides: Map<string, ProviderOverride>;
|
|
104
105
|
error: string | undefined;
|
|
106
|
+
/** Whether the file was found (true) or didn't exist (false) */
|
|
107
|
+
found: boolean;
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
function emptyCustomModelsResult(error?: string): CustomModelsResult {
|
|
108
|
-
return { models: [], replacedProviders: new Set(), overrides: new Map(), error };
|
|
111
|
+
return { models: [], replacedProviders: new Set(), overrides: new Map(), error, found: false };
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
/**
|
|
@@ -137,7 +140,7 @@ export class ModelRegistry {
|
|
|
137
140
|
private fallbackPaths: string[] = [],
|
|
138
141
|
) {
|
|
139
142
|
// Set up fallback resolver for custom provider API keys
|
|
140
|
-
this.authStorage.setFallbackResolver(
|
|
143
|
+
this.authStorage.setFallbackResolver(provider => {
|
|
141
144
|
const keyConfig = this.customProviderApiKeys.get(provider);
|
|
142
145
|
if (keyConfig) {
|
|
143
146
|
return resolveApiKeyConfig(keyConfig);
|
|
@@ -159,7 +162,7 @@ export class ModelRegistry {
|
|
|
159
162
|
instance.customProviderApiKeys = new Map(Object.entries(data.customProviderApiKeys ?? {}));
|
|
160
163
|
instance.loadError = data.loadError;
|
|
161
164
|
|
|
162
|
-
authStorage.setFallbackResolver(
|
|
165
|
+
authStorage.setFallbackResolver(provider => {
|
|
163
166
|
const keyConfig = instance.customProviderApiKeys.get(provider);
|
|
164
167
|
if (keyConfig) {
|
|
165
168
|
return resolveApiKeyConfig(keyConfig);
|
|
@@ -201,7 +204,7 @@ export class ModelRegistry {
|
|
|
201
204
|
return this.loadError;
|
|
202
205
|
}
|
|
203
206
|
|
|
204
|
-
private loadModels()
|
|
207
|
+
private loadModels() {
|
|
205
208
|
// Load custom models from models.json first (to know which providers to skip/override)
|
|
206
209
|
let customModels: Model<Api>[] = [];
|
|
207
210
|
let replacedProviders: Set<string> = new Set();
|
|
@@ -213,19 +216,20 @@ export class ModelRegistry {
|
|
|
213
216
|
}
|
|
214
217
|
|
|
215
218
|
for (const modelsPath of pathsToCheck) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (result.error) {
|
|
220
|
-
this.loadError = result.error;
|
|
221
|
-
// Keep built-in models even if custom models failed to load
|
|
222
|
-
} else {
|
|
223
|
-
customModels = result.models;
|
|
224
|
-
replacedProviders = result.replacedProviders;
|
|
225
|
-
overrides = result.overrides;
|
|
226
|
-
}
|
|
227
|
-
break; // Use first existing file
|
|
219
|
+
const result = this.loadCustomModels(modelsPath);
|
|
220
|
+
if (!result.found) {
|
|
221
|
+
continue; // File doesn't exist, try next path
|
|
228
222
|
}
|
|
223
|
+
logger.debug("ModelRegistry.loadModels loading", { path: modelsPath });
|
|
224
|
+
if (result.error) {
|
|
225
|
+
this.loadError = result.error;
|
|
226
|
+
// Keep built-in models even if custom models failed to load
|
|
227
|
+
} else {
|
|
228
|
+
customModels = result.models;
|
|
229
|
+
replacedProviders = result.replacedProviders;
|
|
230
|
+
overrides = result.overrides;
|
|
231
|
+
}
|
|
232
|
+
break; // Use first existing file
|
|
229
233
|
}
|
|
230
234
|
|
|
231
235
|
const builtInModels = this.loadBuiltInModels(replacedProviders, overrides);
|
|
@@ -238,7 +242,7 @@ export class ModelRegistry {
|
|
|
238
242
|
? (normalizeDomain(copilotCred.enterpriseUrl) ?? undefined)
|
|
239
243
|
: undefined;
|
|
240
244
|
const baseUrl = getGitHubCopilotBaseUrl(copilotCred.access, domain);
|
|
241
|
-
this.models = combined.map(
|
|
245
|
+
this.models = combined.map(m => (m.provider === "github-copilot" ? { ...m, baseUrl } : m));
|
|
242
246
|
} else {
|
|
243
247
|
this.models = combined;
|
|
244
248
|
}
|
|
@@ -247,14 +251,14 @@ export class ModelRegistry {
|
|
|
247
251
|
/** Load built-in models, skipping replaced providers and applying overrides */
|
|
248
252
|
private loadBuiltInModels(replacedProviders: Set<string>, overrides: Map<string, ProviderOverride>): Model<Api>[] {
|
|
249
253
|
return getProviders()
|
|
250
|
-
.filter(
|
|
251
|
-
.flatMap(
|
|
254
|
+
.filter(provider => !replacedProviders.has(provider))
|
|
255
|
+
.flatMap(provider => {
|
|
252
256
|
const models = getModels(provider as any) as Model<Api>[];
|
|
253
257
|
const override = overrides.get(provider);
|
|
254
258
|
if (!override) return models;
|
|
255
259
|
|
|
256
260
|
// Apply baseUrl/headers override to all models of this provider
|
|
257
|
-
return models.map(
|
|
261
|
+
return models.map(m => ({
|
|
258
262
|
...m,
|
|
259
263
|
baseUrl: override.baseUrl ?? m.baseUrl,
|
|
260
264
|
headers: override.headers ? { ...m.headers, ...override.headers } : m.headers,
|
|
@@ -262,14 +266,31 @@ export class ModelRegistry {
|
|
|
262
266
|
});
|
|
263
267
|
}
|
|
264
268
|
|
|
265
|
-
private loadCustomModels(
|
|
266
|
-
|
|
267
|
-
|
|
269
|
+
private loadCustomModels(modelsPath: string): CustomModelsResult {
|
|
270
|
+
let content: string;
|
|
271
|
+
try {
|
|
272
|
+
content = fs.readFileSync(modelsPath, "utf-8");
|
|
273
|
+
} catch (error) {
|
|
274
|
+
if (isEnoent(error)) {
|
|
275
|
+
return emptyCustomModelsResult();
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
...emptyCustomModelsResult(
|
|
279
|
+
`Failed to load models config: ${error instanceof Error ? error.message : error}\n\nFile: ${modelsPath}`,
|
|
280
|
+
),
|
|
281
|
+
found: true,
|
|
282
|
+
};
|
|
268
283
|
}
|
|
269
284
|
|
|
270
285
|
try {
|
|
271
|
-
const
|
|
272
|
-
|
|
286
|
+
const ext = path.extname(modelsPath).toLowerCase();
|
|
287
|
+
let config: ModelsConfig;
|
|
288
|
+
|
|
289
|
+
if (ext === ".yaml" || ext === ".yml") {
|
|
290
|
+
config = YAML.parse(content) as ModelsConfig;
|
|
291
|
+
} else {
|
|
292
|
+
config = JSON.parse(content) as ModelsConfig;
|
|
293
|
+
}
|
|
273
294
|
|
|
274
295
|
// Validate schema
|
|
275
296
|
const ajv = new Ajv();
|
|
@@ -278,7 +299,7 @@ export class ModelRegistry {
|
|
|
278
299
|
const errors =
|
|
279
300
|
validate.errors?.map((e: any) => ` - ${e.instancePath || "root"}: ${e.message}`).join("\n") ||
|
|
280
301
|
"Unknown schema error";
|
|
281
|
-
return emptyCustomModelsResult(`Invalid models
|
|
302
|
+
return emptyCustomModelsResult(`Invalid models config schema:\n${errors}\n\nFile: ${modelsPath}`);
|
|
282
303
|
}
|
|
283
304
|
|
|
284
305
|
// Additional validation
|
|
@@ -306,14 +327,20 @@ export class ModelRegistry {
|
|
|
306
327
|
}
|
|
307
328
|
}
|
|
308
329
|
|
|
309
|
-
return { models: this.parseModels(config), replacedProviders, overrides, error: undefined };
|
|
330
|
+
return { models: this.parseModels(config), replacedProviders, overrides, error: undefined, found: true };
|
|
310
331
|
} catch (error) {
|
|
311
332
|
if (error instanceof SyntaxError) {
|
|
312
|
-
return
|
|
333
|
+
return {
|
|
334
|
+
...emptyCustomModelsResult(`Failed to parse models config: ${error.message}\n\nFile: ${modelsPath}`),
|
|
335
|
+
found: true,
|
|
336
|
+
};
|
|
313
337
|
}
|
|
314
|
-
return
|
|
315
|
-
|
|
316
|
-
|
|
338
|
+
return {
|
|
339
|
+
...emptyCustomModelsResult(
|
|
340
|
+
`Failed to load models config: ${error instanceof Error ? error.message : error}\n\nFile: ${modelsPath}`,
|
|
341
|
+
),
|
|
342
|
+
found: true,
|
|
343
|
+
};
|
|
317
344
|
}
|
|
318
345
|
}
|
|
319
346
|
|
|
@@ -422,21 +449,21 @@ export class ModelRegistry {
|
|
|
422
449
|
* This is a fast check that doesn't refresh OAuth tokens.
|
|
423
450
|
*/
|
|
424
451
|
getAvailable(): Model<Api>[] {
|
|
425
|
-
return this.models.filter(
|
|
452
|
+
return this.models.filter(m => this.authStorage.hasAuth(m.provider));
|
|
426
453
|
}
|
|
427
454
|
|
|
428
455
|
/**
|
|
429
456
|
* Find a model by provider and ID.
|
|
430
457
|
*/
|
|
431
458
|
find(provider: string, modelId: string): Model<Api> | undefined {
|
|
432
|
-
return this.models.find(
|
|
459
|
+
return this.models.find(m => m.provider === provider && m.id === modelId);
|
|
433
460
|
}
|
|
434
461
|
|
|
435
462
|
/**
|
|
436
463
|
* Get the base URL associated with a provider, if any model defines one.
|
|
437
464
|
*/
|
|
438
465
|
getProviderBaseUrl(provider: string): string | undefined {
|
|
439
|
-
return this.models.find(
|
|
466
|
+
return this.models.find(m => m.provider === provider && m.baseUrl)?.baseUrl;
|
|
440
467
|
}
|
|
441
468
|
|
|
442
469
|
/**
|