agency-lang 0.6.4 → 0.7.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/dist/lib/agents/agency-agent/agent.agency +595 -43
- package/dist/lib/agents/agency-agent/agent.js +5134 -2060
- package/dist/lib/agents/agency-agent/images/images.js +36 -15
- package/dist/lib/agents/agency-agent/lib/attachments.agency +115 -0
- package/dist/lib/agents/agency-agent/lib/attachments.js +791 -0
- package/dist/lib/agents/agency-agent/lib/config.agency +2 -0
- package/dist/lib/agents/agency-agent/lib/config.js +47 -15
- package/dist/lib/agents/agency-agent/lib/defaultPolicy.agency +28 -1
- package/dist/lib/agents/agency-agent/lib/defaultPolicy.js +64 -16
- package/dist/lib/agents/agency-agent/lib/modelFilters.agency +29 -0
- package/dist/lib/agents/agency-agent/lib/modelFilters.js +353 -0
- package/dist/lib/agents/agency-agent/lib/models.agency +214 -30
- package/dist/lib/agents/agency-agent/lib/models.js +1296 -278
- package/dist/lib/agents/agency-agent/lib/resolution.agency +191 -0
- package/dist/lib/agents/agency-agent/lib/resolution.js +1538 -0
- package/dist/lib/agents/agency-agent/lib/search.agency +471 -0
- package/dist/lib/agents/agency-agent/lib/search.js +2647 -0
- package/dist/lib/agents/agency-agent/lib/settings.agency +147 -0
- package/dist/lib/agents/agency-agent/lib/settings.js +956 -0
- package/dist/lib/agents/agency-agent/lib/slots.agency +34 -0
- package/dist/lib/agents/agency-agent/lib/slots.js +602 -0
- package/dist/lib/agents/agency-agent/lib/utils.js +38 -21
- package/dist/lib/agents/agency-agent/prompts/codeSample.agency +8 -4
- package/dist/lib/agents/agency-agent/prompts/codeSample.js +77 -45
- package/dist/lib/agents/agency-agent/prompts/design.md +13 -7
- package/dist/lib/agents/agency-agent/shared.agency +187 -27
- package/dist/lib/agents/agency-agent/shared.js +1399 -148
- package/dist/lib/agents/agency-agent/subagents/code.agency +46 -15
- package/dist/lib/agents/agency-agent/subagents/code.js +88 -48
- package/dist/lib/agents/agency-agent/subagents/explorer.agency +4 -2
- package/dist/lib/agents/agency-agent/subagents/explorer.js +57 -43
- package/dist/lib/agents/agency-agent/subagents/oracle.agency +4 -2
- package/dist/lib/agents/agency-agent/subagents/oracle.js +57 -43
- package/dist/lib/agents/agency-agent/subagents/research.agency +9 -10
- package/dist/lib/agents/agency-agent/subagents/research.js +55 -39
- package/dist/lib/agents/agency-agent/subagents/review.js +41 -24
- package/dist/lib/agents/agency-agent/subagents/shell.js +446 -0
- package/dist/lib/agents/agency-agent/tests/agentTurn.agency +222 -1
- package/dist/lib/agents/agency-agent/tests/agentTurn.js +2303 -30
- package/dist/lib/agents/agency-agent/tests/agentTurn.test.json +17 -1
- package/dist/lib/agents/agency-agent/tests/attachments.agency +187 -0
- package/dist/lib/agents/agency-agent/tests/attachments.js +3736 -0
- package/dist/lib/agents/agency-agent/tests/attachments.test.json +254 -0
- package/dist/lib/agents/agency-agent/tests/attachmentsTurn.agency +65 -0
- package/dist/lib/agents/agency-agent/tests/attachmentsTurn.js +1032 -0
- package/dist/lib/agents/agency-agent/tests/attachmentsTurn.test.json +110 -0
- package/dist/lib/agents/agency-agent/tests/execPolicy.js +47 -25
- package/dist/lib/agents/agency-agent/tests/gitPolicy.agency +53 -0
- package/dist/lib/agents/agency-agent/tests/gitPolicy.js +694 -0
- package/dist/lib/agents/agency-agent/tests/gitPolicy.test.json +7 -0
- package/dist/lib/agents/agency-agent/tests/imageTool.agency +51 -0
- package/dist/lib/agents/agency-agent/tests/imageTool.js +1111 -0
- package/dist/lib/agents/agency-agent/tests/imageTool.test.json +81 -0
- package/dist/lib/agents/agency-agent/tests/modelFilters.agency +32 -0
- package/dist/lib/agents/agency-agent/tests/modelFilters.js +723 -0
- package/dist/lib/agents/agency-agent/tests/modelFilters.test.json +7 -0
- package/dist/lib/agents/agency-agent/tests/models.agency +114 -0
- package/dist/lib/agents/agency-agent/tests/models.js +2143 -0
- package/dist/lib/agents/agency-agent/tests/models.test.json +49 -0
- package/dist/lib/agents/agency-agent/tests/resolution.agency +184 -0
- package/dist/lib/agents/agency-agent/tests/resolution.js +1498 -0
- package/dist/lib/agents/agency-agent/tests/resolution.test.json +13 -0
- package/dist/lib/agents/agency-agent/tests/search.agency +101 -0
- package/dist/lib/agents/agency-agent/tests/search.js +2095 -0
- package/dist/lib/agents/agency-agent/tests/search.test.json +19 -0
- package/dist/lib/agents/agency-agent/tests/settings.agency +87 -0
- package/dist/lib/agents/agency-agent/tests/settings.js +978 -0
- package/dist/lib/agents/agency-agent/tests/settings.test.json +26 -0
- package/dist/lib/agents/agency-agent/tests/slots.agency +22 -0
- package/dist/lib/agents/agency-agent/tests/slots.js +648 -0
- package/dist/lib/agents/agency-agent/tests/slots.test.json +10 -0
- package/dist/lib/agents/agency-agent/tests/toolWiring.js +41 -15
- package/dist/lib/agents/agency-agent/tests/turnFailure.agency +35 -0
- package/dist/lib/agents/agency-agent/tests/turnFailure.js +694 -0
- package/dist/lib/agents/agency-agent/tests/turnFailure.test.json +34 -0
- package/dist/lib/agents/docs/cli/cli/editor-integration.md +1 -1
- package/dist/lib/agents/docs/cli/cli/local.md +92 -0
- package/dist/lib/agents/docs/cli/cli/models.md +63 -0
- package/dist/lib/agents/docs/cli/cli/optimize.md +33 -1
- package/dist/lib/agents/docs/cli/cli/run.md +0 -29
- package/dist/lib/agents/docs/cli/editor-integration.md +1 -1
- package/dist/lib/agents/docs/cli/local.md +92 -0
- package/dist/lib/agents/docs/cli/models.md +63 -0
- package/dist/lib/agents/docs/cli/optimize.md +33 -1
- package/dist/lib/agents/docs/cli/run.md +0 -29
- package/dist/lib/agents/docs/guide/agency-config-file.md +205 -3
- package/dist/lib/agents/docs/guide/agency-packages.md +54 -0
- package/dist/lib/agents/docs/guide/agency-stdlib.md +14 -0
- package/dist/lib/agents/docs/guide/agency-vs-typescript.md +33 -0
- package/dist/lib/agents/docs/guide/attachments.md +56 -0
- package/dist/lib/agents/docs/guide/basic-syntax.md +204 -72
- package/dist/lib/agents/docs/guide/blocks.md +64 -34
- package/dist/lib/agents/docs/guide/build-integration.md +99 -0
- package/dist/lib/agents/docs/{appendix/appendix → guide}/builtins.md +27 -4
- package/dist/lib/agents/docs/{appendix/appendix → guide}/callbacks.md +55 -33
- package/dist/lib/agents/docs/guide/checkpointing.md +56 -27
- package/dist/lib/agents/docs/guide/cli-args.md +1 -1
- package/dist/lib/agents/docs/guide/common-functions.md +36 -0
- package/dist/lib/agents/docs/guide/compiling-and-running.md +62 -0
- package/dist/lib/agents/docs/guide/concurrency.md +49 -92
- package/dist/lib/agents/docs/guide/cross-thread-context.md +5 -7
- package/dist/lib/agents/docs/guide/custom-providers.md +195 -0
- package/dist/lib/agents/docs/guide/debugging.md +67 -0
- package/dist/lib/agents/docs/guide/developer-tools.md +90 -0
- package/dist/lib/agents/docs/guide/effects-and-raises.md +73 -92
- package/dist/lib/agents/docs/guide/effects.md +100 -0
- package/dist/lib/agents/docs/guide/error-handling.md +56 -44
- package/dist/lib/agents/docs/guide/exercise-1.md +32 -0
- package/dist/lib/agents/docs/guide/functions.md +71 -10
- package/dist/lib/agents/docs/guide/getting-started.md +5 -12
- package/dist/lib/agents/docs/guide/global-var-initialization.md +70 -0
- package/dist/lib/agents/docs/guide/global-vs-static.md +29 -34
- package/dist/lib/agents/docs/guide/guards.md +57 -108
- package/dist/lib/agents/docs/guide/guide/agency-config-file.md +205 -3
- package/dist/lib/agents/docs/guide/guide/agency-packages.md +54 -0
- package/dist/lib/agents/docs/guide/guide/agency-stdlib.md +14 -0
- package/dist/lib/agents/docs/guide/guide/agency-vs-typescript.md +33 -0
- package/dist/lib/agents/docs/guide/guide/attachments.md +56 -0
- package/dist/lib/agents/docs/guide/guide/basic-syntax.md +204 -72
- package/dist/lib/agents/docs/guide/guide/blocks.md +64 -34
- package/dist/lib/agents/docs/guide/guide/build-integration.md +99 -0
- package/dist/lib/agents/docs/{appendix → guide/guide}/builtins.md +27 -4
- package/dist/lib/agents/docs/{appendix → guide/guide}/callbacks.md +55 -33
- package/dist/lib/agents/docs/guide/guide/checkpointing.md +56 -27
- package/dist/lib/agents/docs/guide/guide/cli-args.md +1 -1
- package/dist/lib/agents/docs/guide/guide/common-functions.md +36 -0
- package/dist/lib/agents/docs/guide/guide/compiling-and-running.md +62 -0
- package/dist/lib/agents/docs/guide/guide/concurrency.md +49 -92
- package/dist/lib/agents/docs/guide/guide/cross-thread-context.md +5 -7
- package/dist/lib/agents/docs/guide/guide/custom-providers.md +195 -0
- package/dist/lib/agents/docs/guide/guide/debugging.md +67 -0
- package/dist/lib/agents/docs/guide/guide/developer-tools.md +90 -0
- package/dist/lib/agents/docs/guide/guide/effects-and-raises.md +73 -92
- package/dist/lib/agents/docs/guide/guide/effects.md +100 -0
- package/dist/lib/agents/docs/guide/guide/error-handling.md +56 -44
- package/dist/lib/agents/docs/guide/guide/exercise-1.md +32 -0
- package/dist/lib/agents/docs/guide/guide/functions.md +71 -10
- package/dist/lib/agents/docs/guide/guide/getting-started.md +5 -12
- package/dist/lib/agents/docs/guide/guide/global-var-initialization.md +70 -0
- package/dist/lib/agents/docs/guide/guide/global-vs-static.md +29 -34
- package/dist/lib/agents/docs/guide/guide/guards.md +57 -108
- package/dist/lib/agents/docs/guide/guide/handlers.md +109 -205
- package/dist/lib/agents/docs/guide/guide/image-generation.md +113 -0
- package/dist/lib/agents/docs/guide/guide/imports-and-packages.md +35 -95
- package/dist/lib/agents/docs/guide/guide/interrupts-from-typescript.md +84 -0
- package/dist/lib/agents/docs/guide/guide/interrupts-part-2.md +54 -0
- package/dist/lib/agents/docs/guide/guide/interrupts.md +98 -58
- package/dist/lib/agents/docs/guide/guide/llm-part-2.md +111 -0
- package/dist/lib/agents/docs/guide/guide/llm.md +53 -124
- package/dist/lib/agents/docs/guide/guide/memory.md +262 -249
- package/dist/lib/agents/docs/guide/guide/message-threads.md +111 -0
- package/dist/lib/agents/docs/guide/guide/nodes.md +32 -17
- package/dist/lib/agents/docs/guide/guide/observability.md +11 -4
- package/dist/lib/agents/docs/guide/guide/partial-application.md +40 -132
- package/dist/lib/agents/docs/guide/guide/pattern-matching.md +216 -43
- package/dist/lib/agents/docs/guide/guide/policies.md +11 -4
- package/dist/lib/agents/docs/guide/guide/schemas.md +22 -9
- package/dist/lib/agents/docs/guide/guide/state-isolation.md +139 -0
- package/dist/lib/agents/docs/guide/guide/streaming.md +28 -0
- package/dist/lib/agents/docs/guide/guide/tags.md +72 -0
- package/dist/lib/agents/docs/guide/guide/testing.md +167 -7
- package/dist/lib/agents/docs/guide/guide/troubleshooting.md +2 -53
- package/dist/lib/agents/docs/{appendix/appendix → guide/guide}/ts-helpers.md +48 -0
- package/dist/lib/agents/docs/guide/guide/ts-interop.md +16 -129
- package/dist/lib/agents/docs/guide/guide/type-validation.md +30 -172
- package/dist/lib/agents/docs/guide/guide/types.md +69 -84
- package/dist/lib/agents/docs/guide/guide/unused.md +178 -0
- package/dist/lib/agents/docs/guide/guide/unused2.md +258 -0
- package/dist/lib/agents/docs/guide/guide/value-parameterized-types.md +186 -0
- package/dist/lib/agents/docs/guide/guide/vscode-extension.md +33 -0
- package/dist/lib/agents/docs/guide/guide/why-agency.md +323 -0
- package/dist/lib/agents/docs/guide/handlers.md +109 -205
- package/dist/lib/agents/docs/guide/image-generation.md +113 -0
- package/dist/lib/agents/docs/guide/imports-and-packages.md +35 -95
- package/dist/lib/agents/docs/guide/interrupts-from-typescript.md +84 -0
- package/dist/lib/agents/docs/guide/interrupts-part-2.md +54 -0
- package/dist/lib/agents/docs/guide/interrupts.md +98 -58
- package/dist/lib/agents/docs/guide/llm-part-2.md +111 -0
- package/dist/lib/agents/docs/guide/llm.md +53 -124
- package/dist/lib/agents/docs/guide/memory.md +262 -249
- package/dist/lib/agents/docs/guide/message-threads.md +111 -0
- package/dist/lib/agents/docs/guide/nodes.md +32 -17
- package/dist/lib/agents/docs/guide/observability.md +11 -4
- package/dist/lib/agents/docs/guide/partial-application.md +40 -132
- package/dist/lib/agents/docs/guide/pattern-matching.md +216 -43
- package/dist/lib/agents/docs/guide/policies.md +11 -4
- package/dist/lib/agents/docs/guide/schemas.md +22 -9
- package/dist/lib/agents/docs/guide/state-isolation.md +139 -0
- package/dist/lib/agents/docs/guide/streaming.md +28 -0
- package/dist/lib/agents/docs/guide/tags.md +72 -0
- package/dist/lib/agents/docs/guide/testing.md +167 -7
- package/dist/lib/agents/docs/guide/troubleshooting.md +2 -53
- package/dist/lib/agents/docs/{appendix → guide}/ts-helpers.md +48 -0
- package/dist/lib/agents/docs/guide/ts-interop.md +16 -129
- package/dist/lib/agents/docs/guide/type-validation.md +30 -172
- package/dist/lib/agents/docs/guide/types.md +69 -84
- package/dist/lib/agents/docs/guide/unused.md +178 -0
- package/dist/lib/agents/docs/guide/unused2.md +258 -0
- package/dist/lib/agents/docs/guide/value-parameterized-types.md +186 -0
- package/dist/lib/agents/docs/guide/vscode-extension.md +33 -0
- package/dist/lib/agents/docs/guide/why-agency.md +323 -0
- package/dist/lib/agents/eval/goalJudge.js +35 -14
- package/dist/lib/agents/eval/judge.js +35 -14
- package/dist/lib/agents/eval/judgePairwise.agency +2 -2
- package/dist/lib/agents/eval/judgePairwise.js +35 -14
- package/dist/lib/agents/optimize/gepaReflect.js +35 -14
- package/dist/lib/agents/optimize/mutatePrompt.agency +2 -0
- package/dist/lib/agents/optimize/mutatePrompt.js +38 -15
- package/dist/lib/agents/policy/agent.agency +2 -2
- package/dist/lib/agents/policy/agent.js +94 -58
- package/dist/lib/agents/review/agent.js +41 -19
- package/dist/lib/backends/agencyGenerator.d.ts +14 -2
- package/dist/lib/backends/agencyGenerator.js +158 -53
- package/dist/lib/backends/agencyGenerator.matchBlock.test.js +106 -0
- package/dist/lib/backends/agencyGenerator.test.js +148 -0
- package/dist/lib/backends/effectDeclarationFormat.test.d.ts +1 -0
- package/dist/lib/backends/effectDeclarationFormat.test.js +32 -0
- package/dist/lib/backends/llmAttachmentCodegen.test.d.ts +1 -0
- package/dist/lib/backends/llmAttachmentCodegen.test.js +24 -0
- package/dist/lib/backends/llmNamedArgsCodegen.test.d.ts +1 -0
- package/dist/lib/backends/llmNamedArgsCodegen.test.js +40 -0
- package/dist/lib/backends/providerModules.codegen.test.d.ts +1 -0
- package/dist/lib/backends/{anthropicApiKey.codegen.test.js → providerModules.codegen.test.js} +12 -15
- package/dist/lib/backends/smoltalkDefaults.codegen.test.d.ts +1 -0
- package/dist/lib/backends/smoltalkDefaults.codegen.test.js +65 -0
- package/dist/lib/backends/typescriptBuilder.d.ts +82 -0
- package/dist/lib/backends/typescriptBuilder.integration.test.js +94 -4
- package/dist/lib/backends/typescriptBuilder.js +499 -158
- package/dist/lib/backends/typescriptGenerator/typeToString.js +8 -2
- package/dist/lib/backends/typescriptGenerator/typeToZodSchema.js +25 -28
- package/dist/lib/backends/typescriptGenerator/typeToZodSchema.test.js +73 -0
- package/dist/lib/cli/commands.d.ts +28 -0
- package/dist/lib/cli/commands.js +53 -4
- package/dist/lib/cli/doc.js +19 -0
- package/dist/lib/cli/doc.test.js +27 -1
- package/dist/lib/cli/eval/run.d.ts +18 -1
- package/dist/lib/cli/eval/run.js +55 -24
- package/dist/lib/cli/eval/run.workdir.test.d.ts +1 -0
- package/dist/lib/cli/eval/run.workdir.test.js +111 -0
- package/dist/lib/cli/fetchMockResolve.d.ts +6 -0
- package/dist/lib/cli/fetchMockResolve.js +51 -0
- package/dist/lib/cli/fetchMockResolve.test.d.ts +1 -0
- package/dist/lib/cli/fetchMockResolve.test.js +36 -0
- package/dist/lib/cli/hostedModels.d.ts +10 -0
- package/dist/lib/cli/hostedModels.js +61 -0
- package/dist/lib/cli/hostedModels.test.d.ts +1 -0
- package/dist/lib/cli/hostedModels.test.js +105 -0
- package/dist/lib/cli/local.d.ts +19 -0
- package/dist/lib/cli/local.js +109 -0
- package/dist/lib/cli/local.test.d.ts +1 -0
- package/dist/lib/cli/local.test.js +50 -0
- package/dist/lib/cli/pack.test.js +18 -0
- package/dist/lib/cli/precompile.d.ts +22 -0
- package/dist/lib/cli/precompile.js +125 -0
- package/dist/lib/cli/precompile.test.d.ts +1 -0
- package/dist/lib/cli/precompile.test.js +172 -0
- package/dist/lib/cli/test.js +55 -5
- package/dist/lib/cli/util.d.ts +8 -2
- package/dist/lib/cli/util.js +23 -6
- package/dist/lib/compiler/compile.js +5 -1
- package/dist/lib/compiler/compile.test.js +54 -1
- package/dist/lib/compiler/compileClosure.js +8 -9
- package/dist/lib/compiler/typecheck.js +10 -3
- package/dist/lib/config.d.ts +114 -6
- package/dist/lib/config.js +39 -3
- package/dist/lib/config.modelAliases.test.d.ts +1 -0
- package/dist/lib/config.modelAliases.test.js +11 -0
- package/dist/lib/config.providerModules.test.d.ts +1 -0
- package/dist/lib/config.providerModules.test.js +16 -0
- package/dist/lib/config.test.js +12 -0
- package/dist/lib/constants.d.ts +12 -0
- package/dist/lib/constants.js +12 -0
- package/dist/lib/effectDeclCollection.test.d.ts +1 -0
- package/dist/lib/effectDeclCollection.test.js +56 -0
- package/dist/lib/eval/runArtifacts.js +4 -10
- package/dist/lib/eval/runArtifacts.test.js +10 -22
- package/dist/lib/eval/runEvalInput.d.ts +11 -3
- package/dist/lib/eval/runEvalInput.js +16 -1
- package/dist/lib/eval/runTypes.d.ts +0 -4
- package/dist/lib/eval/runWorkdir.d.ts +25 -0
- package/dist/lib/eval/runWorkdir.js +46 -0
- package/dist/lib/eval/runWorkdir.test.d.ts +1 -0
- package/dist/lib/eval/runWorkdir.test.js +42 -0
- package/dist/lib/importPaths.d.ts +31 -1
- package/dist/lib/importPaths.js +88 -32
- package/dist/lib/importPaths.test.js +47 -4
- package/dist/lib/ir/builders.d.ts +6 -1
- package/dist/lib/ir/builders.js +3 -0
- package/dist/lib/ir/prettyPrint.js +31 -6
- package/dist/lib/ir/prettyPrint.test.js +70 -7
- package/dist/lib/ir/tsIR.d.ts +12 -2
- package/dist/lib/logsViewer/render.js +2 -0
- package/dist/lib/logsViewer/summary.js +13 -0
- package/dist/lib/logsViewer/summary.test.js +6 -0
- package/dist/lib/logsViewer/tree.js +38 -0
- package/dist/lib/logsViewer/tree.test.js +19 -0
- package/dist/lib/lowering/loweringError.d.ts +10 -0
- package/dist/lib/lowering/loweringError.js +13 -0
- package/dist/lib/lowering/patternLowering.ifExpr.test.d.ts +1 -0
- package/dist/lib/lowering/patternLowering.ifExpr.test.js +59 -0
- package/dist/lib/lowering/patternLowering.js +504 -30
- package/dist/lib/lowering/patternLowering.matchExpr.test.d.ts +1 -0
- package/dist/lib/lowering/patternLowering.matchExpr.test.js +572 -0
- package/dist/lib/lowering/patternLowering.test.js +102 -10
- package/dist/lib/lsp/codeAction.js +3 -3
- package/dist/lib/lsp/codeAction.test.js +13 -10
- package/dist/lib/lsp/completion.js +2 -2
- package/dist/lib/lsp/diagnostics.js +11 -4
- package/dist/lib/lsp/diagnostics.test.js +30 -0
- package/dist/lib/matchVal.d.ts +18 -0
- package/dist/lib/matchVal.js +26 -0
- package/dist/lib/optimize/artifacts.js +8 -35
- package/dist/lib/optimize/artifacts.test.js +12 -5
- package/dist/lib/optimize/baseOptimizer.d.ts +15 -9
- package/dist/lib/optimize/baseOptimizer.js +33 -27
- package/dist/lib/optimize/baseOptimizer.test.js +25 -15
- package/dist/lib/optimize/baseOptimizer.workdir.test.js +29 -24
- package/dist/lib/optimize/constraint.d.ts +45 -0
- package/dist/lib/optimize/constraint.js +78 -0
- package/dist/lib/optimize/constraint.test.d.ts +1 -0
- package/dist/lib/optimize/constraint.test.js +133 -0
- package/dist/lib/optimize/grading/scorecard.d.ts +6 -0
- package/dist/lib/optimize/grading/scorecard.js +8 -0
- package/dist/lib/optimize/mutator.js +2 -0
- package/dist/lib/optimize/mutator.test.js +37 -0
- package/dist/lib/optimize/optimizers/example.d.ts +4 -1
- package/dist/lib/optimize/optimizers/example.js +11 -12
- package/dist/lib/optimize/optimizers/example.test.js +2 -2
- package/dist/lib/optimize/optimizers/gepa.d.ts +1 -1
- package/dist/lib/optimize/optimizers/gepa.js +11 -10
- package/dist/lib/optimize/optimizers/gepa.test.js +5 -5
- package/dist/lib/optimize/optimizers/greedyReflective.d.ts +1 -1
- package/dist/lib/optimize/optimizers/greedyReflective.js +8 -7
- package/dist/lib/optimize/optimizers/greedyReflective.test.js +100 -2
- package/dist/lib/optimize/reporter.test.js +2 -0
- package/dist/lib/optimize/sourceMutator.d.ts +8 -4
- package/dist/lib/optimize/sourceMutator.js +63 -13
- package/dist/lib/optimize/sourceMutator.test.js +117 -0
- package/dist/lib/optimize/targets.d.ts +21 -3
- package/dist/lib/optimize/targets.js +119 -10
- package/dist/lib/optimize/targets.test.js +79 -5
- package/dist/lib/optimize/types.d.ts +8 -1
- package/dist/lib/optimize/workspace.d.ts +8 -30
- package/dist/lib/optimize/workspace.js +5 -78
- package/dist/lib/optimize/workspace.test.js +10 -70
- package/dist/lib/parseCache.d.ts +10 -0
- package/dist/lib/parseCache.js +58 -0
- package/dist/lib/parseCache.test.d.ts +1 -0
- package/dist/lib/parseCache.test.js +113 -0
- package/dist/lib/parser.js +27 -2
- package/dist/lib/parsers/dataStructures.test.js +86 -0
- package/dist/lib/parsers/debugMessagesLeak.test.d.ts +1 -0
- package/dist/lib/parsers/debugMessagesLeak.test.js +31 -0
- package/dist/lib/parsers/effectDeclaration.test.d.ts +1 -0
- package/dist/lib/parsers/effectDeclaration.test.js +107 -0
- package/dist/lib/parsers/function.test.js +39 -2
- package/dist/lib/parsers/ifExpression.test.d.ts +1 -0
- package/dist/lib/parsers/ifExpression.test.js +45 -0
- package/dist/lib/parsers/importStatement.test.js +49 -0
- package/dist/lib/parsers/literals.test.js +52 -0
- package/dist/lib/parsers/matchBlock.test.js +298 -59
- package/dist/lib/parsers/parsers.d.ts +21 -2
- package/dist/lib/parsers/parsers.js +232 -100
- package/dist/lib/parsers/pattern.test.js +10 -10
- package/dist/lib/parsers/typeHints.test.js +70 -0
- package/dist/lib/preprocessors/importResolver.d.ts +3 -1
- package/dist/lib/preprocessors/importResolver.js +37 -7
- package/dist/lib/preprocessors/importResolver.test.js +82 -0
- package/dist/lib/preprocessors/injectSchemaArgs.js +1 -2
- package/dist/lib/preprocessors/liftCallbacks.js +1 -1
- package/dist/lib/preprocessors/parallelDesugar.js +3 -2
- package/dist/lib/preprocessors/parallelDesugar.test.js +3 -2
- package/dist/lib/preprocessors/prunePreludeShadows.d.ts +22 -0
- package/dist/lib/preprocessors/prunePreludeShadows.js +55 -0
- package/dist/lib/preprocessors/prunePreludeShadows.test.d.ts +1 -0
- package/dist/lib/preprocessors/prunePreludeShadows.test.js +112 -0
- package/dist/lib/preprocessors/typescriptPreprocessor.core.test.js +25 -0
- package/dist/lib/preprocessors/typescriptPreprocessor.js +7 -5
- package/dist/lib/runtime/__tests__/testHelpers.js +0 -1
- package/dist/lib/runtime/agency.d.ts +3 -1
- package/dist/lib/runtime/agency.js +6 -7
- package/dist/lib/runtime/agencyFunction.js +13 -4
- package/dist/lib/runtime/agencyFunction.test.js +52 -0
- package/dist/lib/runtime/agencyInterrupt.test.js +91 -6
- package/dist/lib/runtime/agencyLlm.d.ts +14 -3
- package/dist/lib/runtime/agencyLlm.js +10 -0
- package/dist/lib/runtime/agencyLlm.test.js +17 -0
- package/dist/lib/runtime/callDepth.d.ts +36 -0
- package/dist/lib/runtime/callDepth.js +76 -0
- package/dist/lib/runtime/callDepth.test.d.ts +1 -0
- package/dist/lib/runtime/callDepth.test.js +67 -0
- package/dist/lib/runtime/callbackForwarding.d.ts +47 -0
- package/dist/lib/runtime/callbackForwarding.js +76 -0
- package/dist/lib/runtime/callbackForwarding.test.d.ts +1 -0
- package/dist/lib/runtime/callbackForwarding.test.js +72 -0
- package/dist/lib/runtime/configOverrides.d.ts +17 -5
- package/dist/lib/runtime/configOverrides.js +28 -6
- package/dist/lib/runtime/configOverrides.test.js +33 -0
- package/dist/lib/runtime/cost.d.ts +10 -0
- package/dist/lib/runtime/cost.js +17 -0
- package/dist/lib/runtime/costTelemetry.d.ts +24 -0
- package/dist/lib/runtime/costTelemetry.js +39 -0
- package/dist/lib/runtime/costTelemetry.test.d.ts +1 -0
- package/dist/lib/runtime/costTelemetry.test.js +92 -0
- package/dist/lib/runtime/deterministicClient.d.ts +9 -2
- package/dist/lib/runtime/deterministicClient.js +21 -1
- package/dist/lib/runtime/deterministicClient.test.js +29 -0
- package/dist/lib/runtime/eq.d.ts +12 -0
- package/dist/lib/runtime/eq.js +14 -0
- package/dist/lib/runtime/eq.test.d.ts +1 -0
- package/dist/lib/runtime/eq.test.js +32 -0
- package/dist/lib/runtime/errors.d.ts +20 -0
- package/dist/lib/runtime/errors.js +23 -0
- package/dist/lib/runtime/errors.test.js +18 -0
- package/dist/lib/runtime/fetchMock.d.ts +12 -0
- package/dist/lib/runtime/fetchMock.js +167 -0
- package/dist/lib/runtime/fetchMock.test.d.ts +1 -0
- package/dist/lib/runtime/fetchMock.test.js +145 -0
- package/dist/lib/runtime/hooks.d.ts +21 -3
- package/dist/lib/runtime/hooks.js +19 -0
- package/dist/lib/runtime/hooks.test.js +39 -2
- package/dist/lib/runtime/image-client.test.d.ts +1 -0
- package/dist/lib/runtime/image-client.test.js +22 -0
- package/dist/lib/runtime/index.d.ts +4 -1
- package/dist/lib/runtime/index.js +3 -1
- package/dist/lib/runtime/interrupts.d.ts +50 -0
- package/dist/lib/runtime/interrupts.js +206 -126
- package/dist/lib/runtime/interrupts.test.js +110 -1
- package/dist/lib/runtime/ipc.configOverrides.test.js +35 -17
- package/dist/lib/runtime/ipc.d.ts +238 -21
- package/dist/lib/runtime/ipc.js +622 -95
- package/dist/lib/runtime/ipc.test.js +453 -2
- package/dist/lib/runtime/llmClient.d.ts +71 -3
- package/dist/lib/runtime/llmClient.hostedTools.test.d.ts +1 -0
- package/dist/lib/runtime/llmClient.hostedTools.test.js +45 -0
- package/dist/lib/runtime/llmClient.js +71 -11
- package/dist/lib/runtime/llmClient.test.d.ts +1 -0
- package/dist/lib/runtime/llmClient.test.js +80 -0
- package/dist/lib/runtime/llmRetry.d.ts +65 -0
- package/dist/lib/runtime/llmRetry.js +158 -0
- package/dist/lib/runtime/llmRetry.test.d.ts +1 -0
- package/dist/lib/runtime/llmRetry.test.js +94 -0
- package/dist/lib/runtime/memory/manager.d.ts +25 -0
- package/dist/lib/runtime/memory/manager.js +115 -14
- package/dist/lib/runtime/memory/manager.test.js +60 -21
- package/dist/lib/runtime/memory/types.d.ts +7 -0
- package/dist/lib/runtime/node.js +10 -1
- package/dist/lib/runtime/prompt.attachments.test.d.ts +1 -0
- package/dist/lib/runtime/prompt.attachments.test.js +41 -0
- package/dist/lib/runtime/prompt.d.ts +65 -2
- package/dist/lib/runtime/prompt.js +276 -31
- package/dist/lib/runtime/prompt.test.js +170 -1
- package/dist/lib/runtime/promptRunner.d.ts +1 -1
- package/dist/lib/runtime/promptRunner.js +1 -1
- package/dist/lib/runtime/providerModules.d.ts +27 -0
- package/dist/lib/runtime/providerModules.js +87 -0
- package/dist/lib/runtime/providerModules.test.d.ts +1 -0
- package/dist/lib/runtime/providerModules.test.js +90 -0
- package/dist/lib/runtime/redactForStatelog.d.ts +20 -0
- package/dist/lib/runtime/redactForStatelog.js +32 -0
- package/dist/lib/runtime/redactForStatelog.test.d.ts +1 -0
- package/dist/lib/runtime/redactForStatelog.test.js +84 -0
- package/dist/lib/runtime/replyAttachments.d.ts +46 -0
- package/dist/lib/runtime/replyAttachments.js +143 -0
- package/dist/lib/runtime/replyAttachments.test.d.ts +1 -0
- package/dist/lib/runtime/replyAttachments.test.js +205 -0
- package/dist/lib/runtime/result.js +8 -0
- package/dist/lib/runtime/revivers/index.js +2 -0
- package/dist/lib/runtime/revivers/taggedReviver.d.ts +8 -0
- package/dist/lib/runtime/revivers/taggedReviver.js +30 -0
- package/dist/lib/runtime/revivers/taggedReviver.test.d.ts +1 -0
- package/dist/lib/runtime/revivers/taggedReviver.test.js +42 -0
- package/dist/lib/runtime/runBatch.js +33 -16
- package/dist/lib/runtime/runBatch.test.js +62 -0
- package/dist/lib/runtime/runner.d.ts +26 -4
- package/dist/lib/runtime/runner.js +125 -49
- package/dist/lib/runtime/runner.test.js +217 -1
- package/dist/lib/runtime/simpleOpenAIClient.js +1 -1
- package/dist/lib/runtime/state/context.d.ts +22 -12
- package/dist/lib/runtime/state/context.js +43 -14
- package/dist/lib/runtime/state/context.providerModules.test.d.ts +1 -0
- package/dist/lib/runtime/state/context.providerModules.test.js +38 -0
- package/dist/lib/runtime/state/globalStore.d.ts +42 -0
- package/dist/lib/runtime/state/globalStore.js +187 -2
- package/dist/lib/runtime/state/globalStore.tags.test.d.ts +1 -0
- package/dist/lib/runtime/state/globalStore.tags.test.js +211 -0
- package/dist/lib/runtime/state/stateStack.d.ts +34 -0
- package/dist/lib/runtime/state/stateStack.js +46 -0
- package/dist/lib/runtime/state/tagSymbol.d.ts +6 -0
- package/dist/lib/runtime/state/tagSymbol.js +49 -0
- package/dist/lib/runtime/state/tagSymbol.test.d.ts +1 -0
- package/dist/lib/runtime/state/tagSymbol.test.js +60 -0
- package/dist/lib/runtime/streaming.d.ts +7 -2
- package/dist/lib/runtime/streaming.js +31 -8
- package/dist/lib/runtime/subprocess-bootstrap.js +90 -35
- package/dist/lib/runtime/subprocessRunInfo.d.ts +46 -0
- package/dist/lib/runtime/subprocessRunInfo.js +53 -0
- package/dist/lib/runtime/subprocessRunInfo.test.d.ts +1 -0
- package/dist/lib/runtime/subprocessRunInfo.test.js +32 -0
- package/dist/lib/runtime/topsortCycleErrors.test.js +69 -0
- package/dist/lib/runtime/utils.d.ts +16 -2
- package/dist/lib/runtime/utils.js +13 -4
- package/dist/lib/runtime/utils.test.js +27 -0
- package/dist/lib/statelogClient.d.ts +40 -1
- package/dist/lib/statelogClient.js +98 -1
- package/dist/lib/statelogClient.redaction.test.d.ts +1 -0
- package/dist/lib/statelogClient.redaction.test.js +131 -0
- package/dist/lib/statelogClient.test.js +13 -0
- package/dist/lib/stdlib/abortable.d.ts +6 -0
- package/dist/lib/stdlib/abortable.js +26 -1
- package/dist/lib/stdlib/agency.d.ts +7 -2
- package/dist/lib/stdlib/agency.js +17 -13
- package/dist/lib/stdlib/agencyEval.js +7 -1
- package/dist/lib/stdlib/args.d.ts +4 -1
- package/dist/lib/stdlib/args.js +68 -0
- package/dist/lib/stdlib/builtins.d.ts +2 -1
- package/dist/lib/stdlib/builtins.js +22 -13
- package/dist/lib/stdlib/cli.d.ts +65 -0
- package/dist/lib/stdlib/cli.js +217 -39
- package/dist/lib/stdlib/git.d.ts +29 -0
- package/dist/lib/stdlib/git.js +80 -0
- package/dist/lib/stdlib/gitCore.d.ts +132 -0
- package/dist/lib/stdlib/gitCore.js +231 -0
- package/dist/lib/stdlib/gitParse.d.ts +17 -0
- package/dist/lib/stdlib/gitParse.js +259 -0
- package/dist/lib/stdlib/http.d.ts +5 -4
- package/dist/lib/stdlib/http.js +42 -1
- package/dist/lib/stdlib/image.d.ts +7 -0
- package/dist/lib/stdlib/image.js +80 -0
- package/dist/lib/stdlib/layout/ansi.js +35 -3
- package/dist/lib/stdlib/layout/axis.js +14 -5
- package/dist/lib/stdlib/layout/barchart.js +5 -5
- package/dist/lib/stdlib/layout/block.js +2 -2
- package/dist/lib/stdlib/layout/border.js +2 -2
- package/dist/lib/stdlib/layout/box.js +12 -4
- package/dist/lib/stdlib/layout/nodes.d.ts +0 -1
- package/dist/lib/stdlib/layout/nodes.js +40 -17
- package/dist/lib/stdlib/layout/render.js +7 -3
- package/dist/lib/stdlib/layout/sizing.d.ts +1 -0
- package/dist/lib/stdlib/layout/sizing.js +1 -1
- package/dist/lib/stdlib/layout/table.js +11 -11
- package/dist/lib/stdlib/layout.js +1 -1
- package/dist/lib/stdlib/llm.d.ts +54 -1
- package/dist/lib/stdlib/llm.js +104 -0
- package/dist/lib/stdlib/localModels.d.ts +209 -0
- package/dist/lib/stdlib/localModels.js +904 -0
- package/dist/lib/stdlib/mediaPathScan.d.ts +31 -0
- package/dist/lib/stdlib/mediaPathScan.js +79 -0
- package/dist/lib/stdlib/providers/llama-cpp.mjs +79 -0
- package/dist/lib/stdlib/providers/llamaModelConfig.d.ts +7 -0
- package/dist/lib/stdlib/providers/llamaModelConfig.js +7 -0
- package/dist/lib/stdlib/search.d.ts +7 -0
- package/dist/lib/stdlib/search.js +40 -0
- package/dist/lib/stdlib/shell.d.ts +1 -1
- package/dist/lib/stdlib/shell.js +4 -2
- package/dist/lib/stdlib/tag.d.ts +17 -0
- package/dist/lib/stdlib/tag.js +49 -0
- package/dist/lib/stdlib/thread.d.ts +38 -3
- package/dist/lib/stdlib/thread.js +71 -2
- package/dist/lib/stdlib/threads.d.ts +12 -0
- package/dist/lib/stdlib/threads.js +48 -17
- package/dist/lib/stdlib/version.d.ts +1 -1
- package/dist/lib/stdlib/version.js +1 -1
- package/dist/lib/symbolTable.d.ts +10 -1
- package/dist/lib/symbolTable.js +27 -7
- package/dist/lib/templates/backends/agency/template.d.ts +1 -1
- package/dist/lib/templates/backends/agency/template.js +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/imports.d.ts +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/imports.js +14 -2
- package/dist/lib/templates/backends/typescriptGenerator/runnerIfElse.d.ts +2 -1
- package/dist/lib/templates/backends/typescriptGenerator/runnerIfElse.js +1 -1
- package/dist/lib/typeChecker/assignability.d.ts +8 -0
- package/dist/lib/typeChecker/assignability.js +26 -4
- package/dist/lib/typeChecker/assignability.test.js +59 -1
- package/dist/lib/typeChecker/attachments.test.d.ts +1 -0
- package/dist/lib/typeChecker/attachments.test.js +45 -0
- package/dist/lib/typeChecker/builtinNamedArgs.test.js +30 -0
- package/dist/lib/typeChecker/builtins.js +134 -40
- package/dist/lib/typeChecker/checker.d.ts +25 -0
- package/dist/lib/typeChecker/checker.js +41 -4
- package/dist/lib/typeChecker/definiteReturns.d.ts +16 -0
- package/dist/lib/typeChecker/definiteReturns.js +52 -0
- package/dist/lib/typeChecker/definiteReturns.test.d.ts +1 -0
- package/dist/lib/typeChecker/definiteReturns.test.js +203 -0
- package/dist/lib/typeChecker/effectPayloadCheck.d.ts +17 -0
- package/dist/lib/typeChecker/effectPayloadCheck.js +181 -0
- package/dist/lib/typeChecker/effectPayloadCheck.test.d.ts +1 -0
- package/dist/lib/typeChecker/effectPayloadCheck.test.js +192 -0
- package/dist/lib/typeChecker/flow.d.ts +131 -0
- package/dist/lib/typeChecker/flow.js +248 -0
- package/dist/lib/typeChecker/flow.test.d.ts +1 -0
- package/dist/lib/typeChecker/flow.test.js +467 -0
- package/dist/lib/typeChecker/flowAssignments.test.d.ts +1 -0
- package/dist/lib/typeChecker/flowAssignments.test.js +84 -0
- package/dist/lib/typeChecker/flowBuilder.d.ts +32 -0
- package/dist/lib/typeChecker/flowBuilder.js +337 -0
- package/dist/lib/typeChecker/flowBuilder.test.d.ts +1 -0
- package/dist/lib/typeChecker/flowBuilder.test.js +215 -0
- package/dist/lib/typeChecker/flowNarrowing.test.d.ts +1 -0
- package/dist/lib/typeChecker/flowNarrowing.test.js +96 -0
- package/dist/lib/typeChecker/handlerBodyInterrupts.test.js +1 -1
- package/dist/lib/typeChecker/handlerParamTyping.d.ts +31 -0
- package/dist/lib/typeChecker/handlerParamTyping.js +108 -0
- package/dist/lib/typeChecker/handlerParamTyping.test.d.ts +1 -0
- package/dist/lib/typeChecker/handlerParamTyping.test.js +379 -0
- package/dist/lib/typeChecker/ifExpression.test.d.ts +1 -0
- package/dist/lib/typeChecker/ifExpression.test.js +49 -0
- package/dist/lib/typeChecker/index.js +43 -3
- package/dist/lib/typeChecker/inference.d.ts +6 -0
- package/dist/lib/typeChecker/inference.js +1 -1
- package/dist/lib/typeChecker/interruptAnalysis.d.ts +9 -0
- package/dist/lib/typeChecker/interruptAnalysis.js +21 -13
- package/dist/lib/typeChecker/literalType.d.ts +9 -0
- package/dist/lib/typeChecker/literalType.js +18 -0
- package/dist/lib/typeChecker/matchArmNarrowing.test.d.ts +1 -0
- package/dist/lib/typeChecker/matchArmNarrowing.test.js +172 -0
- package/dist/lib/typeChecker/matchExhaustiveness.d.ts +9 -0
- package/dist/lib/typeChecker/matchExhaustiveness.js +238 -0
- package/dist/lib/typeChecker/matchExhaustiveness.test.d.ts +1 -0
- package/dist/lib/typeChecker/matchExhaustiveness.test.js +404 -0
- package/dist/lib/typeChecker/matchExprTypes.d.ts +37 -0
- package/dist/lib/typeChecker/matchExprTypes.js +143 -0
- package/dist/lib/typeChecker/matchExpression.test.d.ts +1 -0
- package/dist/lib/typeChecker/matchExpression.test.js +240 -0
- package/dist/lib/typeChecker/memberPathNarrowing.test.d.ts +1 -0
- package/dist/lib/typeChecker/memberPathNarrowing.test.js +419 -0
- package/dist/lib/typeChecker/narrowing.d.ts +113 -0
- package/dist/lib/typeChecker/narrowing.js +396 -0
- package/dist/lib/typeChecker/narrowing.test.d.ts +1 -0
- package/dist/lib/typeChecker/narrowing.test.js +930 -0
- package/dist/lib/typeChecker/neverType.test.d.ts +1 -0
- package/dist/lib/typeChecker/neverType.test.js +19 -0
- package/dist/lib/typeChecker/nullNarrowing.test.d.ts +1 -0
- package/dist/lib/typeChecker/nullNarrowing.test.js +246 -0
- package/dist/lib/typeChecker/nullish.test.d.ts +1 -0
- package/dist/lib/typeChecker/nullish.test.js +16 -0
- package/dist/lib/typeChecker/pathSegments.d.ts +56 -0
- package/dist/lib/typeChecker/pathSegments.js +73 -0
- package/dist/lib/typeChecker/primitiveMembers.d.ts +2 -2
- package/dist/lib/typeChecker/primitiveMembers.js +5 -5
- package/dist/lib/typeChecker/primitives.d.ts +2 -1
- package/dist/lib/typeChecker/primitives.js +2 -1
- package/dist/lib/typeChecker/recordLike.d.ts +18 -0
- package/dist/lib/typeChecker/recordLike.js +27 -0
- package/dist/lib/typeChecker/resolveCall.js +4 -0
- package/dist/lib/typeChecker/resultUnion.d.ts +8 -0
- package/dist/lib/typeChecker/resultUnion.js +43 -0
- package/dist/lib/typeChecker/scope.d.ts +9 -1
- package/dist/lib/typeChecker/scope.js +25 -4
- package/dist/lib/typeChecker/scope.test.js +15 -0
- package/dist/lib/typeChecker/scopeVisibility.test.d.ts +1 -0
- package/dist/lib/typeChecker/scopeVisibility.test.js +138 -0
- package/dist/lib/typeChecker/scopes.d.ts +7 -0
- package/dist/lib/typeChecker/scopes.js +164 -113
- package/dist/lib/typeChecker/strictMemberAccess.test.d.ts +1 -0
- package/dist/lib/typeChecker/strictMemberAccess.test.js +221 -0
- package/dist/lib/typeChecker/synthesizer.js +257 -47
- package/dist/lib/typeChecker/typeCases.d.ts +28 -0
- package/dist/lib/typeChecker/typeCases.js +122 -0
- package/dist/lib/typeChecker/typeCases.test.d.ts +1 -0
- package/dist/lib/typeChecker/typeCases.test.js +150 -0
- package/dist/lib/typeChecker/types.d.ts +26 -0
- package/dist/lib/typeChecker/utils.d.ts +19 -0
- package/dist/lib/typeChecker/utils.js +50 -10
- package/dist/lib/typeChecker.test.js +351 -34
- package/dist/lib/types/dataStructures.d.ts +18 -1
- package/dist/lib/types/effectDeclaration.d.ts +11 -0
- package/dist/lib/types/effectDeclaration.js +1 -0
- package/dist/lib/types/function.d.ts +1 -1
- package/dist/lib/types/function.js +2 -0
- package/dist/lib/types/function.test.d.ts +1 -0
- package/dist/lib/types/function.test.js +11 -0
- package/dist/lib/types/ifElse.d.ts +4 -0
- package/dist/lib/types/importStatement.d.ts +4 -0
- package/dist/lib/types/matchBlock.d.ts +15 -3
- package/dist/lib/types/matchYield.d.ts +16 -0
- package/dist/lib/types/matchYield.js +1 -0
- package/dist/lib/types.d.ts +54 -3
- package/dist/lib/types.js +37 -0
- package/dist/lib/utils/mapBodies.js +1 -1
- package/dist/lib/utils/node.d.ts +30 -0
- package/dist/lib/utils/node.js +160 -3
- package/dist/lib/utils/projectTree.d.ts +13 -0
- package/dist/lib/utils/projectTree.js +42 -0
- package/dist/lib/utils/projectTree.test.d.ts +1 -0
- package/dist/lib/utils/projectTree.test.js +49 -0
- package/dist/lib/utils/termcolors.d.ts +1 -1
- package/dist/lib/utils/termcolors.js +1 -1
- package/dist/scripts/agency.js +27 -0
- package/dist/scripts/genModelHashes.d.ts +10 -0
- package/dist/scripts/genModelHashes.js +88 -0
- package/package.json +4 -2
- package/stdlib/agency/eval.agency +31 -59
- package/stdlib/agency/eval.js +56 -84
- package/stdlib/agency/local.agency +189 -0
- package/stdlib/agency/local.js +1685 -0
- package/stdlib/agency.agency +169 -98
- package/stdlib/agency.js +278 -286
- package/stdlib/agent.agency +69 -71
- package/stdlib/agent.js +352 -51
- package/stdlib/args.agency +30 -53
- package/stdlib/args.js +44 -20
- package/stdlib/array.agency +21 -221
- package/stdlib/array.js +116 -416
- package/stdlib/{keyring.agency → auth/keyring.agency} +17 -17
- package/stdlib/auth/keyring.js +810 -0
- package/stdlib/{oauth.agency → auth/oauth.agency} +24 -27
- package/stdlib/auth/oauth.js +873 -0
- package/stdlib/browser.js +13 -3
- package/stdlib/calendar.agency +29 -88
- package/stdlib/calendar.js +40 -25
- package/stdlib/capabilities.agency +7 -3
- package/stdlib/capabilities.js +41 -18
- package/stdlib/chart.js +21 -10
- package/stdlib/cli.js +139 -6
- package/stdlib/clipboard.agency +19 -2
- package/stdlib/clipboard.js +40 -19
- package/stdlib/concurrency.agency +34 -22
- package/stdlib/concurrency.js +45 -38
- package/stdlib/data/finance/dbnomics.agency +115 -0
- package/stdlib/data/finance/dbnomics.js +934 -0
- package/stdlib/data/finance/edgar.agency +172 -0
- package/stdlib/data/finance/edgar.js +1598 -0
- package/stdlib/data/finance/fred.agency +215 -0
- package/stdlib/data/finance/fred.js +2028 -0
- package/stdlib/data/finance/gdelt.agency +98 -0
- package/stdlib/data/finance/gdelt.js +873 -0
- package/stdlib/data/people/littlesis.agency +322 -0
- package/stdlib/data/people/littlesis.js +3221 -0
- package/stdlib/data/tech/hackernews.agency +344 -0
- package/stdlib/data/tech/hackernews.js +3814 -0
- package/stdlib/data/tech/yc.agency +253 -0
- package/stdlib/data/tech/yc.js +2913 -0
- package/stdlib/date.agency +34 -81
- package/stdlib/date.js +53 -39
- package/stdlib/email.js +13 -3
- package/stdlib/fs.agency +44 -16
- package/stdlib/fs.js +50 -37
- package/stdlib/git.agency +327 -0
- package/stdlib/git.js +3724 -0
- package/stdlib/http.agency +39 -14
- package/stdlib/http.js +39 -27
- package/stdlib/image.agency +44 -0
- package/stdlib/image.js +404 -0
- package/stdlib/imessage.js +13 -3
- package/stdlib/index.agency +318 -116
- package/stdlib/index.js +1762 -517
- package/stdlib/keyring.js +13 -3
- package/stdlib/layout.js +23 -12
- package/stdlib/llm.agency +115 -16
- package/stdlib/llm.js +726 -36
- package/stdlib/markdown.agency +38 -55
- package/stdlib/markdown.js +58 -66
- package/stdlib/math.agency +16 -0
- package/stdlib/math.js +175 -20
- package/stdlib/memory.agency +82 -90
- package/stdlib/memory.js +67 -114
- package/stdlib/{email.agency → messaging/email.agency} +11 -15
- package/stdlib/messaging/email.js +1112 -0
- package/stdlib/{imessage.agency → messaging/imessage.agency} +7 -8
- package/stdlib/messaging/imessage.js +387 -0
- package/stdlib/{sms.agency → messaging/sms.agency} +8 -8
- package/stdlib/messaging/sms.js +429 -0
- package/stdlib/oauth.js +13 -3
- package/stdlib/object.agency +52 -5
- package/stdlib/object.js +409 -26
- package/stdlib/path.agency +29 -4
- package/stdlib/path.js +54 -30
- package/stdlib/policy.agency +115 -198
- package/stdlib/policy.js +212 -154
- package/stdlib/schemas.js +13 -3
- package/stdlib/search.js +225 -6
- package/stdlib/shell.agency +51 -27
- package/stdlib/shell.js +75 -53
- package/stdlib/skills.agency +41 -20
- package/stdlib/skills.js +81 -43
- package/stdlib/sms.js +13 -3
- package/stdlib/speech.agency +42 -24
- package/stdlib/speech.js +46 -42
- package/stdlib/statelog.agency +64 -46
- package/stdlib/statelog.js +165 -66
- package/stdlib/strategy.agency +27 -0
- package/stdlib/strategy.js +158 -20
- package/stdlib/syntax.agency +34 -27
- package/stdlib/syntax.js +46 -46
- package/stdlib/system.agency +62 -23
- package/stdlib/system.js +210 -49
- package/stdlib/table.js +19 -8
- package/stdlib/tag.agency +62 -0
- package/stdlib/tag.js +966 -0
- package/stdlib/thread.agency +282 -67
- package/stdlib/thread.js +1522 -263
- package/stdlib/threads.js +18 -7
- package/stdlib/types.js +13 -3
- package/stdlib/{chart.agency → ui/chart.agency} +41 -48
- package/stdlib/ui/chart.js +993 -0
- package/stdlib/ui/cli.agency +119 -0
- package/stdlib/ui/cli.js +1096 -0
- package/stdlib/{layout.agency → ui/layout.agency} +110 -178
- package/stdlib/ui/layout.js +3740 -0
- package/stdlib/{table.agency → ui/table.agency} +49 -50
- package/stdlib/ui/table.js +1434 -0
- package/stdlib/ui.agency +194 -316
- package/stdlib/ui.js +442 -364
- package/stdlib/validation.agency +197 -0
- package/stdlib/validation.js +1707 -0
- package/stdlib/validators.js +13 -3
- package/stdlib/weather.agency +27 -4
- package/stdlib/weather.js +39 -21
- package/stdlib/web/browser.agency +52 -0
- package/stdlib/web/browser.js +431 -0
- package/stdlib/web/search.agency +101 -0
- package/stdlib/web/search.js +638 -0
- package/stdlib/wikipedia.agency +28 -3
- package/stdlib/wikipedia.js +46 -21
- package/dist/lib/agents/docs/appendix/agency-stdlib.md +0 -25
- package/dist/lib/agents/docs/appendix/agency-vs-typescript.md +0 -14
- package/dist/lib/agents/docs/appendix/appendix/agency-stdlib.md +0 -25
- package/dist/lib/agents/docs/appendix/appendix/agency-vs-typescript.md +0 -14
- package/dist/lib/agents/docs/appendix/appendix/vscode-extension.md +0 -11
- package/dist/lib/agents/docs/appendix/vscode-extension.md +0 -11
- package/dist/lib/agents/docs/guide/agents-101.md +0 -212
- package/dist/lib/agents/docs/guide/execution-model.md +0 -130
- package/dist/lib/agents/docs/guide/guide/agents-101.md +0 -212
- package/dist/lib/agents/docs/guide/guide/execution-model.md +0 -130
- package/dist/lib/agents/docs/guide/guide/message-history-and-threads.md +0 -88
- package/dist/lib/agents/docs/guide/guide/odds-and-ends.md +0 -41
- package/dist/lib/agents/docs/guide/guide/structured-interrupts.md +0 -49
- package/dist/lib/agents/docs/guide/message-history-and-threads.md +0 -88
- package/dist/lib/agents/docs/guide/odds-and-ends.md +0 -41
- package/dist/lib/agents/docs/guide/structured-interrupts.md +0 -49
- package/stdlib/browser.agency +0 -47
- package/stdlib/cli.agency +0 -132
- package/stdlib/schemas.agency +0 -37
- package/stdlib/search.agency +0 -57
- package/stdlib/threads.agency +0 -198
- package/stdlib/types.agency +0 -58
- package/stdlib/validators.agency +0 -150
- /package/dist/lib/agents/docs/{appendix → guide}/advanced-types.md +0 -0
- /package/dist/lib/agents/docs/{appendix/appendix → guide/guide}/advanced-types.md +0 -0
- /package/dist/lib/agents/docs/{appendix/appendix → guide/guide}/schema-parameter-injection.md +0 -0
- /package/dist/lib/agents/docs/{appendix → guide}/schema-parameter-injection.md +0 -0
- /package/dist/lib/backends/{anthropicApiKey.codegen.test.d.ts → agencyGenerator.matchBlock.test.d.ts} +0 -0
|
@@ -0,0 +1,904 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { execFileSync } from "node:child_process";
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { findFileUp } from "../importPaths.js";
|
|
10
|
+
import { loadProviderModuleByPath } from "../runtime/providerModules.js";
|
|
11
|
+
import { ttyColor } from "../utils/termcolors.js";
|
|
12
|
+
/** Curated short-name → ModelInfo catalog. Permissive licenses only
|
|
13
|
+
* (apache-2.0 / mit). Ordered roughly by size within each grouping. */
|
|
14
|
+
export const CURATED_LOCAL_MODELS = {
|
|
15
|
+
// ── General ─────────────────────────────────────────────────────────────
|
|
16
|
+
"smollm2-135m": {
|
|
17
|
+
uri: "hf:unsloth/SmolLM2-135M-Instruct-GGUF:Q4_K_M",
|
|
18
|
+
sha256: "ed5fa30c487b282ec156c29062f1222e5c20875a944ac98289dbd242e947f747",
|
|
19
|
+
params: "135M", sizeBytes: 105_000_000, category: "general",
|
|
20
|
+
contextWindow: 8192, license: "apache-2.0",
|
|
21
|
+
description: "Smallest practical chat model; used by our integration tests, runs anywhere.",
|
|
22
|
+
},
|
|
23
|
+
"qwen3.5-0.8b": {
|
|
24
|
+
uri: "hf:unsloth/Qwen3.5-0.8B-GGUF:Q4_K_M",
|
|
25
|
+
sha256: "bd258782e35f7f458f8aced1adc053e6e92e89bc735ba3be89d38a06121dc517",
|
|
26
|
+
params: "0.8B", sizeBytes: 500_000_000, category: "general",
|
|
27
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
28
|
+
description: "Tiny model from Alibaba's current generation; good edge-device default.",
|
|
29
|
+
},
|
|
30
|
+
"qwen3.5-2b": {
|
|
31
|
+
uri: "hf:unsloth/Qwen3.5-2B-GGUF:Q4_K_M",
|
|
32
|
+
sha256: "aaf42c8b7c3cab2bf3d69c355048d4a0ee9973d48f16c731c0520ee914699223",
|
|
33
|
+
params: "2B", sizeBytes: 1_280_000_000, category: "general",
|
|
34
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
35
|
+
description: "Most popular modern small general model; runs on CPU comfortably.",
|
|
36
|
+
},
|
|
37
|
+
"qwen3.5-4b": {
|
|
38
|
+
uri: "hf:unsloth/Qwen3.5-4B-GGUF:Q4_K_M",
|
|
39
|
+
sha256: "00fe7986ff5f6b463e62455821146049db6f9313603938a70800d1fb69ef11a4",
|
|
40
|
+
params: "4B", sizeBytes: 2_400_000_000, category: "general",
|
|
41
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
42
|
+
description: "Strong multilingual small general workhorse from Alibaba.",
|
|
43
|
+
},
|
|
44
|
+
"gemma-4-e4b": {
|
|
45
|
+
uri: "hf:unsloth/gemma-4-E4B-it-GGUF:Q4_K_M",
|
|
46
|
+
sha256: "519b9793ed6ce0ff530f1b7c96e848e08e49e7af4d57bb97f76215963a54146d",
|
|
47
|
+
params: "4B (E4B)", sizeBytes: 4_980_000_000, category: "general",
|
|
48
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
49
|
+
description: "Google's compact Gemma 4 (4.5B effective); ~5 GB, laptop-friendly multimodal model.",
|
|
50
|
+
},
|
|
51
|
+
"qwen3.5-9b": {
|
|
52
|
+
uri: "hf:unsloth/Qwen3.5-9B-GGUF:Q4_K_M",
|
|
53
|
+
sha256: "03b74727a860a56338e042c4420bb3f04b2fec5734175f4cb9fa853daf52b7e8",
|
|
54
|
+
params: "9B", sizeBytes: 5_500_000_000, category: "general",
|
|
55
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
56
|
+
description: "Modern medium general model with strong tool use; 128K context.",
|
|
57
|
+
},
|
|
58
|
+
"gemma-4-12b": {
|
|
59
|
+
uri: "hf:unsloth/gemma-4-12b-it-GGUF:Q4_K_M",
|
|
60
|
+
sha256: "43fec98c5102b1c446b4ddd0a9439f1db3a2e1f2e0b8cd143ce1ea619a9403d6",
|
|
61
|
+
params: "12B", sizeBytes: 7_120_000_000, category: "general",
|
|
62
|
+
contextWindow: 262144, license: "apache-2.0",
|
|
63
|
+
description: "Google's mid-size Gemma 4 dense model; strong multilingual multimodal use, 256K context.",
|
|
64
|
+
},
|
|
65
|
+
"gpt-oss-20b": {
|
|
66
|
+
uri: "hf:unsloth/gpt-oss-20b-GGUF:Q4_K_M",
|
|
67
|
+
sha256: "c27536640e410032865dc68781d80a08b98f8db5e93575919af8ccc0568aeb4f",
|
|
68
|
+
params: "20B", sizeBytes: 12_000_000_000, category: "general",
|
|
69
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
70
|
+
description: "OpenAI's open-weights release; balanced general model for ~16 GB machines.",
|
|
71
|
+
},
|
|
72
|
+
"mistral-small-3.1": {
|
|
73
|
+
uri: "hf:unsloth/Mistral-Small-3.1-24B-Instruct-2503-GGUF:Q4_K_M",
|
|
74
|
+
sha256: "6d670773c3908584349d41a5048d1472226b593c881fd394e8ac196c802e81e2",
|
|
75
|
+
params: "24B", sizeBytes: 14_000_000_000, category: "general",
|
|
76
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
77
|
+
description: "Mistral's general 24B base model (also Devstral's foundation); broad utility.",
|
|
78
|
+
},
|
|
79
|
+
"qwen3.5-27b": {
|
|
80
|
+
uri: "hf:unsloth/Qwen3.5-27B-GGUF:Q4_K_M",
|
|
81
|
+
sha256: "84b5f7f112156d63836a01a69dc3f11a6ba63b10a23b8ca7a7efaf52d5a2d806",
|
|
82
|
+
params: "27B", sizeBytes: 16_000_000_000, category: "general",
|
|
83
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
84
|
+
description: "Modern dense general 27B; the practical ceiling for most workstations.",
|
|
85
|
+
},
|
|
86
|
+
"gemma-4-26b-a4b": {
|
|
87
|
+
uri: "hf:unsloth/gemma-4-26B-A4B-it-GGUF:Q4_K_M",
|
|
88
|
+
sha256: "34c746b1d50ab813e29cd46c4796e3f43c741901a582f93a67b55b9fc9687b35",
|
|
89
|
+
params: "26B (A4B)", sizeBytes: 16_900_000_000, category: "general",
|
|
90
|
+
contextWindow: 262144, license: "apache-2.0",
|
|
91
|
+
description: "Google's Gemma 4 MoE (3.8B active); fast yet capable multimodal model, 256K context.",
|
|
92
|
+
},
|
|
93
|
+
"gemma-4-31b": {
|
|
94
|
+
uri: "hf:unsloth/gemma-4-31B-it-GGUF:Q4_K_M",
|
|
95
|
+
sha256: "9fdf3dc8b0384830b4402d151388c140bd8eb2abf8d60588d8224231198254a1",
|
|
96
|
+
params: "31B", sizeBytes: 18_300_000_000, category: "general",
|
|
97
|
+
contextWindow: 262144, license: "apache-2.0",
|
|
98
|
+
description: "Largest dense Gemma 4; top Gemma quality for high-RAM workstations, 256K context.",
|
|
99
|
+
},
|
|
100
|
+
// ── Reasoning ───────────────────────────────────────────────────────────
|
|
101
|
+
"deepseek-r1-distill-llama-8b": {
|
|
102
|
+
uri: "hf:unsloth/DeepSeek-R1-Distill-Llama-8B-GGUF:Q4_K_M",
|
|
103
|
+
sha256: "0addb1339a82385bcd973186cd80d18dcc71885d45eabd899781a118d03827d9",
|
|
104
|
+
params: "8B", sizeBytes: 4_920_000_000, category: "reasoning",
|
|
105
|
+
contextWindow: 131072, license: "mit",
|
|
106
|
+
description: "Chain-of-thought distill into Llama-8B; best small reasoning model.",
|
|
107
|
+
},
|
|
108
|
+
"phi-4-reasoning": {
|
|
109
|
+
uri: "hf:unsloth/Phi-4-reasoning-GGUF:Q4_K_M",
|
|
110
|
+
sha256: "960d3870b218f91116c55bf81dc313e6cdbce31b1047bb2bc8bc7ea47899b032",
|
|
111
|
+
params: "14B", sizeBytes: 9_050_000_000, category: "reasoning",
|
|
112
|
+
contextWindow: 32768, license: "mit",
|
|
113
|
+
description: "Microsoft's reasoning-tuned 14B; competitive with much larger models on math/logic.",
|
|
114
|
+
},
|
|
115
|
+
// ── Coding ──────────────────────────────────────────────────────────────
|
|
116
|
+
"devstral-small-2507": {
|
|
117
|
+
uri: "hf:mistralai/Devstral-Small-2507_gguf:Q4_K_M",
|
|
118
|
+
sha256: "1bcc2b1b7b7ea3168ba2dbe782432c464f2240598bd193930122c41b117c1796",
|
|
119
|
+
params: "24B", sizeBytes: 14_300_000_000, category: "coding",
|
|
120
|
+
contextWindow: 131072, license: "apache-2.0",
|
|
121
|
+
description: "Mistral's official coding-agent GGUF; #1 open-source on SWE-Bench at release.",
|
|
122
|
+
},
|
|
123
|
+
"qwen3-coder-30b-a3b": {
|
|
124
|
+
uri: "hf:unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M",
|
|
125
|
+
sha256: "fadc3e5f8d42bf7e894a785b05082e47daee4df26680389817e2093056f088ad",
|
|
126
|
+
params: "30B (A3B)", sizeBytes: 19_000_000_000, category: "coding",
|
|
127
|
+
contextWindow: 262144, license: "apache-2.0",
|
|
128
|
+
description: "Qwen's MoE coder (3.3B active); strong agentic coding + 256K context.",
|
|
129
|
+
},
|
|
130
|
+
// ── Embedding ───────────────────────────────────────────────────────────
|
|
131
|
+
"nomic-embed-text": {
|
|
132
|
+
uri: "hf:nomic-ai/nomic-embed-text-v1.5-GGUF:Q4_K_M",
|
|
133
|
+
sha256: "d4e388894e09cf3816e8b0896d81d265b55e7a9fff9ab03fe8bf4ef5e11295ac",
|
|
134
|
+
params: "137M", sizeBytes: 89_000_000, category: "embedding",
|
|
135
|
+
contextWindow: 8192, license: "apache-2.0",
|
|
136
|
+
description: "Returns 768-dim embeddings; pair with a chat model for RAG.",
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
/** Where downloaded models live, in precedence order:
|
|
140
|
+
* 1. `AGENCY_MODELS_DIR` env var (per-machine override).
|
|
141
|
+
* 2. `client.modelsDir` in the nearest `agency.json` (read at runtime, like
|
|
142
|
+
* `modelAliases`), so the CLI and the agent share one configurable dir.
|
|
143
|
+
* 3. `~/.agency-agent/models` (the default; shared with the agent so a CLI
|
|
144
|
+
* `agency local download` pre-populates what `agency agent --local-model`
|
|
145
|
+
* reuses). */
|
|
146
|
+
export function defaultCacheDir() {
|
|
147
|
+
if (process.env.AGENCY_MODELS_DIR) {
|
|
148
|
+
return process.env.AGENCY_MODELS_DIR;
|
|
149
|
+
}
|
|
150
|
+
const configured = readJson(resolveAliasConfigPath()).client?.modelsDir;
|
|
151
|
+
if (typeof configured === "string" && configured.length > 0) {
|
|
152
|
+
return configured;
|
|
153
|
+
}
|
|
154
|
+
return path.join(os.homedir(), ".agency-agent", "models");
|
|
155
|
+
}
|
|
156
|
+
/** Treat empty string as "caller wants the default cache dir". */
|
|
157
|
+
function resolveCacheDir(cacheDir) {
|
|
158
|
+
return cacheDir === "" ? defaultCacheDir() : cacheDir;
|
|
159
|
+
}
|
|
160
|
+
function isGgufPath(v) {
|
|
161
|
+
return v.endsWith(".gguf");
|
|
162
|
+
}
|
|
163
|
+
function isModelUri(v) {
|
|
164
|
+
return /^(hf:|https?:)/.test(v);
|
|
165
|
+
}
|
|
166
|
+
/** A model URI we'll accept from the *remote catalog*. Stricter than
|
|
167
|
+
* `isModelUri`: any `scheme://` URL must be `https://` (so an overridden or
|
|
168
|
+
* untrusted catalog can't point a download at a plaintext, MITM-able
|
|
169
|
+
* endpoint — not even an `http://…/x.gguf`). Otherwise accept an `hf:` URI or
|
|
170
|
+
* a local `.gguf` path. */
|
|
171
|
+
function isCatalogUri(v) {
|
|
172
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(v)) {
|
|
173
|
+
return /^https:\/\//.test(v);
|
|
174
|
+
}
|
|
175
|
+
return v.startsWith("hf:") || isGgufPath(v);
|
|
176
|
+
}
|
|
177
|
+
/** The agency.json that owns aliases: nearest `agency.json` walking up from
|
|
178
|
+
* `startDir` (cwd by default); falls back to `~/agency.json` when none is
|
|
179
|
+
* found. Exported so the CLI can echo it on every write. */
|
|
180
|
+
export function resolveAliasConfigPath(startDir = process.cwd()) {
|
|
181
|
+
return findFileUp(startDir, "agency.json") ?? path.join(os.homedir(), "agency.json");
|
|
182
|
+
}
|
|
183
|
+
/** Treat empty string as "caller wants resolveAliasConfigPath()". */
|
|
184
|
+
function resolveAliasFile(file) {
|
|
185
|
+
return file === "" ? resolveAliasConfigPath() : file;
|
|
186
|
+
}
|
|
187
|
+
/** Read a JSON file as a plain object. */
|
|
188
|
+
function readJson(file) {
|
|
189
|
+
if (!fs.existsSync(file)) {
|
|
190
|
+
return {};
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
return JSON.parse(fs.readFileSync(file, "utf-8"));
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
throw new Error(`Failed to parse ${file}: ${err.message}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** Merge `client.modelAliases[name] = uri` (or remove it) into a config object using spread. */
|
|
200
|
+
function withAlias(cfg, name, uri) {
|
|
201
|
+
const existing = cfg.client?.modelAliases ?? {};
|
|
202
|
+
const nextAliases = { ...existing };
|
|
203
|
+
if (uri === undefined) {
|
|
204
|
+
delete nextAliases[name];
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
nextAliases[name] = uri;
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
...cfg,
|
|
211
|
+
client: { ...(cfg.client ?? {}), modelAliases: nextAliases },
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function writeJson(file, value) {
|
|
215
|
+
fs.writeFileSync(file, JSON.stringify(value, null, 2) + "\n");
|
|
216
|
+
}
|
|
217
|
+
/** The URI an alias points at, regardless of string/object form. */
|
|
218
|
+
export function aliasUri(value) {
|
|
219
|
+
return typeof value === "string" ? value : value.uri;
|
|
220
|
+
}
|
|
221
|
+
export function readModelAliases(file = "") {
|
|
222
|
+
const cfg = readJson(resolveAliasFile(file));
|
|
223
|
+
return (cfg.client?.modelAliases ?? {});
|
|
224
|
+
}
|
|
225
|
+
export function _resolveModelName(value, file = "") {
|
|
226
|
+
if (isGgufPath(value) || isModelUri(value)) {
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
const aliases = readModelAliases(file);
|
|
230
|
+
const aliasVal = aliases[value];
|
|
231
|
+
const aliasTarget = aliasVal === undefined ? undefined : aliasUri(aliasVal);
|
|
232
|
+
const curated = CURATED_LOCAL_MODELS[value];
|
|
233
|
+
const mapped = aliasTarget ?? curated?.uri;
|
|
234
|
+
if (!mapped) {
|
|
235
|
+
const names = [...Object.keys(CURATED_LOCAL_MODELS), ...Object.keys(aliases)].join(", ");
|
|
236
|
+
throw new Error(`Unknown local model "${value}". Known names: ${names || "(none)"}; ` +
|
|
237
|
+
`or pass a .gguf path or an "hf:" URI.`);
|
|
238
|
+
}
|
|
239
|
+
return mapped;
|
|
240
|
+
}
|
|
241
|
+
/** Project the optional display-metadata fields off any source shape
|
|
242
|
+
* (`ModelInfo`, or an alias which may be a bare URI string). A string alias
|
|
243
|
+
* carries no metadata, so it yields `{}` — which is why the call sites can
|
|
244
|
+
* pass an `AliasValue` directly without a `typeof` guard. Returns only
|
|
245
|
+
* defined fields so the spread doesn't introduce stray `undefined` keys. */
|
|
246
|
+
function metaFrom(src) {
|
|
247
|
+
if (typeof src === "string")
|
|
248
|
+
return {};
|
|
249
|
+
const out = {};
|
|
250
|
+
if (src.params !== undefined)
|
|
251
|
+
out.params = src.params;
|
|
252
|
+
if (src.sizeBytes !== undefined)
|
|
253
|
+
out.sizeBytes = src.sizeBytes;
|
|
254
|
+
if (src.category !== undefined)
|
|
255
|
+
out.category = src.category;
|
|
256
|
+
if (src.description !== undefined)
|
|
257
|
+
out.description = src.description;
|
|
258
|
+
if (src.contextWindow !== undefined)
|
|
259
|
+
out.contextWindow = src.contextWindow;
|
|
260
|
+
if (src.license !== undefined)
|
|
261
|
+
out.license = src.license;
|
|
262
|
+
if (src.sha256 !== undefined)
|
|
263
|
+
out.sha256 = src.sha256;
|
|
264
|
+
return out;
|
|
265
|
+
}
|
|
266
|
+
export function _listModelNames(file = "") {
|
|
267
|
+
const curatedEntries = Object.entries(CURATED_LOCAL_MODELS).map(([name, info]) => ({ name, target: info.uri, source: "curated", ...metaFrom(info) }));
|
|
268
|
+
const aliasEntries = Object.entries(readModelAliases(file)).map(([name, value]) => ({
|
|
269
|
+
name,
|
|
270
|
+
target: aliasUri(value),
|
|
271
|
+
source: "alias",
|
|
272
|
+
...metaFrom(value),
|
|
273
|
+
}));
|
|
274
|
+
// Alias wins on name collision: the alias entry overwrites the curated one
|
|
275
|
+
// in the object literal because it comes later. `Object.values` then yields
|
|
276
|
+
// exactly one entry per name.
|
|
277
|
+
return Object.values(Object.fromEntries([...curatedEntries, ...aliasEntries].map((e) => [e.name, e])));
|
|
278
|
+
}
|
|
279
|
+
export function _aliasModel(name, uri, file = "") {
|
|
280
|
+
const resolved = resolveAliasFile(file);
|
|
281
|
+
writeJson(resolved, withAlias(readJson(resolved), name, uri));
|
|
282
|
+
return resolved;
|
|
283
|
+
}
|
|
284
|
+
/** Remove an alias. Bails early (no write) if file or alias missing. */
|
|
285
|
+
export function _unaliasModel(name, file = "") {
|
|
286
|
+
const resolved = resolveAliasFile(file);
|
|
287
|
+
if (!fs.existsSync(resolved)) {
|
|
288
|
+
return { file: resolved, removed: false };
|
|
289
|
+
}
|
|
290
|
+
const cfg = readJson(resolved);
|
|
291
|
+
if (!cfg.client?.modelAliases || !(name in cfg.client.modelAliases)) {
|
|
292
|
+
return { file: resolved, removed: false };
|
|
293
|
+
}
|
|
294
|
+
writeJson(resolved, withAlias(cfg, name, undefined));
|
|
295
|
+
return { file: resolved, removed: true };
|
|
296
|
+
}
|
|
297
|
+
export function _listDownloadedModels(cacheDir = "") {
|
|
298
|
+
const dir = resolveCacheDir(cacheDir);
|
|
299
|
+
if (!fs.existsSync(dir)) {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
return fs
|
|
303
|
+
.readdirSync(dir)
|
|
304
|
+
.filter((f) => f.endsWith(".gguf"))
|
|
305
|
+
.map((f) => {
|
|
306
|
+
const p = path.join(dir, f);
|
|
307
|
+
return { name: f, path: p, sizeBytes: fs.statSync(p).size };
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
export function _removeModel(name, cacheDir = "") {
|
|
311
|
+
const p = path.join(resolveCacheDir(cacheDir), name);
|
|
312
|
+
if (!fs.existsSync(p)) {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
fs.rmSync(p);
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
// =============================================================================
|
|
319
|
+
// Remote catalog — fetch + validate the GitHub-hosted model list.
|
|
320
|
+
// =============================================================================
|
|
321
|
+
export const DEFAULT_CATALOG_URL = "https://raw.githubusercontent.com/egonSchiele/agency-lang/main/packages/agency-lang/data/model-catalog.json";
|
|
322
|
+
const SUPPORTED_CATALOG_VERSION = 1;
|
|
323
|
+
/** Resolve the catalog URL: explicit arg → env → config → built-in default. */
|
|
324
|
+
export function resolveCatalogUrl(explicit = "", file = "") {
|
|
325
|
+
if (explicit !== "")
|
|
326
|
+
return explicit;
|
|
327
|
+
if (process.env.AGENCY_MODEL_CATALOG_URL)
|
|
328
|
+
return process.env.AGENCY_MODEL_CATALOG_URL;
|
|
329
|
+
const configured = readJson(resolveAliasFile(file)).client?.modelCatalogUrl;
|
|
330
|
+
if (typeof configured === "string" && configured.length > 0)
|
|
331
|
+
return configured;
|
|
332
|
+
return DEFAULT_CATALOG_URL;
|
|
333
|
+
}
|
|
334
|
+
const CATALOG_CATEGORIES = ["general", "coding", "reasoning", "embedding"];
|
|
335
|
+
/** Bound on how long the default fetcher will wait for the remote catalog
|
|
336
|
+
* before aborting. Long enough to tolerate slow CI mirrors; short enough
|
|
337
|
+
* that a hung server doesn't lock up the CLI. */
|
|
338
|
+
const CATALOG_FETCH_TIMEOUT_MS = 15_000;
|
|
339
|
+
/** Bound on catalog body size. The seed catalog is well under 10 KB; a
|
|
340
|
+
* 5 MB cap guards against a misconfigured URL serving an arbitrary file. */
|
|
341
|
+
const CATALOG_MAX_BYTES = 5_000_000;
|
|
342
|
+
// One catalog entry. zod does the structural validation + coercion; the merge
|
|
343
|
+
// reassembles a canonical-order object from `.data` (see `parseCatalog`). The
|
|
344
|
+
// metadata fields are `.optional().catch(undefined)` so a wrongly-typed field
|
|
345
|
+
// is dropped rather than failing the whole entry (lenient metadata); a
|
|
346
|
+
// missing/insecure `uri` fails the entry (it's then skipped + warned).
|
|
347
|
+
const CatalogModelSchema = z.object({
|
|
348
|
+
uri: z.string().refine(isCatalogUri, "uri must be an hf:/https: URI or a .gguf path"),
|
|
349
|
+
params: z.string().optional().catch(undefined),
|
|
350
|
+
sizeBytes: z.number().optional().catch(undefined),
|
|
351
|
+
category: z.enum(CATALOG_CATEGORIES).optional().catch(undefined),
|
|
352
|
+
contextWindow: z.number().optional().catch(undefined),
|
|
353
|
+
license: z.string().optional().catch(undefined),
|
|
354
|
+
description: z.string().optional().catch(undefined),
|
|
355
|
+
// Must be a 64-hex SHA-256; normalized to lowercase. A malformed value (from
|
|
356
|
+
// an untrusted catalog) is dropped via `.catch`, not stored as a bad pin.
|
|
357
|
+
sha256: z
|
|
358
|
+
.string()
|
|
359
|
+
.regex(/^[0-9a-fA-F]{64}$/)
|
|
360
|
+
.transform((s) => s.toLowerCase())
|
|
361
|
+
.optional()
|
|
362
|
+
.catch(undefined),
|
|
363
|
+
});
|
|
364
|
+
// Top-level catalog shape: a supported version + a name→entry object. Entries
|
|
365
|
+
// are validated individually (below) so one bad entry is skipped, not fatal.
|
|
366
|
+
const CatalogTopSchema = z.object({
|
|
367
|
+
version: z.literal(SUPPORTED_CATALOG_VERSION),
|
|
368
|
+
models: z.record(z.string(), z.unknown()),
|
|
369
|
+
});
|
|
370
|
+
/** Strip keys whose value is `undefined` so the resulting object is JSON-clean
|
|
371
|
+
* (no `"params": undefined` after `JSON.stringify`) and in canonical order. */
|
|
372
|
+
function compact(o) {
|
|
373
|
+
return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined));
|
|
374
|
+
}
|
|
375
|
+
/** Parse + validate the catalog JSON. Throws on blob-level problems (bad JSON,
|
|
376
|
+
* unsupported version, `models` not an object) so refresh aborts without
|
|
377
|
+
* touching agency.json. Skips an individual entry (with a warning) when its
|
|
378
|
+
* `uri` is missing/invalid; metadata fields with the wrong type are dropped
|
|
379
|
+
* but the entry is kept. */
|
|
380
|
+
export function parseCatalog(text) {
|
|
381
|
+
let raw;
|
|
382
|
+
try {
|
|
383
|
+
raw = JSON.parse(text);
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
throw new Error(`catalog is not valid JSON: ${err.message}`);
|
|
387
|
+
}
|
|
388
|
+
const top = CatalogTopSchema.safeParse(raw);
|
|
389
|
+
if (!top.success) {
|
|
390
|
+
// Map zod's first issue to a precise, user-facing message.
|
|
391
|
+
const path = top.error.issues[0]?.path[0];
|
|
392
|
+
if (path === "version") {
|
|
393
|
+
throw new Error(`unsupported catalog version ${JSON.stringify(raw?.version)}; this ` +
|
|
394
|
+
`agency supports version ${SUPPORTED_CATALOG_VERSION}. Upgrade agency.`);
|
|
395
|
+
}
|
|
396
|
+
if (path === "models") {
|
|
397
|
+
throw new Error("catalog.models must be an object keyed by model name");
|
|
398
|
+
}
|
|
399
|
+
throw new Error("catalog must be a JSON object");
|
|
400
|
+
}
|
|
401
|
+
// Validate each entry independently; a bad entry is skipped + warned, not
|
|
402
|
+
// fatal. Rebuild a canonical-order `CatalogModel` from the validated data.
|
|
403
|
+
const entries = Object.entries(top.data.models).map(([name, entry]) => {
|
|
404
|
+
const parsed = CatalogModelSchema.safeParse(entry);
|
|
405
|
+
if (!parsed.success) {
|
|
406
|
+
console.warn(`[catalog] skipping "${name}": ${parsed.error.issues[0]?.message ?? "invalid entry"}`);
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
const d = parsed.data;
|
|
410
|
+
const model = {
|
|
411
|
+
uri: d.uri,
|
|
412
|
+
...compact({
|
|
413
|
+
params: d.params,
|
|
414
|
+
sizeBytes: d.sizeBytes,
|
|
415
|
+
category: d.category,
|
|
416
|
+
contextWindow: d.contextWindow,
|
|
417
|
+
license: d.license,
|
|
418
|
+
description: d.description,
|
|
419
|
+
sha256: d.sha256,
|
|
420
|
+
}),
|
|
421
|
+
};
|
|
422
|
+
return [name, model];
|
|
423
|
+
});
|
|
424
|
+
return Object.fromEntries(entries.filter((e) => e !== null));
|
|
425
|
+
}
|
|
426
|
+
/** If `url` names a local file (a `file://` URL or a plain filesystem path —
|
|
427
|
+
* i.e. not an `hf:`/`http(s)://` URL), return its path; else null. Lets refresh
|
|
428
|
+
* read a catalog from disk (`agency local refresh ./catalog.json`), which also
|
|
429
|
+
* makes the merge logic integration-testable without a network round-trip. */
|
|
430
|
+
function catalogLocalPath(url) {
|
|
431
|
+
if (url.startsWith("file://"))
|
|
432
|
+
return fileURLToPath(url);
|
|
433
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(url) || url.startsWith("hf:"))
|
|
434
|
+
return null;
|
|
435
|
+
return url;
|
|
436
|
+
}
|
|
437
|
+
/** Read a local catalog file, enforcing the byte cap up front via `stat`. */
|
|
438
|
+
function readCatalogFile(path) {
|
|
439
|
+
const size = fs.statSync(path).size;
|
|
440
|
+
if (size > CATALOG_MAX_BYTES) {
|
|
441
|
+
throw new Error(`catalog file too large (${size} bytes; cap ${CATALOG_MAX_BYTES} bytes)`);
|
|
442
|
+
}
|
|
443
|
+
return fs.readFileSync(path, "utf-8");
|
|
444
|
+
}
|
|
445
|
+
/** Stream a response body, enforcing the byte cap as chunks arrive so a
|
|
446
|
+
* large/malicious body can't be fully buffered first. Mirrors the capped
|
|
447
|
+
* reader in `lib/stdlib/http.ts`; counts raw bytes (`byteLength`), not
|
|
448
|
+
* UTF-16 code units. */
|
|
449
|
+
async function readBodyCapped(res, url, maxBytes) {
|
|
450
|
+
if (!res.body)
|
|
451
|
+
return "";
|
|
452
|
+
const reader = res.body.getReader();
|
|
453
|
+
const decoder = new TextDecoder("utf-8");
|
|
454
|
+
const chunks = [];
|
|
455
|
+
let total = 0;
|
|
456
|
+
try {
|
|
457
|
+
while (true) {
|
|
458
|
+
const { done, value } = await reader.read();
|
|
459
|
+
if (done)
|
|
460
|
+
break;
|
|
461
|
+
total += value.byteLength;
|
|
462
|
+
if (total > maxBytes) {
|
|
463
|
+
await reader.cancel().catch(() => { });
|
|
464
|
+
throw new Error(`catalog from ${url} exceeds ${maxBytes} bytes`);
|
|
465
|
+
}
|
|
466
|
+
chunks.push(decoder.decode(value, { stream: true }));
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
finally {
|
|
470
|
+
try {
|
|
471
|
+
reader.releaseLock();
|
|
472
|
+
}
|
|
473
|
+
catch {
|
|
474
|
+
/* already released */
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
chunks.push(decoder.decode());
|
|
478
|
+
return chunks.join("");
|
|
479
|
+
}
|
|
480
|
+
/** Default fetcher: a local file path / `file://` URL is read from disk;
|
|
481
|
+
* otherwise an HTTPS-only GET with a bounded timeout and a streamed byte cap.
|
|
482
|
+
* `http:` (and other non-https URL schemes) are rejected. */
|
|
483
|
+
export async function fetchCatalog(url) {
|
|
484
|
+
const localPath = catalogLocalPath(url);
|
|
485
|
+
if (localPath !== null) {
|
|
486
|
+
return readCatalogFile(localPath);
|
|
487
|
+
}
|
|
488
|
+
if (!url.startsWith("https://")) {
|
|
489
|
+
throw new Error(`catalog URL must be https or a local file path: ${url}`);
|
|
490
|
+
}
|
|
491
|
+
const controller = new AbortController();
|
|
492
|
+
const timer = setTimeout(() => controller.abort(), CATALOG_FETCH_TIMEOUT_MS);
|
|
493
|
+
try {
|
|
494
|
+
const res = await fetch(url, { signal: controller.signal });
|
|
495
|
+
if (!res.ok) {
|
|
496
|
+
throw new Error(`fetch failed: HTTP ${res.status} ${res.statusText}`);
|
|
497
|
+
}
|
|
498
|
+
return await readBodyCapped(res, url, CATALOG_MAX_BYTES);
|
|
499
|
+
}
|
|
500
|
+
finally {
|
|
501
|
+
clearTimeout(timer);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/** Merge a complete `modelAliases` map into a config object (spread, like
|
|
505
|
+
* `withAlias` but replaces the whole map). */
|
|
506
|
+
function withModelAliases(cfg, aliases) {
|
|
507
|
+
return { ...cfg, client: { ...(cfg.client ?? {}), modelAliases: aliases } };
|
|
508
|
+
}
|
|
509
|
+
/** Stable JSON for value-equality. The merge writes objects with consistent
|
|
510
|
+
* key order via the spread below (`{ ...model, source: "remote" }`), so a
|
|
511
|
+
* deep equality check via `JSON.stringify` is sufficient for managed-entry
|
|
512
|
+
* diffing without pulling in `node:util.isDeepStrictEqual`. */
|
|
513
|
+
function sameManagedValue(prev, next) {
|
|
514
|
+
return JSON.stringify(prev) === JSON.stringify(next);
|
|
515
|
+
}
|
|
516
|
+
/** Classify one catalog entry against the previous state. Pure: no I/O, no
|
|
517
|
+
* mutation, deterministic. Tested via `_refreshCatalog`'s end-to-end tests. */
|
|
518
|
+
function classifyEntry(name, model, userAliases, oldManaged) {
|
|
519
|
+
// Own-property checks (not `name in ...` / bare index access): a catalog
|
|
520
|
+
// model named like a prototype member (`toString`, `__proto__`, …) must not
|
|
521
|
+
// be treated as a collision with — or a previous value from — an inherited
|
|
522
|
+
// property the user never set.
|
|
523
|
+
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
|
|
524
|
+
if (has(userAliases, name)) {
|
|
525
|
+
return {
|
|
526
|
+
kind: "skipped",
|
|
527
|
+
name,
|
|
528
|
+
entry: { name, keptUri: aliasUri(userAliases[name]), remoteUri: model.uri },
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
const value = { ...model, source: "remote" };
|
|
532
|
+
const prev = has(oldManaged, name) ? oldManaged[name] : undefined;
|
|
533
|
+
if (prev === undefined) {
|
|
534
|
+
return { kind: "added", name, value };
|
|
535
|
+
}
|
|
536
|
+
if (sameManagedValue(prev, value)) {
|
|
537
|
+
return { kind: "unchanged", name, value };
|
|
538
|
+
}
|
|
539
|
+
return { kind: "updated", name, value };
|
|
540
|
+
}
|
|
541
|
+
/** Predicate factory for declarative filtering by `Classification.kind`. */
|
|
542
|
+
function isKind(k) {
|
|
543
|
+
return (c) => c.kind === k;
|
|
544
|
+
}
|
|
545
|
+
/** Fetch + validate the catalog, then rewrite the `source:"remote"` aliases in
|
|
546
|
+
* agency.json from it. User-owned aliases are preserved and win on name
|
|
547
|
+
* collisions (the remote entry is skipped). Throws (leaving the file
|
|
548
|
+
* untouched) on fetch/parse/validation failure. */
|
|
549
|
+
export async function _refreshCatalog(opts = {}) {
|
|
550
|
+
const file = resolveAliasFile(opts.file ?? "");
|
|
551
|
+
const url = resolveCatalogUrl(opts.url ?? "", file);
|
|
552
|
+
const fetcher = opts.fetcher ?? fetchCatalog;
|
|
553
|
+
// Fetch + validate BEFORE reading/writing agency.json, so a failure leaves
|
|
554
|
+
// the file untouched.
|
|
555
|
+
const text = await fetcher(url);
|
|
556
|
+
const models = parseCatalog(text);
|
|
557
|
+
// Read aliases through the canonical helper (single source of truth for
|
|
558
|
+
// "how aliases come out of agency.json"). `cfg` is needed separately to
|
|
559
|
+
// round-trip non-alias fields back into the file on write.
|
|
560
|
+
const cfg = readJson(file);
|
|
561
|
+
const existing = readModelAliases(file);
|
|
562
|
+
// Partition existing aliases by who manages them.
|
|
563
|
+
const userAliases = Object.fromEntries(Object.entries(existing).filter(([, v]) => !(typeof v === "object" && v.source === "remote")));
|
|
564
|
+
const oldManaged = Object.fromEntries(Object.entries(existing).filter((e) => typeof e[1] === "object" && e[1].source === "remote"));
|
|
565
|
+
// The entire merge policy: classify each catalog entry once. Everything
|
|
566
|
+
// downstream is a filter/project on this array.
|
|
567
|
+
const classifications = Object.entries(models).map(([name, model]) => classifyEntry(name, model, userAliases, oldManaged));
|
|
568
|
+
const namesIn = (k) => classifications.filter(isKind(k)).map((c) => c.name);
|
|
569
|
+
const added = namesIn("added");
|
|
570
|
+
const updated = namesIn("updated");
|
|
571
|
+
const unchanged = namesIn("unchanged");
|
|
572
|
+
const skipped = classifications.filter(isKind("skipped")).map((c) => c.entry);
|
|
573
|
+
// What ends up in `client.modelAliases`: user aliases (untouched) plus
|
|
574
|
+
// every non-skipped classification's value.
|
|
575
|
+
const writtenManaged = Object.fromEntries(classifications.filter((c) => c.kind !== "skipped").map((c) => [c.name, c.value]));
|
|
576
|
+
const next = { ...userAliases, ...writtenManaged };
|
|
577
|
+
const surviving = [...added, ...updated, ...unchanged];
|
|
578
|
+
const removed = Object.keys(oldManaged).filter((n) => !surviving.includes(n));
|
|
579
|
+
writeJson(file, withModelAliases(cfg, next));
|
|
580
|
+
return {
|
|
581
|
+
url,
|
|
582
|
+
file,
|
|
583
|
+
added,
|
|
584
|
+
updated,
|
|
585
|
+
unchanged,
|
|
586
|
+
removed,
|
|
587
|
+
skipped,
|
|
588
|
+
modelCount: Object.keys(models).length,
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
// Cached so we don't shell out repeatedly per process.
|
|
592
|
+
let cachedGlobalRoots = null;
|
|
593
|
+
/** Discover global `node_modules` roots reported by `npm` and `pnpm`, in that
|
|
594
|
+
* order. Each entry is the directory printed by `<tool> root -g` (which is
|
|
595
|
+
* itself a `node_modules` dir, e.g. `/opt/homebrew/lib/node_modules` for
|
|
596
|
+
* Homebrew npm, `~/Library/pnpm/global/5/node_modules` for pnpm). Failures
|
|
597
|
+
* (tool not installed, exit non-zero, dir missing) are silently skipped. */
|
|
598
|
+
function globalNodeModulesRoots() {
|
|
599
|
+
if (cachedGlobalRoots !== null) {
|
|
600
|
+
return cachedGlobalRoots;
|
|
601
|
+
}
|
|
602
|
+
const roots = [];
|
|
603
|
+
for (const cmd of ["npm", "pnpm"]) {
|
|
604
|
+
try {
|
|
605
|
+
const out = execFileSync(cmd, ["root", "-g"], {
|
|
606
|
+
encoding: "utf-8",
|
|
607
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
608
|
+
}).trim();
|
|
609
|
+
if (out && fs.existsSync(out) && !roots.includes(out)) {
|
|
610
|
+
roots.push(out);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
catch {
|
|
614
|
+
/* tool not installed or failed — skip */
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
cachedGlobalRoots = roots;
|
|
618
|
+
return roots;
|
|
619
|
+
}
|
|
620
|
+
/** Try to resolve `smoltalk-llama-cpp` from the given global `node_modules`
|
|
621
|
+
* roots. Each `root` is itself a `node_modules` directory (the convention
|
|
622
|
+
* `npm root -g` / `pnpm root -g` uses). Node's resolver looks for
|
|
623
|
+
* `<parent>/node_modules/<pkg>` for each parent dir it walks up, so the
|
|
624
|
+
* createRequire base must live in the root's PARENT directory — from
|
|
625
|
+
* `<root>/../_resolver.js` it correctly finds `<root>/smoltalk-llama-cpp/...`.
|
|
626
|
+
* Exported for unit-testing with a controllable list of roots. */
|
|
627
|
+
export function resolveSmoltalkLlamaCppFromRoots(roots) {
|
|
628
|
+
for (const root of roots) {
|
|
629
|
+
try {
|
|
630
|
+
const req = createRequire(path.join(root, "..", "_resolver.js"));
|
|
631
|
+
return req.resolve("smoltalk-llama-cpp");
|
|
632
|
+
}
|
|
633
|
+
catch {
|
|
634
|
+
/* not in this root — try the next */
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
/** Resolve `smoltalk-llama-cpp` to the absolute path of its main entry,
|
|
640
|
+
* searching:
|
|
641
|
+
* 1. The local `require` paths walking up from this file (covers in-workspace
|
|
642
|
+
* `pnpm add` and a user-project install).
|
|
643
|
+
* 2. Each global `node_modules` root reported by `npm root -g` / `pnpm root -g`
|
|
644
|
+
* (covers `npm i -g` and `pnpm add -g` — the documented install methods).
|
|
645
|
+
*
|
|
646
|
+
* Returns `null` if the package isn't reachable from any of those. */
|
|
647
|
+
export function resolveSmoltalkLlamaCppEntry() {
|
|
648
|
+
try {
|
|
649
|
+
return createRequire(import.meta.url).resolve("smoltalk-llama-cpp");
|
|
650
|
+
}
|
|
651
|
+
catch {
|
|
652
|
+
/* not local — try global install roots */
|
|
653
|
+
}
|
|
654
|
+
return resolveSmoltalkLlamaCppFromRoots(globalNodeModulesRoots());
|
|
655
|
+
}
|
|
656
|
+
/** True if smoltalk-llama-cpp is reachable from the local require paths OR
|
|
657
|
+
* from a global node_modules root (npm or pnpm). */
|
|
658
|
+
export function _localModelsSupported() {
|
|
659
|
+
return resolveSmoltalkLlamaCppEntry() !== null;
|
|
660
|
+
}
|
|
661
|
+
/** Whether the local-model commands should be allowed to run. True when
|
|
662
|
+
* smoltalk-llama-cpp is installed OR the caller has supplied their own
|
|
663
|
+
* provider module via AGENCY_LLAMA_PROVIDER_MODULE. Mirrors the gate inside
|
|
664
|
+
* `requireSupport()`; used by the CLI so `agency local download/list/remove`
|
|
665
|
+
* works in the override scenario (otherwise the CLI would exit 1 even though
|
|
666
|
+
* the underlying TS functions would happily run). */
|
|
667
|
+
export function hasLocalModelSupport() {
|
|
668
|
+
if (process.env.AGENCY_LLAMA_PROVIDER_MODULE) {
|
|
669
|
+
return true;
|
|
670
|
+
}
|
|
671
|
+
return _localModelsSupported();
|
|
672
|
+
}
|
|
673
|
+
/** Expose the resolved `smoltalk-llama-cpp` entry path to the bundled
|
|
674
|
+
* `llama-cpp.mjs` via the AGENCY_SMOLTALK_LLAMA_CPP_PATH env var, so that
|
|
675
|
+
* the bundled module can dynamically import it even when the package lives
|
|
676
|
+
* in a global `node_modules` that isn't on this file's resolution path.
|
|
677
|
+
* Idempotent. */
|
|
678
|
+
function exposeResolvedLlamaCppPath() {
|
|
679
|
+
if (process.env.AGENCY_SMOLTALK_LLAMA_CPP_PATH) {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
const entry = resolveSmoltalkLlamaCppEntry();
|
|
683
|
+
if (entry !== null) {
|
|
684
|
+
process.env.AGENCY_SMOLTALK_LLAMA_CPP_PATH = entry;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
/** Absolute fs path of the bundled llama-cpp provider module. Tests/advanced
|
|
688
|
+
* callers can override via AGENCY_LLAMA_PROVIDER_MODULE (also an fs path).
|
|
689
|
+
* The override is normalized to an absolute path so `_downloadModel`'s
|
|
690
|
+
* `pathToFileURL(...)` call works even when callers pass a relative path
|
|
691
|
+
* (which `loadProviderModuleByPath` would itself happily resolve, but the
|
|
692
|
+
* download path bypasses that helper). */
|
|
693
|
+
function bundledLlamaModule() {
|
|
694
|
+
const override = process.env.AGENCY_LLAMA_PROVIDER_MODULE;
|
|
695
|
+
if (override !== undefined && override !== "") {
|
|
696
|
+
return path.isAbsolute(override) ? override : path.resolve(process.cwd(), override);
|
|
697
|
+
}
|
|
698
|
+
return fileURLToPath(new URL("./providers/llama-cpp.mjs", import.meta.url));
|
|
699
|
+
}
|
|
700
|
+
/** Guard the install-required commands. If the user set
|
|
701
|
+
* AGENCY_LLAMA_PROVIDER_MODULE they're supplying a provider module directly,
|
|
702
|
+
* so skip the smoltalk-llama-cpp resolve check. */
|
|
703
|
+
function requireSupport() {
|
|
704
|
+
if (process.env.AGENCY_LLAMA_PROVIDER_MODULE) {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
if (!_localModelsSupported()) {
|
|
708
|
+
throw new Error("Local models need smoltalk-llama-cpp — run: npm i -g smoltalk-llama-cpp");
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
/** Register the llama-cpp provider into agency's own smoltalk. */
|
|
712
|
+
export async function _registerLocalProvider() {
|
|
713
|
+
requireSupport();
|
|
714
|
+
exposeResolvedLlamaCppPath();
|
|
715
|
+
await loadProviderModuleByPath(bundledLlamaModule());
|
|
716
|
+
}
|
|
717
|
+
/** Stream-hash a file's SHA-256 (hex), never buffering the whole file. The
|
|
718
|
+
* `update` is guarded so a synchronous throw in the data handler rejects the
|
|
719
|
+
* promise instead of escaping it. */
|
|
720
|
+
export function fileSha256(filePath) {
|
|
721
|
+
return new Promise((resolve, reject) => {
|
|
722
|
+
const hash = createHash("sha256");
|
|
723
|
+
const stream = fs.createReadStream(filePath);
|
|
724
|
+
stream.on("error", reject);
|
|
725
|
+
stream.on("data", (chunk) => {
|
|
726
|
+
try {
|
|
727
|
+
hash.update(chunk);
|
|
728
|
+
}
|
|
729
|
+
catch (err) {
|
|
730
|
+
stream.destroy();
|
|
731
|
+
reject(err);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
stream.on("end", () => resolve(hash.digest("hex")));
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
/** Verify `filePath` against the expected hex SHA-256. On mismatch, rename the
|
|
738
|
+
* file to `<filePath>.invalidSha` (kept for inspection; won't be picked up, so
|
|
739
|
+
* the next run re-downloads) and throw. A failed rename is logged (not
|
|
740
|
+
* swallowed) and reflected in the thrown message. */
|
|
741
|
+
export async function verifyModelFile(filePath, expected, name) {
|
|
742
|
+
// `fileSha256` returns lowercase hex; normalize the expected pin so a
|
|
743
|
+
// valid-but-uppercase hash (e.g. from a hand-written alias) still matches.
|
|
744
|
+
const want = expected.toLowerCase();
|
|
745
|
+
const actual = await fileSha256(filePath);
|
|
746
|
+
if (actual === want)
|
|
747
|
+
return;
|
|
748
|
+
const quarantine = `${filePath}.invalidSha`;
|
|
749
|
+
let moved = true;
|
|
750
|
+
try {
|
|
751
|
+
fs.renameSync(filePath, quarantine);
|
|
752
|
+
}
|
|
753
|
+
catch (err) {
|
|
754
|
+
moved = false;
|
|
755
|
+
console.warn(`Could not move "${filePath}" to "${quarantine}" after SHA-256 mismatch:`, err);
|
|
756
|
+
}
|
|
757
|
+
throw new Error(`SHA-256 verification failed for "${name}": expected ${expected}, got ${actual}. ` +
|
|
758
|
+
(moved
|
|
759
|
+
? `The downloaded file was moved to ${quarantine} for inspection and will be re-downloaded next time.`
|
|
760
|
+
: `The downloaded file at ${filePath} could NOT be moved aside — delete it manually before re-running.`));
|
|
761
|
+
}
|
|
762
|
+
/** The pinned SHA-256 for a model name/alias, or undefined when none is known
|
|
763
|
+
* (raw uri/path, string alias, alias/curated without a hash, or a sharded
|
|
764
|
+
* model). An alias entry governs the name entirely — a user alias shadowing a
|
|
765
|
+
* curated name must NOT borrow the curated hash, but a user MAY opt in by
|
|
766
|
+
* setting their own `sha256` on the alias object. */
|
|
767
|
+
export function pinnedSha256(value, file = "") {
|
|
768
|
+
if (isGgufPath(value) || isModelUri(value))
|
|
769
|
+
return undefined;
|
|
770
|
+
const aliases = readModelAliases(file);
|
|
771
|
+
if (Object.hasOwn(aliases, value)) {
|
|
772
|
+
const v = aliases[value];
|
|
773
|
+
return typeof v === "object" ? v.sha256 : undefined;
|
|
774
|
+
}
|
|
775
|
+
return CURATED_LOCAL_MODELS[value]?.sha256;
|
|
776
|
+
}
|
|
777
|
+
/** Snapshot the cache dir, returning a probe that reports whether a resolved
|
|
778
|
+
* path is newly downloaded. node-llama-cpp stores models FLAT in `dir` with a
|
|
779
|
+
* prefixed filename — no per-repo subdirs (verified against its
|
|
780
|
+
* `buildHuggingFaceFilePrefix`) — so matching by basename is correct. */
|
|
781
|
+
export function snapshotFreshness(dir) {
|
|
782
|
+
const present = fs.existsSync(dir)
|
|
783
|
+
? new Set(fs.readdirSync(dir).filter((f) => f.endsWith(".gguf")))
|
|
784
|
+
: new Set();
|
|
785
|
+
return (resolved) => !present.has(path.basename(resolved));
|
|
786
|
+
}
|
|
787
|
+
/** Resolve a name/uri/path to a local .gguf path, downloading if needed. */
|
|
788
|
+
export async function _downloadModel(value, cacheDir = "") {
|
|
789
|
+
requireSupport();
|
|
790
|
+
exposeResolvedLlamaCppPath();
|
|
791
|
+
const target = _resolveModelName(value);
|
|
792
|
+
const dir = resolveCacheDir(cacheDir);
|
|
793
|
+
const fsPath = bundledLlamaModule();
|
|
794
|
+
let mod;
|
|
795
|
+
try {
|
|
796
|
+
// eslint-disable-next-line no-restricted-syntax -- on-demand load of the optional provider module
|
|
797
|
+
mod = (await import(pathToFileURL(fsPath).href));
|
|
798
|
+
}
|
|
799
|
+
catch (err) {
|
|
800
|
+
throw new Error(`Failed to load the local-model provider: ${err.message}`);
|
|
801
|
+
}
|
|
802
|
+
if (typeof mod.resolveModel !== "function") {
|
|
803
|
+
throw new Error(`Local-model provider module must export resolveModel().`);
|
|
804
|
+
}
|
|
805
|
+
// Snapshot freshness BEFORE resolving so we verify the bytes only once, right
|
|
806
|
+
// after a real download (a cache hit is skipped — the file can't change on
|
|
807
|
+
// disk between runs).
|
|
808
|
+
const wasFresh = snapshotFreshness(dir);
|
|
809
|
+
const resolved = await mod.resolveModel(target, dir);
|
|
810
|
+
const expected = pinnedSha256(value);
|
|
811
|
+
if (expected !== undefined && wasFresh(resolved)) {
|
|
812
|
+
await verifyModelFile(resolved, expected, value);
|
|
813
|
+
}
|
|
814
|
+
return resolved;
|
|
815
|
+
}
|
|
816
|
+
/** Convenience: register the provider + ensure the model is downloaded. */
|
|
817
|
+
export async function _registerLocalModel(value, cacheDir = "") {
|
|
818
|
+
await _registerLocalProvider();
|
|
819
|
+
return await _downloadModel(value, cacheDir);
|
|
820
|
+
}
|
|
821
|
+
// =============================================================================
|
|
822
|
+
// Catalog rendering — shared by `agency local alias list` and the agent's
|
|
823
|
+
// bare `--local-model` discovery output, so both show an identical table.
|
|
824
|
+
// =============================================================================
|
|
825
|
+
const BYTES_PER_GB = 1e9;
|
|
826
|
+
export function formatGB(bytes) {
|
|
827
|
+
return `${(bytes / BYTES_PER_GB).toFixed(2)} GB`;
|
|
828
|
+
}
|
|
829
|
+
/** Context window in compact units: 8192 → "8K", 131072 → "128K", 1e7 → "10M". */
|
|
830
|
+
export function formatCtx(tokens) {
|
|
831
|
+
if (tokens >= 1_000_000)
|
|
832
|
+
return `${Math.round(tokens / 1_000_000)}M`;
|
|
833
|
+
if (tokens >= 1024)
|
|
834
|
+
return `${Math.round(tokens / 1024)}K`;
|
|
835
|
+
return `${tokens}`;
|
|
836
|
+
}
|
|
837
|
+
/** Width of a column: the longer of its header and its widest value. */
|
|
838
|
+
function colWidth(header, values) {
|
|
839
|
+
return Math.max(header.length, ...values.map((v) => v.length));
|
|
840
|
+
}
|
|
841
|
+
/** Render the usable-model list as an aligned table: a header row plus one
|
|
842
|
+
* fact row per curated model (params, category, size, context window,
|
|
843
|
+
* license), the description on a dimmed line below, a blank line between
|
|
844
|
+
* models. User aliases (which carry no metadata) follow in an ALIASES
|
|
845
|
+
* section as `name → target`. Returns the block as a string with no trailing
|
|
846
|
+
* newline (the caller's `console.log` adds exactly one). */
|
|
847
|
+
export function formatModelCatalog() {
|
|
848
|
+
const entries = _listModelNames();
|
|
849
|
+
const hasMetadata = (m) => m.params !== undefined ||
|
|
850
|
+
m.sizeBytes !== undefined ||
|
|
851
|
+
m.category !== undefined ||
|
|
852
|
+
m.contextWindow !== undefined ||
|
|
853
|
+
m.license !== undefined ||
|
|
854
|
+
m.description !== undefined;
|
|
855
|
+
const curated = entries.filter(hasMetadata); // table rows: built-ins + rich aliases
|
|
856
|
+
const aliases = entries.filter((m) => !hasMetadata(m)); // plain name→uri only
|
|
857
|
+
const lines = [];
|
|
858
|
+
if (curated.length > 0) {
|
|
859
|
+
const rows = curated.map((m) => ({
|
|
860
|
+
name: m.name,
|
|
861
|
+
params: m.params ?? "",
|
|
862
|
+
category: m.category ?? "",
|
|
863
|
+
size: m.sizeBytes ? formatGB(m.sizeBytes) : "?",
|
|
864
|
+
ctx: m.contextWindow ? formatCtx(m.contextWindow) : "",
|
|
865
|
+
license: m.license ?? "",
|
|
866
|
+
description: m.description ?? "",
|
|
867
|
+
}));
|
|
868
|
+
// Computed widths so columns fit the actual data (names range from ~10
|
|
869
|
+
// to ~28 chars). SIZE and CTX are numeric, so they right-align.
|
|
870
|
+
const w = {
|
|
871
|
+
name: colWidth("NAME", rows.map((r) => r.name)),
|
|
872
|
+
params: colWidth("PARAMS", rows.map((r) => r.params)),
|
|
873
|
+
category: colWidth("CATEGORY", rows.map((r) => r.category)),
|
|
874
|
+
size: colWidth("SIZE", rows.map((r) => r.size)),
|
|
875
|
+
ctx: colWidth("CTX", rows.map((r) => r.ctx)),
|
|
876
|
+
};
|
|
877
|
+
const row = (name, params, category, size, ctx, license) => `${name.padEnd(w.name)} ${params.padEnd(w.params)} ${category.padEnd(w.category)} ${size.padStart(w.size)} ${ctx.padStart(w.ctx)} ${license}`;
|
|
878
|
+
// LICENSE is the last column, so it needs no trailing pad.
|
|
879
|
+
lines.push(ttyColor.bold(row("NAME", "PARAMS", "CATEGORY", "SIZE", "CTX", "LICENSE")));
|
|
880
|
+
rows.forEach((r, i) => {
|
|
881
|
+
// Blank line *between* models, not after the last one, so the joined
|
|
882
|
+
// string has no trailing newline (console.log adds exactly one).
|
|
883
|
+
if (i > 0)
|
|
884
|
+
lines.push("");
|
|
885
|
+
lines.push(row(r.name, r.params, r.category, r.size, r.ctx, r.license));
|
|
886
|
+
if (r.description)
|
|
887
|
+
lines.push(ttyColor.dim(` ${r.description}`));
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
if (aliases.length > 0) {
|
|
891
|
+
if (lines.length > 0)
|
|
892
|
+
lines.push(""); // separate the table from ALIASES
|
|
893
|
+
lines.push(ttyColor.bold("ALIASES"));
|
|
894
|
+
for (const a of aliases) {
|
|
895
|
+
lines.push(`${a.name} → ${a.target}`);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
return lines.join("\n");
|
|
899
|
+
}
|
|
900
|
+
/** Print the model catalog to stdout. The agent's bare `--local-model`
|
|
901
|
+
* path calls this through `std::agency/local`. */
|
|
902
|
+
export function _printLocalCatalog() {
|
|
903
|
+
console.log(formatModelCatalog());
|
|
904
|
+
}
|