@armadra/agent 0.3.0 → 0.5.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 +257 -0
- package/README.md +263 -95
- package/THIRD_PARTY_NOTICES.md +34 -0
- package/dist/acp.d.ts +18 -0
- package/dist/acp.js +19 -0
- package/dist/agent/limits.d.ts +38 -0
- package/dist/agent/limits.js +127 -0
- package/dist/agent/loop-guard.d.ts +38 -0
- package/dist/agent/loop-guard.js +95 -0
- package/dist/agent/loop.d.ts +4 -0
- package/dist/agent/loop.js +7 -0
- package/dist/agent/prompt-rules.d.ts +12 -0
- package/dist/agent/prompt-rules.js +18 -0
- package/dist/agent/reminders.d.ts +59 -0
- package/dist/agent/reminders.js +327 -0
- package/dist/agent/retry.d.ts +1 -1
- package/dist/agent/retry.js +2 -1
- package/dist/agent/session-cache.d.ts +5 -0
- package/dist/agent/session-cache.js +18 -2
- package/dist/agent/session-classifier.d.ts +18 -0
- package/dist/agent/session-classifier.js +105 -0
- package/dist/agent/session-compaction.d.ts +35 -6
- package/dist/agent/session-compaction.js +157 -31
- package/dist/agent/session-core.d.ts +40 -1
- package/dist/agent/session-extensions.d.ts +61 -0
- package/dist/agent/session-extensions.js +129 -0
- package/dist/agent/session-images.d.ts +23 -0
- package/dist/agent/session-images.js +97 -0
- package/dist/agent/session-plan.d.ts +21 -0
- package/dist/agent/session-plan.js +524 -0
- package/dist/agent/session-rewind.d.ts +81 -0
- package/dist/agent/session-rewind.js +354 -0
- package/dist/agent/session-run.d.ts +28 -1
- package/dist/agent/session-run.js +157 -6
- package/dist/agent/session-settings.d.ts +49 -0
- package/dist/agent/session-settings.js +95 -0
- package/dist/agent/session-subagent.d.ts +36 -24
- package/dist/agent/session-subagent.js +259 -129
- package/dist/agent/session-sync.d.ts +10 -3
- package/dist/agent/session-sync.js +37 -8
- package/dist/agent/session-telemetry.d.ts +39 -0
- package/dist/agent/session-telemetry.js +231 -0
- package/dist/agent/session-tools.js +63 -3
- package/dist/agent/session.d.ts +33 -29
- package/dist/agent/session.js +91 -126
- package/dist/agent/subagent-registry.d.ts +91 -0
- package/dist/agent/subagent-registry.js +494 -0
- package/dist/agent/system-prompt.d.ts +6 -3
- package/dist/agent/system-prompt.js +7 -2
- package/dist/agent/tool-runner.d.ts +8 -1
- package/dist/agent/tool-runner.js +72 -6
- package/dist/agent/types-w5.d.ts +192 -0
- package/dist/agent/types-w5.js +10 -0
- package/dist/agent/types.d.ts +55 -4
- package/dist/agent/types.js +2 -0
- package/dist/agent/worktree.d.ts +36 -0
- package/dist/agent/worktree.js +86 -0
- package/dist/agents/builtin.d.ts +14 -0
- package/dist/agents/builtin.js +39 -0
- package/dist/agents/catalog.d.ts +43 -0
- package/dist/agents/catalog.js +82 -0
- package/dist/agents/discover.d.ts +35 -0
- package/dist/agents/discover.js +83 -0
- package/dist/agents/external.d.ts +82 -0
- package/dist/agents/external.js +326 -0
- package/dist/agents/parse.d.ts +18 -0
- package/dist/agents/parse.js +116 -0
- package/dist/agents/result.d.ts +32 -0
- package/dist/agents/result.js +67 -0
- package/dist/agents/task-control.d.ts +17 -0
- package/dist/agents/task-control.js +17 -0
- package/dist/agents/task-record.d.ts +78 -0
- package/dist/agents/task-record.js +141 -0
- package/dist/agents/types.d.ts +46 -0
- package/dist/agents/types.js +8 -0
- package/dist/ai/apis/anthropic-compat.d.ts +36 -0
- package/dist/ai/apis/anthropic-compat.js +92 -0
- package/dist/ai/apis/anthropic-messages.js +3 -2
- package/dist/ai/apis/anthropic-request.d.ts +7 -6
- package/dist/ai/apis/anthropic-request.js +10 -28
- package/dist/ai/apis/cache-params.d.ts +11 -2
- package/dist/ai/apis/cache-params.js +25 -6
- package/dist/ai/apis/google-generative-ai.js +3 -2
- package/dist/ai/apis/openai-compat.d.ts +4 -1
- package/dist/ai/apis/openai-compat.js +8 -1
- package/dist/ai/apis/openai-completions.js +3 -2
- package/dist/ai/apis/openai-responses.js +3 -2
- package/dist/ai/http.d.ts +28 -6
- package/dist/ai/http.js +41 -8
- package/dist/ai/image-limits.d.ts +45 -0
- package/dist/ai/image-limits.js +68 -0
- package/dist/ai/providers/builtin.d.ts +18 -6
- package/dist/ai/providers/builtin.js +135 -6
- package/dist/ai/providers/catalog-data.js +17 -13
- package/dist/ai/providers/catalog.d.ts +60 -7
- package/dist/ai/providers/catalog.js +197 -38
- package/dist/ai/providers/channels.d.ts +33 -3
- package/dist/ai/providers/channels.js +108 -7
- package/dist/ai/providers/enrich.d.ts +6 -3
- package/dist/ai/providers/enrich.js +19 -4
- package/dist/ai/providers/models-dev-cache.d.ts +28 -24
- package/dist/ai/providers/models-dev-cache.js +92 -78
- package/dist/ai/providers/models-dev-data.d.ts +7 -0
- package/dist/ai/providers/models-dev-data.js +32 -0
- package/dist/ai/providers/models-dev-snapshot.d.ts +50 -0
- package/dist/ai/providers/models-dev-snapshot.js +137 -0
- package/dist/ai/providers/models-dev.d.ts +51 -10
- package/dist/ai/providers/models-dev.js +132 -39
- package/dist/ai/providers/registry.d.ts +28 -11
- package/dist/ai/providers/registry.js +112 -65
- package/dist/ai/providers/suggest.d.ts +18 -0
- package/dist/ai/providers/suggest.js +72 -0
- package/dist/ai/sse.d.ts +6 -2
- package/dist/ai/sse.js +22 -2
- package/dist/ai/types.d.ts +37 -4
- package/dist/ai/types.js +5 -0
- package/dist/bundle/ama.cjs +41979 -21147
- package/dist/checkpoints/backend.d.ts +61 -0
- package/dist/checkpoints/backend.js +135 -0
- package/dist/checkpoints/blobs.d.ts +60 -0
- package/dist/checkpoints/blobs.js +203 -0
- package/dist/checkpoints/gc.d.ts +47 -0
- package/dist/checkpoints/gc.js +144 -0
- package/dist/checkpoints/git-head.d.ts +15 -0
- package/dist/checkpoints/git-head.js +89 -0
- package/dist/checkpoints/index.d.ts +17 -0
- package/dist/checkpoints/index.js +17 -0
- package/dist/checkpoints/replay.d.ts +48 -0
- package/dist/checkpoints/replay.js +154 -0
- package/dist/checkpoints/restore.d.ts +86 -0
- package/dist/checkpoints/restore.js +263 -0
- package/dist/checkpoints/settings.d.ts +14 -0
- package/dist/checkpoints/settings.js +23 -0
- package/dist/checkpoints/shadow-git.d.ts +108 -0
- package/dist/checkpoints/shadow-git.js +491 -0
- package/dist/checkpoints/shadow-restore.d.ts +25 -0
- package/dist/checkpoints/shadow-restore.js +128 -0
- package/dist/checkpoints/tracker.d.ts +64 -0
- package/dist/checkpoints/tracker.js +192 -0
- package/dist/checkpoints/types.d.ts +99 -0
- package/dist/checkpoints/types.js +12 -0
- package/dist/cli/args.d.ts +26 -7
- package/dist/cli/args.js +75 -82
- package/dist/cli/bootstrap.js +40 -4
- package/dist/cli/codemode-notice.d.ts +21 -0
- package/dist/cli/codemode-notice.js +56 -0
- package/dist/cli/compose-agents.d.ts +27 -0
- package/dist/cli/compose-agents.js +111 -0
- package/dist/cli/compose-extensions.d.ts +29 -0
- package/dist/cli/compose-extensions.js +44 -0
- package/dist/cli/compose-session.d.ts +8 -0
- package/dist/cli/compose-session.js +76 -2
- package/dist/cli/compose-store.d.ts +1 -1
- package/dist/cli/compose-store.js +3 -1
- package/dist/cli/compose.d.ts +17 -4
- package/dist/cli/compose.js +60 -14
- package/dist/cli/default-model.d.ts +38 -1
- package/dist/cli/default-model.js +96 -9
- package/dist/cli/deps.d.ts +42 -0
- package/dist/cli/exit-codes.d.ts +12 -0
- package/dist/cli/exit-codes.js +15 -0
- package/dist/cli/fake-visibility.d.ts +13 -0
- package/dist/cli/fake-visibility.js +26 -0
- package/dist/cli/from-prompt.d.ts +18 -0
- package/dist/cli/from-prompt.js +49 -0
- package/dist/cli/help-text.d.ts +4 -0
- package/dist/cli/help-text.js +102 -0
- package/dist/cli/main.d.ts +9 -2
- package/dist/cli/main.js +77 -3
- package/dist/cli/proxy.d.ts +51 -0
- package/dist/cli/proxy.js +135 -0
- package/dist/cli/startup-screen.d.ts +29 -0
- package/dist/cli/startup-screen.js +51 -2
- package/dist/cli/startup-steps.d.ts +1 -1
- package/dist/cli/startup-steps.js +21 -13
- package/dist/cli/subcommands/config.d.ts +22 -3
- package/dist/cli/subcommands/config.js +119 -21
- package/dist/cli/subcommands/context.js +4 -1
- package/dist/cli/subcommands/doctor.js +33 -1
- package/dist/cli/subcommands/init.js +2 -1
- package/dist/cli/subcommands/models-discover.d.ts +15 -9
- package/dist/cli/subcommands/models-discover.js +58 -52
- package/dist/cli/subcommands/models.d.ts +2 -0
- package/dist/cli/subcommands/models.js +33 -14
- package/dist/cli/subcommands/probe-runner.d.ts +96 -0
- package/dist/cli/subcommands/probe-runner.js +264 -0
- package/dist/cli/subcommands/providers-probe.d.ts +34 -0
- package/dist/cli/subcommands/providers-probe.js +87 -0
- package/dist/cli/subcommands/providers.d.ts +3 -2
- package/dist/cli/subcommands/providers.js +53 -51
- package/dist/cli/subcommands/sessions-export.d.ts +10 -0
- package/dist/cli/subcommands/sessions-export.js +59 -0
- package/dist/cli/subcommands/sessions-search.d.ts +13 -0
- package/dist/cli/subcommands/sessions-search.js +103 -0
- package/dist/cli/subcommands/sessions.d.ts +6 -3
- package/dist/cli/subcommands/sessions.js +58 -3
- package/dist/cli/subcommands/stats.d.ts +17 -0
- package/dist/cli/subcommands/stats.js +198 -0
- package/dist/cli/system-prompt-arg.d.ts +11 -0
- package/dist/cli/system-prompt-arg.js +34 -0
- package/dist/codemode/capability.d.ts +24 -7
- package/dist/codemode/capability.js +38 -10
- package/dist/codemode/host-side.d.ts +14 -0
- package/dist/codemode/host-side.js +24 -1
- package/dist/codemode/modes.d.ts +4 -11
- package/dist/codemode/modes.js +5 -27
- package/dist/codemode/tool.d.ts +18 -14
- package/dist/codemode/tool.js +76 -31
- package/dist/compaction/breaker.d.ts +25 -9
- package/dist/compaction/breaker.js +47 -17
- package/dist/compaction/estimate.d.ts +11 -3
- package/dist/compaction/estimate.js +64 -22
- package/dist/compaction/image-budget.d.ts +45 -0
- package/dist/compaction/image-budget.js +115 -0
- package/dist/compaction/post-compact.d.ts +38 -0
- package/dist/compaction/post-compact.js +152 -0
- package/dist/compaction/protect.d.ts +27 -0
- package/dist/compaction/protect.js +56 -0
- package/dist/compaction/prune-tier.d.ts +58 -12
- package/dist/compaction/prune-tier.js +120 -54
- package/dist/compaction/summarize-tier.d.ts +23 -4
- package/dist/compaction/summarize-tier.js +100 -29
- package/dist/config/checker.d.ts +28 -0
- package/dist/config/checker.js +97 -0
- package/dist/config/init.d.ts +6 -2
- package/dist/config/init.js +12 -5
- package/dist/config/json-schema.d.ts +1 -0
- package/dist/config/json-schema.js +98 -4
- package/dist/config/key-docs.d.ts +22 -0
- package/dist/config/key-docs.js +174 -0
- package/dist/config/merge.d.ts +12 -9
- package/dist/config/merge.js +102 -13
- package/dist/config/profile.d.ts +2 -0
- package/dist/config/profile.js +2 -0
- package/dist/config/schema-w5.d.ts +18 -0
- package/dist/config/schema-w5.js +109 -0
- package/dist/config/schema.d.ts +5 -9
- package/dist/config/schema.js +91 -118
- package/dist/config/types-w5.d.ts +118 -0
- package/dist/config/types-w5.js +20 -0
- package/dist/config/types.d.ts +84 -7
- package/dist/config/types.js +29 -1
- package/dist/drivers/acp/client.d.ts +57 -0
- package/dist/drivers/acp/client.js +160 -0
- package/dist/drivers/acp/driver.d.ts +31 -0
- package/dist/drivers/acp/driver.js +274 -0
- package/dist/drivers/acp/testing/fake-agent-main.d.ts +5 -0
- package/dist/drivers/acp/testing/fake-agent-main.js +7 -0
- package/dist/drivers/acp/testing/fake-agent.d.ts +27 -0
- package/dist/drivers/acp/testing/fake-agent.js +211 -0
- package/dist/drivers/acp/types.d.ts +285 -0
- package/dist/drivers/acp/types.js +36 -0
- package/dist/drivers/agents.d.ts +58 -0
- package/dist/drivers/agents.js +142 -0
- package/dist/drivers/base.d.ts +35 -0
- package/dist/drivers/base.js +59 -0
- package/dist/drivers/catalog.d.ts +46 -0
- package/dist/drivers/catalog.js +167 -0
- package/dist/drivers/env.d.ts +20 -0
- package/dist/drivers/env.js +46 -0
- package/dist/drivers/host-runners.d.ts +18 -0
- package/dist/drivers/host-runners.js +45 -0
- package/dist/drivers/jsonrpc.d.ts +58 -0
- package/dist/drivers/jsonrpc.js +180 -0
- package/dist/drivers/native/claude-normalize.d.ts +46 -0
- package/dist/drivers/native/claude-normalize.js +106 -0
- package/dist/drivers/native/claude-stream.d.ts +29 -0
- package/dist/drivers/native/claude-stream.js +456 -0
- package/dist/drivers/native/codex-app-server.d.ts +26 -0
- package/dist/drivers/native/codex-app-server.js +407 -0
- package/dist/drivers/native/codex-normalize.d.ts +38 -0
- package/dist/drivers/native/codex-normalize.js +124 -0
- package/dist/drivers/native/oneshot.d.ts +28 -0
- package/dist/drivers/native/oneshot.js +312 -0
- package/dist/drivers/permissions.d.ts +40 -0
- package/dist/drivers/permissions.js +92 -0
- package/dist/drivers/pids.d.ts +32 -0
- package/dist/drivers/pids.js +93 -0
- package/dist/drivers/pool.d.ts +28 -0
- package/dist/drivers/pool.js +96 -0
- package/dist/drivers/probe.d.ts +47 -0
- package/dist/drivers/probe.js +172 -0
- package/dist/drivers/process.d.ts +48 -0
- package/dist/drivers/process.js +100 -0
- package/dist/drivers/runner.d.ts +61 -0
- package/dist/drivers/runner.js +388 -0
- package/dist/drivers/store.d.ts +49 -0
- package/dist/drivers/store.js +91 -0
- package/dist/drivers/turn.d.ts +41 -0
- package/dist/drivers/turn.js +99 -0
- package/dist/drivers/types.d.ts +122 -0
- package/dist/drivers/types.js +11 -0
- package/dist/git/info.d.ts +75 -0
- package/dist/git/info.js +191 -0
- package/dist/hooks/protocol.js +6 -1
- package/dist/hooks/types.d.ts +10 -1
- package/dist/hooks/types.js +2 -0
- package/dist/host/api-impl.d.ts +7 -0
- package/dist/host/api-impl.js +15 -0
- package/dist/host/types.d.ts +24 -2
- package/dist/host/types.js +4 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/modes/acp/acp-events.d.ts +46 -0
- package/dist/modes/acp/acp-events.js +233 -0
- package/dist/modes/acp/acp-mode.d.ts +17 -0
- package/dist/modes/acp/acp-mode.js +47 -0
- package/dist/modes/acp/acp-server.d.ts +79 -0
- package/dist/modes/acp/acp-server.js +315 -0
- package/dist/modes/commands-core.d.ts +7 -1
- package/dist/modes/commands-core.js +61 -5
- package/dist/modes/image-input.d.ts +12 -4
- package/dist/modes/image-input.js +22 -5
- package/dist/modes/interactive/agent-panels.d.ts +14 -0
- package/dist/modes/interactive/agent-panels.js +103 -0
- package/dist/modes/interactive/agent-ui.d.ts +73 -0
- package/dist/modes/interactive/agent-ui.js +234 -0
- package/dist/modes/interactive/approval-dialog.d.ts +40 -7
- package/dist/modes/interactive/approval-dialog.js +192 -35
- package/dist/modes/interactive/approval-merge.d.ts +41 -0
- package/dist/modes/interactive/approval-merge.js +89 -0
- package/dist/modes/interactive/clipboard-paste.d.ts +18 -0
- package/dist/modes/interactive/clipboard-paste.js +28 -0
- package/dist/modes/interactive/commands.d.ts +20 -3
- package/dist/modes/interactive/commands.js +75 -16
- package/dist/modes/interactive/double-esc.d.ts +20 -0
- package/dist/modes/interactive/double-esc.js +34 -0
- package/dist/modes/interactive/event-notices.d.ts +32 -0
- package/dist/modes/interactive/event-notices.js +79 -0
- package/dist/modes/interactive/external-editor.d.ts +16 -0
- package/dist/modes/interactive/external-editor.js +39 -0
- package/dist/modes/interactive/interactive-mode.d.ts +16 -2
- package/dist/modes/interactive/interactive-mode.js +184 -202
- package/dist/modes/interactive/key-dispatch.d.ts +18 -2
- package/dist/modes/interactive/key-dispatch.js +53 -6
- package/dist/modes/interactive/line/line-mode.d.ts +3 -1
- package/dist/modes/interactive/line/line-mode.js +28 -9
- package/dist/modes/interactive/line/line-render.d.ts +6 -1
- package/dist/modes/interactive/line/line-render.js +66 -8
- package/dist/modes/interactive/message-view.d.ts +49 -10
- package/dist/modes/interactive/message-view.js +262 -46
- package/dist/modes/interactive/panels.d.ts +35 -0
- package/dist/modes/interactive/panels.js +157 -0
- package/dist/modes/interactive/pickers.d.ts +23 -2
- package/dist/modes/interactive/pickers.js +48 -15
- package/dist/modes/interactive/plan-command.d.ts +40 -0
- package/dist/modes/interactive/plan-command.js +129 -0
- package/dist/modes/interactive/plan-dialog.d.ts +98 -0
- package/dist/modes/interactive/plan-dialog.js +290 -0
- package/dist/modes/interactive/plan-flow.d.ts +34 -0
- package/dist/modes/interactive/plan-flow.js +98 -0
- package/dist/modes/interactive/rewind-command.d.ts +31 -0
- package/dist/modes/interactive/rewind-command.js +106 -0
- package/dist/modes/interactive/rewind-flow.d.ts +37 -0
- package/dist/modes/interactive/rewind-flow.js +151 -0
- package/dist/modes/interactive/rewind-list.d.ts +36 -0
- package/dist/modes/interactive/rewind-list.js +123 -0
- package/dist/modes/interactive/rewind-panel.d.ts +77 -0
- package/dist/modes/interactive/rewind-panel.js +309 -0
- package/dist/modes/interactive/rewind-text.d.ts +40 -0
- package/dist/modes/interactive/rewind-text.js +139 -0
- package/dist/modes/interactive/run-indicator.d.ts +51 -0
- package/dist/modes/interactive/run-indicator.js +189 -0
- package/dist/modes/interactive/session-events.d.ts +24 -0
- package/dist/modes/interactive/session-events.js +96 -0
- package/dist/modes/interactive/startup-header.d.ts +40 -0
- package/dist/modes/interactive/startup-header.js +169 -0
- package/dist/modes/interactive/status-area.d.ts +73 -0
- package/dist/modes/interactive/status-area.js +190 -0
- package/dist/modes/interactive/status-bar.d.ts +107 -16
- package/dist/modes/interactive/status-bar.js +306 -81
- package/dist/modes/interactive/status-line.d.ts +33 -0
- package/dist/modes/interactive/status-line.js +113 -0
- package/dist/modes/interactive/subagent-view.d.ts +56 -0
- package/dist/modes/interactive/subagent-view.js +154 -0
- package/dist/modes/interactive/tasks-report.d.ts +27 -0
- package/dist/modes/interactive/tasks-report.js +114 -0
- package/dist/modes/interactive/tool-summary.d.ts +46 -0
- package/dist/modes/interactive/tool-summary.js +218 -0
- package/dist/modes/interactive/tool-view.d.ts +58 -15
- package/dist/modes/interactive/tool-view.js +233 -145
- package/dist/modes/print/print-mode.d.ts +40 -4
- package/dist/modes/print/print-mode.js +161 -8
- package/dist/modes/rpc/commands.d.ts +9 -0
- package/dist/modes/rpc/commands.js +49 -0
- package/dist/modes/rpc/rpc-mode.js +7 -1
- package/dist/modes/session-report.d.ts +11 -0
- package/dist/modes/session-report.js +48 -1
- package/dist/permissions/auto-safe.d.ts +65 -0
- package/dist/permissions/auto-safe.js +547 -0
- package/dist/permissions/classifier.d.ts +68 -0
- package/dist/permissions/classifier.js +186 -0
- package/dist/permissions/dangerous.d.ts +5 -0
- package/dist/permissions/dangerous.js +1 -1
- package/dist/permissions/modes.d.ts +30 -0
- package/dist/permissions/modes.js +78 -0
- package/dist/permissions/pipeline.d.ts +72 -6
- package/dist/permissions/pipeline.js +306 -11
- package/dist/permissions/protected.d.ts +19 -0
- package/dist/permissions/protected.js +74 -0
- package/dist/permissions/readonly-bash.d.ts +30 -0
- package/dist/permissions/readonly-bash.js +118 -0
- package/dist/permissions/rules.js +3 -0
- package/dist/permissions/types.d.ts +92 -3
- package/dist/permissions/types.js +3 -0
- package/dist/plan/compose.d.ts +9 -0
- package/dist/plan/compose.js +19 -0
- package/dist/plan/controller.d.ts +71 -0
- package/dist/plan/controller.js +27 -0
- package/dist/plan/done-markers.d.ts +17 -0
- package/dist/plan/done-markers.js +51 -0
- package/dist/plan/extract.d.ts +29 -0
- package/dist/plan/extract.js +160 -0
- package/dist/plan/prompts.d.ts +36 -0
- package/dist/plan/prompts.js +89 -0
- package/dist/plan/store.d.ts +37 -0
- package/dist/plan/store.js +90 -0
- package/dist/rpc.d.ts +58 -2
- package/dist/rpc.js +7 -0
- package/dist/sandbox/bash.d.ts +74 -0
- package/dist/sandbox/bash.js +126 -0
- package/dist/sandbox/detect.d.ts +48 -0
- package/dist/sandbox/detect.js +149 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/profile.d.ts +33 -0
- package/dist/sandbox/profile.js +76 -0
- package/dist/sandbox/wrap.d.ts +29 -0
- package/dist/sandbox/wrap.js +117 -0
- package/dist/sdk.d.ts +42 -5
- package/dist/sdk.js +34 -4
- package/dist/session/export.d.ts +32 -0
- package/dist/session/export.js +187 -0
- package/dist/session/redact.d.ts +15 -0
- package/dist/session/redact.js +55 -0
- package/dist/session/reuse.d.ts +33 -0
- package/dist/session/reuse.js +86 -0
- package/dist/session/scan.d.ts +34 -0
- package/dist/session/scan.js +140 -0
- package/dist/session/search.d.ts +52 -0
- package/dist/session/search.js +211 -0
- package/dist/session/stats-aggregate.d.ts +63 -0
- package/dist/session/stats-aggregate.js +163 -0
- package/dist/session/stats-index.d.ts +26 -0
- package/dist/session/stats-index.js +91 -0
- package/dist/session/stats-scan.d.ts +54 -0
- package/dist/session/stats-scan.js +236 -0
- package/dist/session/types.d.ts +3 -1
- package/dist/session/types.js +1 -0
- package/dist/skills/builtin.d.ts +31 -0
- package/dist/skills/builtin.js +109 -0
- package/dist/skills/discover.d.ts +2 -1
- package/dist/skills/index-prompt.js +5 -8
- package/dist/tools/background-jobs.d.ts +71 -0
- package/dist/tools/background-jobs.js +198 -0
- package/dist/tools/bash.d.ts +53 -1
- package/dist/tools/bash.js +158 -7
- package/dist/tools/clipboard-image.d.ts +44 -0
- package/dist/tools/clipboard-image.js +148 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +18 -3
- package/dist/tools/image-file.d.ts +38 -3
- package/dist/tools/image-file.js +81 -10
- package/dist/tools/image-resize.d.ts +58 -0
- package/dist/tools/image-resize.js +97 -0
- package/dist/tools/presets.d.ts +40 -8
- package/dist/tools/presets.js +65 -19
- package/dist/tools/read.d.ts +5 -2
- package/dist/tools/read.js +13 -10
- package/dist/tools/registry.d.ts +7 -1
- package/dist/tools/registry.js +27 -4
- package/dist/tools/task-ctl.d.ts +22 -0
- package/dist/tools/task-ctl.js +116 -0
- package/dist/tools/task.d.ts +22 -10
- package/dist/tools/task.js +66 -26
- package/dist/tools/todo.d.ts +22 -2
- package/dist/tools/todo.js +58 -14
- package/dist/tools/truncate.d.ts +15 -0
- package/dist/tools/truncate.js +25 -0
- package/dist/tools/types.d.ts +113 -0
- package/dist/tools/types.js +5 -0
- package/dist/tools/write.js +3 -0
- package/dist/tui/component.d.ts +8 -2
- package/dist/tui/component.js +3 -1
- package/dist/tui/components/box.d.ts +6 -1
- package/dist/tui/components/box.js +16 -6
- package/dist/tui/components/card.d.ts +23 -0
- package/dist/tui/components/card.js +37 -0
- package/dist/tui/components/editor-history.d.ts +6 -0
- package/dist/tui/components/editor-history.js +45 -0
- package/dist/tui/components/editor-paste.d.ts +1 -1
- package/dist/tui/components/editor-paste.js +4 -4
- package/dist/tui/components/editor.d.ts +11 -5
- package/dist/tui/components/editor.js +52 -58
- package/dist/tui/components/key-value.d.ts +3 -0
- package/dist/tui/components/key-value.js +16 -6
- package/dist/tui/components/loader.d.ts +37 -7
- package/dist/tui/components/loader.js +84 -21
- package/dist/tui/components/markdown.d.ts +5 -1
- package/dist/tui/components/markdown.js +45 -21
- package/dist/tui/components/meter.d.ts +3 -3
- package/dist/tui/components/meter.js +13 -11
- package/dist/tui/components/select-list.d.ts +23 -1
- package/dist/tui/components/select-list.js +76 -13
- package/dist/tui/glyphs.d.ts +72 -0
- package/dist/tui/glyphs.js +118 -0
- package/dist/tui/keybindings.d.ts +5 -0
- package/dist/tui/keybindings.js +5 -0
- package/dist/tui/theme.d.ts +30 -6
- package/dist/tui/theme.js +103 -17
- package/dist/tui.d.ts +4 -2
- package/dist/tui.js +3 -1
- package/docs/acp.md +78 -0
- package/docs/agents.md +250 -0
- package/docs/codemode.md +28 -10
- package/docs/hooks.md +36 -32
- package/docs/permissions.md +212 -0
- package/docs/plan.md +107 -0
- package/docs/providers.md +261 -62
- package/docs/rewind-plan.md +181 -0
- package/docs/rpc.md +127 -40
- package/docs/sandbox.md +215 -0
- package/docs/session-format.md +43 -22
- package/docs/sessions.md +174 -0
- package/docs/tui-design.md +751 -0
- package/docs/tui.md +260 -64
- package/package.json +15 -2
|
@@ -5,31 +5,81 @@
|
|
|
5
5
|
* 的字符串表(`UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts` 重新生成,
|
|
6
6
|
* 测试守住两者一致)。本模块解析并校验它,另提供覆盖合并。
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* [W5-M1] 「快照 ⊕ 覆盖」格式(docs/wave5-plan.md §2.2、D6):文件级 `modelsDev` 指向 models.dev
|
|
9
|
+
* 快照里的供应商 id(`false` = 没有对应),条目按 `<modelsDev>/<id>`(或条目自己的 `modelsDev:
|
|
10
|
+
* "provider/model"`)从快照继承数值事实——name、reasoning、contextWindow、maxTokens、input、cost、
|
|
11
|
+
* family / knowledge / releaseDate / inputLimit / status;目录只写覆盖项与 ama 特有字段(`api`、
|
|
12
|
+
* `thinkingLevelMap`、`promptCache`、`compat`、有意调小的 `maxTokens` 等)。`cost` 可只写要覆盖的键。
|
|
13
|
+
* `_reason` 是注释字段(运行时忽略;写了它的条目不做冗余检查,用来有意钉住与快照相同的值)。
|
|
14
|
+
*
|
|
15
|
+
* 合并后的必填字段:id、name、maxTokens、reasoning;contextWindow 与 cost「宁缺不猜」——快照与目录
|
|
16
|
+
* 都没有就不写(缺 contextWindow → 关自动压缩并警告;缺 cost → 显示 `$?`)。`promptCache`
|
|
10
17
|
* (TTL 秒数与最小可缓存长度)同样只写有公开依据的值(第三波 §1.4),留空 = 不承诺。
|
|
11
18
|
*/
|
|
19
|
+
import { isDeepStrictEqual } from "node:util";
|
|
12
20
|
import { AmaError } from "../../errors.js";
|
|
13
21
|
import { CATALOG_SOURCES } from "./catalog-data.js";
|
|
14
22
|
import { THINKING_LEVELS } from "../thinking.js";
|
|
23
|
+
import { modelsDevFields } from "./models-dev.js";
|
|
24
|
+
import { builtinSnapshotIndex } from "./models-dev-snapshot.js";
|
|
25
|
+
/** 从快照继承的字段(顺序即冗余检查与来源展示的顺序)。 */
|
|
26
|
+
export const INHERITED_FIELDS = [
|
|
27
|
+
"name",
|
|
28
|
+
"reasoning",
|
|
29
|
+
"contextWindow",
|
|
30
|
+
"maxTokens",
|
|
31
|
+
"input",
|
|
32
|
+
"cost",
|
|
33
|
+
"family",
|
|
34
|
+
"knowledge",
|
|
35
|
+
"releaseDate",
|
|
36
|
+
"inputLimit",
|
|
37
|
+
"status",
|
|
38
|
+
];
|
|
15
39
|
function isRecord(value) {
|
|
16
40
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17
41
|
}
|
|
18
42
|
function isNonNegative(value) {
|
|
19
43
|
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
20
44
|
}
|
|
21
|
-
/**
|
|
45
|
+
/** 校验合并后的模型(必填齐全、cost 四个价都在),返回问题列表(空 = 合法)。 */
|
|
22
46
|
export function checkCatalogModel(value, path) {
|
|
47
|
+
if (!isRecord(value))
|
|
48
|
+
return [`${path}: must be an object`];
|
|
49
|
+
const problems = [];
|
|
50
|
+
if (typeof value["name"] !== "string")
|
|
51
|
+
problems.push(`${path}.name`);
|
|
52
|
+
if (typeof value["reasoning"] !== "boolean")
|
|
53
|
+
problems.push(`${path}.reasoning`);
|
|
54
|
+
if (value["maxTokens"] === undefined)
|
|
55
|
+
problems.push(`${path}.maxTokens`);
|
|
56
|
+
const cost = value["cost"];
|
|
57
|
+
if (isRecord(cost)) {
|
|
58
|
+
for (const key of ["input", "output", "cacheRead", "cacheWrite"]) {
|
|
59
|
+
if (cost[key] === undefined)
|
|
60
|
+
problems.push(`${path}.cost.${key}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return [...new Set([...problems, ...checkCatalogEntry(value, path)])];
|
|
64
|
+
}
|
|
65
|
+
/** 校验目录里的一条(覆盖格式:只查写了的字段),返回问题列表(空 = 合法)。 */
|
|
66
|
+
export function checkCatalogEntry(value, path) {
|
|
23
67
|
const problems = [];
|
|
24
68
|
if (!isRecord(value))
|
|
25
69
|
return [`${path}: must be an object`];
|
|
26
70
|
if (typeof value["id"] !== "string" || value["id"].length === 0)
|
|
27
71
|
problems.push(`${path}.id`);
|
|
28
|
-
if (typeof value["name"] !== "string")
|
|
72
|
+
if (value["name"] !== undefined && typeof value["name"] !== "string")
|
|
29
73
|
problems.push(`${path}.name`);
|
|
30
|
-
if (typeof value["reasoning"] !== "boolean")
|
|
74
|
+
if (value["reasoning"] !== undefined && typeof value["reasoning"] !== "boolean")
|
|
31
75
|
problems.push(`${path}.reasoning`);
|
|
32
|
-
|
|
76
|
+
const modelsDev = value["modelsDev"];
|
|
77
|
+
if (modelsDev !== undefined && modelsDev !== false && typeof modelsDev !== "string")
|
|
78
|
+
problems.push(`${path}.modelsDev`);
|
|
79
|
+
if (value["_reason"] !== undefined && typeof value["_reason"] !== "string")
|
|
80
|
+
problems.push(`${path}._reason`);
|
|
81
|
+
if (value["maxTokens"] !== undefined &&
|
|
82
|
+
(!isNonNegative(value["maxTokens"]) || value["maxTokens"] === 0)) {
|
|
33
83
|
problems.push(`${path}.maxTokens`);
|
|
34
84
|
}
|
|
35
85
|
if (value["contextWindow"] !== undefined && !isNonNegative(value["contextWindow"])) {
|
|
@@ -46,7 +96,7 @@ export function checkCatalogModel(value, path) {
|
|
|
46
96
|
problems.push(`${path}.cost`);
|
|
47
97
|
else {
|
|
48
98
|
for (const key of ["input", "output", "cacheRead", "cacheWrite"]) {
|
|
49
|
-
if (!isNonNegative(cost[key]))
|
|
99
|
+
if (cost[key] !== undefined && !isNonNegative(cost[key]))
|
|
50
100
|
problems.push(`${path}.cost.${key}`);
|
|
51
101
|
}
|
|
52
102
|
if (cost["tiers"] !== undefined && !Array.isArray(cost["tiers"])) {
|
|
@@ -86,50 +136,159 @@ export function checkCatalogModel(value, path) {
|
|
|
86
136
|
}
|
|
87
137
|
return problems;
|
|
88
138
|
}
|
|
89
|
-
|
|
139
|
+
/** 一条目录条目对应的快照条目 `provider/model`(没有返回 undefined)。 */
|
|
140
|
+
export function snapshotRefOf(file, entry) {
|
|
141
|
+
if (entry.modelsDev === false)
|
|
142
|
+
return undefined;
|
|
143
|
+
if (typeof entry.modelsDev === "string")
|
|
144
|
+
return entry.modelsDev;
|
|
145
|
+
return typeof file.modelsDev === "string" ? `${file.modelsDev}/${entry.id}` : undefined;
|
|
146
|
+
}
|
|
147
|
+
/** 快照能给这条目录条目的字段(catalog 口径:不封顶、缺缓存价记 0)。 */
|
|
148
|
+
export function inheritedFields(file, entry, index = builtinSnapshotIndex()) {
|
|
149
|
+
const ref = snapshotRefOf(file, entry);
|
|
150
|
+
const model = ref !== undefined ? index.get(ref) : undefined;
|
|
151
|
+
if (model === undefined)
|
|
152
|
+
return {};
|
|
153
|
+
const fields = modelsDevFields(model, "catalog");
|
|
154
|
+
const out = {};
|
|
155
|
+
for (const key of INHERITED_FIELDS) {
|
|
156
|
+
if (fields[key] !== undefined)
|
|
157
|
+
out[key] = fields[key];
|
|
158
|
+
}
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
/** 合并:快照 ⊕ 目录条目(`cost` 按键合并);返回模型与从快照继承的字段名。 */
|
|
162
|
+
export function resolveCatalogEntry(entry, inherited) {
|
|
163
|
+
const { modelsDev: _modelsDev, _reason: _r, ...own } = structuredClone(entry);
|
|
164
|
+
const model = { ...structuredClone(inherited), ...own };
|
|
165
|
+
if (own.cost !== undefined && inherited.cost !== undefined)
|
|
166
|
+
model.cost = { ...structuredClone(inherited.cost), ...own.cost };
|
|
167
|
+
// 目录有意把窗口调小(如 272k 计价档)时,继承来的更大的输入上限没有意义
|
|
168
|
+
if (own.inputLimit === undefined &&
|
|
169
|
+
model.inputLimit !== undefined &&
|
|
170
|
+
model.contextWindow !== undefined &&
|
|
171
|
+
model.inputLimit >= model.contextWindow)
|
|
172
|
+
delete model.inputLimit;
|
|
173
|
+
const from = INHERITED_FIELDS.filter((k) => own[k] === undefined && model[k] !== undefined);
|
|
174
|
+
return { model, inherited: from };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 与快照取值相同的覆盖项(冗余,测试报错;`UPDATE_CATALOG=1` 时自动删):`name`、`cost.input` 一类路径。
|
|
178
|
+
* 写了 `_reason` 的条目不查。
|
|
179
|
+
*/
|
|
180
|
+
export function redundantFields(entry, inherited) {
|
|
181
|
+
if (entry._reason !== undefined)
|
|
182
|
+
return [];
|
|
183
|
+
const out = [];
|
|
184
|
+
for (const key of INHERITED_FIELDS) {
|
|
185
|
+
const own = entry[key];
|
|
186
|
+
const base = inherited[key];
|
|
187
|
+
if (own === undefined || base === undefined)
|
|
188
|
+
continue;
|
|
189
|
+
if (key === "cost" && isRecord(own) && isRecord(base)) {
|
|
190
|
+
for (const [k, v] of Object.entries(own))
|
|
191
|
+
if (isDeepStrictEqual(v, base[k]))
|
|
192
|
+
out.push(`cost.${k}`);
|
|
193
|
+
}
|
|
194
|
+
else if (isDeepStrictEqual(own, base))
|
|
195
|
+
out.push(key);
|
|
196
|
+
}
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
function fileProblems(value) {
|
|
90
200
|
const problems = [];
|
|
91
201
|
if (!isRecord(value))
|
|
92
|
-
|
|
202
|
+
return ["$: must be an object"];
|
|
203
|
+
if (value["version"] !== 1)
|
|
204
|
+
problems.push("$.version must be 1");
|
|
205
|
+
if (typeof value["provider"] !== "string")
|
|
206
|
+
problems.push("$.provider");
|
|
207
|
+
const modelsDev = value["modelsDev"];
|
|
208
|
+
if (modelsDev !== undefined && modelsDev !== false && typeof modelsDev !== "string")
|
|
209
|
+
problems.push("$.modelsDev");
|
|
210
|
+
if (!Array.isArray(value["models"]))
|
|
211
|
+
problems.push("$.models must be an array");
|
|
93
212
|
else {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const id = isRecord(model) ? model["id"] : undefined;
|
|
105
|
-
if (typeof id === "string") {
|
|
106
|
-
if (seen.has(id))
|
|
107
|
-
problems.push(`$.models[${i}].id duplicated: ${id}`);
|
|
108
|
-
seen.add(id);
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (problems.length > 0) {
|
|
114
|
-
throw new AmaError("config_invalid", `model catalog ${source} is invalid: ${problems.join(", ")}`);
|
|
213
|
+
const seen = new Set();
|
|
214
|
+
value["models"].forEach((model, i) => {
|
|
215
|
+
problems.push(...checkCatalogEntry(model, `$.models[${i}]`));
|
|
216
|
+
const id = isRecord(model) ? model["id"] : undefined;
|
|
217
|
+
if (typeof id === "string") {
|
|
218
|
+
if (seen.has(id))
|
|
219
|
+
problems.push(`$.models[${i}].id duplicated: ${id}`);
|
|
220
|
+
seen.add(id);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
115
223
|
}
|
|
224
|
+
return problems;
|
|
225
|
+
}
|
|
226
|
+
function invalid(source, problems) {
|
|
227
|
+
return new AmaError("config_invalid", `model catalog ${source} is invalid: ${problems.join(", ")}`);
|
|
228
|
+
}
|
|
229
|
+
/** 校验文件形状(覆盖格式),不合并。 */
|
|
230
|
+
export function parseCatalogSource(value, source) {
|
|
231
|
+
const problems = fileProblems(value);
|
|
232
|
+
if (problems.length > 0)
|
|
233
|
+
throw invalid(source, problems);
|
|
116
234
|
return value;
|
|
117
235
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
236
|
+
function resolveFile(file, source, index) {
|
|
237
|
+
const problems = [];
|
|
238
|
+
const inherited = new Map();
|
|
239
|
+
const builtin = builtinSnapshotIndex();
|
|
240
|
+
const models = file.models.map((entry, i) => {
|
|
241
|
+
const path = `$.models[${i}]`;
|
|
242
|
+
let resolved = resolveCatalogEntry(entry, inheritedFields(file, entry, index ?? builtin));
|
|
243
|
+
let found = checkCatalogModel(resolved.model, path);
|
|
244
|
+
if (found.length > 0 && index !== undefined && index !== builtin) {
|
|
245
|
+
// 用户刷新的数据缺字段(上游改版):这一条退回内置快照,不让启动失败。
|
|
246
|
+
resolved = resolveCatalogEntry(entry, inheritedFields(file, entry, builtin));
|
|
247
|
+
found = checkCatalogModel(resolved.model, path);
|
|
248
|
+
}
|
|
249
|
+
problems.push(...found);
|
|
250
|
+
inherited.set(entry.id, resolved.inherited);
|
|
251
|
+
return resolved.model;
|
|
252
|
+
});
|
|
253
|
+
if (problems.length > 0)
|
|
254
|
+
throw invalid(source, problems);
|
|
255
|
+
return { file: { version: 1, provider: file.provider, models }, inherited };
|
|
256
|
+
}
|
|
257
|
+
/** 校验并合并(快照 ⊕ 目录)一个目录文件;`index` 缺省用内置快照。 */
|
|
258
|
+
export function parseCatalogFile(value, source, index) {
|
|
259
|
+
return resolveFile(parseCatalogSource(value, source), source, index).file;
|
|
260
|
+
}
|
|
261
|
+
const caches = new WeakMap();
|
|
262
|
+
let lastInherited = new Map();
|
|
263
|
+
/**
|
|
264
|
+
* 内置目录:供应商 id → 模型条目(深拷贝,调用方可随意修改)。`index` 缺省用内置快照;传入
|
|
265
|
+
* 「快照 ⊕ 用户刷新」的索引时目录也吃刷新后的数值(缺字段的条目退回内置快照)。
|
|
266
|
+
*/
|
|
267
|
+
export function loadBuiltinCatalog(index) {
|
|
268
|
+
const key = index ?? builtinSnapshotIndex();
|
|
269
|
+
let cache = caches.get(key);
|
|
270
|
+
if (cache === undefined) {
|
|
122
271
|
cache = new Map();
|
|
123
272
|
for (const [provider, raw] of Object.entries(CATALOG_SOURCES)) {
|
|
124
|
-
const
|
|
125
|
-
|
|
273
|
+
const source = `catalog/${provider}.json`;
|
|
274
|
+
const resolved = resolveFile(parseCatalogSource(JSON.parse(raw), source), source, index);
|
|
275
|
+
cache.set(resolved.file.provider, resolved);
|
|
126
276
|
}
|
|
277
|
+
caches.set(key, cache);
|
|
127
278
|
}
|
|
128
279
|
const copy = new Map();
|
|
129
|
-
|
|
130
|
-
|
|
280
|
+
lastInherited = new Map();
|
|
281
|
+
for (const [provider, resolved] of cache) {
|
|
282
|
+
copy.set(provider, structuredClone(resolved.file.models));
|
|
283
|
+
for (const [id, fields] of resolved.inherited)
|
|
284
|
+
lastInherited.set(`${provider}/${id}`, fields);
|
|
285
|
+
}
|
|
131
286
|
return copy;
|
|
132
287
|
}
|
|
288
|
+
/** 最近一次 `loadBuiltinCatalog()` 里,该目录模型从快照继承的字段(来源展示用)。 */
|
|
289
|
+
export function catalogInherited(provider, modelId) {
|
|
290
|
+
return lastInherited.get(`${provider}/${modelId}`) ?? [];
|
|
291
|
+
}
|
|
133
292
|
/** 目录条目 → Model(补 provider / api 与缺省 input)。 */
|
|
134
293
|
export function toModel(entry, provider, api) {
|
|
135
294
|
return { ...structuredClone(entry), input: entry.input ?? ["text"], provider, api };
|
|
@@ -10,17 +10,32 @@
|
|
|
10
10
|
* auth.json 的同名条目),没有时用供应商的 key。
|
|
11
11
|
*/
|
|
12
12
|
import type { ProviderConfig } from "../../config/types.js";
|
|
13
|
-
import type { Api, ProviderChannel } from "../types.js";
|
|
13
|
+
import type { Api, Model, ProviderChannel, ProviderData } from "../types.js";
|
|
14
14
|
/** 隐式渠道名(单渠道供应商)。 */
|
|
15
15
|
export declare const DEFAULT_CHANNEL = "default";
|
|
16
16
|
/** 渠道 key 在 key 解析里的键。 */
|
|
17
17
|
export declare function channelKeyId(providerId: string, channel: string): string;
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* 内置渠道 ⊕ 用户渠道([W5-M2]):同名按字段覆盖(`headers` / `compat` 再合并一层)、新名追加在后。
|
|
20
|
+
*/
|
|
21
|
+
export declare function mergeChannels(base: readonly ProviderChannel[], user: readonly ProviderChannel[]): ProviderChannel[];
|
|
22
|
+
/**
|
|
23
|
+
* config 的 `channels` → 物化渠道表(跳过名字非法或缺 api / baseUrl 的,返回警告)。给了 `builtin`
|
|
24
|
+
* (内置供应商的内置渠道)时与之合并:同名渠道可只写要改的字段;`defaultChannel` 用户优先,其次内置。
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseChannels(providerId: string, config: ProviderConfig, builtin?: {
|
|
27
|
+
channels: readonly ProviderChannel[];
|
|
28
|
+
defaultChannel: string | undefined;
|
|
29
|
+
}): {
|
|
20
30
|
channels: ProviderChannel[];
|
|
21
31
|
defaultChannel: string | undefined;
|
|
22
32
|
warnings: string[];
|
|
23
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* 内置供应商目录模型的渠道表:目录条目写了 `channels` 就用它(去掉不存在的),否则挂全部渠道;
|
|
36
|
+
* 缺省渠道在表里时排到首位(首个 = 首选)。
|
|
37
|
+
*/
|
|
38
|
+
export declare function catalogChannels(wanted: readonly string[] | undefined, known: readonly ProviderChannel[], defaultChannel: string): string[];
|
|
24
39
|
/** 模型的渠道表:去掉不存在的;空 → [defaultChannel]。 */
|
|
25
40
|
export declare function modelChannels(wanted: readonly string[] | undefined, known: readonly ProviderChannel[], defaultChannel: string, onUnknown: (name: string) => void): string[];
|
|
26
41
|
/**
|
|
@@ -49,3 +64,18 @@ export declare function modelRefOf(model: {
|
|
|
49
64
|
};
|
|
50
65
|
/** 协议的短名(表格用)。 */
|
|
51
66
|
export declare function apiShortName(api: Api): string;
|
|
67
|
+
/**
|
|
68
|
+
* 物化:模型补齐供应商级字段(不可变:返回新对象)。给了 `channel` 时协议与地址取渠道的(模型级
|
|
69
|
+
* `explicit` 覆盖优先),headers / compat 按 供应商 ← 渠道 ← 模型 合并,并记下渠道名。
|
|
70
|
+
*/
|
|
71
|
+
export declare function materializeModel(model: Model, provider: ProviderData, channel?: ProviderChannel, explicit?: {
|
|
72
|
+
api?: Api | undefined;
|
|
73
|
+
baseUrl?: string | undefined;
|
|
74
|
+
}): Model;
|
|
75
|
+
/** 内置渠道作废:按供应商级 api / baseUrl 单渠道处理。 */
|
|
76
|
+
export declare function dropChannels(provider: ProviderData): void;
|
|
77
|
+
/**
|
|
78
|
+
* 内置渠道 + 用户只改供应商级字段:改了 baseUrl → 内置渠道作废(单渠道回落);只写 `api` → 选同协议的
|
|
79
|
+
* 内置渠道作缺省(没有就作废);`defaultChannel` 必须是内置渠道名。
|
|
80
|
+
*/
|
|
81
|
+
export declare function pickBuiltinChannel(provider: ProviderData, config: ProviderConfig, warn: (message: string) => void): void;
|
|
@@ -10,37 +10,84 @@
|
|
|
10
10
|
* auth.json 的同名条目),没有时用供应商的 key。
|
|
11
11
|
*/
|
|
12
12
|
import { CHANNEL_NAME_PATTERN } from "../../config/types.js";
|
|
13
|
+
import { mergeHeaders } from "../http.js";
|
|
13
14
|
/** 隐式渠道名(单渠道供应商)。 */
|
|
14
15
|
export const DEFAULT_CHANNEL = "default";
|
|
15
16
|
/** 渠道 key 在 key 解析里的键。 */
|
|
16
17
|
export function channelKeyId(providerId, channel) {
|
|
17
18
|
return `${providerId}@${channel}`;
|
|
18
19
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* 内置渠道 ⊕ 用户渠道([W5-M2]):同名按字段覆盖(`headers` / `compat` 再合并一层)、新名追加在后。
|
|
22
|
+
*/
|
|
23
|
+
export function mergeChannels(base, user) {
|
|
24
|
+
const out = base.map((c) => structuredClone(c));
|
|
25
|
+
for (const channel of user) {
|
|
26
|
+
const index = out.findIndex((c) => c.name === channel.name);
|
|
27
|
+
const current = out[index];
|
|
28
|
+
if (current === undefined) {
|
|
29
|
+
out.push(channel);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const next = { ...current, ...channel };
|
|
33
|
+
if (current.headers && channel.headers)
|
|
34
|
+
next.headers = { ...current.headers, ...channel.headers };
|
|
35
|
+
if (current.compat && channel.compat)
|
|
36
|
+
next.compat = { ...current.compat, ...channel.compat };
|
|
37
|
+
out[index] = next;
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* config 的 `channels` → 物化渠道表(跳过名字非法或缺 api / baseUrl 的,返回警告)。给了 `builtin`
|
|
43
|
+
* (内置供应商的内置渠道)时与之合并:同名渠道可只写要改的字段;`defaultChannel` 用户优先,其次内置。
|
|
44
|
+
*/
|
|
45
|
+
export function parseChannels(providerId, config, builtin) {
|
|
21
46
|
const warnings = [];
|
|
22
|
-
const
|
|
47
|
+
const own = [];
|
|
48
|
+
const known = new Set((builtin?.channels ?? []).map((c) => c.name));
|
|
23
49
|
for (const [name, raw] of Object.entries(config.channels ?? {})) {
|
|
24
50
|
const c = raw;
|
|
25
|
-
|
|
51
|
+
const partial = known.has(name);
|
|
52
|
+
if (!CHANNEL_NAME_PATTERN.test(name) || !c || (!partial && (!c.api || !c.baseUrl))) {
|
|
26
53
|
warnings.push(`provider "${providerId}" channel "${name}" is invalid; ignored`);
|
|
27
54
|
continue;
|
|
28
55
|
}
|
|
29
|
-
const channel = { name
|
|
56
|
+
const channel = { name };
|
|
57
|
+
if (c.api)
|
|
58
|
+
channel.api = c.api;
|
|
59
|
+
if (c.baseUrl)
|
|
60
|
+
channel.baseUrl = c.baseUrl;
|
|
30
61
|
if (c.authHeader !== undefined)
|
|
31
62
|
channel.authHeader = c.authHeader;
|
|
32
63
|
if (c.headers !== undefined)
|
|
33
64
|
channel.headers = { ...c.headers };
|
|
34
65
|
if (c.compat !== undefined)
|
|
35
66
|
channel.compat = { ...c.compat };
|
|
36
|
-
|
|
67
|
+
own.push(channel);
|
|
37
68
|
}
|
|
69
|
+
const channels = mergeChannels(builtin?.channels ?? [], own);
|
|
38
70
|
let defaultChannel = config.defaultChannel;
|
|
39
71
|
if (defaultChannel !== undefined && !channels.some((c) => c.name === defaultChannel)) {
|
|
40
72
|
warnings.push(`provider "${providerId}" defaultChannel "${defaultChannel}" not found`);
|
|
41
73
|
defaultChannel = undefined;
|
|
42
74
|
}
|
|
43
|
-
|
|
75
|
+
const fallback = channels.some((c) => c.name === builtin?.defaultChannel)
|
|
76
|
+
? builtin?.defaultChannel
|
|
77
|
+
: channels[0]?.name;
|
|
78
|
+
return { channels, defaultChannel: defaultChannel ?? fallback, warnings };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 内置供应商目录模型的渠道表:目录条目写了 `channels` 就用它(去掉不存在的),否则挂全部渠道;
|
|
82
|
+
* 缺省渠道在表里时排到首位(首个 = 首选)。
|
|
83
|
+
*/
|
|
84
|
+
export function catalogChannels(wanted, known, defaultChannel) {
|
|
85
|
+
const names = known.map((c) => c.name);
|
|
86
|
+
const list = wanted === undefined ? names : wanted.filter((name) => names.includes(name));
|
|
87
|
+
const out = list.includes(defaultChannel)
|
|
88
|
+
? [defaultChannel, ...list.filter((name) => name !== defaultChannel)]
|
|
89
|
+
: [...list];
|
|
90
|
+
return out.length > 0 ? out : [defaultChannel];
|
|
44
91
|
}
|
|
45
92
|
/** 模型的渠道表:去掉不存在的;空 → [defaultChannel]。 */
|
|
46
93
|
export function modelChannels(wanted, known, defaultChannel, onUnknown) {
|
|
@@ -94,3 +141,57 @@ export function apiShortName(api) {
|
|
|
94
141
|
return api;
|
|
95
142
|
}
|
|
96
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* 物化:模型补齐供应商级字段(不可变:返回新对象)。给了 `channel` 时协议与地址取渠道的(模型级
|
|
146
|
+
* `explicit` 覆盖优先),headers / compat 按 供应商 ← 渠道 ← 模型 合并,并记下渠道名。
|
|
147
|
+
*/
|
|
148
|
+
export function materializeModel(model, provider, channel, explicit) {
|
|
149
|
+
const out = {
|
|
150
|
+
...model,
|
|
151
|
+
provider: provider.id,
|
|
152
|
+
baseUrl: model.baseUrl ?? provider.baseUrl,
|
|
153
|
+
};
|
|
154
|
+
if (channel !== undefined) {
|
|
155
|
+
out.api = explicit?.api ?? channel.api;
|
|
156
|
+
out.baseUrl = explicit?.baseUrl ?? channel.baseUrl;
|
|
157
|
+
out.channel = channel.name;
|
|
158
|
+
}
|
|
159
|
+
if (provider.headers || channel?.headers || model.headers)
|
|
160
|
+
out.headers = mergeHeaders(provider.headers, channel?.headers, model.headers);
|
|
161
|
+
if (provider.compat || channel?.compat || model.compat)
|
|
162
|
+
out.compat = { ...provider.compat, ...channel?.compat, ...model.compat };
|
|
163
|
+
const authHeader = channel?.authHeader ?? provider.authHeader;
|
|
164
|
+
if (authHeader !== undefined)
|
|
165
|
+
out.authHeader = model.authHeader ?? authHeader;
|
|
166
|
+
out.requiresApiKey = provider.requiresApiKey;
|
|
167
|
+
return out;
|
|
168
|
+
}
|
|
169
|
+
/** 内置渠道作废:按供应商级 api / baseUrl 单渠道处理。 */
|
|
170
|
+
export function dropChannels(provider) {
|
|
171
|
+
delete provider.channels;
|
|
172
|
+
delete provider.defaultChannel;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* 内置渠道 + 用户只改供应商级字段:改了 baseUrl → 内置渠道作废(单渠道回落);只写 `api` → 选同协议的
|
|
176
|
+
* 内置渠道作缺省(没有就作废);`defaultChannel` 必须是内置渠道名。
|
|
177
|
+
*/
|
|
178
|
+
export function pickBuiltinChannel(provider, config, warn) {
|
|
179
|
+
if (config.baseUrl !== undefined) {
|
|
180
|
+
dropChannels(provider);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const channels = provider.channels ?? [];
|
|
184
|
+
if (config.defaultChannel !== undefined) {
|
|
185
|
+
if (channels.some((c) => c.name === config.defaultChannel))
|
|
186
|
+
provider.defaultChannel = config.defaultChannel;
|
|
187
|
+
else
|
|
188
|
+
warn(`provider "${provider.id}" defaultChannel "${config.defaultChannel}" not found`);
|
|
189
|
+
}
|
|
190
|
+
else if (config.api !== undefined) {
|
|
191
|
+
const same = channels.find((c) => c.api === config.api);
|
|
192
|
+
if (same !== undefined)
|
|
193
|
+
provider.defaultChannel = same.name;
|
|
194
|
+
else
|
|
195
|
+
dropChannels(provider);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* 用 models.dev 缓存给自定义模型补元数据(docs/providers.md「模型元数据:models.dev」)。
|
|
3
3
|
*
|
|
4
4
|
* 优先级:用户配置写了的字段 > models.dev > 自定义缺省(maxTokens 8192、input ["text"]、
|
|
5
|
-
* reasoning false、不猜 contextWindow
|
|
6
|
-
*
|
|
5
|
+
* reasoning false、不猜 contextWindow)。内置目录的模型不经过这里:目录在 catalog.ts 里已经
|
|
6
|
+
* 「快照 ⊕ 覆盖」合并好([W5-M1]),这里只给它们标来源。只读传入的索引,不联网。
|
|
7
7
|
*/
|
|
8
8
|
import type { ModelConfig } from "../../config/types.js";
|
|
9
9
|
import type { Model } from "../types.js";
|
|
@@ -29,6 +29,9 @@ export declare function enrichEntry(entry: ModelConfig, index: () => ModelsDevIn
|
|
|
29
29
|
entry: Omit<ModelConfig, "modelsDev" | "channels">;
|
|
30
30
|
metadata: ModelMetadata;
|
|
31
31
|
};
|
|
32
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* 内置目录模型的来源:目录自己写的为 catalog,从入库快照继承的为 models.dev(catalog.ts),
|
|
34
|
+
* 都没有的为缺省。
|
|
35
|
+
*/
|
|
33
36
|
export declare function catalogMetadata(model: Model): ModelMetadata;
|
|
34
37
|
export declare function sourceText(source: FieldSource): string;
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* 用 models.dev 缓存给自定义模型补元数据(docs/providers.md「模型元数据:models.dev」)。
|
|
3
3
|
*
|
|
4
4
|
* 优先级:用户配置写了的字段 > models.dev > 自定义缺省(maxTokens 8192、input ["text"]、
|
|
5
|
-
* reasoning false、不猜 contextWindow
|
|
6
|
-
*
|
|
5
|
+
* reasoning false、不猜 contextWindow)。内置目录的模型不经过这里:目录在 catalog.ts 里已经
|
|
6
|
+
* 「快照 ⊕ 覆盖」合并好([W5-M1]),这里只给它们标来源。只读传入的索引,不联网。
|
|
7
7
|
*/
|
|
8
|
+
import { catalogInherited } from "./catalog.js";
|
|
8
9
|
import { ENRICHABLE_FIELDS, modelsDevFields, } from "./models-dev.js";
|
|
9
10
|
/** 惰性取索引:只有真的要补字段时才读缓存(启动时没有自定义模型就不读约 2 MB 的缓存)。 */
|
|
10
11
|
export function lazyIndex(source) {
|
|
@@ -25,6 +26,8 @@ export function lazyIndex(source) {
|
|
|
25
26
|
return index;
|
|
26
27
|
};
|
|
27
28
|
}
|
|
29
|
+
/** 只作说明的元数据(不进来源表):缺了就从 models.dev 补。 */
|
|
30
|
+
const METADATA_FIELDS = ["family", "knowledge", "releaseDate", "inputLimit", "status"];
|
|
28
31
|
function needsLookup(entry) {
|
|
29
32
|
return ENRICHABLE_FIELDS.some((field) => entry[field] === undefined);
|
|
30
33
|
}
|
|
@@ -65,13 +68,25 @@ export function enrichEntry(entry, index) {
|
|
|
65
68
|
}
|
|
66
69
|
if (out.name === undefined && fields.name !== undefined)
|
|
67
70
|
out.name = fields.name;
|
|
71
|
+
for (const field of METADATA_FIELDS) {
|
|
72
|
+
if (out[field] === undefined && fields[field] !== undefined)
|
|
73
|
+
out[field] = fields[field];
|
|
74
|
+
}
|
|
68
75
|
return { entry: out, metadata };
|
|
69
76
|
}
|
|
70
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* 内置目录模型的来源:目录自己写的为 catalog,从入库快照继承的为 models.dev(catalog.ts),
|
|
79
|
+
* 都没有的为缺省。
|
|
80
|
+
*/
|
|
71
81
|
export function catalogMetadata(model) {
|
|
82
|
+
const inherited = catalogInherited(model.provider, model.id);
|
|
72
83
|
const sources = {};
|
|
73
84
|
for (const field of ENRICHABLE_FIELDS) {
|
|
74
|
-
sources[field] =
|
|
85
|
+
sources[field] = inherited.includes(field)
|
|
86
|
+
? "models.dev"
|
|
87
|
+
: model[field] !== undefined
|
|
88
|
+
? "catalog"
|
|
89
|
+
: "default";
|
|
75
90
|
}
|
|
76
91
|
return { sources, looked: false };
|
|
77
92
|
}
|
|
@@ -1,53 +1,57 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* models.dev
|
|
2
|
+
* models.dev 索引 = 内置快照 ⊕ 用户级覆盖(docs/wave5-plan.md §2.2、docs/providers.md「模型元数据」)。
|
|
3
3
|
*
|
|
4
|
-
* -
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* - 内置快照随 bundle 携带(models-dev-snapshot.ts),**启动与运行都不联网**。
|
|
5
|
+
* - 覆盖文件 `<dataDir>/models-dev.json`:`{ version: 2, url, fetchedAt, providers }`,只有
|
|
6
|
+
* `ama models refresh` 会写(`refreshModelsDev()`,显式联网,按快照同一清单裁剪)。存在且
|
|
7
|
+
* fetchedAt 晚于快照才叠加;同 provider/model 以覆盖为准。旧版(version 1,全量 2 MB 缓存)忽略。
|
|
8
|
+
* - `loadModelsDevIndex()` 按覆盖文件路径 + mtime + 大小记忆,同一进程只解析一次。
|
|
9
|
+
* - `AMA_MODELS_DEV_URL` 换刷新的数据源。
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
11
|
+
import type { ModelsDevData, ModelsDevIndex } from "./models-dev.js";
|
|
12
|
+
import { type SnapshotDiff } from "./models-dev-snapshot.js";
|
|
12
13
|
export declare const MODELS_DEV_URL = "https://models.dev/api.json";
|
|
13
14
|
export declare const MODELS_DEV_URL_ENV = "AMA_MODELS_DEV_URL";
|
|
14
15
|
export declare const MODELS_DEV_FILE = "models-dev.json";
|
|
15
|
-
export declare const
|
|
16
|
-
export declare const MODELS_DEV_TIMEOUT_MS = 30000;
|
|
16
|
+
export declare const MODELS_DEV_TIMEOUT_MS = 60000;
|
|
17
17
|
export interface ModelsDevCacheFile {
|
|
18
|
-
version:
|
|
18
|
+
version: 2;
|
|
19
19
|
url: string;
|
|
20
20
|
/** ISO 8601。 */
|
|
21
21
|
fetchedAt: string;
|
|
22
|
-
etag?: string;
|
|
23
22
|
providers: ModelsDevData;
|
|
24
23
|
}
|
|
25
24
|
export declare function modelsDevCachePath(dataDir: string): string;
|
|
26
25
|
export declare function modelsDevUrl(env?: Readonly<Record<string, string | undefined>>): string;
|
|
27
|
-
/**
|
|
26
|
+
/** 读覆盖文件;不存在、旧版或损坏返回 undefined(损坏不报错:下次 refresh 会覆盖)。 */
|
|
28
27
|
export declare function readModelsDevCache(dataDir: string): ModelsDevCacheFile | undefined;
|
|
29
28
|
export declare function writeModelsDevCache(dataDir: string, file: ModelsDevCacheFile): void;
|
|
30
|
-
/**
|
|
31
|
-
export declare function
|
|
32
|
-
|
|
29
|
+
/** 覆盖文件是否生效:fetchedAt 晚于内置快照。 */
|
|
30
|
+
export declare function overrideApplies(file: ModelsDevCacheFile): boolean;
|
|
31
|
+
/** 快照 ⊕ 覆盖(零网络;没有覆盖文件时只做一次 stat)。 */
|
|
32
|
+
export declare function loadModelsDevIndex(dataDir: string): ModelsDevIndex;
|
|
33
|
+
/** 当前索引的来源说明(`providers add` / `models discover` 输出用)。 */
|
|
34
|
+
export declare function describeModelsDev(dataDir: string): string;
|
|
35
|
+
export type RefreshStatus = "updated" | "unchanged" | "failed";
|
|
33
36
|
export interface RefreshResult {
|
|
34
37
|
status: RefreshStatus;
|
|
35
|
-
index?: ModelsDevIndex;
|
|
36
|
-
fetchedAt?: string;
|
|
37
38
|
url: string;
|
|
39
|
+
fetchedAt?: string;
|
|
40
|
+
/** 与刷新前的索引(快照 ⊕ 旧覆盖)相比。 */
|
|
41
|
+
diff?: SnapshotDiff;
|
|
42
|
+
index: ModelsDevIndex;
|
|
38
43
|
warning?: string;
|
|
39
44
|
}
|
|
40
45
|
export interface RefreshOptions {
|
|
41
46
|
dataDir: string;
|
|
42
47
|
env?: Readonly<Record<string, string | undefined>>;
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
ttlMs?: number;
|
|
48
|
+
/** 只刷新这几家(须在快照清单里)。 */
|
|
49
|
+
providers?: readonly string[];
|
|
46
50
|
timeoutMs?: number;
|
|
47
51
|
now?: () => number;
|
|
48
52
|
fetch?: typeof fetch;
|
|
49
53
|
}
|
|
50
|
-
/**
|
|
54
|
+
/** 显式联网刷新(只被 `ama models refresh` 调用):拉 api.json、按清单裁剪、写用户级覆盖。 */
|
|
51
55
|
export declare function refreshModelsDev(options: RefreshOptions): Promise<RefreshResult>;
|
|
52
|
-
/**
|
|
53
|
-
export declare function describeRefresh(result: RefreshResult): string;
|
|
56
|
+
/** 刷新结果的说明(命令输出用):一行状态 + 新增 / 删除 / 变化清单。 */
|
|
57
|
+
export declare function describeRefresh(result: RefreshResult, limit?: number): string;
|