akm-cli 0.10.261012-beta → 0.10.261014-beta
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 +710 -3
- package/README.md +15 -0
- package/SECURITY.md +11 -10
- package/STABILITY.md +47 -51
- package/dist/assets/hints/cli-hints-full.md +21 -19
- package/dist/assets/hints/cli-hints-short.md +3 -4
- package/dist/assets/opencode/akm-plugin.js +177 -0
- package/dist/assets/stash-skeleton/README.md +1 -1
- package/dist/assets/tasks/core/improve.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/assets/ui/config.js +27 -10
- package/dist/assets/workflows/workflow-template.md +2 -2
- package/dist/cli/clack.js +3 -1
- package/dist/cli/selection.js +33 -0
- package/dist/cli/shared.js +14 -1
- package/dist/cli/unknown-flags.js +6 -37
- package/dist/cli.js +69 -48
- package/dist/commands/agent/agent-dispatch.js +17 -25
- package/dist/commands/agent/contribute-cli.js +9 -8
- package/dist/commands/command/command-cli.js +4 -8
- package/dist/commands/command/command-execution.js +25 -39
- package/dist/commands/command/execution-source-loader.js +10 -14
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +14 -5
- package/dist/commands/env/child-env.js +12 -14
- package/dist/commands/env/env-binding.js +47 -58
- package/dist/commands/env/env-cli.js +22 -24
- package/dist/commands/env/env.js +10 -58
- package/dist/commands/env/secret-cli.js +11 -29
- package/dist/commands/env/secret.js +3 -10
- package/dist/commands/health/checks.js +10 -849
- package/dist/commands/health/connections-and-harnesses-check.js +109 -0
- package/dist/commands/health/egress.js +3 -3
- package/dist/commands/health/html-report.js +9 -10
- package/dist/commands/health/plugin-staleness.js +18 -11
- package/dist/commands/health/report-view-model.js +16 -12
- package/dist/commands/health/scheduler-binary.js +1 -1
- package/dist/commands/health/semantic-search-check.js +85 -0
- package/dist/commands/health/type-directory-check.js +0 -3
- package/dist/commands/health.js +30 -42
- package/dist/commands/improve/consolidate/pair-pass.js +10 -25
- package/dist/commands/improve/consolidate.js +10 -15
- package/dist/commands/improve/distill.js +5 -17
- package/dist/commands/improve/eligibility.js +1 -3
- package/dist/commands/improve/execution.js +37 -40
- package/dist/commands/improve/extract-cli.js +6 -11
- package/dist/commands/improve/extract-prompt.js +2 -2
- package/dist/commands/improve/extract.js +67 -97
- package/dist/commands/improve/improve-cli.js +22 -128
- package/dist/commands/improve/improve-report.js +1 -1
- package/dist/commands/improve/improve-strategies.js +25 -108
- package/dist/commands/improve/improve.js +10 -14
- package/dist/commands/improve/loop-stages.js +3 -0
- package/dist/commands/improve/memory/memory-improve.js +1 -1
- package/dist/commands/improve/preparation.js +8 -13
- package/dist/commands/improve/reflect.js +203 -332
- package/dist/commands/improve/retrieval-scope.js +1 -1
- package/dist/commands/improve/session-asset.js +3 -2
- package/dist/commands/improve/stage.js +87 -115
- package/dist/commands/lint/base-linter.js +3 -3
- package/dist/commands/lint/env-key-rules.js +7 -6
- package/dist/commands/lint/index.js +3 -3
- package/dist/commands/models-cli.js +103 -63
- package/dist/commands/proposal/drain.js +26 -39
- package/dist/commands/proposal/proposal-cli.js +14 -18
- package/dist/commands/proposal/propose-cli.js +4 -2
- package/dist/commands/proposal/propose.js +37 -64
- package/dist/commands/proposal/repository.js +17 -17
- package/dist/commands/proposal/validators/proposal-validators.js +3 -6
- package/dist/commands/read/curate.js +10 -6
- package/dist/commands/read/registry-search.js +2 -48
- package/dist/commands/read/search-cli.js +1 -8
- package/dist/commands/read/search.js +5 -6
- package/dist/commands/read/show.js +6 -29
- package/dist/commands/remember.js +25 -40
- package/dist/commands/sources/add-cli.js +8 -63
- package/dist/commands/sources/bundle-cli.js +8 -9
- package/dist/commands/sources/bundle-config-ops.js +2 -2
- package/dist/commands/sources/info.js +12 -1
- package/dist/commands/sources/init.js +1 -1
- package/dist/commands/sources/installed-stashes.js +119 -63
- package/dist/commands/sources/migration-help.js +1 -1
- package/dist/commands/sources/plugin-upgrade.js +8 -15
- package/dist/commands/sources/schema-repair.js +4 -10
- package/dist/commands/sources/source-add.js +2 -2
- package/dist/commands/sources/source-clone.js +31 -7
- package/dist/commands/sources/source-manage.js +4 -4
- package/dist/commands/targets.js +175 -0
- package/dist/commands/tasks/explain.js +104 -69
- package/dist/commands/tasks/tasks-cli.js +9 -11
- package/dist/commands/tasks/tasks.js +75 -97
- package/dist/commands/ui/api.js +11 -3
- package/dist/commands/ui/redact.js +5 -31
- package/dist/commands/ui/workspace-actions.js +1 -1
- package/dist/commands/workflow/plan.js +48 -9
- package/dist/commands/workflow-cli.js +40 -45
- package/dist/core/adapter/adapters/agent-skills-adapter.js +10 -11
- package/dist/core/adapter/adapters/akm-adapter.js +36 -41
- package/dist/core/adapter/adapters/akm-lint.js +10 -12
- package/dist/core/adapter/adapters/akm-metadata.js +2 -2
- package/dist/core/adapter/adapters/akm-task-adapter.js +8 -9
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +5 -5
- package/dist/core/adapter/adapters/claude-adapter.js +1 -1
- package/dist/core/adapter/adapters/dotenv-adapter.js +7 -6
- package/dist/core/adapter/adapters/generic-files-adapter.js +5 -5
- package/dist/core/adapter/adapters/index.js +3 -4
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +12 -14
- package/dist/core/adapter/adapters/okf-adapter.js +8 -10
- package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
- package/dist/core/adapter/adapters/shared.js +3 -3
- package/dist/core/adapter/adapters/tool-dir-shared.js +7 -25
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +3 -3
- package/dist/core/adapter/detect-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +13 -35
- package/dist/core/adapter/registry.js +1 -1
- package/dist/core/adapter/validate-context.js +2 -4
- package/dist/core/asset/asset-placement.js +1 -1
- package/dist/core/asset/asset-ref.js +3 -3
- package/dist/core/asset/resolve-ref.js +5 -0
- package/dist/core/bundle-rename.js +12 -4
- package/dist/core/closest-match.js +37 -0
- package/dist/core/common.js +37 -57
- package/dist/core/config/config-io.js +26 -18
- package/dist/core/config/config-schema.js +19 -106
- package/dist/core/config/config-sources.js +3 -3
- package/dist/core/config/config-types.js +4 -4
- package/dist/core/config/config-walker.js +50 -77
- package/dist/core/config/config.js +438 -109
- package/dist/core/config/convert-engine-references.js +114 -0
- package/dist/core/config/convert-engines-shared.js +40 -0
- package/dist/core/config/convert-engines.js +300 -0
- package/dist/core/config/convert-models-overlay.js +137 -0
- package/dist/core/config/credentials.js +304 -0
- package/dist/core/config/engine-semantics.js +3 -3
- package/dist/core/config/migrate-keys.js +222 -0
- package/dist/core/config/model-aliases.js +37 -0
- package/dist/core/config/models-file.js +34 -0
- package/dist/core/config/retired-engines.js +53 -0
- package/dist/core/config/schema/connections.js +41 -0
- package/dist/core/config/schema/embedding.js +2 -2
- package/dist/core/config/schema/harnesses.js +41 -0
- package/dist/core/config/schema/improve-processes.js +9 -28
- package/dist/core/config/schema/improve.js +36 -1
- package/dist/core/config/schema/index-config.js +18 -20
- package/dist/core/config/schema/primitives.js +42 -17
- package/dist/core/config/schema/search.js +6 -11
- package/dist/core/config/schema/sources-bundles.js +9 -9
- package/dist/core/config/schema/workflow.js +2 -6
- package/dist/core/config/unusable-entries.js +66 -0
- package/dist/core/content-safety.js +3 -6
- package/dist/core/endpoint-url.js +47 -0
- package/dist/core/env-secret-ref.js +84 -73
- package/dist/core/errors.js +10 -16
- package/dist/core/extra-params.js +3 -3
- package/dist/core/improve-result.js +8 -9
- package/dist/core/json-schema.js +1 -1
- package/dist/core/lesson-lint.js +1 -1
- package/dist/core/llm-inference.js +80 -0
- package/dist/core/parse.js +2 -2
- package/dist/core/paths.js +33 -10
- package/dist/core/recognition-util.js +8 -10
- package/dist/core/redaction.js +94 -55
- package/dist/core/ref-token.js +82 -0
- package/dist/core/secret-value.js +14 -0
- package/dist/core/state/migrations.js +17 -22
- package/dist/core/structured.js +2 -68
- package/dist/core/subprocess.js +63 -22
- package/dist/core/type-presentation.js +10 -14
- package/dist/core/write-source.js +20 -4
- package/dist/execution/input-contract.js +3 -6
- package/dist/execution/notices.js +49 -0
- package/dist/execution/resolved-request.js +24 -40
- package/dist/execution/source.js +21 -45
- package/dist/execution/target-ref.js +2 -2
- package/dist/indexer/bundle-identity-guard.js +6 -5
- package/dist/indexer/ensure-index.js +1 -1
- package/dist/indexer/index-writer-lock.js +1 -1
- package/dist/indexer/indexer.js +46 -42
- package/dist/indexer/installations.js +12 -22
- package/dist/indexer/lookup/adapter-concept-owner.js +40 -14
- package/dist/indexer/materialize-embeddings.js +20 -16
- package/dist/indexer/passes/memory-inference.js +21 -50
- package/dist/indexer/passes/metadata.js +5 -5
- package/dist/indexer/scan/doc-to-entry.js +1 -1
- package/dist/indexer/scan/drain-dir.js +9 -11
- package/dist/indexer/search/db-search.js +9 -7
- package/dist/indexer/search/search-source.js +42 -22
- package/dist/indexer/usage/usage-events.js +2 -3
- package/dist/indexer/walk/index-context.js +2 -1
- package/dist/indexer/walk/matchers.js +3 -11
- package/dist/indexer/walk/path-resolver.js +13 -68
- package/dist/indexer/walk/walker.js +32 -26
- package/dist/integrations/agent/akm-read-tools.js +81 -0
- package/dist/integrations/agent/config.js +1 -1
- package/dist/integrations/agent/detect.js +32 -36
- package/dist/integrations/agent/execution.js +130 -428
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +24 -28
- package/dist/integrations/agent/prompts.js +17 -30
- package/dist/integrations/agent/request-lowering.js +67 -101
- package/dist/integrations/agent/resolution.js +332 -0
- package/dist/integrations/agent/runner-dispatch.js +156 -181
- package/dist/integrations/agent/runner.js +20 -70
- package/dist/integrations/agent/runtime-port.js +4 -0
- package/dist/integrations/agent/runtime.js +10 -0
- package/dist/integrations/agent/spawn.js +65 -190
- package/dist/integrations/harnesses/aider/index.js +19 -39
- package/dist/integrations/harnesses/amazonq/index.js +17 -32
- package/dist/integrations/harnesses/claude/index.js +59 -28
- package/dist/integrations/harnesses/claude/session-log.js +7 -5
- package/dist/integrations/harnesses/codex/index.js +19 -31
- package/dist/integrations/harnesses/copilot/index.js +17 -35
- package/dist/integrations/harnesses/gemini/index.js +18 -34
- package/dist/integrations/harnesses/harness.js +36 -0
- package/dist/integrations/harnesses/index.js +20 -51
- package/dist/integrations/harnesses/opencode/agent-builder.js +132 -100
- package/dist/integrations/harnesses/opencode/index.js +11 -33
- package/dist/integrations/harnesses/opencode/roots.js +50 -0
- package/dist/integrations/harnesses/opencode/runtime/binary.js +206 -0
- package/dist/integrations/harnesses/opencode/runtime/command.js +152 -0
- package/dist/integrations/harnesses/opencode/runtime/index.js +177 -0
- package/dist/integrations/harnesses/opencode/runtime/tar.js +107 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +15 -7
- package/dist/integrations/harnesses/opencode/session-log-v2.js +72 -48
- package/dist/integrations/harnesses/opencode/session-log.js +58 -137
- package/dist/integrations/harnesses/opencode/version.js +34 -53
- package/dist/integrations/harnesses/openhands/index.js +13 -37
- package/dist/integrations/harnesses/pi/index.js +21 -32
- package/dist/integrations/lockfile.js +1 -1
- package/dist/integrations/session-logs/index.js +11 -31
- package/dist/llm/client.js +93 -111
- package/dist/llm/embedder.js +19 -34
- package/dist/llm/embedders/connection.js +31 -0
- package/dist/llm/embedders/local-model-files.js +56 -0
- package/dist/llm/embedders/local.js +146 -115
- package/dist/llm/embedders/remote.js +26 -23
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/index-passes.js +33 -39
- package/dist/llm/memory-infer.js +67 -77
- package/dist/llm/model-list.js +35 -0
- package/dist/llm/rerank-client.js +8 -14
- package/dist/llm/structured-call.js +45 -99
- package/dist/llm/structured.js +60 -0
- package/dist/output/renderers.js +2 -8
- package/dist/output/shapes/helpers.js +18 -44
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/output/shapes.js +1 -7
- package/dist/output/text/command-format.js +41 -39
- package/dist/output/text/health-format.js +8 -2
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +12 -0
- package/dist/output/text/models.js +3 -2
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +16 -28
- package/dist/output/text/show-format.js +0 -2
- package/dist/output/text/targets-table.js +70 -0
- package/dist/output/text/workflow-format.js +44 -15
- package/dist/output/text.js +1 -1
- package/dist/registry/providers/skills-sh.js +1 -28
- package/dist/registry/providers/static-index.js +1 -71
- package/dist/runtime.js +6 -2
- package/dist/scripts/akm-migrate-node.js +47095 -44905
- package/dist/scripts/akm-migrate.js +46946 -44755
- package/dist/setup/detect.js +28 -273
- package/dist/setup/endpoint.js +36 -0
- package/dist/setup/semantic-assets.js +13 -19
- package/dist/setup/setup-flags.js +77 -0
- package/dist/setup/setup-plan.js +144 -0
- package/dist/setup/setup.js +134 -358
- package/dist/setup/steps/connection-shared.js +49 -101
- package/dist/setup/steps/connection.js +121 -524
- package/dist/setup/steps/embeddings.js +151 -0
- package/dist/setup/steps/harnesses.js +118 -0
- package/dist/setup/steps/platforms.js +2 -81
- package/dist/setup/steps/tasks.js +1 -2
- package/dist/setup/steps.js +10 -0
- package/dist/setup/summary.js +67 -0
- package/dist/sources/freshness.js +16 -21
- package/dist/sources/providers/git-provider.js +2 -9
- package/dist/sources/providers/provider-utils.js +13 -5
- package/dist/sources/resolve.js +12 -16
- package/dist/sources/snapshot-fetchers/robots.js +11 -12
- package/dist/sources/snapshot-fetchers/secret-seam.js +2 -4
- package/dist/sources/snapshot-fetchers/website-ingest.js +8 -15
- package/dist/sources/snapshot-fetchers/x.js +1 -1
- package/dist/standalone/onnxruntime-library.js +52 -0
- package/dist/storage/repositories/improve-ledger-repository.js +1 -1
- package/dist/storage/repositories/improve-runs-repository.js +0 -13
- package/dist/storage/repositories/index-entries-repository.js +2 -2
- package/dist/storage/repositories/proposals-repository.js +2 -2
- package/dist/storage/repositories/task-history-repository.js +2 -2
- package/dist/storage/repositories/workflow-runs-repository.js +44 -129
- package/dist/storage/sqlite-read-snapshot.js +33 -29
- package/dist/tasks/embedded.js +1 -1
- package/dist/tasks/log-redaction.js +7 -119
- package/dist/tasks/prepare/prepare-support.js +8 -7
- package/dist/tasks/prepare/prepare.js +8 -9
- package/dist/tasks/prepare/script-capture.js +9 -25
- package/dist/tasks/run/attempt-lifecycle.js +17 -35
- package/dist/tasks/run/load-task.js +54 -27
- package/dist/tasks/run/run-command-task.js +15 -10
- package/dist/tasks/run/run-native-task.js +8 -21
- package/dist/tasks/run/run-task.js +5 -8
- package/dist/tasks/run/run-workflow-task.js +14 -21
- package/dist/tasks/run/task-history.js +9 -17
- package/dist/tasks/run/task-log.js +1 -5
- package/dist/tasks/scheduler-invocation.js +13 -18
- package/dist/tasks/scheduler-sync.js +0 -1
- package/dist/tasks/source/bounded-document.js +31 -117
- package/dist/tasks/source/parse-task-source.js +0 -1
- package/dist/tasks/source/project-v4.js +5 -3
- package/dist/tasks/source/task-input-diagnostics.js +3 -4
- package/dist/tasks/source/task-source-v4.js +48 -72
- package/dist/tasks/source-v3.js +2 -5
- package/dist/tasks/task-run-reserved-flags.js +1 -2
- package/dist/workflows/authoring/authoring.js +2 -7
- package/dist/workflows/compile.js +1 -15
- package/dist/workflows/concurrency-policy.js +4 -4
- package/dist/workflows/exec/child-workflow.js +1 -4
- package/dist/workflows/exec/dispatch-redaction.js +35 -86
- package/dist/workflows/exec/environment.js +13 -77
- package/dist/workflows/exec/exec-unit.js +14 -55
- package/dist/workflows/exec/frozen-judge.js +26 -28
- package/dist/workflows/exec/native-executor.js +126 -71
- package/dist/workflows/exec/run-workflow.js +38 -42
- package/dist/workflows/exec/step-work.js +13 -17
- package/dist/workflows/exec/unit-dispatch.js +7 -21
- package/dist/workflows/freeze/environment.js +14 -119
- package/dist/workflows/freeze/freeze.js +14 -33
- package/dist/workflows/freeze/step-values.js +6 -13
- package/dist/workflows/freeze/targets/child-workflow.js +3 -5
- package/dist/workflows/freeze/targets/command.js +9 -15
- package/dist/workflows/freeze/targets/shell.js +0 -3
- package/dist/workflows/freeze/task-bindings.js +0 -1
- package/dist/workflows/parser.js +50 -59
- package/dist/workflows/plan.js +8 -2
- package/dist/workflows/renderer.js +83 -9
- package/dist/workflows/resource-limits.js +2 -2
- package/dist/workflows/runtime/run-plan.js +38 -23
- package/dist/workflows/runtime/runs.js +55 -93
- package/dist/workflows/runtime/workflow-asset-loader.js +55 -86
- package/dist/workflows/source-files.js +7 -19
- package/docs/README.md +10 -16
- package/docs/architecture/README.md +2 -37
- package/docs/architecture/adapters.md +2 -2
- package/docs/architecture/akm-core-principles.md +256 -118
- package/docs/architecture/architecture.md +283 -99
- package/docs/architecture/improvement.md +8 -2
- package/docs/architecture/internals/classification.md +1 -3
- package/docs/architecture/internals/fresh-host-rebuild-runbook.md +7 -6
- package/docs/architecture/internals/health-advisories.md +35 -74
- package/docs/architecture/internals/improve-workflow.md +27 -26
- package/docs/architecture/internals/indexing.md +3 -3
- package/docs/architecture/internals/storage-locations.md +48 -15
- package/docs/architecture/persisted-data-compat.md +10 -6
- package/docs/architecture/specs/okf-support.md +9 -11
- package/docs/architecture/specs/ref.md +7 -9
- package/docs/architecture/testing/testing-workflow.md +172 -52
- package/docs/architecture/workflow-engine.md +51 -34
- package/docs/guides/README.md +0 -1
- package/docs/guides/author-bundles.md +15 -20
- package/docs/guides/author-workflows.md +93 -71
- package/docs/guides/bundles.md +20 -16
- package/docs/guides/discover-and-load.md +1 -1
- package/docs/guides/getting-started.md +49 -3
- package/docs/guides/improve-the-library.md +10 -4
- package/docs/guides/recipes/headless-install.md +11 -16
- package/docs/guides/run-workflows.md +29 -20
- package/docs/guides/scheduling.md +2 -2
- package/docs/guides/use-with-any-agent.md +20 -22
- package/docs/integration/bundling-akm.md +19 -9
- package/docs/maintainers/README.md +2 -6
- package/docs/maintainers/release-checklist.md +73 -126
- package/docs/migration/README.md +10 -3
- package/docs/migration/release-notes/0.10.0.md +81 -16
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +1 -1
- package/docs/migration/release-notes/README.md +1 -1
- package/docs/migration/v0.9-to-v0.10.md +300 -60
- package/docs/migration/v0.9.1-to-v0.9.2.md +6 -5
- package/docs/posts/config-v2-lessons-16.md +1 -1
- package/docs/posts/llm-mode-reflect-13.md +1 -1
- package/docs/posts/release-0.6.0.md +11 -11
- package/docs/posts/release-0.8.0.md +4 -4
- package/docs/posts/workflows-vaults-09.md +1 -1
- package/docs/reference/README.md +1 -1
- package/docs/reference/asset-types.md +2 -2
- package/docs/reference/cli.md +477 -388
- package/docs/reference/configuration.md +569 -550
- package/docs/reference/data-and-telemetry.md +9 -6
- package/docs/reference/env-and-secrets.md +72 -15
- package/docs/reference/refs.md +3 -20
- package/docs/reference/registry.md +12 -38
- package/docs/reference/supported-formats.md +1 -1
- package/docs/reference/tasks.md +22 -11
- package/docs/reference/ui-api.md +14 -9
- package/docs/reference/workflow-schema.md +199 -154
- package/docs/reference/workflows.md +4 -6
- package/package.json +9 -11
- package/schemas/akm-config.json +1696 -2922
- package/schemas/akm-task.json +4 -4
- package/schemas/akm-workflow.json +36 -9
- package/ROADMAP.md +0 -112
- package/dist/assets/models.json +0 -35
- package/dist/commands/health/engine-usage.js +0 -45
- package/dist/commands/sources/dangerous-env-audit.js +0 -134
- package/dist/core/activation-policy.js +0 -67
- package/dist/core/config/schema/engines.js +0 -160
- package/dist/core/config/schema/execution.js +0 -23
- package/dist/core/spawn-env.js +0 -268
- package/dist/execution/directory-identity.js +0 -78
- package/dist/integrations/agent/builder-shared.js +0 -33
- package/dist/integrations/agent/builders.js +0 -43
- package/dist/integrations/agent/engine-fallback.js +0 -59
- package/dist/integrations/agent/engine-resolution.js +0 -333
- package/dist/integrations/agent/model-map.js +0 -475
- package/dist/integrations/harnesses/aider/agent-builder.js +0 -107
- package/dist/integrations/harnesses/aider/result-extractor.js +0 -53
- package/dist/integrations/harnesses/amazonq/agent-builder.js +0 -138
- package/dist/integrations/harnesses/amazonq/result-extractor.js +0 -48
- package/dist/integrations/harnesses/claude/agent-builder.js +0 -106
- package/dist/integrations/harnesses/claude/config-import.js +0 -67
- package/dist/integrations/harnesses/claude/result-extractor.js +0 -67
- package/dist/integrations/harnesses/codex/agent-builder.js +0 -150
- package/dist/integrations/harnesses/codex/result-extractor.js +0 -110
- package/dist/integrations/harnesses/copilot/agent-builder.js +0 -117
- package/dist/integrations/harnesses/copilot/result-extractor.js +0 -178
- package/dist/integrations/harnesses/gemini/agent-builder.js +0 -114
- package/dist/integrations/harnesses/gemini/result-extractor.js +0 -149
- package/dist/integrations/harnesses/opencode/config-import.js +0 -149
- package/dist/integrations/harnesses/opencode/model-config.js +0 -33
- package/dist/integrations/harnesses/opencode/model-work-agent.js +0 -115
- package/dist/integrations/harnesses/opencode/session-log-types.js +0 -12
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -44
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -1052
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +0 -199
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +0 -254
- package/dist/integrations/harnesses/opencode-sdk/wire.js +0 -66
- package/dist/integrations/harnesses/openhands/agent-builder.js +0 -120
- package/dist/integrations/harnesses/openhands/result-extractor.js +0 -135
- package/dist/integrations/harnesses/pi/agent-builder.js +0 -89
- package/dist/integrations/harnesses/pi/result-extractor.js +0 -168
- package/dist/integrations/harnesses/shared.js +0 -18
- package/dist/integrations/harnesses/types.js +0 -55
- package/dist/llm/feature-gate.js +0 -115
- package/dist/output/shapes/models-list.js +0 -16
- package/dist/output/shapes/registry-search.js +0 -10
- package/dist/setup/detected-engines.js +0 -136
- package/dist/setup/engine-config.js +0 -97
- package/dist/setup/harness-config-import.js +0 -47
- package/dist/setup/providers.js +0 -14
- package/dist/setup/steps/semantic.js +0 -39
- package/dist/workflows/authoring/scope-key.js +0 -79
- package/dist/workflows/exec/lowering-notices.js +0 -23
- package/dist/workflows/source-semantics.js +0 -110
- package/docs/architecture/0.10-process-rules.md +0 -832
- package/docs/architecture/akm-architecture-decision-history.md +0 -2055
- package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +0 -550
- package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +0 -72
- package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +0 -142
- package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +0 -189
- package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +0 -97
- package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +0 -108
- package/docs/architecture/decisions/0006-task-source-version-routing.md +0 -124
- package/docs/architecture/decisions/0007-workflow-composition-bounds.md +0 -83
- package/docs/architecture/decisions/0008-task-binding-normalization.md +0 -88
- package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +0 -80
- package/docs/architecture/decisions/0010-driver-protocol-cut.md +0 -36
- package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +0 -125
- package/docs/architecture/decisions/README.md +0 -62
- package/docs/architecture/internals/functional-contract-patterns.md +0 -340
- package/docs/architecture/internals/registry-network-boundary.md +0 -57
- package/docs/architecture/internals/search.md +0 -248
- package/docs/architecture/reviews/env-secret-access.md +0 -319
- package/docs/architecture/runtime-boundary-design.md +0 -153
- package/docs/architecture/specs/0.9.0-close-out-plan.md +0 -361
- package/docs/architecture/specs/0.9.0-decisions.md +0 -532
- package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +0 -745
- package/docs/architecture/specs/0.9.0-open-items-register.md +0 -135
- package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +0 -740
- package/docs/architecture/specs/0.9.0-release-surface-review.md +0 -636
- package/docs/architecture/specs/agent-command-engine-model-design.md +0 -513
- package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +0 -501
- package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +0 -291
- package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +0 -2059
- package/docs/architecture/specs/di-seams-plan.md +0 -539
- package/docs/architecture/specs/driver-protocol-keep-or-cut.md +0 -275
- package/docs/architecture/specs/fact-asset-type.md +0 -142
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +0 -634
- package/docs/architecture/specs/reviews/task-workflow-unification/README.md +0 -72
- package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +0 -152
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +0 -352
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +0 -300
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +0 -402
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +0 -758
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +0 -645
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +0 -602
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +0 -74
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +0 -15
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +0 -132
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +0 -147
- package/docs/architecture/specs/stash-conventions-code-spec.md +0 -275
- package/docs/architecture/specs/stash-organization-conventions.md +0 -377
- package/docs/architecture/specs/task-workflow-format-unification.md +0 -721
- package/docs/architecture/specs/workflow-engine-buy-vs-build.md +0 -231
- package/docs/architecture/specs/workflow-format-unification.md +0 -432
- package/docs/architecture/testing/manual-testing-checklist.md +0 -3411
- package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +0 -924
- package/docs/architecture/testing/task-workflow-manual-tests.md +0 -1720
- package/docs/guides/claude-code-vs-akm-workflows.md +0 -29
- package/docs/guides/knowledge-management.md +0 -18
- package/docs/maintainers/curate-workmap.md +0 -335
- package/docs/migration/v0.5-to-v0.6.md +0 -759
- package/docs/migration/v0.7-to-v0.8.md +0 -1378
- package/docs/plans/0.9.2-agent-command-workflow-plan.md +0 -423
package/dist/llm/client.js
CHANGED
|
@@ -8,13 +8,11 @@
|
|
|
8
8
|
* probing, and availability checks) separate from higher-level workflows.
|
|
9
9
|
*/
|
|
10
10
|
import { fetchWithTimeout, readBodyWithByteCap } from "../core/common.js";
|
|
11
|
-
import {
|
|
12
|
-
import { isApiKeyReference } from "../core/config/schema/primitives.js";
|
|
11
|
+
import { openAiBaseUrl, openAiOperationUrl } from "../core/endpoint-url.js";
|
|
13
12
|
import { formatExtraParamsIssue, validateExtraParams } from "../core/extra-params.js";
|
|
14
|
-
import {
|
|
13
|
+
import { effectiveRequestFields } from "../core/llm-inference.js";
|
|
14
|
+
import { redactErrorBody, redactSensitiveText, redactUrlCredentials } from "../core/redaction.js";
|
|
15
15
|
import { warn, warnVerbose } from "../core/warn.js";
|
|
16
|
-
import { DEFAULT_LLM_TIMEOUT_MS } from "../integrations/agent/config.js";
|
|
17
|
-
import { resolveSecretFromStore } from "../sources/snapshot-fetchers/secret-seam.js";
|
|
18
16
|
import { emitLlmUsage, extractUsageTokens, } from "./usage-telemetry.js";
|
|
19
17
|
/** Maximum length of an upstream response excerpt included in thrown errors. */
|
|
20
18
|
const ERROR_BODY_MAX_LEN = 200;
|
|
@@ -183,25 +181,37 @@ export async function chatCompletion(config, messages, options) {
|
|
|
183
181
|
return chatCompletionOverride(config, messages, options);
|
|
184
182
|
return chatCompletionReal(config, messages, options);
|
|
185
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* One call's time budget: the first attempt is given all of it and a retry
|
|
186
|
+
* only what is left, so a call and its retries never outlast its timeout.
|
|
187
|
+
*/
|
|
188
|
+
function timeBudget(totalMs) {
|
|
189
|
+
if (totalMs === null)
|
|
190
|
+
return () => null;
|
|
191
|
+
let deadlineAt;
|
|
192
|
+
return () => {
|
|
193
|
+
const now = Date.now();
|
|
194
|
+
deadlineAt ??= now + totalMs;
|
|
195
|
+
return Math.max(0, deadlineAt - now);
|
|
196
|
+
};
|
|
197
|
+
}
|
|
186
198
|
async function chatCompletionReal(config, messages, options) {
|
|
187
199
|
const effectiveTimeoutMs = options && Object.hasOwn(options, "timeoutMs")
|
|
188
200
|
? (options.timeoutMs ?? null)
|
|
189
201
|
: Object.hasOwn(config, "timeoutMs")
|
|
190
202
|
? (config.timeoutMs ?? null)
|
|
191
|
-
:
|
|
203
|
+
: null;
|
|
192
204
|
const started = Date.now();
|
|
205
|
+
const budget = timeBudget(effectiveTimeoutMs);
|
|
193
206
|
try {
|
|
194
|
-
return await chatCompletionAttempt(config, messages, options,
|
|
207
|
+
return await chatCompletionAttempt(config, messages, options, budget);
|
|
195
208
|
}
|
|
196
209
|
catch (err) {
|
|
197
210
|
if (!(err instanceof LlmCallError) || !isRetryable(err))
|
|
198
211
|
throw err;
|
|
199
212
|
// Timeout-budget guard: if the first attempt already burned most of the
|
|
200
213
|
// budget, a second attempt cannot complete — skip the retry.
|
|
201
|
-
|
|
202
|
-
const remaining = effectiveTimeoutMs === null ? null : effectiveTimeoutMs - elapsed;
|
|
203
|
-
if (effectiveTimeoutMs !== null &&
|
|
204
|
-
(elapsed >= effectiveTimeoutMs * RETRY_BUDGET_FRACTION || (remaining !== null && remaining <= 0))) {
|
|
214
|
+
if (effectiveTimeoutMs !== null && Date.now() - started >= effectiveTimeoutMs * RETRY_BUDGET_FRACTION) {
|
|
205
215
|
throw err;
|
|
206
216
|
}
|
|
207
217
|
// Signal the caller so it can bump `retryAttempts` (NOT `failureCount`).
|
|
@@ -211,8 +221,8 @@ async function chatCompletionReal(config, messages, options) {
|
|
|
211
221
|
warnVerbose(`[akm] LLM transient failure (${err.code}); retrying once: ${err.message}`);
|
|
212
222
|
const wait = retryBackoffMs();
|
|
213
223
|
await waitForRetry(wait, options?.sleep ?? sleep, options?.signal);
|
|
214
|
-
// The retry
|
|
215
|
-
return await chatCompletionAttempt(config, messages, options,
|
|
224
|
+
// The retry spends what is left of the original budget.
|
|
225
|
+
return await chatCompletionAttempt(config, messages, options, budget);
|
|
216
226
|
}
|
|
217
227
|
}
|
|
218
228
|
// ── Structured-output attempt-then-fallback ─────────────────────────────────
|
|
@@ -286,10 +296,8 @@ const RESPONSE_FORMAT_NAMED = /format_ignored|response_format|json_schema/;
|
|
|
286
296
|
* inline fallback-once when a schema was requested and the provider 4xx's
|
|
287
297
|
* (never retried by the transient-failure policy below, by design — 4xx is
|
|
288
298
|
* a same-request-will-always-fail signal EXCEPT for this one specific,
|
|
289
|
-
* request-shape-dependent case).
|
|
290
|
-
*
|
|
291
|
-
* and that is a value a human (or workflow author) set explicitly, not one
|
|
292
|
-
* a probe wrote automatically.
|
|
299
|
+
* request-shape-dependent case). Only what a real call this process made has
|
|
300
|
+
* shown (`isJsonSchemaKnownUnsupported`) skips the first attempt.
|
|
293
301
|
*
|
|
294
302
|
* The thinking-control fields get the same treatment (#1045): a 4xx that
|
|
295
303
|
* names `chat_template_kwargs` or `enable_thinking` is answered by one retry
|
|
@@ -298,9 +306,8 @@ const RESPONSE_FORMAT_NAMED = /format_ignored|response_format|json_schema/;
|
|
|
298
306
|
* same way: the connection stops sending `temperature`, or sends the token cap
|
|
299
307
|
* as `max_completion_tokens`, for the rest of the process.
|
|
300
308
|
*/
|
|
301
|
-
async function chatCompletionAttempt(config, messages, options,
|
|
302
|
-
!
|
|
303
|
-
const wantsSchema = Boolean(options?.responseSchema) && config.supportsJsonSchema !== false && !isJsonSchemaKnownUnsupported(config);
|
|
309
|
+
async function chatCompletionAttempt(config, messages, options, budget, includeThinking = sendsThinkingFields(config, options) && !isThinkingControlKnownRejected(config)) {
|
|
310
|
+
const wantsSchema = Boolean(options?.responseSchema) && !isJsonSchemaKnownUnsupported(config);
|
|
304
311
|
// The schema attempt's error record is held, not emitted: when the retry without the schema
|
|
305
312
|
// recovers the call, that call is ONE success, not a failure plus a success. Every other exit
|
|
306
313
|
// flushes the held record, so a failed call is still recorded once.
|
|
@@ -310,12 +317,12 @@ async function chatCompletionAttempt(config, messages, options, timeoutMs, inclu
|
|
|
310
317
|
emitLlmUsage(held.record);
|
|
311
318
|
};
|
|
312
319
|
try {
|
|
313
|
-
return await chatCompletionAttemptOnce(config, messages, options,
|
|
320
|
+
return await chatCompletionAttemptOnce(config, messages, options, budget(), wantsSchema, includeThinking, held);
|
|
314
321
|
}
|
|
315
322
|
catch (err) {
|
|
316
323
|
// A 5xx that names the response format is answered like the 4xx rejection below (#1150).
|
|
317
324
|
if (wantsSchema && err instanceof LlmCallError && err.namesResponseFormat) {
|
|
318
|
-
return retryWithoutSchema(config, messages, options,
|
|
325
|
+
return retryWithoutSchema(config, messages, options, budget, includeThinking, err);
|
|
319
326
|
}
|
|
320
327
|
if (!isRejectedRequest(err)) {
|
|
321
328
|
flushHeld();
|
|
@@ -326,56 +333,76 @@ async function chatCompletionAttempt(config, messages, options, timeoutMs, inclu
|
|
|
326
333
|
flushHeld();
|
|
327
334
|
warnVerbose(`[akm] LLM rejected temperature (${err.statusCode}); retrying once without it: ${err.message}`);
|
|
328
335
|
temperatureRejectedConnections.add(key);
|
|
329
|
-
return chatCompletionAttempt(config, messages, options,
|
|
336
|
+
return chatCompletionAttempt(config, messages, options, budget, includeThinking);
|
|
330
337
|
}
|
|
331
338
|
if (MAX_TOKENS_REPLACED.test(err.message) && !maxCompletionTokensConnections.has(key)) {
|
|
332
339
|
flushHeld();
|
|
333
340
|
warnVerbose(`[akm] LLM rejected max_tokens (${err.statusCode}); retrying once with max_completion_tokens: ${err.message}`);
|
|
334
341
|
maxCompletionTokensConnections.add(key);
|
|
335
|
-
return chatCompletionAttempt(config, messages, options,
|
|
342
|
+
return chatCompletionAttempt(config, messages, options, budget, includeThinking);
|
|
336
343
|
}
|
|
337
344
|
if (includeThinking && THINKING_FIELD_NAMED.test(err.message)) {
|
|
338
345
|
flushHeld();
|
|
339
346
|
warnVerbose(`[akm] LLM rejected chat_template_kwargs/enable_thinking (${err.statusCode}); retrying once without them: ${err.message}`);
|
|
340
|
-
const fallback = await chatCompletionAttempt(config, messages, options,
|
|
347
|
+
const fallback = await chatCompletionAttempt(config, messages, options, budget, false);
|
|
341
348
|
thinkingControlRejectedConnections.add(connectionKey(config));
|
|
342
349
|
return fallback;
|
|
343
350
|
}
|
|
344
351
|
if (!wantsSchema)
|
|
345
352
|
throw err;
|
|
346
|
-
return retryWithoutSchema(config, messages, options,
|
|
353
|
+
return retryWithoutSchema(config, messages, options, budget, includeThinking, err);
|
|
347
354
|
}
|
|
348
355
|
}
|
|
349
|
-
async function retryWithoutSchema(config, messages, options,
|
|
356
|
+
async function retryWithoutSchema(config, messages, options, budget, includeThinking, err) {
|
|
350
357
|
warnVerbose(`[akm] LLM rejected response_format:json_schema (${err.statusCode}); retrying once without it: ${err.message}`);
|
|
351
|
-
const fallback = await chatCompletionAttemptOnce(config, messages, options,
|
|
358
|
+
const fallback = await chatCompletionAttemptOnce(config, messages, options, budget(), false, includeThinking);
|
|
352
359
|
jsonSchemaUnsupportedConnections.add(connectionKey(config));
|
|
353
360
|
return fallback;
|
|
354
361
|
}
|
|
362
|
+
/** Whether this request carries the two thinking-control fields, from a setting or as written. */
|
|
363
|
+
function sendsThinkingFields(config, options) {
|
|
364
|
+
return ((options?.enableThinking ?? config.inference?.enableThinking) !== undefined ||
|
|
365
|
+
config.request?.chat_template_kwargs !== undefined ||
|
|
366
|
+
config.request?.enable_thinking !== undefined);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* The fields of one request: akm's default temperature, the connection's request
|
|
370
|
+
* fields as written, and the portable settings (the call's own over the
|
|
371
|
+
* connection's) translated, nearest last. A field the endpoint has rejected on an
|
|
372
|
+
* earlier call is left out, and the token cap goes by the name it asked for.
|
|
373
|
+
*/
|
|
374
|
+
function requestFields(config, options, includeThinking) {
|
|
375
|
+
const settings = {
|
|
376
|
+
...config.inference,
|
|
377
|
+
...(options?.temperature !== undefined ? { temperature: options.temperature } : {}),
|
|
378
|
+
...(options?.maxTokens !== undefined ? { maxTokens: options.maxTokens } : {}),
|
|
379
|
+
...(options?.enableThinking !== undefined ? { enableThinking: options.enableThinking } : {}),
|
|
380
|
+
};
|
|
381
|
+
const fields = effectiveRequestFields({ temperature: 0.3, ...config.request }, settings);
|
|
382
|
+
const key = connectionKey(config);
|
|
383
|
+
if (temperatureRejectedConnections.has(key))
|
|
384
|
+
delete fields.temperature;
|
|
385
|
+
if (!includeThinking) {
|
|
386
|
+
delete fields.chat_template_kwargs;
|
|
387
|
+
delete fields.enable_thinking;
|
|
388
|
+
}
|
|
389
|
+
if (maxCompletionTokensConnections.has(key) && fields.max_tokens !== undefined) {
|
|
390
|
+
fields.max_completion_tokens = fields.max_tokens;
|
|
391
|
+
delete fields.max_tokens;
|
|
392
|
+
}
|
|
393
|
+
return fields;
|
|
394
|
+
}
|
|
355
395
|
async function chatCompletionAttemptOnce(config, messages, options, timeoutMs, includeSchema, includeThinking, held) {
|
|
356
|
-
if (config.extraParams !== undefined) {
|
|
357
|
-
const issue = validateExtraParams(config.extraParams)[0];
|
|
396
|
+
if (config.inference?.extraParams !== undefined) {
|
|
397
|
+
const issue = validateExtraParams(config.inference.extraParams)[0];
|
|
358
398
|
if (issue)
|
|
359
399
|
throw new Error(formatExtraParamsIssue("LLM extraParams", issue));
|
|
360
400
|
}
|
|
361
401
|
const headers = { "Content-Type": "application/json" };
|
|
362
|
-
|
|
363
|
-
// The execution boundary normally hands us a materialized credential after
|
|
364
|
-
// resolving the reference upstream, so re-running the substitution over a
|
|
365
|
-
// literal key mangled any credential containing `$` — `sk-live$ecret` lost
|
|
366
|
-
// everything from the `$` onward, and the request failed with an opaque
|
|
367
|
-
// 401. The narrow check keeps the symbolic form working for any direct
|
|
368
|
-
// caller that still passes one.
|
|
369
|
-
const resolvedKey = isApiKeyReference(config.apiKey ?? "")
|
|
370
|
-
? resolveSecret(config.apiKey, resolveSecretFromStore)
|
|
371
|
-
: config.apiKey;
|
|
402
|
+
const resolvedKey = config.apiKey;
|
|
372
403
|
if (resolvedKey) {
|
|
373
404
|
headers.Authorization = `Bearer ${resolvedKey}`;
|
|
374
405
|
}
|
|
375
|
-
// Only include max_tokens when explicitly set. The model/API knows its own
|
|
376
|
-
// limits; a hardcoded default creates silent truncation failures when the
|
|
377
|
-
// guess is wrong. Users who need a cap can set llm.maxTokens in config.
|
|
378
|
-
const resolvedMaxTokens = options?.maxTokens ?? config.maxTokens;
|
|
379
406
|
const responseFormat = includeSchema && options?.responseSchema
|
|
380
407
|
? {
|
|
381
408
|
response_format: {
|
|
@@ -384,32 +411,11 @@ async function chatCompletionAttemptOnce(config, messages, options, timeoutMs, i
|
|
|
384
411
|
},
|
|
385
412
|
}
|
|
386
413
|
: {};
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
// Send both whenever thinking is explicitly resolved so the same engine
|
|
393
|
-
// block keeps working across a direct vhost or any gateway in front of it.
|
|
394
|
-
const resolvedEnableThinking = includeThinking ? (options?.enableThinking ?? config.enableThinking) : undefined;
|
|
395
|
-
const thinkingParams = resolvedEnableThinking === undefined
|
|
396
|
-
? {}
|
|
397
|
-
: { chat_template_kwargs: { enable_thinking: resolvedEnableThinking }, enable_thinking: resolvedEnableThinking };
|
|
398
|
-
const reasoningEffortParams = config.reasoningEffort === undefined ? {} : { reasoning_effort: config.reasoningEffort };
|
|
399
|
-
const key = connectionKey(config);
|
|
400
|
-
const maxTokensField = maxCompletionTokensConnections.has(key) ? "max_completion_tokens" : "max_tokens";
|
|
401
|
-
const requestBody = JSON.stringify({
|
|
402
|
-
model: config.model,
|
|
403
|
-
messages,
|
|
404
|
-
...(temperatureRejectedConnections.has(key)
|
|
405
|
-
? {}
|
|
406
|
-
: { temperature: options?.temperature ?? config.temperature ?? 0.3 }),
|
|
407
|
-
...(resolvedMaxTokens !== undefined ? { [maxTokensField]: resolvedMaxTokens } : {}),
|
|
408
|
-
...config.extraParams,
|
|
409
|
-
...responseFormat,
|
|
410
|
-
...thinkingParams,
|
|
411
|
-
...reasoningEffortParams,
|
|
412
|
-
});
|
|
414
|
+
const fields = requestFields(config, options, includeThinking);
|
|
415
|
+
const requestBody = JSON.stringify({ ...fields, model: config.model, messages, ...responseFormat });
|
|
416
|
+
const endpointUrl = openAiOperationUrl(config.endpoint, "chat/completions");
|
|
417
|
+
// What a message says about the endpoint: never a username or password the URL carries.
|
|
418
|
+
const shownEndpoint = redactUrlCredentials(config.endpoint);
|
|
413
419
|
// Wall-clock start for per-attempt usage telemetry (#576). Captured here so the
|
|
414
420
|
// emitted duration covers the full request/response/parse cycle of a single
|
|
415
421
|
// attempt, not the retry-wrapping `chatCompletion`.
|
|
@@ -423,7 +429,7 @@ async function chatCompletionAttemptOnce(config, messages, options, timeoutMs, i
|
|
|
423
429
|
try {
|
|
424
430
|
let response;
|
|
425
431
|
try {
|
|
426
|
-
response = await fetchWithTimeout(
|
|
432
|
+
response = await fetchWithTimeout(endpointUrl, {
|
|
427
433
|
method: "POST",
|
|
428
434
|
headers,
|
|
429
435
|
body: requestBody,
|
|
@@ -460,15 +466,15 @@ async function chatCompletionAttemptOnce(config, messages, options, timeoutMs, i
|
|
|
460
466
|
const safeBody = redactSensitiveText(redactErrorBody(rawBody), resolvedKey ? [resolvedKey] : []);
|
|
461
467
|
const status = response.status;
|
|
462
468
|
if (status === 429) {
|
|
463
|
-
throw new LlmCallError(`LLM request rate limited (429) ${
|
|
469
|
+
throw new LlmCallError(`LLM request rate limited (429) ${shownEndpoint}: ${safeBody}`, "rate_limited", status);
|
|
464
470
|
}
|
|
465
471
|
if (status >= 500 && isHtmlResponse(rawBody)) {
|
|
466
|
-
throw new LlmCallError(`LLM provider returned HTML instead of JSON (${status}) ${
|
|
472
|
+
throw new LlmCallError(`LLM provider returned HTML instead of JSON (${status}) ${shownEndpoint}: ${redactSensitiveText(htmlExcerpt(rawBody), resolvedKey ? [resolvedKey] : [])}`, "provider_html_error", status);
|
|
467
473
|
}
|
|
468
474
|
if (status >= 500) {
|
|
469
|
-
throw new LlmCallError(`LLM provider error (${status}) ${
|
|
475
|
+
throw new LlmCallError(`LLM provider error (${status}) ${shownEndpoint}: ${safeBody}`, "provider_error", status, RESPONSE_FORMAT_NAMED.test(rawBody));
|
|
470
476
|
}
|
|
471
|
-
throw new LlmCallError(`LLM request failed (${status}) ${
|
|
477
|
+
throw new LlmCallError(`LLM request failed (${status}) ${shownEndpoint}: ${safeBody}`, "provider_error", status);
|
|
472
478
|
}
|
|
473
479
|
// A 2xx response is still an error if the body is HTML where JSON was
|
|
474
480
|
// expected (e.g. a provider serving its web UI). Read the raw body first so
|
|
@@ -489,19 +495,19 @@ async function chatCompletionAttemptOnce(config, messages, options, timeoutMs, i
|
|
|
489
495
|
throw err;
|
|
490
496
|
}
|
|
491
497
|
if (isHtmlResponse(rawOkBody)) {
|
|
492
|
-
throw new LlmCallError(`LLM provider returned HTML instead of JSON (${response.status}) ${
|
|
498
|
+
throw new LlmCallError(`LLM provider returned HTML instead of JSON (${response.status}) ${shownEndpoint}: ${redactSensitiveText(htmlExcerpt(rawOkBody), resolvedKey ? [resolvedKey] : [])}`, "provider_html_error", response.status);
|
|
493
499
|
}
|
|
494
500
|
let json;
|
|
495
501
|
try {
|
|
496
502
|
json = JSON.parse(rawOkBody);
|
|
497
503
|
}
|
|
498
504
|
catch {
|
|
499
|
-
throw new LlmCallError(`LLM response was not valid JSON ${
|
|
505
|
+
throw new LlmCallError(`LLM response was not valid JSON ${shownEndpoint}: ${redactSensitiveText(redactErrorBody(rawOkBody), resolvedKey ? [resolvedKey] : [])}`, "parse_error", response.status);
|
|
500
506
|
}
|
|
501
507
|
// A 2xx can still carry a provider failure. OpenRouter answers a provider
|
|
502
508
|
// that fails after the headers with a body holding only `error`.
|
|
503
509
|
if (json.error !== undefined && json.error !== null && !json.choices?.length) {
|
|
504
|
-
throw new LlmCallError(`LLM provider error (${response.status}) ${
|
|
510
|
+
throw new LlmCallError(`LLM provider error (${response.status}) ${shownEndpoint}: ${redactSensitiveText(redactErrorBody(rawOkBody), resolvedKey ? [resolvedKey] : [])}`, "provider_error", response.status);
|
|
505
511
|
}
|
|
506
512
|
const responseModel = typeof json.model === "string" && json.model.trim().length > 0 ? json.model : undefined;
|
|
507
513
|
terminalFields = {
|
|
@@ -510,8 +516,8 @@ async function chatCompletionAttemptOnce(config, messages, options, timeoutMs, i
|
|
|
510
516
|
finishReason: typeof json.choices?.[0]?.finish_reason === "string" ? json.choices[0].finish_reason : undefined,
|
|
511
517
|
...extractUsageTokens(json.usage),
|
|
512
518
|
};
|
|
513
|
-
if (
|
|
514
|
-
warn(`[akm] LLM returned ${terminalFields.reasoningTokens} reasoning tokens despite
|
|
519
|
+
if (fields.enable_thinking === false && (terminalFields.reasoningTokens ?? 0) > 0) {
|
|
520
|
+
warn(`[akm] LLM returned ${terminalFields.reasoningTokens} reasoning tokens despite thinking being off; ` +
|
|
515
521
|
'the provider may not honor that control. Configure reasoningEffort: "none" when the provider supports it.');
|
|
516
522
|
}
|
|
517
523
|
const content = (json.choices?.[0]?.message?.content ?? "").trim();
|
|
@@ -540,30 +546,6 @@ async function chatCompletionAttemptOnce(config, messages, options, timeoutMs, i
|
|
|
540
546
|
}
|
|
541
547
|
// ── Availability check ──────────────────────────────────────────────────────
|
|
542
548
|
// ── Reachability probe ──────────────────────────────────────────────────────
|
|
543
|
-
/**
|
|
544
|
-
* Best-effort reachability check with an error message, for setup's optional
|
|
545
|
-
* `--probe` connectivity verification. Deliberately does NOT probe or cache
|
|
546
|
-
* `response_format: json_schema` support: that used to be persisted as
|
|
547
|
-
* `capabilities.structuredOutput` and consulted on every later call, so a
|
|
548
|
-
* config edit that changed the endpoint/model left a stale verdict in place
|
|
549
|
-
* with no invalidation, and a stale `true` sent an unsupported request that
|
|
550
|
-
* the retry policy explicitly does not retry (4xx). `chatCompletion` now
|
|
551
|
-
* attempts the schema request fresh every time and falls back once per call
|
|
552
|
-
* on a 4xx — see the in-memory tracker below.
|
|
553
|
-
*/
|
|
554
|
-
export async function probeLlmReachable(config, timeoutMs) {
|
|
555
|
-
try {
|
|
556
|
-
const raw = await chatCompletion(config, [{ role: "user", content: "Respond with just the word: ok" }], {
|
|
557
|
-
maxTokens: 16,
|
|
558
|
-
temperature: 0,
|
|
559
|
-
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
560
|
-
});
|
|
561
|
-
return raw.length > 0 ? { reachable: true } : { reachable: false, error: "empty response" };
|
|
562
|
-
}
|
|
563
|
-
catch (err) {
|
|
564
|
-
return { reachable: false, error: err instanceof Error ? err.message : String(err) };
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
549
|
/**
|
|
568
550
|
* Reachability probe for `akm health` (#914): one GET against the
|
|
569
551
|
* OpenAI-compatible `/models` route, bounded by `timeoutMs`. Any HTTP
|
|
@@ -573,7 +555,7 @@ export async function probeLlmReachable(config, timeoutMs) {
|
|
|
573
555
|
*/
|
|
574
556
|
export async function probeLlmEndpoint(config, timeoutMs = 3_000) {
|
|
575
557
|
try {
|
|
576
|
-
await fetch(
|
|
558
|
+
await fetch(openAiOperationUrl(config.endpoint, "models"), { signal: AbortSignal.timeout(timeoutMs) });
|
|
577
559
|
return { reachable: true };
|
|
578
560
|
}
|
|
579
561
|
catch (err) {
|
|
@@ -581,16 +563,16 @@ export async function probeLlmEndpoint(config, timeoutMs = 3_000) {
|
|
|
581
563
|
}
|
|
582
564
|
}
|
|
583
565
|
/**
|
|
584
|
-
* Endpoint-keyed probe memoization (#957):
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
588
|
-
*
|
|
566
|
+
* Endpoint-keyed probe memoization (#957): a caller that probes several
|
|
567
|
+
* connections in one pass (`akm health`'s connections-and-harnesses check)
|
|
568
|
+
* shares one in-flight probe per distinct endpoint (trailing slashes
|
|
569
|
+
* normalized) instead of firing a duplicate probe when two connections point
|
|
570
|
+
* at the same server. `cache` must be scoped to one
|
|
589
571
|
* invocation and never shared across calls — a stale "reachable" surviving
|
|
590
572
|
* past the run that produced it is the failure mode this exists to avoid.
|
|
591
573
|
*/
|
|
592
574
|
export function probeEndpointOnce(connection, cache, probe) {
|
|
593
|
-
const key = connection.endpoint
|
|
575
|
+
const key = openAiBaseUrl(connection.endpoint);
|
|
594
576
|
let pending = cache.get(key);
|
|
595
577
|
if (!pending) {
|
|
596
578
|
pending = probe(connection);
|
package/dist/llm/embedder.js
CHANGED
|
@@ -3,31 +3,21 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { embedCacheKey, getCachedEmbedding, setCachedEmbedding } from "./embedders/cache.js";
|
|
5
5
|
import { DETERMINISTIC_EMBED_MODEL_ID, deterministicEmbed, isDeterministicEmbedEnabled, } from "./embedders/deterministic.js";
|
|
6
|
-
import { DEFAULT_LOCAL_MODEL,
|
|
6
|
+
import { DEFAULT_LOCAL_MODEL, LocalEmbedder, LocalRuntimeUnavailableError } from "./embedders/local.js";
|
|
7
7
|
import { hasRemoteEndpoint, RemoteEmbedder } from "./embedders/remote.js";
|
|
8
8
|
// ── Shared exports ──────────────────────────────────────────────────────────
|
|
9
9
|
export { clearEmbeddingCache } from "./embedders/cache.js";
|
|
10
|
-
export {
|
|
10
|
+
export { _setLocalPipelineLoaderForTests, DEFAULT_LOCAL_MODEL } from "./embedders/local.js";
|
|
11
11
|
let embedderOverrides;
|
|
12
12
|
/** TEST-ONLY. Swap embedder implementations; pass undefined to restore. */
|
|
13
13
|
export function _setEmbedderForTests(fakes) {
|
|
14
14
|
embedderOverrides = fakes;
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Check whether the external Transformers dependency is available.
|
|
18
|
-
* Delegating wrapper around `./embedders/local`'s probe so tests can swap it
|
|
19
|
-
* via {@link _setEmbedderForTests}.
|
|
20
|
-
*/
|
|
21
|
-
export function isTransformersAvailable() {
|
|
22
|
-
if (embedderOverrides?.isTransformersAvailable)
|
|
23
|
-
return embedderOverrides.isTransformersAvailable();
|
|
24
|
-
return isTransformersAvailableReal();
|
|
25
|
-
}
|
|
26
16
|
// ── Singleton local embedder ────────────────────────────────────────────────
|
|
27
17
|
// `_localEmbedder` is an intentional module-level singleton but constructed
|
|
28
|
-
// lazily on first use. The
|
|
29
|
-
//
|
|
30
|
-
//
|
|
18
|
+
// lazily on first use. The loaded model is expensive to initialise (model
|
|
19
|
+
// download, runtime and session load) and is safe to share across calls
|
|
20
|
+
// because it is stateless once created. Deferring
|
|
31
21
|
// construction to first call keeps the module side-effect-free at import time,
|
|
32
22
|
// which matters for the test suite (single Bun process, ~120 test files).
|
|
33
23
|
let _localEmbedder;
|
|
@@ -44,11 +34,18 @@ function getLocalEmbedder() {
|
|
|
44
34
|
export function resetLocalEmbedder() {
|
|
45
35
|
getLocalEmbedder().reset();
|
|
46
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* The runtime the local embedder has embedded with in this process, or
|
|
39
|
+
* `undefined` when it has not loaded a model (nothing was embedded locally).
|
|
40
|
+
*/
|
|
41
|
+
export function localEmbeddingRuntime() {
|
|
42
|
+
return _localEmbedder?.runtime;
|
|
43
|
+
}
|
|
47
44
|
// ── Public API ──────────────────────────────────────────────────────────────
|
|
48
45
|
/**
|
|
49
46
|
* Generate an embedding for the given text.
|
|
50
47
|
* If embeddingConfig has a remote endpoint, uses the configured OpenAI-compatible endpoint.
|
|
51
|
-
* Otherwise falls back to local
|
|
48
|
+
* Otherwise falls back to the local embedder using the model from
|
|
52
49
|
* `embeddingConfig.localModel` or `DEFAULT_LOCAL_MODEL`.
|
|
53
50
|
*
|
|
54
51
|
* Results are cached in an LRU cache (max ~100 entries) keyed by query text
|
|
@@ -98,8 +95,8 @@ async function embedOnce(text, embeddingConfig, signal) {
|
|
|
98
95
|
* sub-batch or oversized document that fails is skipped rather than
|
|
99
96
|
* aborting the whole call — pass `onSkip` to learn which indices were
|
|
100
97
|
* skipped and why; the result array holds `undefined` at those indices.
|
|
101
|
-
* Uses the LocalEmbedder.embedBatch path for the local
|
|
102
|
-
*
|
|
98
|
+
* Uses the LocalEmbedder.embedBatch path for the local model, which processes
|
|
99
|
+
* texts in chunks of 32 for genuine batched inference.
|
|
103
100
|
*
|
|
104
101
|
* `onBatch`, when given, fires once per provider/local batch as it completes
|
|
105
102
|
* (#954) so a caller can commit each batch's rows durably as they land
|
|
@@ -123,7 +120,7 @@ export async function embedBatch(texts, embeddingConfig, signal, onSkip, onBatch
|
|
|
123
120
|
if (embeddingConfig && hasRemoteEndpoint(embeddingConfig)) {
|
|
124
121
|
return new RemoteEmbedder(embeddingConfig).embedBatch(texts, signal, onSkip, onBatch);
|
|
125
122
|
}
|
|
126
|
-
// Local
|
|
123
|
+
// Local model: use the batched path (chunks of 32 via LocalEmbedder).
|
|
127
124
|
// When a localModel override is set we cannot share the singleton (which uses
|
|
128
125
|
// the default model), so fall back to per-text embedWithModel in that case.
|
|
129
126
|
const localModel = embeddingConfig?.localModel;
|
|
@@ -144,7 +141,7 @@ export async function embedBatch(texts, embeddingConfig, signal, onSkip, onBatch
|
|
|
144
141
|
// ── Similarity ──────────────────────────────────────────────────────────────
|
|
145
142
|
// `cosineSimilarity` was moved to `./embedders/types.ts` so importers
|
|
146
143
|
// (notably `db.ts`) can pull the math function without dragging in this
|
|
147
|
-
// module and
|
|
144
|
+
// module and the local embedder's import chain.
|
|
148
145
|
export { cosineSimilarity } from "./embedders/types.js";
|
|
149
146
|
// ── Model ID resolution ─────────────────────────────────────────────────────
|
|
150
147
|
/**
|
|
@@ -154,7 +151,7 @@ export { cosineSimilarity } from "./embedders/types.js";
|
|
|
154
151
|
*
|
|
155
152
|
* Rules:
|
|
156
153
|
* - Remote endpoint: use `config.model` (the API-level model name).
|
|
157
|
-
* - Local
|
|
154
|
+
* - Local model: use `config.localModel ?? DEFAULT_LOCAL_MODEL`.
|
|
158
155
|
* - No config: use `DEFAULT_LOCAL_MODEL` (the shared singleton model).
|
|
159
156
|
*/
|
|
160
157
|
export function resolveEmbeddingModelId(embeddingConfig) {
|
|
@@ -193,14 +190,6 @@ export async function checkEmbeddingAvailability(embeddingConfig) {
|
|
|
193
190
|
};
|
|
194
191
|
}
|
|
195
192
|
}
|
|
196
|
-
// Check if the package is importable before attempting the model download.
|
|
197
|
-
if (!isTransformersAvailable()) {
|
|
198
|
-
return {
|
|
199
|
-
available: false,
|
|
200
|
-
reason: "missing-package",
|
|
201
|
-
message: "The @huggingface/transformers dependency is unavailable.",
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
193
|
try {
|
|
205
194
|
await getLocalEmbedder().getPipeline(embeddingConfig?.localModel);
|
|
206
195
|
return { available: true };
|
|
@@ -208,12 +197,8 @@ export async function checkEmbeddingAvailability(embeddingConfig) {
|
|
|
208
197
|
catch (err) {
|
|
209
198
|
return {
|
|
210
199
|
available: false,
|
|
211
|
-
reason: "model-download-failed",
|
|
200
|
+
reason: err instanceof LocalRuntimeUnavailableError ? "runtime-unavailable" : "model-download-failed",
|
|
212
201
|
message: err instanceof Error ? err.message : String(err),
|
|
213
202
|
};
|
|
214
203
|
}
|
|
215
204
|
}
|
|
216
|
-
export async function isEmbeddingAvailable(embeddingConfig) {
|
|
217
|
-
const result = await checkEmbeddingAvailability(embeddingConfig);
|
|
218
|
-
return result.available;
|
|
219
|
-
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { defaultConnection } from "../../core/config/config.js";
|
|
5
|
+
import { apiKeyReference } from "../../core/config/credentials.js";
|
|
6
|
+
import { openAiBaseUrl } from "../../core/endpoint-url.js";
|
|
7
|
+
import { warnOnce } from "../../core/warn.js";
|
|
8
|
+
/**
|
|
9
|
+
* The embedding block as the embedder uses it. `embedding.model` without an
|
|
10
|
+
* `embedding.endpoint` means the model is served by the default connection: its
|
|
11
|
+
* endpoint, and its key (its `$VAR`, else `credentials.json` under its name).
|
|
12
|
+
* With no default connection there is nothing to serve it, so the built-in local
|
|
13
|
+
* embedder runs, with one warning. Computed where the embedder is used and never
|
|
14
|
+
* stored, so a config write cannot persist it.
|
|
15
|
+
*/
|
|
16
|
+
export function effectiveEmbedding(config) {
|
|
17
|
+
const embedding = config.embedding;
|
|
18
|
+
if (!embedding || embedding.endpoint !== undefined || !embedding.model)
|
|
19
|
+
return embedding;
|
|
20
|
+
const found = defaultConnection(config);
|
|
21
|
+
if (!found) {
|
|
22
|
+
warnOnce("embedding:no-default-connection", "embedding.model is set, but there is no embedding.endpoint and no default connection to serve it; using the built-in local embedder. Add a connection with `akm setup`.");
|
|
23
|
+
return embedding;
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
...embedding,
|
|
27
|
+
endpoint: openAiBaseUrl(found.connection.endpoint),
|
|
28
|
+
...(apiKeyReference(found.connection.apiKey) !== undefined ? { apiKey: found.connection.apiKey } : {}),
|
|
29
|
+
credentialName: found.name,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* The files of a local embedding model, fetched from the Hugging Face Hub into
|
|
6
|
+
* akm's model cache on first use. The layout is `<HF_HOME>/<repo>/<file>` (HF_HOME
|
|
7
|
+
* defaults to `<akm cache>/models`), the one earlier releases wrote through
|
|
8
|
+
* Transformers.js, so a cache they filled is reused as it is.
|
|
9
|
+
*/
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { fetchWithRetry } from "../../core/common.js";
|
|
13
|
+
import { getCacheDir } from "../../core/paths.js";
|
|
14
|
+
import { writeResponseToFileCapped } from "../../runtime.js";
|
|
15
|
+
/** `config.json` is not read here; releases that ran the model through Transformers.js require it, so it stays in the cache. */
|
|
16
|
+
const MODEL_FILES = ["tokenizer.json", "tokenizer_config.json", "config.json", "onnx/model.onnx"];
|
|
17
|
+
function isEnabledEnvironmentFlag(value) {
|
|
18
|
+
return /^(?:1|true|yes|on)$/i.test(value?.trim() ?? "");
|
|
19
|
+
}
|
|
20
|
+
async function downloadFile(url, target) {
|
|
21
|
+
const response = await fetchWithRetry(url, undefined, { timeout: 60_000 });
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
await response.body?.cancel().catch(() => undefined);
|
|
24
|
+
throw new Error(`Could not download ${url}: HTTP ${response.status}`);
|
|
25
|
+
}
|
|
26
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
27
|
+
const partial = `${target}.${process.pid}.tmp`;
|
|
28
|
+
try {
|
|
29
|
+
// No overall deadline for a 127 MB file on a slow link (Transformers.js had none): only 60 s without bytes fails it.
|
|
30
|
+
await writeResponseToFileCapped(partial, response, { stallTimeoutMs: 60_000 });
|
|
31
|
+
fs.renameSync(partial, target);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
fs.rmSync(partial, { force: true });
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Make sure every file of `modelName` (a Hub repo id) is cached and return the
|
|
40
|
+
* directory holding them. With `HF_HUB_OFFLINE` set nothing is fetched and a
|
|
41
|
+
* missing file is an error.
|
|
42
|
+
*/
|
|
43
|
+
export async function ensureLocalModelFiles(modelName) {
|
|
44
|
+
const modelDir = path.join(process.env.HF_HOME || path.join(getCacheDir(), "models"), ...modelName.split("/"));
|
|
45
|
+
const offline = isEnabledEnvironmentFlag(process.env.HF_HUB_OFFLINE);
|
|
46
|
+
for (const file of MODEL_FILES) {
|
|
47
|
+
const target = path.join(modelDir, ...file.split("/"));
|
|
48
|
+
if (fs.existsSync(target))
|
|
49
|
+
continue;
|
|
50
|
+
if (offline) {
|
|
51
|
+
throw new Error(`The local embedding model file ${target} is not cached and HF_HUB_OFFLINE is set.`);
|
|
52
|
+
}
|
|
53
|
+
await downloadFile(`https://huggingface.co/${modelName}/resolve/main/${file}`, target);
|
|
54
|
+
}
|
|
55
|
+
return modelDir;
|
|
56
|
+
}
|