agency-lang 0.8.1 → 0.10.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 +110 -1848
- package/dist/lib/agents/agency-agent/agent.js +865 -10821
- package/dist/lib/agents/agency-agent/images/images.js +17 -6
- package/dist/lib/agents/agency-agent/lib/args.agency +88 -0
- package/dist/lib/agents/agency-agent/lib/args.js +407 -0
- package/dist/lib/agents/agency-agent/lib/attachments.js +108 -25
- package/dist/lib/agents/agency-agent/lib/budget.agency +213 -0
- package/dist/lib/agents/agency-agent/lib/budget.js +1504 -0
- package/dist/lib/agents/agency-agent/lib/capabilities.agency +22 -20
- package/dist/lib/agents/agency-agent/lib/capabilities.js +217 -59
- package/dist/lib/agents/agency-agent/lib/capabilitiesUi.agency +330 -0
- package/dist/lib/agents/agency-agent/lib/capabilitiesUi.js +2621 -0
- package/dist/lib/agents/agency-agent/lib/commandPalette.agency +38 -0
- package/dist/lib/agents/agency-agent/lib/commandPalette.js +503 -0
- package/dist/lib/agents/agency-agent/lib/config.js +29 -12
- package/dist/lib/agents/agency-agent/lib/coordinator.agency +373 -0
- package/dist/lib/agents/agency-agent/lib/coordinator.js +2377 -0
- package/dist/lib/agents/agency-agent/lib/header.agency +82 -0
- package/dist/lib/agents/agency-agent/lib/header.js +1069 -0
- package/dist/lib/agents/agency-agent/lib/images.agency +62 -0
- package/dist/lib/agents/agency-agent/lib/images.js +730 -0
- package/dist/lib/agents/agency-agent/lib/mcp.agency +103 -0
- package/dist/lib/agents/agency-agent/lib/mcp.js +1324 -0
- package/dist/lib/agents/agency-agent/lib/modelFilters.js +21 -7
- package/dist/lib/agents/agency-agent/lib/models.agency +7 -6
- package/dist/lib/agents/agency-agent/lib/models.js +228 -86
- package/dist/lib/agents/agency-agent/lib/policy.agency +111 -0
- package/dist/lib/agents/agency-agent/lib/policy.js +1080 -0
- package/dist/lib/agents/agency-agent/lib/repl.agency +415 -0
- package/dist/lib/agents/agency-agent/lib/repl.js +3174 -0
- package/dist/lib/agents/agency-agent/lib/resolution.js +208 -61
- package/dist/lib/agents/agency-agent/lib/search.agency +21 -3
- package/dist/lib/agents/agency-agent/lib/search.js +496 -80
- package/dist/lib/agents/agency-agent/lib/session.agency +331 -0
- package/dist/lib/agents/agency-agent/lib/session.js +2071 -0
- package/dist/lib/agents/agency-agent/lib/settings.js +185 -54
- package/dist/lib/agents/agency-agent/lib/slots.agency +0 -1
- package/dist/lib/agents/agency-agent/lib/slots.js +58 -17
- package/dist/lib/agents/agency-agent/lib/trace.agency +150 -0
- package/dist/lib/agents/agency-agent/lib/trace.js +2057 -0
- package/dist/lib/agents/agency-agent/lib/utils/renderLLMCallResponse.agency +27 -0
- package/dist/lib/agents/agency-agent/lib/utils/renderLLMCallResponse.js +361 -0
- package/dist/lib/agents/agency-agent/lib/utils.agency +54 -0
- package/dist/lib/agents/agency-agent/lib/utils.js +650 -41
- package/dist/lib/agents/agency-agent/prompts/code.md +268 -0
- package/dist/lib/agents/agency-agent/prompts/codeSample.js +46 -21
- package/dist/lib/agents/agency-agent/prompts/main-large.md +170 -0
- package/dist/lib/agents/agency-agent/prompts/main-small.md +30 -0
- package/dist/lib/agents/agency-agent/prompts/oneShot.md +21 -0
- package/dist/lib/agents/agency-agent/shared.agency +1 -4
- package/dist/lib/agents/agency-agent/shared.js +380 -107
- package/dist/lib/agents/agency-agent/subagents/brainstorm.agency +201 -0
- package/dist/lib/agents/agency-agent/subagents/brainstorm.js +1652 -0
- package/dist/lib/agents/agency-agent/subagents/code.agency +378 -431
- package/dist/lib/agents/agency-agent/subagents/code.js +3203 -645
- package/dist/lib/agents/agency-agent/subagents/explorer.agency +19 -132
- package/dist/lib/agents/agency-agent/subagents/explorer.js +103 -242
- package/dist/lib/agents/agency-agent/subagents/oracle.agency +23 -104
- package/dist/lib/agents/agency-agent/subagents/oracle.js +103 -222
- package/dist/lib/agents/agency-agent/subagents/research.agency +57 -155
- package/dist/lib/agents/agency-agent/subagents/research.js +156 -257
- package/dist/lib/agents/agency-agent/subagents/review.agency +78 -41
- package/dist/lib/agents/agency-agent/subagents/review.js +723 -178
- package/dist/lib/agents/agency-agent/subagents/supervisor.agency +378 -0
- package/dist/lib/agents/agency-agent/subagents/supervisor.js +2486 -0
- package/dist/lib/agents/agency-agent/subagents/verify.js +249 -204
- package/dist/lib/agents/agency-agent/tests/agentDir.js +33 -9
- package/dist/lib/agents/agency-agent/tests/agentTurn.agency +31 -4
- package/dist/lib/agents/agency-agent/tests/agentTurn.js +992 -247
- package/dist/lib/agents/agency-agent/tests/agentTurn.test.json +33 -3
- package/dist/lib/agents/agency-agent/tests/attachments.agency +6 -1
- package/dist/lib/agents/agency-agent/tests/attachments.js +364 -285
- package/dist/lib/agents/agency-agent/tests/attachmentsTurn.agency +5 -10
- package/dist/lib/agents/agency-agent/tests/attachmentsTurn.js +178 -175
- package/dist/lib/agents/agency-agent/tests/attachmentsTurn.test.json +0 -16
- package/dist/lib/agents/agency-agent/tests/brainstorm.agency +94 -0
- package/dist/lib/agents/agency-agent/tests/brainstorm.js +1235 -0
- package/dist/lib/agents/agency-agent/tests/brainstorm.test.json +59 -0
- package/dist/lib/agents/agency-agent/tests/capabilities.js +271 -87
- package/dist/lib/agents/agency-agent/tests/execPolicy.js +213 -63
- package/dist/lib/agents/agency-agent/tests/gitPolicy.js +137 -41
- package/dist/lib/agents/agency-agent/tests/imageTool.agency +1 -1
- package/dist/lib/agents/agency-agent/tests/imageTool.js +140 -38
- package/dist/lib/agents/agency-agent/tests/mcpGating.js +56 -21
- package/dist/lib/agents/agency-agent/tests/memoryWiring.js +108 -27
- package/dist/lib/agents/agency-agent/tests/modelFilters.js +98 -42
- package/dist/lib/agents/agency-agent/tests/models.js +192 -97
- package/dist/lib/agents/agency-agent/tests/models.test.json +4 -4
- package/dist/lib/agents/agency-agent/tests/oneShotRounds.js +104 -39
- package/dist/lib/agents/agency-agent/tests/resolution.js +538 -143
- package/dist/lib/agents/agency-agent/tests/resolution.test.json +2 -2
- package/dist/lib/agents/agency-agent/tests/search.js +496 -147
- package/dist/lib/agents/agency-agent/tests/settings.agency +5 -1
- package/dist/lib/agents/agency-agent/tests/settings.js +173 -88
- package/dist/lib/agents/agency-agent/tests/slots.js +28 -21
- package/dist/lib/agents/agency-agent/tests/subagentFailure.js +749 -0
- package/dist/lib/agents/agency-agent/tests/supervisor.agency +197 -0
- package/dist/lib/agents/agency-agent/tests/supervisor.js +2713 -0
- package/dist/lib/agents/agency-agent/tests/supervisor.test.json +169 -0
- package/dist/lib/agents/agency-agent/tests/toolWiring.agency +23 -4
- package/dist/lib/agents/agency-agent/tests/toolWiring.js +313 -29
- package/dist/lib/agents/agency-agent/tests/toolWiring.test.json +14 -0
- package/dist/lib/agents/agency-agent/tests/turnFailure.agency +8 -3
- package/dist/lib/agents/agency-agent/tests/turnFailure.js +108 -47
- package/dist/lib/agents/eval/goalJudge.agency +4 -2
- package/dist/lib/agents/eval/goalJudge.js +24 -11
- package/dist/lib/agents/eval/judge.agency +4 -2
- package/dist/lib/agents/eval/judge.js +22 -11
- package/dist/lib/agents/eval/judgePairwise.js +20 -9
- package/dist/lib/agents/optimize/gepaReflect.js +20 -9
- package/dist/lib/agents/optimize/mutatePrompt.js +20 -9
- package/dist/lib/agents/policy/agent.agency +5 -4
- package/dist/lib/agents/policy/agent.js +237 -63
- package/dist/lib/agents/review/agent.agency +2 -2
- package/dist/lib/agents/review/agent.js +81 -16
- package/dist/lib/analysis/bodyFacts.d.ts +52 -0
- package/dist/lib/analysis/bodyFacts.js +87 -0
- package/dist/lib/analysis/effectPropagation.test.js +167 -0
- package/dist/lib/analysis/effects.d.ts +66 -0
- package/dist/lib/analysis/effects.js +238 -0
- package/dist/lib/analysis/effects.test.d.ts +1 -0
- package/dist/lib/analysis/effects.test.js +247 -0
- package/dist/lib/analysis/effectsOracle.test.d.ts +1 -0
- package/dist/lib/analysis/effectsOracle.test.js +74 -0
- package/dist/lib/analysis/interrupts.js +6 -1
- package/dist/lib/backends/agencyGenerator.d.ts +52 -6
- package/dist/lib/backends/agencyGenerator.finalizeBlock.test.d.ts +1 -0
- package/dist/lib/backends/agencyGenerator.finalizeBlock.test.js +36 -0
- package/dist/lib/backends/agencyGenerator.guardBlock.test.d.ts +1 -0
- package/dist/lib/backends/agencyGenerator.guardBlock.test.js +33 -0
- package/dist/lib/backends/agencyGenerator.hole.test.d.ts +1 -0
- package/dist/lib/backends/agencyGenerator.hole.test.js +61 -0
- package/dist/lib/backends/agencyGenerator.js +264 -18
- package/dist/lib/backends/agencyGenerator.matchBlock.test.js +41 -0
- package/dist/lib/backends/agencyGenerator.roundtrip.test.d.ts +1 -0
- package/dist/lib/backends/agencyGenerator.roundtrip.test.js +250 -0
- package/dist/lib/backends/agencyGenerator.splice.test.d.ts +1 -0
- package/dist/lib/backends/agencyGenerator.splice.test.js +43 -0
- package/dist/lib/backends/agencyGenerator.test.js +52 -0
- package/dist/lib/backends/draftSchemaCodegen.test.d.ts +1 -0
- package/dist/lib/backends/draftSchemaCodegen.test.js +70 -0
- package/dist/lib/backends/finalizeBinderCodegen.test.d.ts +1 -0
- package/dist/lib/backends/finalizeBinderCodegen.test.js +26 -0
- package/dist/lib/backends/frameClaims.test.d.ts +1 -0
- package/dist/lib/backends/frameClaims.test.js +58 -0
- package/dist/lib/backends/functionContainsDestructiveBlock.d.ts +22 -0
- package/dist/lib/backends/functionContainsDestructiveBlock.js +30 -0
- package/dist/lib/backends/functionContainsDestructiveBlock.test.d.ts +1 -0
- package/dist/lib/backends/functionContainsDestructiveBlock.test.js +31 -0
- package/dist/lib/backends/holeRefusal.test.d.ts +1 -0
- package/dist/lib/backends/holeRefusal.test.js +58 -0
- package/dist/lib/backends/typescriptBuilder/destructiveTracking.d.ts +19 -12
- package/dist/lib/backends/typescriptBuilder/destructiveTracking.js +31 -17
- package/dist/lib/backends/typescriptBuilder/destructiveTracking.test.js +15 -8
- package/dist/lib/backends/typescriptBuilder/finalizeCodegen.d.ts +104 -0
- package/dist/lib/backends/typescriptBuilder/finalizeCodegen.js +146 -0
- package/dist/lib/backends/typescriptBuilder/nameClassifier.d.ts +2 -11
- package/dist/lib/backends/typescriptBuilder/nameClassifier.js +7 -31
- package/dist/lib/backends/typescriptBuilder/scopeManager.d.ts +11 -0
- package/dist/lib/backends/typescriptBuilder/scopeManager.js +34 -0
- package/dist/lib/backends/typescriptBuilder/scopeManager.test.js +36 -0
- package/dist/lib/backends/typescriptBuilder/sectionAssembler.js +11 -11
- package/dist/lib/backends/typescriptBuilder/stepPathTracker.js +2 -1
- package/dist/lib/backends/typescriptBuilder.d.ts +45 -5
- package/dist/lib/backends/typescriptBuilder.js +308 -60
- package/dist/lib/backends/typescriptGenerator/typeToString.js +1 -1
- package/dist/lib/backends/typescriptGenerator/validationDescriptor.js +42 -16
- package/dist/lib/cli/agent.d.ts +4 -1
- package/dist/lib/cli/agent.js +2 -2
- package/dist/lib/cli/budget.d.ts +19 -0
- package/dist/lib/cli/budget.js +44 -0
- package/dist/lib/cli/budget.test.d.ts +1 -0
- package/dist/lib/cli/budget.test.js +46 -0
- package/dist/lib/cli/budgetRun.spawn.test.d.ts +1 -0
- package/dist/lib/cli/budgetRun.spawn.test.js +109 -0
- package/dist/lib/cli/bundle.test.js +2 -2
- package/dist/lib/cli/commands.d.ts +3 -0
- package/dist/lib/cli/commands.js +11 -2
- package/dist/lib/cli/definition.js +3 -2
- package/dist/lib/cli/diagnosticsDocs.js +46 -2
- package/dist/lib/cli/diagnosticsDocs.test.js +24 -2
- package/dist/lib/cli/doc.d.ts +1 -0
- package/dist/lib/cli/doc.js +53 -12
- package/dist/lib/cli/doc.test.js +134 -5
- package/dist/lib/cli/doctor.js +2 -2
- package/dist/lib/cli/doctor.test.js +3 -3
- package/dist/lib/cli/events.test.js +2 -1
- package/dist/lib/cli/expectedCompileError.d.ts +30 -0
- package/dist/lib/cli/expectedCompileError.js +58 -0
- package/dist/lib/cli/expectedCompileError.test.d.ts +1 -0
- package/dist/lib/cli/expectedCompileError.test.js +81 -0
- package/dist/lib/cli/explain.js +37 -0
- package/dist/lib/cli/explain.test.js +28 -2
- package/dist/lib/cli/lint.d.ts +4 -0
- package/dist/lib/cli/lint.js +11 -0
- package/dist/lib/cli/lint.test.d.ts +1 -0
- package/dist/lib/cli/lint.test.js +18 -0
- package/dist/lib/cli/literate.d.ts +1 -1
- package/dist/lib/cli/literate.js +89 -9
- package/dist/lib/cli/literate.test.js +96 -1
- package/dist/lib/cli/policy.d.ts +2 -0
- package/dist/lib/cli/policy.js +1 -1
- package/dist/lib/cli/policyCrossModule.test.d.ts +1 -0
- package/dist/lib/cli/policyCrossModule.test.js +30 -0
- package/dist/lib/cli/precompile.js +16 -7
- package/dist/lib/cli/precompile.test.js +22 -0
- package/dist/lib/cli/runAgencyAgent.js +4 -3
- package/dist/lib/cli/runBundledAgent.d.ts +4 -1
- package/dist/lib/cli/runBundledAgent.js +23 -7
- package/dist/lib/cli/runBundledAgent.test.js +40 -8
- package/dist/lib/cli/serve.js +16 -28
- package/dist/lib/cli/test.d.ts +8 -2
- package/dist/lib/cli/test.js +194 -10
- package/dist/lib/cli/test.test.d.ts +1 -0
- package/dist/lib/cli/test.test.js +76 -0
- package/dist/lib/cli/util.d.ts +2 -1
- package/dist/lib/cli/util.js +10 -4
- package/dist/lib/compilationUnit.js +8 -4
- package/dist/lib/compiler/buildSession.js +14 -1
- package/dist/lib/compiler/compile.js +24 -1
- package/dist/lib/compiler/compileClosure.d.ts +14 -1
- package/dist/lib/compiler/compileClosure.js +13 -1
- package/dist/lib/compiler/initDepGraph.js +3 -2
- package/dist/lib/compiler/splice/cache.d.ts +60 -0
- package/dist/lib/compiler/splice/cache.js +126 -0
- package/dist/lib/compiler/splice/cache.test.d.ts +1 -0
- package/dist/lib/compiler/splice/cache.test.js +124 -0
- package/dist/lib/compiler/splice/eligibility.d.ts +114 -0
- package/dist/lib/compiler/splice/eligibility.js +253 -0
- package/dist/lib/compiler/splice/eligibility.test.d.ts +1 -0
- package/dist/lib/compiler/splice/eligibility.test.js +153 -0
- package/dist/lib/compiler/splice/generatorEffects.d.ts +18 -0
- package/dist/lib/compiler/splice/generatorEffects.js +210 -0
- package/dist/lib/compiler/splice/rebuild.test.d.ts +1 -0
- package/dist/lib/compiler/splice/rebuild.test.js +124 -0
- package/dist/lib/compiler/splice/report.d.ts +12 -0
- package/dist/lib/compiler/splice/report.js +20 -0
- package/dist/lib/compiler/splice/runGenerator.d.ts +43 -0
- package/dist/lib/compiler/splice/runGenerator.js +385 -0
- package/dist/lib/compiler/splice/runGenerator.test.d.ts +1 -0
- package/dist/lib/compiler/splice/runGenerator.test.js +216 -0
- package/dist/lib/compiler/splice/types.d.ts +28 -0
- package/dist/lib/compiler/splice/types.js +1 -0
- package/dist/lib/compiler/typecheck.d.ts +10 -0
- package/dist/lib/compiler/typecheck.js +28 -7
- package/dist/lib/compiler/typecheckEffects.test.d.ts +1 -0
- package/dist/lib/compiler/typecheckEffects.test.js +35 -0
- package/dist/lib/config.d.ts +18 -1
- package/dist/lib/config.js +19 -3
- package/dist/lib/config.test.js +7 -1
- package/dist/lib/constants.d.ts +21 -0
- package/dist/lib/constants.js +21 -0
- package/dist/lib/debugger/uiState.test.js +1 -0
- package/dist/lib/formatter.comprehension.test.d.ts +1 -0
- package/dist/lib/formatter.comprehension.test.js +34 -0
- package/dist/lib/formatter.test.js +36 -0
- package/dist/lib/ir/builders.js +4 -8
- package/dist/lib/ir/prettyPrint.js +11 -1
- package/dist/lib/linter/diagnosticExplanations.d.ts +3 -0
- package/dist/lib/linter/diagnosticExplanations.js +20 -0
- package/dist/lib/linter/diagnostics.d.ts +35 -0
- package/dist/lib/linter/diagnostics.js +43 -0
- package/dist/lib/linter/diagnostics.test.d.ts +1 -0
- package/dist/lib/linter/diagnostics.test.js +23 -0
- package/dist/lib/linter/registry.d.ts +14 -0
- package/dist/lib/linter/registry.js +28 -0
- package/dist/lib/linter/registry.test.d.ts +1 -0
- package/dist/lib/linter/registry.test.js +23 -0
- package/dist/lib/linter/rules/importFixes.d.ts +8 -0
- package/dist/lib/linter/rules/importFixes.js +71 -0
- package/dist/lib/linter/rules/missingDocstring.d.ts +2 -0
- package/dist/lib/linter/rules/missingDocstring.js +27 -0
- package/dist/lib/linter/rules/missingDocstring.test.d.ts +1 -0
- package/dist/lib/linter/rules/missingDocstring.test.js +62 -0
- package/dist/lib/linter/rules/redundantPreludeImport.d.ts +2 -0
- package/dist/lib/linter/rules/redundantPreludeImport.js +50 -0
- package/dist/lib/linter/rules/redundantPreludeImport.test.d.ts +1 -0
- package/dist/lib/linter/rules/redundantPreludeImport.test.js +74 -0
- package/dist/lib/linter/rules/unusedImports.d.ts +26 -0
- package/dist/lib/linter/rules/unusedImports.fix.test.d.ts +1 -0
- package/dist/lib/linter/rules/unusedImports.fix.test.js +86 -0
- package/dist/lib/linter/rules/unusedImports.js +102 -0
- package/dist/lib/linter/rules/unusedImports.test.d.ts +1 -0
- package/dist/lib/linter/rules/unusedImports.test.js +107 -0
- package/dist/lib/linter/rules/util.d.ts +36 -0
- package/dist/lib/linter/rules/util.js +93 -0
- package/dist/lib/linter/rules/util.test.d.ts +1 -0
- package/dist/lib/linter/rules/util.test.js +37 -0
- package/dist/lib/linter/types.d.ts +41 -0
- package/dist/lib/linter/types.js +1 -0
- package/dist/lib/lowering/comprehensionDesugar.d.ts +26 -0
- package/dist/lib/lowering/comprehensionDesugar.js +228 -0
- package/dist/lib/lowering/comprehensionDesugar.locations.test.d.ts +1 -0
- package/dist/lib/lowering/comprehensionDesugar.locations.test.js +57 -0
- package/dist/lib/lowering/comprehensionDesugar.test.d.ts +1 -0
- package/dist/lib/lowering/comprehensionDesugar.test.js +171 -0
- package/dist/lib/lowering/patternGuards.tripwire.test.d.ts +27 -0
- package/dist/lib/lowering/patternGuards.tripwire.test.js +362 -0
- package/dist/lib/lowering/patternLowering.js +303 -28
- package/dist/lib/lowering/patternLowering.test.js +120 -7
- package/dist/lib/lsp/builtinHover.js +4 -3
- package/dist/lib/lsp/codeAction.d.ts +13 -1
- package/dist/lib/lsp/codeAction.js +70 -1
- package/dist/lib/lsp/codeAction.test.js +86 -0
- package/dist/lib/lsp/completion.js +2 -1
- package/dist/lib/lsp/diagnostics.d.ts +4 -0
- package/dist/lib/lsp/diagnostics.js +116 -18
- package/dist/lib/lsp/diagnostics.test.js +254 -0
- package/dist/lib/lsp/documentState.d.ts +10 -0
- package/dist/lib/lsp/documentStateCache.d.ts +50 -0
- package/dist/lib/lsp/documentStateCache.js +47 -0
- package/dist/lib/lsp/documentStateCache.test.d.ts +1 -0
- package/dist/lib/lsp/documentStateCache.test.js +95 -0
- package/dist/lib/lsp/documentSymbol.js +3 -2
- package/dist/lib/lsp/inlayHint.js +2 -1
- package/dist/lib/lsp/scopeResolution.d.ts +17 -0
- package/dist/lib/lsp/scopeResolution.js +42 -22
- package/dist/lib/lsp/semanticTokens.d.ts +32 -0
- package/dist/lib/lsp/semanticTokens.js +220 -0
- package/dist/lib/lsp/semanticTokens.test.d.ts +1 -0
- package/dist/lib/lsp/semanticTokens.test.js +338 -0
- package/dist/lib/lsp/semantics.js +7 -6
- package/dist/lib/lsp/server.js +136 -13
- package/dist/lib/lsp/typeResolution.js +2 -1
- package/dist/lib/optimize/targets.js +3 -2
- package/dist/lib/parseCache.d.ts +10 -0
- package/dist/lib/parseCache.js +13 -0
- package/dist/lib/parseCache.test.js +26 -1
- package/dist/lib/parser.d.ts +1 -1
- package/dist/lib/parser.js +67 -8
- package/dist/lib/parser.test.js +12 -3
- package/dist/lib/parsers/chainNewlineBoundary.test.d.ts +1 -0
- package/dist/lib/parsers/chainNewlineBoundary.test.js +121 -0
- package/dist/lib/parsers/codeLiteral.test.d.ts +1 -0
- package/dist/lib/parsers/codeLiteral.test.js +241 -0
- package/dist/lib/parsers/comprehension.test.d.ts +1 -0
- package/dist/lib/parsers/comprehension.test.js +325 -0
- package/dist/lib/parsers/destructiveBlock.test.d.ts +1 -0
- package/dist/lib/parsers/destructiveBlock.test.js +36 -0
- package/dist/lib/parsers/finalizeBinder.test.d.ts +1 -0
- package/dist/lib/parsers/finalizeBinder.test.js +59 -0
- package/dist/lib/parsers/finalizeBlock.test.d.ts +1 -0
- package/dist/lib/parsers/finalizeBlock.test.js +37 -0
- package/dist/lib/parsers/guardBlock.test.d.ts +1 -0
- package/dist/lib/parsers/guardBlock.test.js +81 -0
- package/dist/lib/parsers/hashRemoved.test.d.ts +1 -0
- package/dist/lib/parsers/hashRemoved.test.js +11 -0
- package/dist/lib/parsers/hole.test.d.ts +1 -0
- package/dist/lib/parsers/hole.test.js +171 -0
- package/dist/lib/parsers/literalDelimiter.test.d.ts +1 -0
- package/dist/lib/parsers/literalDelimiter.test.js +60 -0
- package/dist/lib/parsers/matchBlock.test.js +100 -0
- package/dist/lib/parsers/objectTypeTags.test.js +0 -13
- package/dist/lib/parsers/parsers.d.ts +108 -6
- package/dist/lib/parsers/parsers.js +829 -55
- package/dist/lib/parsers/pattern.test.js +235 -4
- package/dist/lib/parsers/splice.test.d.ts +1 -0
- package/dist/lib/parsers/splice.test.js +81 -0
- package/dist/lib/parsers/typeHints.test.js +1 -300
- package/dist/lib/perf/compile.perf.test.d.ts +1 -0
- package/dist/lib/perf/compile.perf.test.js +76 -0
- package/dist/lib/perf/doc.perf.test.d.ts +1 -0
- package/dist/lib/perf/doc.perf.test.js +30 -0
- package/dist/lib/perf/fixtures.d.ts +25 -0
- package/dist/lib/perf/fixtures.js +100 -0
- package/dist/lib/perf/fixtures.test.d.ts +1 -0
- package/dist/lib/perf/fixtures.test.js +37 -0
- package/dist/lib/perf/fmt.perf.test.d.ts +1 -0
- package/dist/lib/perf/fmt.perf.test.js +16 -0
- package/dist/lib/perf/harness.d.ts +31 -0
- package/dist/lib/perf/harness.js +114 -0
- package/dist/lib/perf/harness.perf.test.d.ts +1 -0
- package/dist/lib/perf/harness.perf.test.js +45 -0
- package/dist/lib/perf/harness.test.d.ts +1 -0
- package/dist/lib/perf/harness.test.js +79 -0
- package/dist/lib/perf/lint.perf.test.d.ts +1 -0
- package/dist/lib/perf/lint.perf.test.js +76 -0
- package/dist/lib/perf/lsp.perf.test.d.ts +1 -0
- package/dist/lib/perf/lsp.perf.test.js +60 -0
- package/dist/lib/perf/parse.perf.test.d.ts +1 -0
- package/dist/lib/perf/parse.perf.test.js +20 -0
- package/dist/lib/perf/symbolTable.perf.test.d.ts +1 -0
- package/dist/lib/perf/symbolTable.perf.test.js +63 -0
- package/dist/lib/perf/typecheck.perf.test.d.ts +1 -0
- package/dist/lib/perf/typecheck.perf.test.js +35 -0
- package/dist/lib/prelude.d.ts +27 -0
- package/dist/lib/prelude.js +62 -0
- package/dist/lib/prelude.test.d.ts +1 -0
- package/dist/lib/prelude.test.js +41 -0
- package/dist/lib/preprocessors/expandSplices.d.ts +14 -0
- package/dist/lib/preprocessors/expandSplices.js +451 -0
- package/dist/lib/preprocessors/expandSplices.test.d.ts +1 -0
- package/dist/lib/preprocessors/expandSplices.test.js +287 -0
- package/dist/lib/preprocessors/guardDesugar.d.ts +37 -0
- package/dist/lib/preprocessors/guardDesugar.js +98 -0
- package/dist/lib/preprocessors/guardDesugar.test.d.ts +1 -0
- package/dist/lib/preprocessors/guardDesugar.test.js +158 -0
- package/dist/lib/preprocessors/hoistCalls.d.ts +83 -0
- package/dist/lib/preprocessors/hoistCalls.js +354 -0
- package/dist/lib/preprocessors/hoistCalls.test.d.ts +1 -0
- package/dist/lib/preprocessors/hoistCalls.test.js +385 -0
- package/dist/lib/preprocessors/importResolver.d.ts +13 -0
- package/dist/lib/preprocessors/importResolver.js +188 -102
- package/dist/lib/preprocessors/importResolver.test.js +115 -0
- package/dist/lib/preprocessors/liftCallbacks.js +8 -3
- package/dist/lib/preprocessors/liftCallbacks.test.js +1 -1
- package/dist/lib/preprocessors/parallelDesugar.js +17 -1
- package/dist/lib/preprocessors/parallelDesugar.test.js +24 -0
- package/dist/lib/preprocessors/prunePreludeShadows.d.ts +0 -20
- package/dist/lib/preprocessors/prunePreludeShadows.js +18 -3
- package/dist/lib/preprocessors/typescriptPreprocessor.js +37 -7
- package/dist/lib/runtime/__tests__/testHelpers.js +2 -1
- package/dist/lib/runtime/abortedResult.d.ts +100 -0
- package/dist/lib/runtime/abortedResult.js +217 -0
- package/dist/lib/runtime/abortedResult.test.d.ts +1 -0
- package/dist/lib/runtime/abortedResult.test.js +295 -0
- package/dist/lib/runtime/agency.test.js +9 -0
- package/dist/lib/runtime/agencyFunction.d.ts +8 -0
- package/dist/lib/runtime/agencyFunction.js +32 -2
- package/dist/lib/runtime/agencyFunction.test.js +39 -0
- package/dist/lib/runtime/agencyInterrupt.js +1 -0
- package/dist/lib/runtime/agencyInterrupt.test.js +79 -53
- package/dist/lib/runtime/asyncContext.d.ts +2 -26
- package/dist/lib/runtime/asyncContext.js +12 -14
- package/dist/lib/runtime/asyncContext.test.js +1 -25
- package/dist/lib/runtime/blockNames.d.ts +28 -0
- package/dist/lib/runtime/blockNames.js +40 -0
- package/dist/lib/runtime/blockNames.test.d.ts +1 -0
- package/dist/lib/runtime/blockNames.test.js +32 -0
- package/dist/lib/runtime/budgetExit.d.ts +20 -0
- package/dist/lib/runtime/budgetExit.js +35 -0
- package/dist/lib/runtime/budgetExit.test.d.ts +1 -0
- package/dist/lib/runtime/budgetExit.test.js +59 -0
- package/dist/lib/runtime/call.js +77 -0
- package/dist/lib/runtime/clock.d.ts +48 -0
- package/dist/lib/runtime/clock.js +71 -0
- package/dist/lib/runtime/clock.test.d.ts +1 -0
- package/dist/lib/runtime/clock.test.js +118 -0
- package/dist/lib/runtime/configOverrides.test.js +1 -1
- package/dist/lib/runtime/crossModuleInitRegistry.d.ts +24 -0
- package/dist/lib/runtime/crossModuleInitRegistry.js +32 -0
- package/dist/lib/runtime/crossModuleInitRegistry.test.d.ts +1 -0
- package/dist/lib/runtime/crossModuleInitRegistry.test.js +31 -0
- package/dist/lib/runtime/deterministicClient.d.ts +9 -1
- package/dist/lib/runtime/deterministicClient.js +23 -1
- package/dist/lib/runtime/effectMerge.d.ts +31 -0
- package/dist/lib/runtime/effectMerge.js +93 -0
- package/dist/lib/runtime/effectMerge.test.d.ts +1 -0
- package/dist/lib/runtime/effectMerge.test.js +92 -0
- package/dist/lib/runtime/errors.d.ts +8 -0
- package/dist/lib/runtime/errors.js +10 -0
- package/dist/lib/runtime/executingHandlers.d.ts +7 -0
- package/dist/lib/runtime/executingHandlers.js +47 -0
- package/dist/lib/runtime/executingHandlers.test.d.ts +1 -0
- package/dist/lib/runtime/executingHandlers.test.js +51 -0
- package/dist/lib/runtime/guard.clock.test.d.ts +1 -0
- package/dist/lib/runtime/guard.clock.test.js +78 -0
- package/dist/lib/runtime/guard.d.ts +268 -35
- package/dist/lib/runtime/guard.js +386 -62
- package/dist/lib/runtime/guard.test.js +235 -23
- package/dist/lib/runtime/guardScope.d.ts +74 -0
- package/dist/lib/runtime/guardScope.js +140 -0
- package/dist/lib/runtime/guardScope.test.d.ts +1 -0
- package/dist/lib/runtime/guardScope.test.js +228 -0
- package/dist/lib/runtime/guardTripInterrupt.d.ts +61 -0
- package/dist/lib/runtime/guardTripInterrupt.inHandler.test.d.ts +1 -0
- package/dist/lib/runtime/guardTripInterrupt.inHandler.test.js +47 -0
- package/dist/lib/runtime/guardTripInterrupt.js +295 -0
- package/dist/lib/runtime/index.d.ts +8 -3
- package/dist/lib/runtime/index.js +8 -3
- package/dist/lib/runtime/interrupts.d.ts +14 -10
- package/dist/lib/runtime/interrupts.executingHandlers.test.d.ts +1 -0
- package/dist/lib/runtime/interrupts.executingHandlers.test.js +112 -0
- package/dist/lib/runtime/interrupts.js +162 -32
- package/dist/lib/runtime/interrupts.test.js +64 -16
- package/dist/lib/runtime/intrinsicToolSchema.test.d.ts +1 -0
- package/dist/lib/runtime/intrinsicToolSchema.test.js +188 -0
- package/dist/lib/runtime/intrinsicTools.d.ts +91 -0
- package/dist/lib/runtime/intrinsicTools.js +82 -0
- package/dist/lib/runtime/ipc.js +8 -2
- package/dist/lib/runtime/jsonValue.d.ts +15 -0
- package/dist/lib/runtime/jsonValue.js +66 -0
- package/dist/lib/runtime/jsonValue.test.d.ts +1 -0
- package/dist/lib/runtime/jsonValue.test.js +52 -0
- package/dist/lib/runtime/memory/cacheEntry.d.ts +10 -0
- package/dist/lib/runtime/memory/cacheEntry.js +10 -0
- package/dist/lib/runtime/memory/compaction.d.ts +8 -3
- package/dist/lib/runtime/memory/compaction.js +10 -4
- package/dist/lib/runtime/memory/compaction.test.js +32 -18
- package/dist/lib/runtime/memory/manager.js +23 -5
- package/dist/lib/runtime/memory/manager.test.js +91 -0
- package/dist/lib/runtime/node.d.ts +2 -6
- package/dist/lib/runtime/node.js +23 -21
- package/dist/lib/runtime/prompt.d.ts +18 -0
- package/dist/lib/runtime/prompt.js +428 -238
- package/dist/lib/runtime/promptLabels.test.d.ts +1 -0
- package/dist/lib/runtime/promptLabels.test.js +159 -0
- package/dist/lib/runtime/promptRunner.d.ts +7 -2
- package/dist/lib/runtime/promptRunner.js +1 -0
- package/dist/lib/runtime/promptRunner.test.js +3 -3
- package/dist/lib/runtime/requireLength.d.ts +15 -0
- package/dist/lib/runtime/requireLength.js +21 -0
- package/dist/lib/runtime/result.d.ts +6 -4
- package/dist/lib/runtime/result.js +37 -2
- package/dist/lib/runtime/result.test.js +58 -0
- package/dist/lib/runtime/resumableScope.js +4 -4
- package/dist/lib/runtime/revivers/functionRefReviver.d.ts +7 -1
- package/dist/lib/runtime/revivers/functionRefReviver.js +192 -15
- package/dist/lib/runtime/revivers/functionRefReviver.test.js +268 -3
- package/dist/lib/runtime/rewind.d.ts +0 -2
- package/dist/lib/runtime/rewind.js +3 -4
- package/dist/lib/runtime/rootBudget.d.ts +13 -0
- package/dist/lib/runtime/rootBudget.js +52 -0
- package/dist/lib/runtime/rootBudget.test.d.ts +1 -0
- package/dist/lib/runtime/rootBudget.test.js +70 -0
- package/dist/lib/runtime/runBatch.js +191 -14
- package/dist/lib/runtime/runBatch.test.js +30 -1
- package/dist/lib/runtime/runPolicyHandler.d.ts +1 -1
- package/dist/lib/runtime/runPolicyHandler.js +5 -1
- package/dist/lib/runtime/runner.d.ts +9 -0
- package/dist/lib/runtime/runner.js +110 -21
- package/dist/lib/runtime/runner.test.js +99 -3
- package/dist/lib/runtime/saveDraftTool.d.ts +15 -0
- package/dist/lib/runtime/saveDraftTool.js +72 -0
- package/dist/lib/runtime/saveDraftTool.test.d.ts +1 -0
- package/dist/lib/runtime/saveDraftTool.test.js +123 -0
- package/dist/lib/runtime/state/checkpointStore.test.js +1 -0
- package/dist/lib/runtime/state/context.clock.test.d.ts +1 -0
- package/dist/lib/runtime/state/context.clock.test.js +47 -0
- package/dist/lib/runtime/state/context.d.ts +36 -3
- package/dist/lib/runtime/state/context.js +47 -3
- package/dist/lib/runtime/state/globalStore.js +7 -0
- package/dist/lib/runtime/state/messageThread.d.ts +104 -2
- package/dist/lib/runtime/state/messageThread.js +183 -5
- package/dist/lib/runtime/state/messageThread.test.js +240 -0
- package/dist/lib/runtime/state/pendingPromiseStore.d.ts +10 -1
- package/dist/lib/runtime/state/pendingPromiseStore.js +22 -1
- package/dist/lib/runtime/state/pendingPromiseStore.test.js +41 -0
- package/dist/lib/runtime/state/schemas.d.ts +3 -0
- package/dist/lib/runtime/state/schemas.js +3 -0
- package/dist/lib/runtime/state/stateStack.d.ts +234 -6
- package/dist/lib/runtime/state/stateStack.executingHandlers.test.d.ts +1 -0
- package/dist/lib/runtime/state/stateStack.executingHandlers.test.js +42 -0
- package/dist/lib/runtime/state/stateStack.js +390 -11
- package/dist/lib/runtime/state/stateStack.test.js +75 -1
- package/dist/lib/runtime/state/stateStack.tripwire.test.d.ts +1 -0
- package/dist/lib/runtime/state/stateStack.tripwire.test.js +47 -0
- package/dist/lib/runtime/template/code.d.ts +19 -0
- package/dist/lib/runtime/template/code.js +12 -0
- package/dist/lib/runtime/template/codeLiteral.d.ts +10 -0
- package/dist/lib/runtime/template/codeLiteral.js +40 -0
- package/dist/lib/runtime/template/combine.test.d.ts +1 -0
- package/dist/lib/runtime/template/combine.test.js +97 -0
- package/dist/lib/runtime/template/escaping.test.d.ts +1 -0
- package/dist/lib/runtime/template/escaping.test.js +107 -0
- package/dist/lib/runtime/template/fill.d.ts +19 -0
- package/dist/lib/runtime/template/fill.js +247 -0
- package/dist/lib/runtime/template/fill.test.d.ts +1 -0
- package/dist/lib/runtime/template/fill.test.js +318 -0
- package/dist/lib/runtime/template/hygiene.d.ts +89 -0
- package/dist/lib/runtime/template/hygiene.js +426 -0
- package/dist/lib/runtime/template/hygiene.test.d.ts +1 -0
- package/dist/lib/runtime/template/hygiene.test.js +253 -0
- package/dist/lib/runtime/template/lift.d.ts +10 -0
- package/dist/lib/runtime/template/lift.js +47 -0
- package/dist/lib/runtime/template/literals.d.ts +17 -0
- package/dist/lib/runtime/template/literals.js +44 -0
- package/dist/lib/runtime/template/origin.d.ts +30 -0
- package/dist/lib/runtime/template/origin.js +47 -0
- package/dist/lib/runtime/threadRepair.d.ts +76 -5
- package/dist/lib/runtime/threadRepair.js +153 -31
- package/dist/lib/runtime/threadRepair.test.js +177 -3
- package/dist/lib/runtime/toolMessageProvider.test.d.ts +1 -0
- package/dist/lib/runtime/toolMessageProvider.test.js +69 -0
- package/dist/lib/runtime/trace/eventLog.d.ts +1 -0
- package/dist/lib/runtime/trace/eventLog.js +2 -0
- package/dist/lib/runtime/trace/eventLog.test.js +29 -25
- package/dist/lib/runtime/trace/traceReader.test.js +4 -3
- package/dist/lib/runtime/trace/traceWriter.test.js +2 -2
- package/dist/lib/runtime/turnBoundary.d.ts +81 -0
- package/dist/lib/runtime/turnBoundary.js +89 -0
- package/dist/lib/runtime/turnBoundary.test.d.ts +1 -0
- package/dist/lib/runtime/turnBoundary.test.js +191 -0
- package/dist/lib/runtime/typeTest.d.ts +5 -0
- package/dist/lib/runtime/typeTest.js +21 -0
- package/dist/lib/runtime/typeTest.test.d.ts +1 -0
- package/dist/lib/runtime/typeTest.test.js +43 -0
- package/dist/lib/runtime/types.d.ts +19 -1
- package/dist/lib/runtime/utils.d.ts +7 -0
- package/dist/lib/runtime/utils.js +102 -16
- package/dist/lib/runtime/utils.test.js +224 -7
- package/dist/lib/runtime/validateChain.d.ts +12 -0
- package/dist/lib/runtime/validateChain.js +24 -0
- package/dist/lib/runtime/validateChain.test.js +78 -0
- package/dist/lib/serve/createServeHandler.d.ts +34 -0
- package/dist/lib/serve/createServeHandler.js +43 -0
- package/dist/lib/serve/createServeHandler.test.d.ts +1 -0
- package/dist/lib/serve/createServeHandler.test.js +115 -0
- package/dist/lib/serve/http/adapter.d.ts +8 -7
- package/dist/lib/serve/http/adapter.js +6 -2
- package/dist/lib/serve/http/adapter.test.js +7 -3
- package/dist/lib/serve/http/functionFrame.integration.test.js +0 -1
- package/dist/lib/serve/metadata.d.ts +22 -0
- package/dist/lib/serve/metadata.js +33 -0
- package/dist/lib/serve/metadata.test.d.ts +1 -0
- package/dist/lib/serve/metadata.test.js +46 -0
- package/dist/lib/serve/public.d.ts +8 -0
- package/dist/lib/serve/public.js +4 -0
- package/dist/lib/serve/public.test.d.ts +1 -0
- package/dist/lib/serve/public.test.js +16 -0
- package/dist/lib/sourceIsText.test.d.ts +1 -0
- package/dist/lib/sourceIsText.test.js +40 -0
- package/dist/lib/statelogClient.d.ts +38 -4
- package/dist/lib/statelogClient.js +34 -1
- package/dist/lib/stdlib/abortable.js +34 -0
- package/dist/lib/stdlib/agency.d.ts +27 -0
- package/dist/lib/stdlib/agency.js +207 -2
- package/dist/lib/stdlib/appleNotes.d.ts +111 -0
- package/dist/lib/stdlib/appleNotes.js +314 -0
- package/dist/lib/stdlib/assertContained.js +3 -4
- package/dist/lib/stdlib/builtins.d.ts +27 -0
- package/dist/lib/stdlib/builtins.js +89 -9
- package/dist/lib/stdlib/cli.d.ts +149 -0
- package/dist/lib/stdlib/cli.js +488 -84
- package/dist/lib/stdlib/date.d.ts +15 -12
- package/dist/lib/stdlib/date.js +131 -122
- package/dist/lib/stdlib/expandPath.d.ts +5 -3
- package/dist/lib/stdlib/expandPath.js +5 -3
- package/dist/lib/stdlib/fs.js +7 -7
- package/dist/lib/stdlib/git.d.ts +4 -0
- package/dist/lib/stdlib/git.js +24 -1
- package/dist/lib/stdlib/http.js +8 -0
- package/dist/lib/stdlib/imessage.js +24 -23
- package/dist/lib/stdlib/jsonValue.d.ts +5 -0
- package/dist/lib/stdlib/jsonValue.js +12 -0
- package/dist/lib/stdlib/layout/table.js +22 -4
- package/dist/lib/stdlib/markdown.d.ts +8 -0
- package/dist/lib/stdlib/markdown.js +238 -0
- package/dist/lib/stdlib/memory.d.ts +2 -2
- package/dist/lib/stdlib/memory.js +2 -2
- package/dist/lib/stdlib/policy.js +1 -1
- package/dist/lib/stdlib/resolveDir.d.ts +9 -8
- package/dist/lib/stdlib/resolveDir.js +13 -13
- package/dist/lib/stdlib/resolvePath.d.ts +8 -16
- package/dist/lib/stdlib/resolvePath.js +10 -52
- package/dist/lib/stdlib/safeBash.d.ts +1 -0
- package/dist/lib/stdlib/safeBash.js +1 -0
- package/dist/lib/stdlib/shell.js +15 -14
- package/dist/lib/stdlib/skills.d.ts +22 -16
- package/dist/lib/stdlib/skills.js +32 -20
- package/dist/lib/stdlib/speech.js +3 -3
- package/dist/lib/stdlib/statelog.js +1 -1
- package/dist/lib/stdlib/system.d.ts +0 -8
- package/dist/lib/stdlib/system.js +2 -12
- package/dist/lib/stdlib/template.d.ts +32 -0
- package/dist/lib/stdlib/template.js +81 -0
- package/dist/lib/stdlib/thread.d.ts +28 -7
- package/dist/lib/stdlib/thread.js +122 -27
- package/dist/lib/stdlib/wikipedia.js +17 -3
- package/dist/lib/symbolTable.d.ts +27 -1
- package/dist/lib/symbolTable.importModule.test.d.ts +1 -0
- package/dist/lib/symbolTable.importModule.test.js +54 -0
- package/dist/lib/symbolTable.js +123 -16
- package/dist/lib/symbolTable.test.js +68 -8
- package/dist/lib/templates/applescript/notes/accountWalk.d.ts +4 -0
- package/dist/lib/templates/applescript/notes/accountWalk.js +18 -0
- package/dist/lib/templates/applescript/notes/appendBody.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/appendBody.js +15 -0
- package/dist/lib/templates/applescript/notes/appendScoped.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/appendScoped.js +12 -0
- package/dist/lib/templates/applescript/notes/appendUnscoped.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/appendUnscoped.js +12 -0
- package/dist/lib/templates/applescript/notes/create.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/create.js +20 -0
- package/dist/lib/templates/applescript/notes/deleteScoped.d.ts +4 -0
- package/dist/lib/templates/applescript/notes/deleteScoped.js +13 -0
- package/dist/lib/templates/applescript/notes/deleteUnscoped.d.ts +4 -0
- package/dist/lib/templates/applescript/notes/deleteUnscoped.js +13 -0
- package/dist/lib/templates/applescript/notes/folderExists.d.ts +4 -0
- package/dist/lib/templates/applescript/notes/folderExists.js +11 -0
- package/dist/lib/templates/applescript/notes/listAll.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/listAll.js +16 -0
- package/dist/lib/templates/applescript/notes/listFolders.d.ts +4 -0
- package/dist/lib/templates/applescript/notes/listFolders.js +20 -0
- package/dist/lib/templates/applescript/notes/listInFolder.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/listInFolder.js +16 -0
- package/dist/lib/templates/applescript/notes/noteRow.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/noteRow.js +13 -0
- package/dist/lib/templates/applescript/notes/preflight.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/preflight.js +16 -0
- package/dist/lib/templates/applescript/notes/readScoped.d.ts +4 -0
- package/dist/lib/templates/applescript/notes/readScoped.js +13 -0
- package/dist/lib/templates/applescript/notes/readUnscoped.d.ts +4 -0
- package/dist/lib/templates/applescript/notes/readUnscoped.js +13 -0
- package/dist/lib/templates/applescript/notes/searchAll.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/searchAll.js +16 -0
- package/dist/lib/templates/applescript/notes/searchInFolder.d.ts +6 -0
- package/dist/lib/templates/applescript/notes/searchInFolder.js +16 -0
- package/dist/lib/templates/applescript/notes/withTimeout.d.ts +7 -0
- package/dist/lib/templates/applescript/notes/withTimeout.js +13 -0
- package/dist/lib/templates/backends/agency/template.d.ts +2 -1
- package/dist/lib/templates/backends/agency/template.js +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/blockSetup.d.ts +4 -2
- package/dist/lib/templates/backends/typescriptGenerator/blockSetup.js +13 -1
- package/dist/lib/templates/backends/typescriptGenerator/finalizeClosure.d.ts +10 -0
- package/dist/lib/templates/backends/typescriptGenerator/finalizeClosure.js +14 -0
- package/dist/lib/templates/backends/typescriptGenerator/forkBlockSetup.d.ts +2 -2
- package/dist/lib/templates/backends/typescriptGenerator/forkBlockSetup.js +3 -0
- package/dist/lib/templates/backends/typescriptGenerator/functionCatchFailure.d.ts +2 -1
- package/dist/lib/templates/backends/typescriptGenerator/functionCatchFailure.js +6 -1
- package/dist/lib/templates/backends/typescriptGenerator/imports.d.ts +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/imports.js +12 -10
- package/dist/lib/templates/backends/typescriptGenerator/withHandlerWrapper.d.ts +9 -0
- package/dist/lib/templates/backends/typescriptGenerator/withHandlerWrapper.js +14 -0
- package/dist/lib/templates/runtime/guardTripMessage.d.ts +9 -0
- package/dist/lib/templates/runtime/guardTripMessage.js +9 -0
- package/dist/lib/typeChecker/anySentinelRetired.test.d.ts +1 -0
- package/dist/lib/typeChecker/anySentinelRetired.test.js +53 -0
- package/dist/lib/typeChecker/assignability.d.ts +3 -3
- package/dist/lib/typeChecker/assignability.js +84 -14
- package/dist/lib/typeChecker/assignability.test.js +14 -1
- package/dist/lib/typeChecker/builtinGenerics.js +13 -6
- package/dist/lib/typeChecker/builtinGenerics.test.js +13 -1
- package/dist/lib/typeChecker/builtinVariables.test.d.ts +1 -0
- package/dist/lib/typeChecker/builtinVariables.test.js +53 -0
- package/dist/lib/typeChecker/builtins.d.ts +6 -0
- package/dist/lib/typeChecker/builtins.js +43 -24
- package/dist/lib/typeChecker/callbackCallEffects.test.js +4 -15
- package/dist/lib/typeChecker/checker.d.ts +1 -1
- package/dist/lib/typeChecker/checker.js +91 -28
- package/dist/lib/typeChecker/codeLiteral.test.d.ts +1 -0
- package/dist/lib/typeChecker/codeLiteral.test.js +160 -0
- package/dist/lib/typeChecker/conflictingMarkers.js +2 -1
- package/dist/lib/typeChecker/crossModuleEffectDiagnostics.test.d.ts +1 -0
- package/dist/lib/typeChecker/crossModuleEffectDiagnostics.test.js +80 -0
- package/dist/lib/typeChecker/definiteReturns.js +7 -0
- package/dist/lib/typeChecker/diagnosticExplanations.js +138 -2
- package/dist/lib/typeChecker/diagnostics.d.ts +141 -1
- package/dist/lib/typeChecker/diagnostics.js +138 -1
- package/dist/lib/typeChecker/effectPayloadCheck.js +2 -1
- package/dist/lib/typeChecker/effectSets.js +2 -1
- package/dist/lib/typeChecker/finalize.test.d.ts +1 -0
- package/dist/lib/typeChecker/finalize.test.js +312 -0
- package/dist/lib/typeChecker/finalizeBinder.d.ts +21 -0
- package/dist/lib/typeChecker/finalizeBinder.js +70 -0
- package/dist/lib/typeChecker/finalizeBinder.test.d.ts +1 -0
- package/dist/lib/typeChecker/finalizeBinder.test.js +132 -0
- package/dist/lib/typeChecker/finalizeChecks.d.ts +16 -0
- package/dist/lib/typeChecker/finalizeChecks.js +161 -0
- package/dist/lib/typeChecker/fixtureTypeCheck.integration.test.js +3 -0
- package/dist/lib/typeChecker/flow.js +14 -12
- package/dist/lib/typeChecker/flow.test.js +12 -11
- package/dist/lib/typeChecker/flowBuilder.js +34 -2
- package/dist/lib/typeChecker/forkRaceReturnTypes.test.d.ts +1 -0
- package/dist/lib/typeChecker/forkRaceReturnTypes.test.js +260 -0
- package/dist/lib/typeChecker/functionTypeRaises.js +2 -1
- package/dist/lib/typeChecker/functionValueEffects.js +2 -1
- package/dist/lib/typeChecker/guardConstruct.test.d.ts +1 -0
- package/dist/lib/typeChecker/guardConstruct.test.js +143 -0
- package/dist/lib/typeChecker/handlerParamTyping.d.ts +1 -1
- package/dist/lib/typeChecker/handlerParamTyping.js +1 -1
- package/dist/lib/typeChecker/holes.test.d.ts +1 -0
- package/dist/lib/typeChecker/holes.test.js +75 -0
- package/dist/lib/typeChecker/index.d.ts +1 -1
- package/dist/lib/typeChecker/index.js +64 -12
- package/dist/lib/typeChecker/inference.d.ts +1 -1
- package/dist/lib/typeChecker/inference.js +13 -15
- package/dist/lib/typeChecker/interruptAnalysis.d.ts +0 -17
- package/dist/lib/typeChecker/interruptAnalysis.js +47 -122
- package/dist/lib/typeChecker/matchExhaustiveness.js +64 -2
- package/dist/lib/typeChecker/matchExhaustiveness.test.js +71 -0
- package/dist/lib/typeChecker/matchExprTypes.js +7 -8
- package/dist/lib/typeChecker/missingImportDiagnostic.d.ts +12 -0
- package/dist/lib/typeChecker/missingImportDiagnostic.js +69 -0
- package/dist/lib/typeChecker/missingImportDiagnostic.test.d.ts +1 -0
- package/dist/lib/typeChecker/missingImportDiagnostic.test.js +183 -0
- package/dist/lib/typeChecker/narrowing.d.ts +3 -0
- package/dist/lib/typeChecker/narrowing.js +25 -2
- package/dist/lib/typeChecker/raisesDiagnostic.d.ts +2 -2
- package/dist/lib/typeChecker/raisesDiagnostic.js +2 -2
- package/dist/lib/typeChecker/reservedNameDeclaration.test.js +21 -1
- package/dist/lib/typeChecker/resolveCall.js +26 -21
- package/dist/lib/typeChecker/resolveType.test.js +92 -1
- package/dist/lib/typeChecker/resolveVariable.d.ts +4 -2
- package/dist/lib/typeChecker/resolveVariable.js +7 -2
- package/dist/lib/typeChecker/saveDraft.test.d.ts +1 -0
- package/dist/lib/typeChecker/saveDraft.test.js +139 -0
- package/dist/lib/typeChecker/scope.d.ts +5 -1
- package/dist/lib/typeChecker/scope.js +6 -0
- package/dist/lib/typeChecker/scope.test.js +9 -8
- package/dist/lib/typeChecker/scopes.js +51 -14
- package/dist/lib/typeChecker/spliceDiagnostics.test.d.ts +1 -0
- package/dist/lib/typeChecker/spliceDiagnostics.test.js +67 -0
- package/dist/lib/typeChecker/strictMemberAccess.test.js +62 -0
- package/dist/lib/typeChecker/synthesizer.d.ts +5 -2
- package/dist/lib/typeChecker/synthesizer.js +293 -72
- package/dist/lib/typeChecker/templateHoles.d.ts +17 -0
- package/dist/lib/typeChecker/templateHoles.js +30 -0
- package/dist/lib/typeChecker/testUtils.d.ts +2 -1
- package/dist/lib/typeChecker/testUtils.js +3 -3
- package/dist/lib/typeChecker/toolArgArrayType.test.d.ts +1 -0
- package/dist/lib/typeChecker/toolArgArrayType.test.js +128 -0
- package/dist/lib/typeChecker/typeCases.d.ts +1 -1
- package/dist/lib/typeChecker/typeCases.js +3 -2
- package/dist/lib/typeChecker/typeCases.test.js +2 -1
- package/dist/lib/typeChecker/typePatterns.test.d.ts +1 -0
- package/dist/lib/typeChecker/typePatterns.test.js +238 -0
- package/dist/lib/typeChecker/types.d.ts +10 -10
- package/dist/lib/typeChecker/undefinedFunctionDiagnostic.js +4 -0
- package/dist/lib/typeChecker/undefinedFunctionDiagnostic.test.js +43 -0
- package/dist/lib/typeChecker/utils.d.ts +7 -2
- package/dist/lib/typeChecker/utils.js +6 -4
- package/dist/lib/types/base.d.ts +8 -0
- package/dist/lib/types/blockArgument.d.ts +8 -1
- package/dist/lib/types/codeLiteral.d.ts +13 -0
- package/dist/lib/types/codeLiteral.js +1 -0
- package/dist/lib/types/comprehension.d.ts +55 -0
- package/dist/lib/types/comprehension.js +32 -0
- package/dist/lib/types/finalizeBlock.d.ts +19 -0
- package/dist/lib/types/finalizeBlock.js +1 -0
- package/dist/lib/types/function.d.ts +15 -1
- package/dist/lib/types/graphNode.d.ts +4 -1
- package/dist/lib/types/guardBlock.d.ts +25 -0
- package/dist/lib/types/guardBlock.js +1 -0
- package/dist/lib/types/hole.d.ts +26 -0
- package/dist/lib/types/hole.js +18 -0
- package/dist/lib/types/importStatement.d.ts +4 -1
- package/dist/lib/types/importStatement.js +9 -2
- package/dist/lib/types/markDestructiveRan.d.ts +8 -0
- package/dist/lib/types/markDestructiveRan.js +1 -0
- package/dist/lib/types/parallelBlock.d.ts +5 -0
- package/dist/lib/types/pattern.d.ts +14 -4
- package/dist/lib/types/splice.d.ts +20 -0
- package/dist/lib/types/splice.js +1 -0
- package/dist/lib/types/typeHints.d.ts +11 -0
- package/dist/lib/types.d.ts +21 -3
- package/dist/lib/types.js +12 -0
- package/dist/lib/utils/agencyTempDir.d.ts +19 -0
- package/dist/lib/utils/agencyTempDir.js +26 -0
- package/dist/lib/utils/bodySlots.d.ts +17 -1
- package/dist/lib/utils/bodySlots.js +58 -2
- package/dist/lib/utils/bodySlots.test.d.ts +1 -0
- package/dist/lib/utils/bodySlots.test.js +33 -0
- package/dist/lib/utils/docStringText.d.ts +7 -0
- package/dist/lib/utils/docStringText.js +7 -0
- package/dist/lib/utils/expressionSlots.d.ts +91 -0
- package/dist/lib/utils/expressionSlots.js +322 -0
- package/dist/lib/utils/expressionSlots.test.d.ts +1 -0
- package/dist/lib/utils/expressionSlots.test.js +505 -0
- package/dist/lib/utils/holes.d.ts +41 -0
- package/dist/lib/utils/holes.js +68 -0
- package/dist/lib/utils/identifierSlots.d.ts +71 -0
- package/dist/lib/utils/identifierSlots.js +173 -0
- package/dist/lib/utils/identifierSlots.test.d.ts +1 -0
- package/dist/lib/utils/identifierSlots.test.js +148 -0
- package/dist/lib/utils/iteration.d.ts +37 -0
- package/dist/lib/utils/iteration.js +9 -0
- package/dist/lib/utils/iteration.test.d.ts +1 -0
- package/dist/lib/utils/iteration.test.js +26 -0
- package/dist/lib/utils/moduleDoc.d.ts +18 -0
- package/dist/lib/utils/moduleDoc.js +56 -0
- package/dist/lib/utils/node.js +104 -87
- package/dist/scripts/agency.js +147 -24
- package/dist/scripts/agency.test.js +30 -1
- package/package.json +11 -3
- package/stdlib/agency/eval.js +70 -19
- package/stdlib/agency/local.agency +1 -0
- package/stdlib/agency/local.js +68 -22
- package/stdlib/agency.agency +154 -298
- package/stdlib/agency.js +751 -1375
- package/stdlib/agent.agency +2 -296
- package/stdlib/agent.js +30 -1167
- package/stdlib/agents/agency/coding.agency +313 -0
- package/stdlib/agents/agency/coding.js +2345 -0
- package/stdlib/agents/agency/expert.agency +98 -0
- package/stdlib/agents/agency/expert.js +967 -0
- package/stdlib/agents/agency/researcher.agency +109 -0
- package/stdlib/agents/agency/researcher.js +976 -0
- package/stdlib/agents/agency/review.agency +143 -0
- package/stdlib/agents/agency/review.js +1602 -0
- package/stdlib/agents/agency/verifier.agency +131 -0
- package/stdlib/agents/agency/verifier.js +1241 -0
- package/stdlib/agents/coding.agency +148 -0
- package/stdlib/agents/coding.js +1099 -0
- package/stdlib/agents/data.agency +150 -0
- package/stdlib/agents/data.js +1017 -0
- package/stdlib/agents/expert.agency +111 -0
- package/stdlib/agents/expert.js +970 -0
- package/stdlib/agents/explorer.agency +199 -0
- package/stdlib/agents/explorer.js +1098 -0
- package/stdlib/agents/lib/expertGuidance.agency +40 -0
- package/stdlib/agents/lib/expertGuidance.js +644 -0
- package/stdlib/agents/lib/feedback.agency +89 -0
- package/stdlib/agents/lib/feedback.js +1216 -0
- package/stdlib/agents/lib/search.agency +65 -0
- package/stdlib/agents/lib/search.js +794 -0
- package/stdlib/agents/lib/shared.agency +59 -0
- package/stdlib/agents/lib/shared.js +606 -0
- package/stdlib/agents/lib/toolkits.agency +198 -0
- package/stdlib/agents/lib/toolkits.js +1720 -0
- package/stdlib/agents/oracle.agency +172 -0
- package/stdlib/agents/oracle.js +1081 -0
- package/stdlib/agents/planner.agency +284 -0
- package/stdlib/agents/planner.js +3103 -0
- package/stdlib/agents/researcher.agency +169 -0
- package/stdlib/agents/researcher.js +1380 -0
- package/stdlib/agents/review.agency +117 -0
- package/stdlib/agents/review.js +1040 -0
- package/stdlib/agents/skills/coding/gh-auth.md +65 -0
- package/stdlib/agents/skills/coding/gh-pr-and-issues.md +150 -0
- package/stdlib/agents/skills/coding/gh-repos-and-releases.md +87 -0
- package/stdlib/agents/skills/data/finding-identifiers.md +26 -0
- package/stdlib/agents/verifier.agency +155 -0
- package/stdlib/agents/verifier.js +1247 -0
- package/stdlib/args.js +21 -7
- package/stdlib/array.agency +1 -0
- package/stdlib/array.js +37 -19
- package/stdlib/auth/keyring.agency +8 -4
- package/stdlib/auth/keyring.js +32 -11
- package/stdlib/auth/oauth.agency +5 -2
- package/stdlib/auth/oauth.js +30 -11
- package/stdlib/calendar.agency +27 -21
- package/stdlib/calendar.js +38 -13
- package/stdlib/capabilities.agency +9 -0
- package/stdlib/capabilities.js +23 -6
- package/stdlib/clipboard.agency +4 -2
- package/stdlib/clipboard.js +31 -9
- package/stdlib/concurrency.agency +52 -0
- package/stdlib/concurrency.js +311 -8
- package/stdlib/data/finance/dbnomics.js +141 -38
- package/stdlib/data/finance/edgar.agency +1 -0
- package/stdlib/data/finance/edgar.js +221 -56
- package/stdlib/data/finance/fred.agency +1 -0
- package/stdlib/data/finance/fred.js +372 -108
- package/stdlib/data/finance/gdelt.js +136 -41
- package/stdlib/data/people/littlesis.agency +2 -2
- package/stdlib/data/people/littlesis.js +517 -159
- package/stdlib/data/tech/hackernews.js +661 -200
- package/stdlib/data/tech/yc.js +489 -145
- package/stdlib/data/usaspending.agency +1 -0
- package/stdlib/data/usaspending.js +369 -131
- package/stdlib/data/wikidata.js +492 -152
- package/stdlib/date.agency +136 -87
- package/stdlib/date.js +735 -427
- package/stdlib/docs/agent/index.md +105 -0
- package/stdlib/docs/agent/mcp.md +134 -0
- package/stdlib/docs/agent/memory.md +58 -0
- package/stdlib/docs/agent/models.md +85 -0
- package/stdlib/docs/agent/project-context.md +28 -0
- package/stdlib/docs/cli/agent.md +7 -0
- package/stdlib/docs/cli/editor-integration.md +23 -0
- package/stdlib/docs/cli/format.md +2 -0
- package/stdlib/docs/cli/lint.md +42 -0
- package/stdlib/docs/cli/run.md +2 -0
- package/stdlib/docs/diagnostics/effects.md +12 -10
- package/stdlib/docs/diagnostics/index.md +43 -3
- package/stdlib/docs/diagnostics/lint.md +48 -0
- package/stdlib/docs/diagnostics/match.md +10 -0
- package/stdlib/docs/diagnostics/names.md +30 -0
- package/stdlib/docs/diagnostics/templates.md +174 -0
- package/stdlib/docs/diagnostics/tools.md +93 -0
- package/stdlib/docs/diagnostics/types-aliases.md +10 -0
- package/stdlib/docs/guide/basic-syntax.md +27 -2
- package/stdlib/docs/guide/builtins.md +13 -0
- package/stdlib/docs/guide/comprehensions.md +111 -0
- package/stdlib/docs/guide/concurrency.md +4 -2
- package/stdlib/docs/guide/guards.md +141 -44
- package/stdlib/docs/guide/handlers.md +32 -2
- package/stdlib/docs/guide/llm-part-2.md +20 -3
- package/stdlib/docs/guide/llm.md +5 -3
- package/stdlib/docs/guide/match-expressions.md +208 -0
- package/stdlib/docs/guide/memory.md +3 -3
- package/stdlib/docs/guide/partial-results.md +175 -0
- package/stdlib/docs/guide/pattern-matching.md +227 -194
- package/stdlib/docs/guide/splices.md +94 -0
- package/stdlib/docs/guide/state-isolation.md +10 -4
- package/stdlib/docs/guide/template-agency.md +381 -0
- package/stdlib/docs/guide/ts-helpers.md +28 -0
- package/stdlib/docs/guide/type-validation.md +19 -0
- package/stdlib/docs/guide/types.md +18 -2
- package/stdlib/docs/stdlib/agency/eval.md +513 -0
- package/stdlib/docs/stdlib/agency/local.md +319 -0
- package/stdlib/docs/stdlib/agency.md +972 -0
- package/stdlib/docs/stdlib/agent.md +121 -0
- package/stdlib/docs/stdlib/agents/agency/coding.md +118 -0
- package/stdlib/docs/stdlib/agents/agency/expert.md +78 -0
- package/stdlib/docs/stdlib/agents/agency/researcher.md +75 -0
- package/stdlib/docs/stdlib/agents/agency/review.md +96 -0
- package/stdlib/docs/stdlib/agents/agency/verifier.md +75 -0
- package/stdlib/docs/stdlib/agents/coding.md +81 -0
- package/stdlib/docs/stdlib/agents/data.md +75 -0
- package/stdlib/docs/stdlib/agents/expert.md +80 -0
- package/stdlib/docs/stdlib/agents/explorer.md +81 -0
- package/stdlib/docs/stdlib/agents/lib/expertGuidance.md +87 -0
- package/stdlib/docs/stdlib/agents/lib/feedback.md +127 -0
- package/stdlib/docs/stdlib/agents/lib/search.md +64 -0
- package/stdlib/docs/stdlib/agents/lib/shared.md +83 -0
- package/stdlib/docs/stdlib/agents/lib/toolkits.md +192 -0
- package/stdlib/docs/stdlib/agents/oracle.md +83 -0
- package/stdlib/docs/stdlib/agents/planner.md +168 -0
- package/stdlib/docs/stdlib/agents/researcher.md +77 -0
- package/stdlib/docs/stdlib/agents/review.md +77 -0
- package/stdlib/docs/stdlib/agents/verifier.md +77 -0
- package/stdlib/docs/stdlib/args.md +235 -0
- package/stdlib/docs/stdlib/array.md +11 -0
- package/stdlib/docs/stdlib/auth/keyring.md +149 -0
- package/stdlib/docs/stdlib/auth/oauth.md +183 -0
- package/stdlib/docs/stdlib/calendar.md +279 -0
- package/stdlib/docs/stdlib/capabilities.md +193 -0
- package/stdlib/docs/stdlib/clipboard.md +71 -0
- package/stdlib/docs/stdlib/concurrency.md +94 -0
- package/stdlib/docs/stdlib/data/finance/dbnomics.md +112 -0
- package/stdlib/docs/stdlib/data/finance/edgar.md +133 -0
- package/stdlib/docs/stdlib/data/finance/fred.md +224 -0
- package/stdlib/docs/stdlib/data/finance/gdelt.md +99 -0
- package/stdlib/docs/stdlib/data/people/littlesis.md +219 -0
- package/stdlib/docs/stdlib/data/tech/hackernews.md +219 -0
- package/stdlib/docs/stdlib/data/tech/yc.md +206 -0
- package/stdlib/docs/stdlib/data/usaspending.md +174 -0
- package/stdlib/docs/stdlib/data/wikidata.md +168 -0
- package/stdlib/docs/stdlib/date.md +433 -0
- package/stdlib/docs/stdlib/fs.md +283 -0
- package/stdlib/docs/stdlib/git.md +916 -0
- package/stdlib/docs/stdlib/http.md +207 -0
- package/stdlib/docs/stdlib/image.md +68 -0
- package/stdlib/docs/stdlib/index.md +746 -0
- package/stdlib/docs/stdlib/llm.md +260 -0
- package/stdlib/docs/stdlib/markdown.md +605 -0
- package/stdlib/docs/stdlib/math.md +109 -0
- package/stdlib/docs/stdlib/mcp.md +128 -0
- package/stdlib/docs/stdlib/memory.md +310 -0
- package/stdlib/docs/stdlib/messaging/email.md +226 -0
- package/stdlib/docs/stdlib/messaging/imessage.md +69 -0
- package/stdlib/docs/stdlib/messaging/sms.md +79 -0
- package/stdlib/docs/stdlib/notes/apple.md +428 -0
- package/stdlib/docs/stdlib/object.md +195 -0
- package/stdlib/docs/stdlib/path.md +165 -0
- package/stdlib/docs/stdlib/policy.md +727 -0
- package/stdlib/docs/stdlib/safeBash/actions.md +236 -0
- package/stdlib/docs/stdlib/safeBash.md +398 -0
- package/stdlib/docs/stdlib/shell.md +405 -0
- package/stdlib/docs/stdlib/skills.md +239 -0
- package/stdlib/docs/stdlib/speech.md +160 -0
- package/stdlib/docs/stdlib/statelog.md +249 -0
- package/stdlib/docs/stdlib/strategy.md +195 -0
- package/stdlib/docs/stdlib/supervise.md +87 -0
- package/stdlib/docs/stdlib/syntax.md +295 -0
- package/stdlib/docs/stdlib/system.md +293 -0
- package/stdlib/docs/stdlib/tag.md +150 -0
- package/stdlib/docs/stdlib/thread.md +430 -0
- package/stdlib/docs/stdlib/ui/chart.md +147 -0
- package/stdlib/docs/stdlib/ui/cli.md +154 -0
- package/stdlib/docs/stdlib/ui/layout.md +408 -0
- package/stdlib/docs/stdlib/ui/table.md +194 -0
- package/stdlib/docs/stdlib/ui.md +883 -0
- package/stdlib/docs/stdlib/validation.md +613 -0
- package/stdlib/docs/stdlib/weather.md +109 -0
- package/stdlib/docs/stdlib/web/browser.md +80 -0
- package/stdlib/docs/stdlib/web/search.md +132 -0
- package/stdlib/docs/stdlib/wikipedia.md +123 -0
- package/stdlib/fs.agency +25 -12
- package/stdlib/fs.js +98 -57
- package/stdlib/git.agency +110 -24
- package/stdlib/git.js +807 -164
- package/stdlib/http.js +25 -9
- package/stdlib/image.agency +3 -1
- package/stdlib/image.js +22 -8
- package/stdlib/index.agency +114 -7
- package/stdlib/index.js +1206 -208
- package/stdlib/llm.agency +1 -0
- package/stdlib/llm.js +63 -16
- package/stdlib/markdown.agency +27 -0
- package/stdlib/markdown.js +157 -12
- package/stdlib/math.agency +4 -0
- package/stdlib/math.js +34 -16
- package/stdlib/mcp.agency +6 -6
- package/stdlib/mcp.js +35 -16
- package/stdlib/memory.agency +15 -12
- package/stdlib/memory.js +152 -49
- package/stdlib/messaging/email.agency +54 -47
- package/stdlib/messaging/email.js +32 -10
- package/stdlib/messaging/imessage.agency +7 -5
- package/stdlib/messaging/imessage.js +24 -8
- package/stdlib/messaging/sms.agency +10 -8
- package/stdlib/messaging/sms.js +24 -8
- package/stdlib/notes/apple.agency +361 -0
- package/stdlib/notes/apple.js +2060 -0
- package/stdlib/object.js +181 -55
- package/stdlib/path.js +33 -13
- package/stdlib/policy.agency +43 -11
- package/stdlib/policy.js +341 -90
- package/stdlib/safeBash/actions.agency +166 -0
- package/stdlib/safeBash/actions.js +805 -0
- package/stdlib/safeBash.agency +975 -0
- package/stdlib/safeBash.js +6955 -0
- package/stdlib/shell.agency +45 -13
- package/stdlib/shell.js +78 -41
- package/stdlib/skills.agency +116 -37
- package/stdlib/skills.js +878 -147
- package/stdlib/speech.js +30 -9
- package/stdlib/statelog.agency +1 -0
- package/stdlib/statelog.js +43 -14
- package/stdlib/strategy.agency +40 -0
- package/stdlib/strategy.js +325 -20
- package/stdlib/supervise.agency +116 -0
- package/stdlib/supervise.js +501 -0
- package/stdlib/syntax.js +27 -10
- package/stdlib/system.agency +0 -21
- package/stdlib/system.js +52 -124
- package/stdlib/tag.js +31 -12
- package/stdlib/thread.agency +59 -70
- package/stdlib/thread.js +498 -145
- package/stdlib/ui/chart.agency +1 -0
- package/stdlib/ui/chart.js +69 -29
- package/stdlib/ui/cli.agency +35 -0
- package/stdlib/ui/cli.js +270 -17
- package/stdlib/ui/layout.js +229 -93
- package/stdlib/ui/table.agency +1 -0
- package/stdlib/ui/table.js +105 -53
- package/stdlib/ui.agency +1 -0
- package/stdlib/ui.js +997 -309
- package/stdlib/validation.agency +38 -0
- package/stdlib/validation.js +317 -18
- package/stdlib/weather.agency +2 -0
- package/stdlib/weather.js +28 -12
- package/stdlib/web/browser.js +21 -7
- package/stdlib/web/search.js +23 -8
- package/stdlib/wikipedia.js +25 -9
- package/dist/lib/agents/agency-agent/lib/defaultPolicy.js +0 -1066
- package/dist/lib/agents/agency-agent/prompts/system.md +0 -4
- package/dist/lib/agents/agency-agent/subagents/verify.agency +0 -112
- package/dist/lib/typeChecker/handlerBodyInterrupts.test.js +0 -171
- /package/dist/lib/{typeChecker/handlerBodyInterrupts.test.d.ts → analysis/effectPropagation.test.d.ts} +0 -0
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
printLocalCatalog,
|
|
4
|
-
localModelsSupported,
|
|
5
|
-
listModelNames,
|
|
6
|
-
} from "std::agency/local"
|
|
1
|
+
import { localModelsSupported, listModelNames } from "std::agency/local"
|
|
7
2
|
import { parseArgs } from "std::args"
|
|
8
3
|
import { map } from "std::array"
|
|
9
4
|
import { today } from "std::date"
|
|
10
5
|
import { generateImage } from "std::image"
|
|
11
|
-
import { applyAgentCwd, setAgentCwd } from "std::index"
|
|
12
6
|
import { listHostedModels, hostedModelInfo, setLlmOptions } from "std::llm"
|
|
13
7
|
import { setMemoryId, disableMemory } from "std::memory"
|
|
14
|
-
import { keys } from "std::object"
|
|
15
8
|
import { basename, dirname } from "std::path"
|
|
16
9
|
import {
|
|
17
10
|
ScopedRuleFields,
|
|
@@ -24,7 +17,6 @@ import {
|
|
|
24
17
|
builtinPolicyNames,
|
|
25
18
|
BUILTIN_POLICIES,
|
|
26
19
|
} from "std::policy"
|
|
27
|
-
import { loadMcpToolsWithStatus, mergeMcpServers, isMcpAvailable, readProjectMcpConfig } from "std::mcp"
|
|
28
20
|
import { exists } from "std::shell"
|
|
29
21
|
import { commandsDir, expandSlash } from "std::skills"
|
|
30
22
|
import { highlight } from "std::syntax"
|
|
@@ -45,19 +37,42 @@ import {
|
|
|
45
37
|
clearScreen,
|
|
46
38
|
clearHistory,
|
|
47
39
|
} from "std::ui/cli"
|
|
48
|
-
import { box, render } from "std::ui/layout"
|
|
49
40
|
|
|
50
|
-
import {
|
|
41
|
+
import { parseAgentArgs } from "./lib/args.agency"
|
|
51
42
|
import { detectAttachments, modalityFilter } from "./lib/attachments.agency"
|
|
43
|
+
import { showCapabilities, editCapabilities } from "./lib/capabilitiesUi.agency"
|
|
44
|
+
import { mergedPalette, projectCommands } from "./lib/commandPalette.agency"
|
|
52
45
|
import {
|
|
53
46
|
POLICY_PATH,
|
|
54
47
|
SESSION_POLICY_PATH,
|
|
55
48
|
HISTORY_PATH,
|
|
56
49
|
ALWAYS_FIELDS,
|
|
57
50
|
} from "./lib/config.agency"
|
|
51
|
+
import {
|
|
52
|
+
runTurn,
|
|
53
|
+
setGroundingContext,
|
|
54
|
+
loadAgentsMd,
|
|
55
|
+
maybeEnableMemory,
|
|
56
|
+
checkMainPrompts,
|
|
57
|
+
START_AGENTS,
|
|
58
|
+
} from "./lib/coordinator.agency"
|
|
59
|
+
import { getHeader } from "./lib/header.agency"
|
|
60
|
+
import { generateImageFile } from "./lib/images.agency"
|
|
61
|
+
import { getMcpTools, maybeLoadMcp, mcpSlashCommand } from "./lib/mcp.agency"
|
|
58
62
|
import { filterHostedModels, ModelFilters } from "./lib/modelFilters.agency"
|
|
59
|
-
import {
|
|
60
|
-
|
|
63
|
+
import {
|
|
64
|
+
parseModelFlag,
|
|
65
|
+
parseModelSpec,
|
|
66
|
+
knownProviders,
|
|
67
|
+
missingProviderEnvVar,
|
|
68
|
+
Resolved,
|
|
69
|
+
} from "./lib/models.agency"
|
|
70
|
+
import {
|
|
71
|
+
givePolicyChoice,
|
|
72
|
+
printPolicyHelp,
|
|
73
|
+
getPolicyForAgent,
|
|
74
|
+
} from "./lib/policy.agency"
|
|
75
|
+
import { startInteractive, renderAgentResponse } from "./lib/repl.agency"
|
|
61
76
|
import {
|
|
62
77
|
buildLayers,
|
|
63
78
|
resolveAll,
|
|
@@ -72,21 +87,30 @@ import {
|
|
|
72
87
|
availableBackendItems,
|
|
73
88
|
} from "./lib/search.agency"
|
|
74
89
|
import {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
Session,
|
|
91
|
+
switchModel,
|
|
92
|
+
reactToSlotChange,
|
|
93
|
+
modelChoiceItems,
|
|
94
|
+
parseModelsFilters,
|
|
95
|
+
markMemoryEmbeddingsPinned,
|
|
96
|
+
pickModelsForAgent,
|
|
97
|
+
} from "./lib/session.agency"
|
|
81
98
|
import {
|
|
82
|
-
Settings,
|
|
83
99
|
getCapabilitySettings,
|
|
84
100
|
getModelSettings,
|
|
85
|
-
getMcpServers,
|
|
86
101
|
loadSettings,
|
|
87
102
|
saveSettings,
|
|
88
103
|
} from "./lib/settings.agency"
|
|
89
|
-
import {
|
|
104
|
+
import { SLOTS } from "./lib/slots.agency"
|
|
105
|
+
import { setDebug, setVerbose, setInteractive } from "./lib/trace.agency"
|
|
106
|
+
import {
|
|
107
|
+
truncate,
|
|
108
|
+
formatArgs,
|
|
109
|
+
formatToolResponse,
|
|
110
|
+
retryReasonLabel,
|
|
111
|
+
formatTurnFailure,
|
|
112
|
+
} from "./lib/utils.agency"
|
|
113
|
+
import { renderLLMCallResponse } from "./lib/utils/renderLLMCallResponse.agency"
|
|
90
114
|
import {
|
|
91
115
|
configureModels,
|
|
92
116
|
configureLocalModel,
|
|
@@ -106,7 +130,6 @@ import {
|
|
|
106
130
|
overrideFromResolved,
|
|
107
131
|
embeddingsOverride,
|
|
108
132
|
providerEnvMissing,
|
|
109
|
-
demoteProvider,
|
|
110
133
|
} from "./shared.agency"
|
|
111
134
|
import { codeAgent, setCodeOneShot } from "./subagents/code.agency"
|
|
112
135
|
import { explorerAgent } from "./subagents/explorer.agency"
|
|
@@ -123,1527 +146,27 @@ import { reviewAgent } from "./subagents/review.agency"
|
|
|
123
146
|
//
|
|
124
147
|
//import { clearMessages, pushMessage, repl } from "std::ui"
|
|
125
148
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
*
|
|
129
|
-
* Multi-thread architecture: the agent splits work across two
|
|
130
|
-
* specialists, each with its own thread / system prompt / tool set:
|
|
131
|
-
* - `code.agency` — writes, edits, typechecks, runs code
|
|
132
|
-
* - `research.agency` — looks up docs, fetches URLs, browses web
|
|
133
|
-
*
|
|
134
|
-
* The standard library does the heavy lifting:
|
|
135
|
-
* - `std::agent.route` runs the per-turn hop loop, owns the
|
|
136
|
-
* handoff signal, and force-answers when the hop limit is hit.
|
|
137
|
-
* - `std::policy.cliPolicyHandler` provides the interactive
|
|
138
|
-
* approve/reject/always menu and persists "always" decisions to
|
|
139
|
-
* `~/.agency-agent/policy.json`.
|
|
140
|
-
* - `std::ui.repl` provides the terminal UI: a bordered scroll
|
|
141
|
-
* output area, status line (cost + label), command palette
|
|
142
|
-
* opened with `/`, and history-aware input bar.
|
|
143
|
-
*
|
|
144
|
-
* This file's responsibilities collapse to:
|
|
145
|
-
* 1. Per-turn callback (`_runTurn`) wiring the user message into
|
|
146
|
-
* `mainAgent` and printing the reply into the scroll output.
|
|
147
|
-
* 2. Per-effect ALWAYS_FIELDS map for the policy handler's
|
|
148
|
-
* "approve-always-here" option.
|
|
149
|
-
* 3. Wire the two specialists into one `RouterConfig`.
|
|
150
|
-
*
|
|
151
|
-
* Other features:
|
|
152
|
-
* - Doc-as-skills: bundles `docs/site/guide` etc. (copied to
|
|
153
|
-
* `dist/lib/agents/docs/` at build time, see makefile) and
|
|
154
|
-
* exposes each Markdown file as a skill the research agent can
|
|
155
|
-
* read on demand.
|
|
156
|
-
* - Typechecking: the code agent can call `typecheck` on any
|
|
157
|
-
* source it generates to verify the code before showing it.
|
|
158
|
-
* - File I/O tools: `read`, `write`, `edit` for actually creating /
|
|
159
|
-
* editing `.agency` files.
|
|
160
|
-
*/
|
|
161
|
-
|
|
162
|
-
// Verbose tool-call tracing. Enabled either by `AGENT_DEBUG=1` (legacy)
|
|
163
|
-
// or by passing `--debug` / `--verbose` on the command line (set in main()).
|
|
164
|
-
let AGENT_DEBUG: boolean = env("AGENT_DEBUG") == "1"
|
|
165
|
-
let VERBOSE: boolean = false
|
|
166
|
-
|
|
167
|
-
// Whether the agent is running in interactive (TTY) mode. Set in main()
|
|
168
|
-
// before any tool calls happen, so the callbacks below can suppress
|
|
169
|
-
// scroll-output writes when stdout is destined for a Unix pipe.
|
|
170
|
-
let _isInteractive: boolean = true
|
|
171
|
-
|
|
172
|
-
// The `--policy` argument (a built-in name or a policy-file path), or ""
|
|
173
|
-
// when the flag is absent. Set in main() before `setupSession` runs;
|
|
174
|
-
// consumed there to override the saved policy for this run only.
|
|
149
|
+
// The `--policy` argument (a built-in name or a policy-file path), or "" when
|
|
150
|
+
// absent. CLI-owned: main() sets it, setupSession() reads it.
|
|
175
151
|
let _policyArg: string = ""
|
|
176
152
|
|
|
177
|
-
// Live tool-call tracing. Always shown in the interactive REPL; in
|
|
178
|
-
// one-shot mode it's suppressed so piped output is just the reply,
|
|
179
|
-
// unless the user opts in with `--verbose` / `--debug` (AGENT_DEBUG).
|
|
180
|
-
def _showTraces(): boolean {
|
|
181
|
-
return _isInteractive || VERBOSE || AGENT_DEBUG
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
callback("onToolCallStart") as data {
|
|
185
|
-
if (_showTraces()) {
|
|
186
|
-
pushMessage(color.yellow("⏺ ${data.toolName}(${formatArgs(data.args)})"))
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
callback("onToolCallEnd") as data {
|
|
191
|
-
if (_showTraces()) {
|
|
192
|
-
if (data.result is success(_result)) {
|
|
193
|
-
pushMessage(color.dim.green("${formatToolResponse(_result)}"))
|
|
194
|
-
} else if (data.result is failure(_error)) {
|
|
195
|
-
pushMessage(color.red(" ⎿ Error: ${_error}"))
|
|
196
|
-
} else {
|
|
197
|
-
pushMessage(color.dim("${formatToolResponse(data.result)}"))
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
callback("onLLMCallStart") as data {
|
|
203
|
-
if (AGENT_DEBUG || VERBOSE) {
|
|
204
|
-
pushMessage(color.green.dim("💬 [${data.model}] ${data.prompt}"))
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
callback("onLLMCallEnd") as data {
|
|
209
|
-
if (AGENT_DEBUG || VERBOSE) {
|
|
210
|
-
pushMessage(
|
|
211
|
-
color.green.dim("💬 [${data.model}] ${renderLLMCallResponse(data.result)}"),
|
|
212
|
-
)
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Map a transient LLM retry reason (an `LLMRetryReason` from the runtime
|
|
217
|
-
// retry layer) to a short, human-facing label. `connectionLost` is the
|
|
218
|
-
// lost-internet / closed-the-laptop case; the rest cover provider hiccups
|
|
219
|
-
// and our own per-call timeout.
|
|
220
|
-
export def retryReasonLabel(reason: string): string {
|
|
221
|
-
if (reason == "connectionLost") {
|
|
222
|
-
return "Connection lost"
|
|
223
|
-
}
|
|
224
|
-
if (reason == "timeout") {
|
|
225
|
-
return "Request timed out"
|
|
226
|
-
}
|
|
227
|
-
if (reason == "streamInterrupted") {
|
|
228
|
-
return "Connection interrupted"
|
|
229
|
-
}
|
|
230
|
-
if (reason == "rateLimit") {
|
|
231
|
-
return "Rate limited"
|
|
232
|
-
}
|
|
233
|
-
if (reason == "overloaded") {
|
|
234
|
-
return "Model overloaded"
|
|
235
|
-
}
|
|
236
|
-
if (reason == "serverError") {
|
|
237
|
-
return "Server error"
|
|
238
|
-
}
|
|
239
|
-
if (reason == "invalidStructuredOutput") {
|
|
240
|
-
return "Output failed validation"
|
|
241
|
-
}
|
|
242
|
-
return reason
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// A transient LLM failure (lost connection, timeout, server hiccup) the
|
|
246
|
-
// runtime is about to retry. Surface a dim, one-line heads-up so the user
|
|
247
|
-
// understands the pause instead of staring at a frozen prompt — this is the
|
|
248
|
-
// "lost internet / closed the laptop" experience the abort taxonomy made
|
|
249
|
-
// distinguishable. Gated like the other traces so piped one-shot output
|
|
250
|
-
// stays clean. `attempt` is the 1-based retry number; `maxRetries` is the
|
|
251
|
-
// configured retry budget.
|
|
252
|
-
callback("onLLMRetry") as data {
|
|
253
|
-
if (_showTraces()) {
|
|
254
|
-
pushMessage(
|
|
255
|
-
color.dim(
|
|
256
|
-
"⟳ ${retryReasonLabel(data.reason)} — retrying (${data.attempt}/${data.maxRetries})…",
|
|
257
|
-
),
|
|
258
|
-
)
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Turn a terminal (retries-exhausted) LLM failure into a short, actionable
|
|
263
|
-
// message. The runtime's exhausted-retry error text embeds the reason in
|
|
264
|
-
// parens, e.g. "LLM call failed after 3 attempts (connectionLost): ...". We
|
|
265
|
-
// recognize the transport reasons that mean "the network or model dropped"
|
|
266
|
-
// and give concrete advice; anything else echoes the raw error so nothing
|
|
267
|
-
// is hidden.
|
|
268
|
-
export def formatTurnFailure(errText: string): string {
|
|
269
|
-
if (errText.includes("(connectionLost)") || errText.includes("(streamInterrupted)")) {
|
|
270
|
-
return "⚠ Lost the connection to the model and couldn't recover after retrying.\nCheck your internet connection and try again."
|
|
271
|
-
}
|
|
272
|
-
if (errText.includes("(timeout)")) {
|
|
273
|
-
return "⚠ The model took too long to respond — the request timed out after retrying.\nTry again, perhaps with a smaller request."
|
|
274
|
-
}
|
|
275
|
-
if (errText.includes("(rateLimit)") || errText.includes("(overloaded)") || errText.includes("(serverError)")) {
|
|
276
|
-
return "⚠ The model provider is busy and the request failed after retrying.\nWait a moment and try again."
|
|
277
|
-
}
|
|
278
|
-
return "⚠ The request failed: ${errText}"
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
type ToolCallData = {
|
|
282
|
-
name: string;
|
|
283
|
-
arguments: any
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
type LLMResponse = {
|
|
287
|
-
output?: string;
|
|
288
|
-
toolCalls: ToolCallData[];
|
|
289
|
-
usage: { inputTokens: number; outputTokens: number; totalTokens: number; cachedInputTokens: number };
|
|
290
|
-
cost: { inputCost: number; outputCost: number; cachedInputCost: number; totalCost: number; currency: string };
|
|
291
|
-
model: string
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
def renderLLMCallResponse(data: LLMResponse): string {
|
|
295
|
-
let response = []
|
|
296
|
-
if (data.output != "" && data.output != null && data.output != undefined) {
|
|
297
|
-
response.push(data.output)
|
|
298
|
-
}
|
|
299
|
-
if (data.toolCalls.length > 0) {
|
|
300
|
-
for (toolCall in data.toolCalls) {
|
|
301
|
-
response.push(`${toolCall.name}(${formatArgs(toolCall.arguments)})`)
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
return response.join("\n")
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
def loadAgentsMd(dir: string): string {
|
|
308
|
-
"""
|
|
309
|
-
Read `AGENTS.md` from `dir` if it exists and return it wrapped in a
|
|
310
|
-
<project_context> block ready to splice into a system prompt. Returns
|
|
311
|
-
an empty string if there is no AGENTS.md or it cannot be read. The
|
|
312
|
-
read is auto-approved — the user implicitly opted in to scanning the
|
|
313
|
-
project directory by running the agent there.
|
|
314
|
-
"""
|
|
315
|
-
if (!exists("AGENTS.md", dir)) {
|
|
316
|
-
return ""
|
|
317
|
-
}
|
|
318
|
-
const result = read("AGENTS.md", dir) with approve
|
|
319
|
-
if (isFailure(result)) {
|
|
320
|
-
return ""
|
|
321
|
-
}
|
|
322
|
-
return "\n\n<project_context>\n${result.value}\n</project_context>"
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Per-turn grounding context. Captured at startup and re-used so the
|
|
326
|
-
// LLM doesn't have to re-ground each turn. Initialized in `main()`.
|
|
327
|
-
let _context: string = ""
|
|
328
|
-
|
|
329
|
-
// Project-local slash commands. `cwd()` works at module-init time so
|
|
330
|
-
// we anchor at the user's project root (not the agent's source dir).
|
|
331
|
-
// `with approve` auto-approves the `glob`/`read` during init — the
|
|
332
|
-
// user implicitly opted in by running the agent in this directory.
|
|
333
|
-
static const projectCommands = commandsDir("${cwd()}/.claude/commands") with approve
|
|
334
|
-
|
|
335
|
-
def builtinPalette(): Record<string, string> {
|
|
336
|
-
return {
|
|
337
|
-
"/exit": "Exit the agent",
|
|
338
|
-
"/clear": "Clear the conversation transcript",
|
|
339
|
-
"/clear-history": "Clear the input history (recall + saved file)",
|
|
340
|
-
"/cost": "Show cumulative LLM cost and tokens",
|
|
341
|
-
"/model": "Switch the model (bare to pick, or slot=model)",
|
|
342
|
-
"/models": "List / filter the hosted model catalog",
|
|
343
|
-
"/local": "Switch to a local model",
|
|
344
|
-
"/search": "Choose the web search backend (hosted / Tavily / Brave / off)",
|
|
345
|
-
"/settings": "View and change capability settings for the current model",
|
|
346
|
-
"/mcp": "List configured MCP servers and their tools",
|
|
347
|
-
"/paste": "Multi-line paste mode (Ctrl+D submits, Ctrl+C cancels)",
|
|
348
|
-
"/help": "Show available slash commands"
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// Built-ins win over file commands so a user `/clear.md` can't shadow
|
|
353
|
-
// the built-in `/clear`. Build file entries first, then overlay builtins.
|
|
354
|
-
def mergedPalette(): Record<string, string> {
|
|
355
|
-
let out: Record<string, string> = {}
|
|
356
|
-
for (cmd in projectCommands) {
|
|
357
|
-
let label = cmd.description
|
|
358
|
-
if (cmd.argHint != "") {
|
|
359
|
-
label = "${cmd.description} ${cmd.argHint}"
|
|
360
|
-
}
|
|
361
|
-
out["/${cmd.name}"] = label
|
|
362
|
-
}
|
|
363
|
-
const builtins = builtinPalette()
|
|
364
|
-
for (key in builtins) {
|
|
365
|
-
out[key] = builtins[key]
|
|
366
|
-
}
|
|
367
|
-
return out
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// In-session model selection state. One mutable cell holding the current
|
|
371
|
-
// Session (the pin + per-slot overrides chosen via /model this run). switchModel
|
|
372
|
-
// is pure over this value — it copies, never mutates — so it stays testable.
|
|
373
|
-
export type Session = {
|
|
374
|
-
pin: string;
|
|
375
|
-
slots: Record<string, string>
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
let _session: Session = {
|
|
379
|
-
pin: "",
|
|
380
|
-
slots: {}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/** Apply an in-session model selection. Copies `prior` (never mutates), folds in
|
|
384
|
-
the new spec (bare → pin; slot=model → per-slot), resolves, applies, and returns
|
|
385
|
-
the new session + assignment + the slots that changed (so the caller can react,
|
|
386
|
-
e.g. the cross-provider recall notice). Turn-boundary semantics: takes effect on
|
|
387
|
-
the NEXT turn; no in-flight call is mutated. */
|
|
388
|
-
export def switchModel(
|
|
389
|
-
prior: Session,
|
|
390
|
-
spec: string,
|
|
391
|
-
ctx: Ctx,
|
|
392
|
-
before: Record<string, Resolved>,
|
|
393
|
-
): { session: Session; resolved: Record<string, Resolved>; changes: SlotChange[] } {
|
|
394
|
-
// The caller builds ctx from currentProvider(), which returns the
|
|
395
|
-
// PROMOTED name on openai sessions. priceDefault and the built-in
|
|
396
|
-
// tables key by public provider names, so demote before resolving —
|
|
397
|
-
// otherwise a switch that lets any slot fall through to the built-in
|
|
398
|
-
// defaults fails with "openai-responses has no built-in defaults".
|
|
399
|
-
const ctx2: Ctx = {
|
|
400
|
-
provider: demoteProvider(ctx.provider),
|
|
401
|
-
price: ctx.price
|
|
402
|
-
}
|
|
403
|
-
let nextSlots: Record<string, string> = {}
|
|
404
|
-
for (key in Object.keys(prior.slots)) {
|
|
405
|
-
nextSlots[key] = prior.slots[key]
|
|
406
|
-
}
|
|
407
|
-
let next: Session = {
|
|
408
|
-
pin: prior.pin,
|
|
409
|
-
slots: nextSlots
|
|
410
|
-
}
|
|
411
|
-
const parsed = parseModelFlag(spec)
|
|
412
|
-
if (parsed.slot != "" && !SLOTS.includes(parsed.slot)) {
|
|
413
|
-
pushMessage(
|
|
414
|
-
color.red("Unknown model slot '${parsed.slot}'. Valid slots: ${SLOTS.join(", ")}."),
|
|
415
|
-
)
|
|
416
|
-
return {
|
|
417
|
-
session: prior,
|
|
418
|
-
resolved: before,
|
|
419
|
-
changes: []
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
if (parsed.slot == "embedding" && !embeddingSpecHasProvider(parsed.model)) {
|
|
423
|
-
// The embedding slot exists to point AWAY from the chat provider, so
|
|
424
|
-
// the provider can never be inferred. Require the explicit form.
|
|
425
|
-
pushMessage(
|
|
426
|
-
color.red(
|
|
427
|
-
"Embedding models need the provider/model form, e.g. embedding=openai/text-embedding-3-small.",
|
|
428
|
-
),
|
|
429
|
-
)
|
|
430
|
-
return {
|
|
431
|
-
session: prior,
|
|
432
|
-
resolved: before,
|
|
433
|
-
changes: []
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
if (parsed.slot == "") {
|
|
437
|
-
next.pin = parsed.model
|
|
438
|
-
} else {
|
|
439
|
-
next.slots[parsed.slot] = parsed.model
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// A saved provider (settings.model.provider) means a provider is established,
|
|
443
|
-
// so a unified provider/model spec should not be split during resolution.
|
|
444
|
-
const settings = getModelSettings(loadSettings())
|
|
445
|
-
const providerEstablished = settings.provider != null && settings.provider != ""
|
|
446
|
-
const layers = buildLayers(
|
|
447
|
-
next.pin,
|
|
448
|
-
next.slots,
|
|
449
|
-
"",
|
|
450
|
-
{},
|
|
451
|
-
settings,
|
|
452
|
-
knownProviders(),
|
|
453
|
-
providerEstablished,
|
|
454
|
-
)
|
|
455
|
-
const all = resolveAll(layers, ctx2)
|
|
456
|
-
if (isFailure(all)) {
|
|
457
|
-
pushMessage(color.red("Could not switch model: ${all.error}"))
|
|
458
|
-
return {
|
|
459
|
-
session: prior,
|
|
460
|
-
resolved: before,
|
|
461
|
-
changes: []
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
const resolved = promoteAll(all.value)
|
|
465
|
-
applyResolved(resolved)
|
|
466
|
-
return {
|
|
467
|
-
session: next,
|
|
468
|
-
resolved: resolved,
|
|
469
|
-
changes: diffResolved(before, resolved)
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/** React to one resolved-slot change. Phase 1: a `main`-slot provider change
|
|
474
|
-
means the embedding space behind memory changed, so pause memory and warn.
|
|
475
|
-
(std::memory has no tier-2-only toggle yet -- full pause; structured recall
|
|
476
|
-
returns when a selective toggle lands.) Returns true if it emitted the notice. */
|
|
477
|
-
export def reactToSlotChange(change: SlotChange): boolean {
|
|
478
|
-
if (change.slot == "main" && change.before.provider != change.after.provider) {
|
|
479
|
-
// Skip the pause only when startup actually enabled memory WITH the
|
|
480
|
-
// override. A set-but-keyless slot took the fallback path, so memory
|
|
481
|
-
// runs on derived embeddings and the provider change still shifts
|
|
482
|
-
// the embedding space behind recall.
|
|
483
|
-
if (_memoryEmbeddingsPinned) {
|
|
484
|
-
return false
|
|
485
|
-
}
|
|
486
|
-
pushMessage(
|
|
487
|
-
color.dim(
|
|
488
|
-
"Warning: provider changed - memory is paused until restart (recall would be unreliable).",
|
|
489
|
-
),
|
|
490
|
-
)
|
|
491
|
-
// `with approve`: the agent is deliberately auto-pausing memory on a
|
|
492
|
-
// provider switch, not asking the user — so don't surface an approval prompt.
|
|
493
|
-
disableMemory() with approve
|
|
494
|
-
return true
|
|
495
|
-
}
|
|
496
|
-
if (change.slot == "embedding") {
|
|
497
|
-
const override = overrideFromResolved(change.after)
|
|
498
|
-
if (override != null) {
|
|
499
|
-
const missing = missingProviderEnvVar(override.provider)
|
|
500
|
-
if (missing != "") {
|
|
501
|
-
pushMessage(
|
|
502
|
-
color.yellow(
|
|
503
|
-
"Warning: the embedding slot needs ${missing}, which is not set. The assignment takes effect at next agent start, and memory falls back to the default embedding behavior until it is exported.",
|
|
504
|
-
),
|
|
505
|
-
)
|
|
506
|
-
return true
|
|
507
|
-
}
|
|
508
|
-
// The healthy path must not be silent: enableMemory already ran,
|
|
509
|
-
// so the user would otherwise believe embeddings switched now.
|
|
510
|
-
pushMessage(
|
|
511
|
-
color.dim(
|
|
512
|
-
"Embedding slot set: memory embeddings use ${override.provider}/${override.model} at next agent start.",
|
|
513
|
-
),
|
|
514
|
-
)
|
|
515
|
-
return true
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
return false
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// ChoiceItem list for the model pickers: the hosted catalog, filtered, each
|
|
522
|
-
// labeled with provider + input price for an informed pick.
|
|
523
|
-
export def modelChoiceItems(filters: ModelFilters): ChoiceItem[] {
|
|
524
|
-
let items: ChoiceItem[] = []
|
|
525
|
-
for (model in filterHostedModels(listHostedModels(), filters)) {
|
|
526
|
-
const label = "${model.name} (${model.provider}, $${model.inputCost}/1M in)"
|
|
527
|
-
items.push({
|
|
528
|
-
key: model.name,
|
|
529
|
-
label: label
|
|
530
|
-
})
|
|
531
|
-
}
|
|
532
|
-
return items
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// Parse a `/models [provider]` command line into filters. Bare `/models` (or a
|
|
536
|
-
// trailing-space-only arg) yields no filters; `/models <provider>` narrows to
|
|
537
|
-
// one provider. Extracted from the handler so it is unit-testable.
|
|
538
|
-
export def parseModelsFilters(cmd: string): ModelFilters {
|
|
539
|
-
const prefix = "/models "
|
|
540
|
-
if (!cmd.startsWith(prefix)) {
|
|
541
|
-
return {}
|
|
542
|
-
}
|
|
543
|
-
const arg = cmd.substring(prefix.length).trim()
|
|
544
|
-
if (arg == "") {
|
|
545
|
-
return {}
|
|
546
|
-
}
|
|
547
|
-
return {
|
|
548
|
-
provider: arg
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
/** Human label for a capability source layer. Interprets the source
|
|
553
|
-
strings resolveCapabilities emits (capabilities.agency). */
|
|
554
|
-
def capabilitySourceLabel(source: string): string {
|
|
555
|
-
if (source == "default") {
|
|
556
|
-
return "built-in default"
|
|
557
|
-
}
|
|
558
|
-
if (source == "provider") {
|
|
559
|
-
return "provider default: ${getCapabilityProvider()}"
|
|
560
|
-
}
|
|
561
|
-
if (source == "model") {
|
|
562
|
-
return "built-in for ${getCapabilityModelKey()}"
|
|
563
|
-
}
|
|
564
|
-
if (source == "user-global") {
|
|
565
|
-
return "your global override"
|
|
566
|
-
}
|
|
567
|
-
if (source == "user-provider") {
|
|
568
|
-
return "your override for ${getCapabilityProvider()}"
|
|
569
|
-
}
|
|
570
|
-
return "your override for ${getCapabilityModelKey()}"
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
/** One "value (source)" cell. The typed Capabilities shape cannot be
|
|
574
|
-
indexed by a dynamic key, so this is the renderer's per-field switch. */
|
|
575
|
-
def capabilityRow(fieldKey: string): string {
|
|
576
|
-
const resolved = getCapabilitiesResolved()
|
|
577
|
-
const values = resolved.values
|
|
578
|
-
const sources = resolved.sources
|
|
579
|
-
if (fieldKey == "prompt") {
|
|
580
|
-
return "${values.prompt} (${capabilitySourceLabel(sources.prompt)})"
|
|
581
|
-
}
|
|
582
|
-
if (fieldKey == "summarize") {
|
|
583
|
-
return "${values.summarize} (${capabilitySourceLabel(sources.summarize)})"
|
|
584
|
-
}
|
|
585
|
-
if (fieldKey == "memory") {
|
|
586
|
-
return "${values.memory} (${capabilitySourceLabel(sources.memory)})"
|
|
587
|
-
}
|
|
588
|
-
let cap = "none"
|
|
589
|
-
if (values.maxTokens != null) {
|
|
590
|
-
cap = "${values.maxTokens}"
|
|
591
|
-
}
|
|
592
|
-
return "${cap} (${capabilitySourceLabel(sources.maxTokens)})"
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
/** Render the current profile with per-field provenance. */
|
|
596
|
-
def showCapabilities() {
|
|
597
|
-
pushMessage("Capabilities for ${getCapabilityModelKey()} (${getCapabilityProvider()}):")
|
|
598
|
-
for (field in CAPABILITY_FIELDS) {
|
|
599
|
-
pushMessage(" ${field.label} ${capabilityRow(field.key)}")
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/** The settings.json key a scope writes under. Global's key is unused. */
|
|
604
|
-
def scopeTargetName(scopeKey: string): string {
|
|
605
|
-
if (scopeKey == "provider") {
|
|
606
|
-
return getCapabilityProvider()
|
|
607
|
-
}
|
|
608
|
-
return getCapabilityModelKey()
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
/** Persist one override patch at a scope, then re-resolve. */
|
|
612
|
-
def saveCapabilityOverride(scopeKey: string, patch: CapabilityPatch) {
|
|
613
|
-
let settings = loadSettings()
|
|
614
|
-
settings.capabilities = mergeCapabilityOverride(
|
|
615
|
-
getCapabilitySettings(settings),
|
|
616
|
-
scopeKey,
|
|
617
|
-
scopeTargetName(scopeKey),
|
|
618
|
-
patch,
|
|
619
|
-
)
|
|
620
|
-
saveSettings(settings)
|
|
621
|
-
refreshCapabilities(getCapabilityModelKey(), getCapabilityProvider())
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
/** Remove one field override at a scope, then re-resolve. */
|
|
625
|
-
def removeCapabilityOverride(scopeKey: string, fieldKey: string) {
|
|
626
|
-
let settings = loadSettings()
|
|
627
|
-
settings.capabilities = removeCapabilityField(
|
|
628
|
-
getCapabilitySettings(settings),
|
|
629
|
-
scopeKey,
|
|
630
|
-
scopeTargetName(scopeKey),
|
|
631
|
-
fieldKey,
|
|
632
|
-
)
|
|
633
|
-
saveSettings(settings)
|
|
634
|
-
refreshCapabilities(getCapabilityModelKey(), getCapabilityProvider())
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
/** Ask which scope an override applies to. Returns "" on cancel. */
|
|
638
|
-
def pickOverrideScope(): string {
|
|
639
|
-
let scopeItems: ChoiceItem[] = []
|
|
640
|
-
scopeItems.push({
|
|
641
|
-
key: "model",
|
|
642
|
-
label: "this model (${getCapabilityModelKey()})"
|
|
643
|
-
})
|
|
644
|
-
scopeItems.push({
|
|
645
|
-
key: "provider",
|
|
646
|
-
label: "this provider (${getCapabilityProvider()})"
|
|
647
|
-
})
|
|
648
|
-
scopeItems.push({
|
|
649
|
-
key: "global",
|
|
650
|
-
label: "all models"
|
|
651
|
-
})
|
|
652
|
-
const scopeKey = chooseOption("Scope", "Where should this apply?", scopeItems, allowCancel: true)
|
|
653
|
-
if (scopeKey == null) {
|
|
654
|
-
return ""
|
|
655
|
-
}
|
|
656
|
-
return scopeKey
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
/** Re-apply the resolved cap as the branch default. After a reset the
|
|
660
|
-
resolved value falls back to a built-in layer, which is always numeric
|
|
661
|
-
for known providers, so live-apply covers removal too. */
|
|
662
|
-
def applyLiveMaxTokens() {
|
|
663
|
-
const capValue = getCapabilities().maxTokens
|
|
664
|
-
if (capValue != null) {
|
|
665
|
-
setLlmOptions({ maxTokens: capValue })
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
153
|
|
|
669
|
-
/** Positive-integer parse. parseInt and isNaN appear nowhere in the
|
|
670
|
-
repo's .agency code, so this uses a digits check instead. Returns -1
|
|
671
|
-
for anything that is not all digits. */
|
|
672
|
-
def parsePositiveInt(text: string): number {
|
|
673
|
-
// Bound to a const because the parser rejects method calls on string
|
|
674
|
-
// LITERALS ("0123456789".includes(...) does not parse; a variable does).
|
|
675
|
-
const digits = "0123456789"
|
|
676
|
-
const trimmed = text.trim()
|
|
677
|
-
if (trimmed == "") {
|
|
678
|
-
return -1
|
|
679
|
-
}
|
|
680
|
-
for (ch in trimmed.split("")) {
|
|
681
|
-
if (!digits.includes(ch)) {
|
|
682
|
-
return -1
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
return Number(trimmed)
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
/** Interactive edit: field → value → scope → save → live-apply. */
|
|
689
|
-
def editCapabilities() {
|
|
690
|
-
let fieldItems: ChoiceItem[] = []
|
|
691
|
-
for (field in CAPABILITY_FIELDS) {
|
|
692
|
-
fieldItems.push({
|
|
693
|
-
key: field.key,
|
|
694
|
-
label: "${field.label} — ${field.description}"
|
|
695
|
-
})
|
|
696
|
-
}
|
|
697
|
-
const fieldKey = chooseOption(
|
|
698
|
-
"Settings",
|
|
699
|
-
"Pick a setting to change (empty to exit).",
|
|
700
|
-
fieldItems,
|
|
701
|
-
allowCancel: true,
|
|
702
|
-
)
|
|
703
|
-
if (fieldKey == "" || fieldKey == null) {
|
|
704
|
-
return
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
let patch: CapabilityPatch = {}
|
|
708
|
-
if (fieldKey == "prompt") {
|
|
709
|
-
let promptItems: ChoiceItem[] = []
|
|
710
|
-
promptItems.push({
|
|
711
|
-
key: "large",
|
|
712
|
-
label: "large — full coordinator prompt"
|
|
713
|
-
})
|
|
714
|
-
promptItems.push({
|
|
715
|
-
key: "small",
|
|
716
|
-
label: "small — compact prompt for small-context models"
|
|
717
|
-
})
|
|
718
|
-
const picked = chooseOption("prompt", "System prompt size.", promptItems, allowCancel: true)
|
|
719
|
-
if (picked == "" || picked == null) {
|
|
720
|
-
return
|
|
721
|
-
}
|
|
722
|
-
patch = {
|
|
723
|
-
prompt: picked
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (fieldKey == "summarize" || fieldKey == "memory") {
|
|
727
|
-
let onOffItems: ChoiceItem[] = []
|
|
728
|
-
onOffItems.push({
|
|
729
|
-
key: "on",
|
|
730
|
-
label: "on"
|
|
731
|
-
})
|
|
732
|
-
onOffItems.push({
|
|
733
|
-
key: "off",
|
|
734
|
-
label: "off"
|
|
735
|
-
})
|
|
736
|
-
const picked = chooseOption(fieldKey, "Enable ${fieldKey}?", onOffItems, allowCancel: true)
|
|
737
|
-
if (picked == "" || picked == null) {
|
|
738
|
-
return
|
|
739
|
-
}
|
|
740
|
-
if (fieldKey == "summarize") {
|
|
741
|
-
patch = {
|
|
742
|
-
summarize: picked == "on"
|
|
743
|
-
}
|
|
744
|
-
} else {
|
|
745
|
-
patch = {
|
|
746
|
-
memory: picked == "on"
|
|
747
|
-
}
|
|
748
|
-
if (picked == "on") {
|
|
749
|
-
const status = embeddingKeyStatus(getResolvedSlots())
|
|
750
|
-
if (status.state == "key-missing") {
|
|
751
|
-
pushMessage(
|
|
752
|
-
color.red(
|
|
753
|
-
"Cannot enable memory: the embedding slot needs ${status.varName}, which is not set. Export it, or point the embedding slot elsewhere via /model.",
|
|
754
|
-
),
|
|
755
|
-
)
|
|
756
|
-
return
|
|
757
|
-
}
|
|
758
|
-
if (status.state == "no-override" && providerLacksEmbeddings(getCapabilityProvider())) {
|
|
759
|
-
pushMessage(
|
|
760
|
-
color.dim(
|
|
761
|
-
"Note: ${getCapabilityProvider()} has no embeddings endpoint, so Tier-2 semantic recall stays off. Point the embedding slot at a provider that has one, e.g. /model embedding=openai/text-embedding-3-small.",
|
|
762
|
-
),
|
|
763
|
-
)
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
if (fieldKey == "maxTokens") {
|
|
769
|
-
let capItems: ChoiceItem[] = []
|
|
770
|
-
capItems.push({
|
|
771
|
-
key: "reset",
|
|
772
|
-
label: "reset — remove my override, use the default"
|
|
773
|
-
})
|
|
774
|
-
const picked = chooseOption(
|
|
775
|
-
"maxTokens",
|
|
776
|
-
"Default output-token cap. Type a number, or pick reset.",
|
|
777
|
-
capItems,
|
|
778
|
-
allowFreeText: true,
|
|
779
|
-
allowCancel: true,
|
|
780
|
-
)
|
|
781
|
-
if (picked == "" || picked == null) {
|
|
782
|
-
return
|
|
783
|
-
}
|
|
784
|
-
if (picked == "reset") {
|
|
785
|
-
const scopeKey = pickOverrideScope()
|
|
786
|
-
if (scopeKey == "") {
|
|
787
|
-
return
|
|
788
|
-
}
|
|
789
|
-
removeCapabilityOverride(scopeKey, "maxTokens")
|
|
790
|
-
applyLiveMaxTokens()
|
|
791
|
-
pushMessage("Override removed.")
|
|
792
|
-
showCapabilities()
|
|
793
|
-
return
|
|
794
|
-
}
|
|
795
|
-
const parsed = parsePositiveInt(picked)
|
|
796
|
-
if (parsed <= 0) {
|
|
797
|
-
pushMessage(color.red("Not a positive number: ${picked}"))
|
|
798
|
-
return
|
|
799
|
-
}
|
|
800
|
-
patch = {
|
|
801
|
-
maxTokens: parsed
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
const scopeKey = pickOverrideScope()
|
|
806
|
-
if (scopeKey == "") {
|
|
807
|
-
return
|
|
808
|
-
}
|
|
809
|
-
saveCapabilityOverride(scopeKey, patch)
|
|
810
|
-
|
|
811
|
-
// Live-apply what can apply now; explain what can't.
|
|
812
|
-
if (fieldKey == "memory") {
|
|
813
|
-
if (getCapabilities().memory) {
|
|
814
|
-
// The ON direction cannot live-apply. enableAgentMemory's
|
|
815
|
-
// `with approve` cannot override the outer policy handler that
|
|
816
|
-
// startInteractive installed, so the memory-dir fs interrupts
|
|
817
|
-
// would surface as policy prompts mid-flow, or get denied and
|
|
818
|
-
// half-apply the toggle. The OFF direction stays live below:
|
|
819
|
-
// disableMemory raises no fs interrupts and already runs in-REPL
|
|
820
|
-
// from reactToSlotChange.
|
|
821
|
-
pushMessage(color.dim("Memory turns on at next agent start (enabling mid-session would raise policy prompts)."))
|
|
822
|
-
} else {
|
|
823
|
-
disableMemory() with approve
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
if (fieldKey == "maxTokens") {
|
|
827
|
-
applyLiveMaxTokens()
|
|
828
|
-
}
|
|
829
|
-
if (fieldKey == "prompt") {
|
|
830
|
-
pushMessage(color.dim("Prompt change applies on next agent start (this session's system message is already sent)."))
|
|
831
|
-
}
|
|
832
|
-
pushMessage("Saved.")
|
|
833
|
-
showCapabilities()
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
// Slash-command + user-message dispatcher invoked by `repl()` for
|
|
837
|
-
// every Enter keystroke. Return `false` to terminate the loop.
|
|
838
|
-
def _runTurn(msg: string): boolean {
|
|
839
|
-
// Trim once for built-in matching so `"/help\n"` (piped) or
|
|
840
|
-
// `" /clear"` behave the same as `"/clear"`. `expandSlash` is
|
|
841
|
-
// whitespace-tolerant in its own right, but it still receives the
|
|
842
|
-
// raw `msg` so the LLM sees the exact text the user typed when
|
|
843
|
-
// nothing matches.
|
|
844
|
-
const trimmed = msg.trim()
|
|
845
|
-
if (trimmed == "") {
|
|
846
|
-
return true
|
|
847
|
-
}
|
|
848
|
-
if (trimmed == "/exit" || trimmed == "/quit") {
|
|
849
|
-
return false
|
|
850
|
-
}
|
|
851
|
-
if (trimmed == "/clear") {
|
|
852
|
-
clearMessages()
|
|
853
|
-
return true
|
|
854
|
-
}
|
|
855
|
-
if (trimmed == "/clear-history") {
|
|
856
|
-
clearHistory()
|
|
857
|
-
pushMessage("Input history cleared.")
|
|
858
|
-
return true
|
|
859
|
-
}
|
|
860
|
-
if (trimmed == "/help") {
|
|
861
|
-
pushMessage(
|
|
862
|
-
"Commands: /exit, /clear, /clear-history, /cost, /model, /models, /local, /search, /settings, /mcp, /paste, /help",
|
|
863
|
-
)
|
|
864
|
-
return true
|
|
865
|
-
}
|
|
866
|
-
if (trimmed == "/settings") {
|
|
867
|
-
showCapabilities()
|
|
868
|
-
editCapabilities()
|
|
869
|
-
return true
|
|
870
|
-
}
|
|
871
|
-
if (trimmed == "/mcp") {
|
|
872
|
-
if (!isMcpAvailable()) {
|
|
873
|
-
pushMessage(color.yellow("MCP is not installed. Run: npm install @agency-lang/mcp"))
|
|
874
|
-
return true
|
|
875
|
-
}
|
|
876
|
-
const merged = mergeMcpServers(getMcpServers(loadSettings()), readProjectMcpConfig(cwd()))
|
|
877
|
-
if (keys(merged).length == 0) {
|
|
878
|
-
pushMessage(color.dim("No MCP servers configured. Add an mcpServers block to agency.json or settings.json."))
|
|
879
|
-
return true
|
|
880
|
-
}
|
|
881
|
-
pushMessage(color.bold("MCP servers:"))
|
|
882
|
-
for (name in keys(merged)) {
|
|
883
|
-
// mcpServerStatus is populated at session start. A server present in the
|
|
884
|
-
// config but absent from the status map was never loaded (e.g. /mcp run
|
|
885
|
-
// before startup finished) — show it as unknown rather than connected.
|
|
886
|
-
let status = mcpServerStatus[name]
|
|
887
|
-
if (status == null) {
|
|
888
|
-
status = "not loaded"
|
|
889
|
-
}
|
|
890
|
-
pushMessage(" ${name} — ${status}")
|
|
891
|
-
}
|
|
892
|
-
pushMessage(color.dim("Loaded ${mcpTools.length} MCP tool(s) this session."))
|
|
893
|
-
return true
|
|
894
|
-
}
|
|
895
|
-
if (trimmed == "/search") {
|
|
896
|
-
const opts = availableBackendItems()
|
|
897
|
-
const choice = chooseOption(
|
|
898
|
-
"Web search backend",
|
|
899
|
-
"Pick how this agent searches the web. Current: ${getSearchBackend()}",
|
|
900
|
-
opts,
|
|
901
|
-
false,
|
|
902
|
-
true,
|
|
903
|
-
)
|
|
904
|
-
if (choice != "" && choice != null && choice != undefined) {
|
|
905
|
-
setSearchBackend(choice)
|
|
906
|
-
pushMessage("Web search backend set to: ${choice}")
|
|
907
|
-
}
|
|
908
|
-
return true
|
|
909
|
-
}
|
|
910
|
-
if (trimmed == "/cost") {
|
|
911
|
-
// Derive BOTH the header total and the per-model breakdown from the
|
|
912
|
-
// same process-wide accumulator (getModelCosts), so the `Cost:` /
|
|
913
|
-
// `Tokens:` lines and the rows below them can never visibly disagree.
|
|
914
|
-
// (getCost()/getTokens() read the per-branch accumulator, a different
|
|
915
|
-
// scope — adjacent in the output, they could in principle diverge.)
|
|
916
|
-
// Rows are sorted by cost descending by getModelCosts(); a subagent
|
|
917
|
-
// on a pricier model (e.g. the oracle on opus-4.8) shows up here.
|
|
918
|
-
const byModel = getModelCosts()
|
|
919
|
-
let totalCost = 0.0
|
|
920
|
-
let totalTokens = 0
|
|
921
|
-
for (m in byModel) {
|
|
922
|
-
totalCost = totalCost + m.cost
|
|
923
|
-
totalTokens = totalTokens + m.inputTokens + m.outputTokens
|
|
924
|
-
}
|
|
925
|
-
pushMessage("Cost: $${totalCost.toFixed(4)}")
|
|
926
|
-
pushMessage("Tokens: ${totalTokens}")
|
|
927
|
-
if (byModel.length > 0) {
|
|
928
|
-
pushMessage("")
|
|
929
|
-
pushMessage("By model:")
|
|
930
|
-
for (m in byModel) {
|
|
931
|
-
pushMessage(
|
|
932
|
-
" ${m.model} ↑${m.inputTokens} ↓${m.outputTokens} $${m.cost.toFixed(4)}",
|
|
933
|
-
)
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
return true
|
|
937
|
-
}
|
|
938
|
-
if (trimmed == "/model" || trimmed.startsWith("/model ")) {
|
|
939
|
-
let spec = ""
|
|
940
|
-
if (trimmed != "/model") {
|
|
941
|
-
spec = trimmed.substring(7).trim()
|
|
942
|
-
}
|
|
943
|
-
if (spec == "") {
|
|
944
|
-
pushMessage("Current models:")
|
|
945
|
-
const current = getResolvedSlots()
|
|
946
|
-
for (slot in Object.keys(current)) {
|
|
947
|
-
const resolved = current[slot]
|
|
948
|
-
if (resolved != null) {
|
|
949
|
-
pushMessage(" ${slot}: ${resolved.model} (${resolved.via})")
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
const items = modelChoiceItems({})
|
|
953
|
-
const choice = chooseOption(
|
|
954
|
-
"Model",
|
|
955
|
-
"Pick a model, or type one (or slot=model, e.g. reasoning=claude-opus-4-8). Empty to cancel.",
|
|
956
|
-
items,
|
|
957
|
-
allowFreeText: true,
|
|
958
|
-
allowCancel: true,
|
|
959
|
-
)
|
|
960
|
-
if (choice == "" || choice == null) {
|
|
961
|
-
return true
|
|
962
|
-
}
|
|
963
|
-
spec = choice
|
|
964
|
-
}
|
|
965
|
-
const ctx: Ctx = {
|
|
966
|
-
provider: currentProvider(),
|
|
967
|
-
price: "standard"
|
|
968
|
-
}
|
|
969
|
-
const out = switchModel(_session, spec, ctx, getResolvedSlots())
|
|
970
|
-
_session = out.session
|
|
971
|
-
for (change in out.changes) {
|
|
972
|
-
reactToSlotChange(change)
|
|
973
|
-
}
|
|
974
|
-
pushMessage("Model set:")
|
|
975
|
-
for (slot in Object.keys(out.resolved)) {
|
|
976
|
-
const resolved = out.resolved[slot]
|
|
977
|
-
if (resolved != null) {
|
|
978
|
-
pushMessage(color.dim(" ${slot}: ${resolved.model} (${resolved.via})"))
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
return true
|
|
982
|
-
}
|
|
983
|
-
if (trimmed == "/models" || trimmed.startsWith("/models ")) {
|
|
984
|
-
const filters = parseModelsFilters(trimmed)
|
|
985
|
-
const models = filterHostedModels(listHostedModels(), filters)
|
|
986
|
-
if (models.length == 0) {
|
|
987
|
-
pushMessage("No models match.")
|
|
988
|
-
return true
|
|
989
|
-
}
|
|
990
|
-
for (model in models) {
|
|
991
|
-
pushMessage(
|
|
992
|
-
" ${model.name} (${model.provider}, $${model.inputCost}/1M in, ${model.contextWindow} ctx)",
|
|
993
|
-
)
|
|
994
|
-
}
|
|
995
|
-
return true
|
|
996
|
-
}
|
|
997
|
-
if (trimmed == "/local") {
|
|
998
|
-
if (!localModelsSupported()) {
|
|
999
|
-
pushMessage(
|
|
1000
|
-
color.yellow(
|
|
1001
|
-
"Local models need smoltalk-llama-cpp. Install: ! npm i -g smoltalk-llama-cpp",
|
|
1002
|
-
),
|
|
1003
|
-
)
|
|
1004
|
-
return true
|
|
1005
|
-
}
|
|
1006
|
-
let items: ChoiceItem[] = []
|
|
1007
|
-
for (modelName in listModelNames()) {
|
|
1008
|
-
items.push({
|
|
1009
|
-
key: modelName.name,
|
|
1010
|
-
label: modelName.name
|
|
1011
|
-
})
|
|
1012
|
-
}
|
|
1013
|
-
const choice = chooseOption(
|
|
1014
|
-
"Local model",
|
|
1015
|
-
"Pick a local model, or type an hf: URI / .gguf path (downloads on first use):",
|
|
1016
|
-
items,
|
|
1017
|
-
allowFreeText: true,
|
|
1018
|
-
allowCancel: true,
|
|
1019
|
-
)
|
|
1020
|
-
if (choice == "" || choice == null) {
|
|
1021
|
-
return true
|
|
1022
|
-
}
|
|
1023
|
-
const before = getResolvedSlots()
|
|
1024
|
-
configureLocalModel(choice)
|
|
1025
|
-
configureSearch(true)
|
|
1026
|
-
for (change in diffResolved(before, getResolvedSlots())) {
|
|
1027
|
-
reactToSlotChange(change)
|
|
1028
|
-
}
|
|
1029
|
-
pushMessage("Switched to local model: ${choice}")
|
|
1030
|
-
return true
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
// Hand the message to the agent. `agentReply` does the slash-command
|
|
1034
|
-
// expansion and the actual agent work; the REPL just renders the reply.
|
|
1035
|
-
// Wrap in `try` so a terminal LLM failure (e.g. the connection dropped and
|
|
1036
|
-
// retries were exhausted) renders a friendly heads-up instead of a raw
|
|
1037
|
-
// Failure object. Aborts/interrupts are NOT caught here — `try` re-throws
|
|
1038
|
-
// them so an Esc-cancel still reaches the policy handler.
|
|
1039
|
-
const result = try agentReply(msg)
|
|
1040
|
-
if (result is success(reply)) {
|
|
1041
|
-
if (reply != "" && reply != null && reply != undefined) {
|
|
1042
|
-
pushMessage(highlight("${reply}\n", language: "markdown"))
|
|
1043
|
-
} else {
|
|
1044
|
-
pushMessage(color.red("No reply generated."))
|
|
1045
|
-
}
|
|
1046
|
-
} else if (result is failure(f)) {
|
|
1047
|
-
pushMessage(color.red(formatTurnFailure("${f.error}")))
|
|
1048
|
-
}
|
|
1049
|
-
return true
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
let first = true
|
|
1053
|
-
|
|
1054
|
-
// Valid `--agent` targets. Empty / "main" routes through the coordinator;
|
|
1055
|
-
// the rest route the starting prompt's first turn directly to that
|
|
1056
|
-
// subagent. Used to validate the flag and to dispatch in `agentReplyVia`.
|
|
1057
|
-
static const START_AGENTS = ["main", "code", "research", "oracle", "explorer", "review"]
|
|
1058
|
-
|
|
1059
|
-
static const MAIN_PROMPT_LARGE = """
|
|
1060
|
-
You are the top-level coordinator of an Agency-language assistant. You
|
|
1061
|
-
receive every user message and decide how to respond.
|
|
1062
|
-
|
|
1063
|
-
You have five subagent tools (each running in its own isolated
|
|
1064
|
-
context) and one direct tool:
|
|
1065
|
-
|
|
1066
|
-
- `codeAgent(userMsg)` — anything that touches code or the filesystem:
|
|
1067
|
-
reading, writing, editing, typechecking, running shell commands,
|
|
1068
|
-
and answering Agency syntax / CLI questions. Use this for any task
|
|
1069
|
-
that involves inspecting or modifying source code.
|
|
1070
|
-
- `researchAgent(userMsg)` — web search, URL fetches, Wikipedia,
|
|
1071
|
-
external API lookups, summarizing external content.
|
|
1072
|
-
- `reviewAgent(userMsg)` — reviews Agency code for syntax and type
|
|
1073
|
-
errors. Call this after `codeAgent` produces non-trivial new or
|
|
1074
|
-
modified Agency code, passing the code to be reviewed.
|
|
1075
|
-
- `oracleAgent(userMsg)` — a read-only senior reviewer on a stronger
|
|
1076
|
-
reasoning model. Read the **Oracle** section below — you are
|
|
1077
|
-
expected to use this tool **frequently**.
|
|
1078
|
-
- `explorerAgent(userMsg)` — a read-only researcher that produces
|
|
1079
|
-
broad, synthesizing answers about the codebase or bundled docs.
|
|
1080
|
-
Read the **Explorer** section below.
|
|
1081
|
-
- `generateImageFile(prompt, path, size, images)` — generate an image
|
|
1082
|
-
from a text prompt (or modify existing images by passing their paths
|
|
1083
|
-
in `images`) and save it to `path`. Call it directly whenever the
|
|
1084
|
-
user asks you to create, draw, edit, or restyle an image — do NOT
|
|
1085
|
-
route image generation to `codeAgent`.
|
|
1086
|
-
|
|
1087
|
-
**Answer directly (no tool call) when** the message is conversational,
|
|
1088
|
-
a clarifying question, or something you can answer from context alone.
|
|
1089
|
-
|
|
1090
|
-
**Delegate when** the message clearly needs one of the subagents'
|
|
1091
|
-
capabilities. Pick one based on what the message actually needs —
|
|
1092
|
-
don't pre-emptively call multiple subagents.
|
|
1093
|
-
|
|
1094
|
-
## Picking between oracle, explorer, and code agent
|
|
1095
|
-
|
|
1096
|
-
These three overlap on "reads the codebase," but they're for
|
|
1097
|
-
different jobs. Pick by **the shape of the answer the user wants**:
|
|
1098
|
-
|
|
1099
|
-
- **oracle** → sharp verdict on a specific plan, diff, or bug.
|
|
1100
|
-
Output: short, decisive ("this plan won't work because X").
|
|
1101
|
-
- **explorer** → broad synthesis from reading many files.
|
|
1102
|
-
Output: structured overview ("Agency's five main features
|
|
1103
|
-
are..."). Use for "summarize", "tour", "what are the main",
|
|
1104
|
-
"how does X work across...".
|
|
1105
|
-
- **codeAgent** → targeted action: edit, run, typecheck, or
|
|
1106
|
-
answer a focused Agency-syntax question. Output: the edit
|
|
1107
|
-
itself, or a concise factual reply.
|
|
1108
|
-
|
|
1109
|
-
Default: if the user asks a broad/synthesizing question,
|
|
1110
|
-
`explorerAgent` beats `codeAgent` every time. The code agent is
|
|
1111
|
-
optimized for terse action and will under-read on broad asks.
|
|
1112
|
-
|
|
1113
|
-
Subagents return summary text. Surface that result to the user (in
|
|
1114
|
-
your own words if you're combining multiple results), formatted as
|
|
1115
|
-
Markdown.
|
|
1116
|
-
|
|
1117
|
-
## Oracle
|
|
1118
|
-
|
|
1119
|
-
The oracle is the most powerful tool you have. Use it **FREQUENTLY**.
|
|
1120
|
-
It is a read-only senior reviewer running on a stronger reasoning
|
|
1121
|
-
model than you. It can read the codebase and the Agency docs but
|
|
1122
|
-
cannot write, edit, or run anything. Its job is to **think hard so
|
|
1123
|
-
you don't have to guess**.
|
|
1124
|
-
|
|
1125
|
-
Call the oracle:
|
|
1126
|
-
|
|
1127
|
-
- **Before** dispatching `codeAgent` for any non-trivial task — ask
|
|
1128
|
-
the oracle to sanity-check the plan, find existing code that
|
|
1129
|
-
already solves the problem, or suggest a simpler approach.
|
|
1130
|
-
- **After** `codeAgent` produces a non-trivial diff — ask the oracle
|
|
1131
|
-
to review the work for correctness, missed edge cases, and
|
|
1132
|
-
better alternatives.
|
|
1133
|
-
- When `codeAgent` reports it's stuck on a bug after one or two
|
|
1134
|
-
attempts — ask the oracle what's actually going on.
|
|
1135
|
-
- When the user proposes a plan or approach — ask the oracle
|
|
1136
|
-
whether the plan is sound, **before** you act on it. If the
|
|
1137
|
-
oracle finds a flaw, surface that to the user *before* taking
|
|
1138
|
-
any action.
|
|
1139
|
-
- Whenever you're tempted to guess about the codebase ("I think
|
|
1140
|
-
there's probably already a helper for X") — ask the oracle to
|
|
1141
|
-
look.
|
|
1142
|
-
|
|
1143
|
-
**Tell the user when you're consulting the oracle.** Say something
|
|
1144
|
-
like "Let me ask the oracle to review this plan before we start"
|
|
1145
|
-
or "I'll have the oracle look for an existing implementation." The
|
|
1146
|
-
visibility is half the value — the user benefits from knowing a
|
|
1147
|
-
second opinion is being sought.
|
|
1148
|
-
|
|
1149
|
-
Pass the oracle a self-contained question with full context. It
|
|
1150
|
-
does not see your conversation. Include the user's request, the
|
|
1151
|
-
plan or diff under review, relevant file paths, and the specific
|
|
1152
|
-
question you want answered.
|
|
1153
|
-
|
|
1154
|
-
Default bias: when in doubt, **consult the oracle**. The cost of
|
|
1155
|
-
asking is small; the cost of executing a flawed plan is large.
|
|
1156
|
-
|
|
1157
|
-
## Explorer
|
|
1158
|
-
|
|
1159
|
-
The explorer is your go-to for **broad, synthesizing questions**
|
|
1160
|
-
about the codebase or the bundled Agency docs. It is read-only and
|
|
1161
|
-
runs on a stronger reasoning model with extended thinking. Its job
|
|
1162
|
-
is **coverage** — it reads widely and returns a structured synthesis.
|
|
1163
|
-
|
|
1164
|
-
Call the explorer when the user asks:
|
|
1165
|
-
|
|
1166
|
-
- "Summarize the Agency docs" / "What are the main features?"
|
|
1167
|
-
- "Give me a tour of `lib/X/`" / "What's in this module?"
|
|
1168
|
-
- "How does X work across the codebase?"
|
|
1169
|
-
- "Walk me through the compilation pipeline"
|
|
1170
|
-
- Anything where a good answer requires reading 5+ files and
|
|
1171
|
-
organizing the findings by theme.
|
|
1172
|
-
|
|
1173
|
-
Do NOT use the explorer for:
|
|
1174
|
-
- Specific factual lookups ("what does function X return?") — use
|
|
1175
|
-
`codeAgent`.
|
|
1176
|
-
- Plan critique or bug diagnosis — use `oracleAgent`.
|
|
1177
|
-
- External / web research — use `researchAgent`.
|
|
1178
|
-
|
|
1179
|
-
**Tell the user when you're consulting the explorer.** "Let me have
|
|
1180
|
-
the explorer go through the docs and put together an overview." Like
|
|
1181
|
-
with the oracle, the visibility is part of the value — the user
|
|
1182
|
-
benefits from knowing breadth is being applied.
|
|
1183
|
-
|
|
1184
|
-
Pass the explorer a self-contained question with explicit scope
|
|
1185
|
-
("all of `docs/site/guide/`", "the `lib/parsers/` module"). It does
|
|
1186
|
-
not see your conversation. Be clear about the level of detail
|
|
1187
|
-
expected.
|
|
1188
|
-
|
|
1189
|
-
## Style
|
|
1190
|
-
|
|
1191
|
-
Never start a response by calling the user's question or idea good,
|
|
1192
|
-
great, fascinating, profound, excellent, or perfect. Skip flattery
|
|
1193
|
-
and respond directly. Don't pad replies with "happy to help",
|
|
1194
|
-
"certainly", or trailing summaries the user can read in the diff.
|
|
1195
|
-
|
|
1196
|
-
**Use ASCII diagrams when they clarify.** For control flow, state
|
|
1197
|
-
machines, pipelines, module relationships, or any "how do the parts
|
|
1198
|
-
fit together" answer, draw a small ASCII diagram in a fenced
|
|
1199
|
-
```text block. Boxes, arrows, and trees beat paragraphs for
|
|
1200
|
-
structural explanations:
|
|
1201
|
-
|
|
1202
|
-
```text
|
|
1203
|
-
parse → SymbolTable.build → preprocess → TypeScriptBuilder → printTs
|
|
1204
|
-
```
|
|
1205
|
-
|
|
1206
|
-
Keep diagrams small. Skip them where prose or code is clearer —
|
|
1207
|
-
diagrams earn their space by showing **relationships** or **flow**.
|
|
1208
|
-
|
|
1209
|
-
## Be proactive
|
|
1210
|
-
|
|
1211
|
-
When the user asks you to look at, debug, or change a file or some code,
|
|
1212
|
-
**delegate to `codeAgent` to do it** — don't ask the user to paste a file
|
|
1213
|
-
or describe code a subagent could read. The code agent has `read`, `glob`,
|
|
1214
|
-
and `ls` and resolves relative paths against the user's working directory
|
|
1215
|
-
automatically, so a bare filename like `foo.agency` is enough. Only ask
|
|
1216
|
-
the user for information you genuinely cannot obtain through a subagent.
|
|
1217
|
-
|
|
1218
|
-
## Answer before action
|
|
1219
|
-
|
|
1220
|
-
When the user asks a question, asks for an opinion, or asks how to
|
|
1221
|
-
plan or approach something, **answer the question first**. Don't
|
|
1222
|
-
jump straight into delegating to a subagent or making tool calls
|
|
1223
|
-
unless the user has clearly asked for an action ("do X", "fix Y",
|
|
1224
|
-
"build Z"). If the user is exploring or thinking out loud, think
|
|
1225
|
-
with them — don't sprint to implementation.
|
|
1226
|
-
"""
|
|
1227
|
-
|
|
1228
|
-
// Compact coordinator prompt for small-context models, ~350 tokens
|
|
1229
|
-
// instead of ~3,400. Selected when the capability profile says
|
|
1230
|
-
// prompt: "small". An 8K-context model loses 40% of its window to the
|
|
1231
|
-
// large prompt before the user types anything. The phrase "compact
|
|
1232
|
-
// coordinator" is a deliberate marker that verification greps for in
|
|
1233
|
-
// statelogs.
|
|
1234
|
-
static const MAIN_PROMPT_SMALL = """
|
|
1235
|
-
You are the compact coordinator of an Agency-language assistant. Decide
|
|
1236
|
-
how to answer each user message.
|
|
1237
|
-
|
|
1238
|
-
Tools (each runs in its own context; pass a self-contained message):
|
|
1239
|
-
- `codeAgent(userMsg)` — anything touching code or files: read, write,
|
|
1240
|
-
edit, run, typecheck. Also Agency syntax and CLI questions.
|
|
1241
|
-
- `researchAgent(userMsg)` — web search, URL fetches, external facts.
|
|
1242
|
-
- `reviewAgent(userMsg)` — check non-trivial new Agency code for
|
|
1243
|
-
syntax and type errors; pass the code to review.
|
|
1244
|
-
- `oracleAgent(userMsg)` — deep reasoning on a hard question; include
|
|
1245
|
-
all needed context in the message.
|
|
1246
|
-
- `explorerAgent(userMsg)` — broad read-only codebase/docs questions.
|
|
1247
|
-
- `generateImageFile(prompt, path, size, images)` — create or edit an
|
|
1248
|
-
image; do not route image work to codeAgent.
|
|
1249
|
-
|
|
1250
|
-
Routing rules:
|
|
1251
|
-
- Simple chat, greetings, quick factual answers: reply directly, no
|
|
1252
|
-
tools.
|
|
1253
|
-
- Anything code- or file-related: codeAgent. Current/external info:
|
|
1254
|
-
researchAgent. Broad "summarize/tour/how does X work" questions:
|
|
1255
|
-
explorerAgent.
|
|
1256
|
-
- Surface tool results to the user concisely; do not re-run a tool the
|
|
1257
|
-
user did not ask to re-run.
|
|
1258
|
-
|
|
1259
|
-
Style: plain, direct answers in Markdown. No preamble. Keep replies
|
|
1260
|
-
short unless the task demands detail.
|
|
1261
|
-
"""
|
|
1262
|
-
|
|
1263
|
-
// Exported for tests: agent-cwd resolution of edit inputs is a spec
|
|
1264
|
-
// invariant with no other observable (the deterministic image client
|
|
1265
|
-
// ignores its images argument). generateImage accepts path / URL /
|
|
1266
|
-
// data-URI strings, so only local paths get agent-cwd resolution —
|
|
1267
|
-
// running a URL through applyAgentCwd would mangle it into
|
|
1268
|
-
// "<agentCwd>/https:/…".
|
|
1269
|
-
export def resolveEditInputs(images: string[]): string[] {
|
|
1270
|
-
return map(images) as inputPath {
|
|
1271
|
-
if (inputPath.startsWith("http://") || inputPath.startsWith("https://") || inputPath.startsWith("data:")) {
|
|
1272
|
-
return inputPath
|
|
1273
|
-
}
|
|
1274
|
-
return applyAgentCwd(inputPath)
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
// Direct image generation for the coordinator. Saves to disk and
|
|
1279
|
-
// returns the path — never base64, which would flood the LLM context.
|
|
1280
|
-
// The write rides the std::writeBinary interrupt gate (writes are not
|
|
1281
|
-
// auto-approved by policy) and generation cost accrues to the agent's
|
|
1282
|
-
// cost tracking like any llm() call.
|
|
1283
|
-
export def generateImageFile(
|
|
1284
|
-
prompt: string,
|
|
1285
|
-
path: string,
|
|
1286
|
-
size: string = "",
|
|
1287
|
-
images: string[] = [],
|
|
1288
|
-
): string {
|
|
1289
|
-
"""
|
|
1290
|
-
Generate an image from a text prompt and save it to `path`. To MODIFY
|
|
1291
|
-
existing images (edit / variation), pass their paths in `images`.
|
|
1292
|
-
Returns the saved path on success. Use this when the user asks to
|
|
1293
|
-
create, draw, edit, or restyle an image.
|
|
1294
|
-
|
|
1295
|
-
@param prompt - What to generate, or how to modify the input images.
|
|
1296
|
-
@param path - Where to save the resulting image (e.g. "diagram.png").
|
|
1297
|
-
@param size - Optional size like "1024x1024".
|
|
1298
|
-
@param images - Optional input image paths to edit / vary.
|
|
1299
|
-
"""
|
|
1300
|
-
// LLM-supplied paths resolve against the agent cwd, like every other
|
|
1301
|
-
// agent file tool.
|
|
1302
|
-
const inputs = resolveEditInputs(images)
|
|
1303
|
-
const generated = generateImage(prompt, size: size, images: inputs)
|
|
1304
|
-
if (isFailure(generated)) {
|
|
1305
|
-
return "Image generation failed: ${generated.error}"
|
|
1306
|
-
}
|
|
1307
|
-
// writeBinary rejects an absolute filename when dir is set, so split
|
|
1308
|
-
// path into (dir, name); useAgentCwd resolves a relative dir against
|
|
1309
|
-
// the agent cwd (absolute dirs pass through untouched).
|
|
1310
|
-
const written = writeBinary(
|
|
1311
|
-
basename(path),
|
|
1312
|
-
generated.value.base64,
|
|
1313
|
-
dirname(path),
|
|
1314
|
-
useAgentCwd: true,
|
|
1315
|
-
)
|
|
1316
|
-
if (isFailure(written)) {
|
|
1317
|
-
return "Generated the image, but saving to ${path} failed: ${written.error}"
|
|
1318
|
-
}
|
|
1319
|
-
// Show the model what it made (generate -> view -> refine). The loop
|
|
1320
|
-
// inlines the bytes when it builds the injected user message; the
|
|
1321
|
-
// path resolves the same way the write did.
|
|
1322
|
-
attachToReply(image(applyAgentCwd(path)))
|
|
1323
|
-
return "Saved image to ${path}"
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
static const mainAgentTools = [
|
|
1327
|
-
researchAgent.partial(allowHandoff: false),
|
|
1328
|
-
codeAgent.partial(allowHandoff: false),
|
|
1329
|
-
reviewAgent.partial(allowHandoff: false),
|
|
1330
|
-
oracleAgent.partial(allowHandoff: false),
|
|
1331
|
-
explorerAgent.partial(allowHandoff: false),
|
|
1332
|
-
generateImageFile,
|
|
1333
|
-
]
|
|
1334
|
-
|
|
1335
|
-
// MCP tools are appended to the coordinator's tools. ORDERING CONTRACT:
|
|
1336
|
-
// maybeLoadMcp (session start, in main()) must run before mainAgent's first
|
|
1337
|
-
// turn, or MCP tools silently vanish.
|
|
1338
|
-
let mcpTools: any[] = []
|
|
1339
|
-
// Per-server load outcome ("connected" / "unavailable"), for /mcp.
|
|
1340
|
-
let mcpServerStatus: Record<string, string> = {}
|
|
1341
|
-
|
|
1342
|
-
export def setMcpTools(tools: any[]) {
|
|
1343
|
-
mcpTools = tools
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
def setMcpServerStatus(status: Record<string, string>) {
|
|
1347
|
-
mcpServerStatus = status
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
// MCP OAuth notification. The @agency-lang/mcp package opens the browser itself
|
|
1351
|
-
// (macOS-only today); we only print the URL so the user can complete auth.
|
|
1352
|
-
def onMcpOAuth(data: any) {
|
|
1353
|
-
print(color.yellow("MCP authorization needed — opening browser. If it does not open, visit:\n${data.authUrl}"))
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
/** Load MCP tools from the project agency.json merged with the global settings
|
|
1357
|
-
and hand them to the coordinator. No-op when @agency-lang/mcp is not installed
|
|
1358
|
-
or no servers are configured. loadMcpTools warns-and-skips internally on any
|
|
1359
|
-
per-server failure, so it always returns an array. */
|
|
1360
|
-
def maybeLoadMcp(settings: Settings) {
|
|
1361
|
-
if (!isMcpAvailable()) {
|
|
1362
|
-
return
|
|
1363
|
-
}
|
|
1364
|
-
const merged = mergeMcpServers(getMcpServers(settings), readProjectMcpConfig(cwd()))
|
|
1365
|
-
if (keys(merged).length == 0) {
|
|
1366
|
-
return
|
|
1367
|
-
}
|
|
1368
|
-
// Always returns a result (per-server failures warn-and-skip internally), so
|
|
1369
|
-
// there is no Failure branch. The status map drives /mcp.
|
|
1370
|
-
const loaded = loadMcpToolsWithStatus(merged, onMcpOAuth)
|
|
1371
|
-
setMcpTools(loaded.tools)
|
|
1372
|
-
setMcpServerStatus(loaded.status)
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
/** Enable memory when the capability profile allows it. When the user
|
|
1376
|
-
pointed the embedding slot at a provider, embeddings run there. A
|
|
1377
|
-
missing API key degrades to the default embedding behavior with one
|
|
1378
|
-
notice. It never blocks startup. */
|
|
1379
|
-
// Whether startup actually enabled memory WITH the embedding override.
|
|
1380
|
-
// The pause guard in reactToSlotChange consults this instead of
|
|
1381
|
-
// re-deriving from the slots: a keyless override took the fallback path,
|
|
1382
|
-
// so memory runs on DERIVED embeddings and a main-provider change still
|
|
1383
|
-
// shifts the embedding space. Exported mutator so tests can drive the
|
|
1384
|
-
// guard directly.
|
|
1385
|
-
let _memoryEmbeddingsPinned = false
|
|
1386
|
-
|
|
1387
|
-
export def markMemoryEmbeddingsPinned(pinned: boolean) {
|
|
1388
|
-
_memoryEmbeddingsPinned = pinned
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
def maybeEnableMemory() {
|
|
1392
|
-
const status = embeddingKeyStatus(getResolvedSlots())
|
|
1393
|
-
const plan = memoryEnablePlan(getCapabilities().memory, status)
|
|
1394
|
-
markMemoryEmbeddingsPinned(plan == "enable-override")
|
|
1395
|
-
if (plan == "skip") {
|
|
1396
|
-
return
|
|
1397
|
-
}
|
|
1398
|
-
if (plan == "enable-override") {
|
|
1399
|
-
enableAgentMemory(status.override)
|
|
1400
|
-
return
|
|
1401
|
-
}
|
|
1402
|
-
if (plan == "enable-fallback") {
|
|
1403
|
-
print(
|
|
1404
|
-
color.dim(
|
|
1405
|
-
"Memory: the embedding slot needs ${status.varName}, which is not set. Falling back to the default embedding behavior.",
|
|
1406
|
-
),
|
|
1407
|
-
)
|
|
1408
|
-
}
|
|
1409
|
-
enableAgentMemory()
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
def mainAgent(prompt: string | (string | Attachment)[]): string {
|
|
1413
|
-
const doSummarize = getCapabilities().summarize
|
|
1414
|
-
thread(label: "main", summarize: doSummarize, session: "main") {
|
|
1415
|
-
setMemoryId("main")
|
|
1416
|
-
if (first) {
|
|
1417
|
-
// `_context` carries the per-run grounding (date, cwd, AGENTS.md),
|
|
1418
|
-
// set by `setupSession`. Appending it to the system prompt is what
|
|
1419
|
-
// actually gets that context to the LLM.
|
|
1420
|
-
let sysPrompt = MAIN_PROMPT_LARGE
|
|
1421
|
-
if (getCapabilities().prompt == "small") {
|
|
1422
|
-
sysPrompt = MAIN_PROMPT_SMALL
|
|
1423
|
-
}
|
|
1424
|
-
systemMessage("${sysPrompt}${_context}")
|
|
1425
|
-
first = false
|
|
1426
|
-
}
|
|
1427
|
-
const result = llm(prompt, {
|
|
1428
|
-
memory: true,
|
|
1429
|
-
tools: [...mainAgentTools, ...mcpTools]
|
|
1430
|
-
})
|
|
1431
|
-
}
|
|
1432
|
-
return result
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
// Dispatch one turn. `target` empty (or "main") runs the coordinator
|
|
1436
|
-
// `mainAgent`, which routes as usual; any subagent name routes the turn
|
|
1437
|
-
// directly to that subagent. All subagents share `(userMsg, allowHandoff)`
|
|
1438
|
-
// and the seed turn never hands off (allowHandoff: false). Used by both
|
|
1439
|
-
// the one-shot path and the interactive seed turn.
|
|
1440
|
-
export def agentReplyVia(target: string, userMsg: string): string {
|
|
1441
|
-
const expanded = expandSlash(userMsg, projectCommands)
|
|
1442
|
-
if (target == "code") {
|
|
1443
|
-
return codeAgent(expanded, false)
|
|
1444
|
-
}
|
|
1445
|
-
if (target == "research") {
|
|
1446
|
-
return researchAgent(expanded, false)
|
|
1447
|
-
}
|
|
1448
|
-
if (target == "oracle") {
|
|
1449
|
-
return oracleAgent(expanded, false)
|
|
1450
|
-
}
|
|
1451
|
-
if (target == "explorer") {
|
|
1452
|
-
return explorerAgent(expanded, false)
|
|
1453
|
-
}
|
|
1454
|
-
if (target == "review") {
|
|
1455
|
-
return reviewAgent(expanded, false)
|
|
1456
|
-
}
|
|
1457
|
-
// Auto-attach image/PDF files the user referenced (drag-drop or typed
|
|
1458
|
-
// path), filtered to what the resolved model accepts. Never silent:
|
|
1459
|
-
// every attach and every skip prints a visible line.
|
|
1460
|
-
const detected = modalityFilter(detectAttachments(expanded))
|
|
1461
|
-
for (skippedFile in detected.skipped) {
|
|
1462
|
-
pushMessage(
|
|
1463
|
-
color.yellow("📎 skipped ${skippedFile.label} (${skippedFile.reason})"),
|
|
1464
|
-
)
|
|
1465
|
-
}
|
|
1466
|
-
if (detected.attached.length == 0) {
|
|
1467
|
-
// Deliberate special case: a text-only turn stays a bare string. A
|
|
1468
|
-
// one-element array is API-equivalent, but the stored thread message
|
|
1469
|
-
// shape (string vs parts array) — and with it every serialized
|
|
1470
|
-
// session and message fixture — would change for EVERY turn.
|
|
1471
|
-
return mainAgent(expanded)
|
|
1472
|
-
}
|
|
1473
|
-
for (item in detected.attached) {
|
|
1474
|
-
pushMessage(color.dim("📎 attached ${item.label}"))
|
|
1475
|
-
}
|
|
1476
|
-
const attachments = map(detected.attached) as item {
|
|
1477
|
-
return item.attachment
|
|
1478
|
-
}
|
|
1479
|
-
const parts: (string | Attachment)[] = [expanded, ...attachments]
|
|
1480
|
-
return mainAgent(parts)
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
// The agent's core turn, decoupled from the terminal: expand any project
|
|
1484
|
-
// slash command, then run the prompt through `mainAgent` and return the
|
|
1485
|
-
// reply. The REPL (`main` / `_runTurn`) owns input, output, and built-in
|
|
1486
|
-
// commands; everything the *agent* does for a user message lives here, so
|
|
1487
|
-
// it can be driven and tested without a terminal or user input. See
|
|
1488
|
-
// `tests/agentTurn.agency`.
|
|
1489
|
-
export def agentReply(userMsg: string): string {
|
|
1490
|
-
return agentReplyVia("", userMsg)
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
|
-
def roundedCost(): string {
|
|
1494
|
-
return "$${getCost().toFixed(4)}"
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
def _buildStatus(): { left: string; right: string; context: string } {
|
|
1498
|
-
return {
|
|
1499
|
-
left: "",
|
|
1500
|
-
right: roundedCost(),
|
|
1501
|
-
context: ""
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
def sample(arr: any[]): any {
|
|
1506
|
-
return arr[Math.floor(Math.random() * arr.length)]
|
|
1507
|
-
}
|
|
1508
|
-
|
|
1509
|
-
def printHeader() {
|
|
1510
|
-
const fig = sample(figs)
|
|
1511
|
-
const data = box(
|
|
1512
|
-
title: "Agency",
|
|
1513
|
-
padding: 1,
|
|
1514
|
-
borderColor: "cyan",
|
|
1515
|
-
titleColor: "cyan",
|
|
1516
|
-
width: "full",
|
|
1517
|
-
) as b {
|
|
1518
|
-
b.row(gap: 1) as r {
|
|
1519
|
-
r.column(width: "66%") as left {
|
|
1520
|
-
left.text("Welcome to the Agency Agent!", bold: true)
|
|
1521
|
-
left.text("Ask me to write code, look up docs, or just chat.")
|
|
1522
|
-
left.text("All costs are estimates. Actual costs may be higher.", dim: true)
|
|
1523
|
-
left.hline()
|
|
1524
|
-
left.text("Getting Started", bold: true, fgColor: "cyan")
|
|
1525
|
-
left.text("/help for commands · /exit to quit", dim: true)
|
|
1526
|
-
}
|
|
1527
|
-
r.vline()
|
|
1528
|
-
r.column(width: "30%", align: "center") as right {
|
|
1529
|
-
right.raw(fig, align: "center")
|
|
1530
|
-
}
|
|
1531
|
-
}
|
|
1532
|
-
}
|
|
1533
|
-
print(render(data, color: true))
|
|
1534
|
-
}
|
|
1535
|
-
|
|
1536
|
-
// Print `--policy` usage and list the built-in policies (name + one-line
|
|
1537
|
-
// description). Shown when `--policy` is passed with no value.
|
|
1538
|
-
def printPolicyHelp() {
|
|
1539
|
-
print(color.bold("Usage: agency agent --policy <name | path>"))
|
|
1540
|
-
print(
|
|
1541
|
-
"Select the approval policy for this run: a built-in name below, or a path to a policy JSON file.",
|
|
1542
|
-
)
|
|
1543
|
-
print("")
|
|
1544
|
-
print(color.bold("Built-in policies:"))
|
|
1545
|
-
for (p in BUILTIN_POLICIES) {
|
|
1546
|
-
print(" ${color.cyan(p.name)}")
|
|
1547
|
-
print(" ${p.description}")
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
|
|
1551
|
-
def givePolicyChoice() {
|
|
1552
|
-
const title = "Welcome to the agency agent. Please pick a policy to start."
|
|
1553
|
-
const body = "Don't worry, you can change this later. The policy just controls how the agent asks for your approval when it wants to do something. You can also create your own custom policy file at ${POLICY_PATH} and the agent will use it automatically."
|
|
1554
|
-
let items: ChoiceItem[] = [
|
|
1555
|
-
{
|
|
1556
|
-
key: "minimal",
|
|
1557
|
-
label: "minimal default policy, you do most approvals manually"
|
|
1558
|
-
},
|
|
1559
|
-
{
|
|
1560
|
-
key: "recommended",
|
|
1561
|
-
label: "recommended default policy, allow reading files and browsing the web, no writes"
|
|
1562
|
-
},
|
|
1563
|
-
]
|
|
1564
|
-
|
|
1565
|
-
const answer = chooseOption(title, body, items, allowFreeText: true)
|
|
1566
|
-
return match(answer) {
|
|
1567
|
-
"minimal" => minimalAutoApprovePolicy
|
|
1568
|
-
"recommended" => recommendedAutoApprovePolicy
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
// Shared session setup for both interactive and one-shot modes. Builds
|
|
1573
|
-
// the per-run grounding context, loads (or initializes) the policy, and
|
|
1574
|
-
// returns the installed CLI policy handler. `interactive` gates the
|
|
1575
|
-
// first-run policy-choice prompt: one-shot has no user to answer it, so
|
|
1576
|
-
// it falls back to the recommended default (reads/web auto-approved;
|
|
1577
|
-
// writes still require approval, which a non-interactive run can't
|
|
1578
|
-
// grant — those tasks block, which is the safe behavior).
|
|
1579
154
|
def setupSession(interactive: boolean): any {
|
|
1580
|
-
// Point every path-taking tool at the user's working directory so the
|
|
1581
|
-
// agent's relative file/shell commands resolve against where the user
|
|
1582
|
-
// launched it. The user (via the agent) can change this later with
|
|
1583
|
-
// setAgentCwd.
|
|
1584
155
|
setAgentCwd(cwd())
|
|
1585
156
|
|
|
1586
157
|
// Grounding: the LLM shouldn't have to ask where it is or what day it
|
|
1587
|
-
// is.
|
|
1588
|
-
// present so the LLM follows the project's conventions.
|
|
158
|
+
// is. Also load `AGENTS.md` if present.
|
|
1589
159
|
const projectContext = loadAgentsMd(cwd()) with approve
|
|
1590
|
-
|
|
160
|
+
const grounding = """
|
|
1591
161
|
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
162
|
+
Current date: ${today()}
|
|
163
|
+
Current working directory: ${cwd()}
|
|
164
|
+
${projectContext}
|
|
165
|
+
"""
|
|
166
|
+
setGroundingContext(grounding)
|
|
167
|
+
|
|
168
|
+
const { policyFile, sessionPolicy } = getPolicyForAgent(_policyArg, interactive)
|
|
1598
169
|
|
|
1599
|
-
if (_policyArg != "") {
|
|
1600
|
-
// `--policy` override: a built-in name or a path to a policy file.
|
|
1601
|
-
// The cwd-scoped built-ins pin the launch directory, so we resolve
|
|
1602
|
-
// them against `cwd()` (what `setAgentCwd` just stored, and what the
|
|
1603
|
-
// write/git/bash interrupts resolve their default paths back to).
|
|
1604
|
-
const builtin = builtinPolicy(_policyArg, cwd())
|
|
1605
|
-
if (builtin != null) {
|
|
1606
|
-
// Hand the policy to the handler in memory (no disk write): a
|
|
1607
|
-
// one-off, cwd-scoped override must not clobber the saved policy
|
|
1608
|
-
// or leak into a later run from a different directory. Any new
|
|
1609
|
-
// interactive "always" decision persists to the session file.
|
|
1610
|
-
policyFile = SESSION_POLICY_PATH
|
|
1611
|
-
sessionPolicy = builtin
|
|
1612
|
-
} else {
|
|
1613
|
-
// Not a built-in name — treat it as a policy file path and use it
|
|
1614
|
-
// directly (the handler loads/persists it). Validate up front so a
|
|
1615
|
-
// typo fails fast instead of silently starting from empty.
|
|
1616
|
-
const loaded = parsePolicyFile(_policyArg)
|
|
1617
|
-
if (loaded is failure(f)) {
|
|
1618
|
-
print(
|
|
1619
|
-
color.red(
|
|
1620
|
-
"--policy '${_policyArg}' is neither a built-in policy (${builtinPolicyNames().join(", ")}) nor a readable policy file (${f.status}).",
|
|
1621
|
-
),
|
|
1622
|
-
)
|
|
1623
|
-
process.exit(1)
|
|
1624
|
-
}
|
|
1625
|
-
policyFile = _policyArg
|
|
1626
|
-
}
|
|
1627
|
-
} else {
|
|
1628
|
-
const policy = parsePolicyFile(POLICY_PATH)
|
|
1629
|
-
if (policy is failure(f)) {
|
|
1630
|
-
if (f.status == "doesnt-exist") {
|
|
1631
|
-
if (interactive) {
|
|
1632
|
-
print(color.yellow("No existing policy found at ${POLICY_PATH}."))
|
|
1633
|
-
setPolicy(POLICY_PATH, givePolicyChoice())
|
|
1634
|
-
} else {
|
|
1635
|
-
setPolicy(POLICY_PATH, recommendedAutoApprovePolicy)
|
|
1636
|
-
}
|
|
1637
|
-
} else {
|
|
1638
|
-
print(color.red("Failed to load policy: ${JSON.stringify(f.error)}"))
|
|
1639
|
-
process.exit(1)
|
|
1640
|
-
}
|
|
1641
|
-
} else {
|
|
1642
|
-
setPolicy(POLICY_PATH, policy.value)
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
// Bind the handler to a local var so `with handler` parses (the
|
|
1646
|
-
// `with` clause only accepts an identifier, not a call expression).
|
|
1647
170
|
return cliPolicyHandler(
|
|
1648
171
|
file: policyFile,
|
|
1649
172
|
fields: ALWAYS_FIELDS,
|
|
@@ -1651,176 +174,42 @@ def setupSession(interactive: boolean): any {
|
|
|
1651
174
|
)
|
|
1652
175
|
}
|
|
1653
176
|
|
|
1654
|
-
// One-shot entry: run a single turn through the same `mainAgent` the
|
|
1655
|
-
// REPL uses, with the same session setup and policy handler, and return
|
|
1656
|
-
// the reply. Used for `agency agent -p "..."`, a positional query, or
|
|
1657
|
-
// piped stdin. Slash commands are expanded so `-p /foo bar` works like
|
|
1658
|
-
// typing it in the REPL; the loop-only built-ins (`/exit` etc.) are
|
|
1659
|
-
// meaningless here and aren't checked.
|
|
1660
177
|
def oneShotAgent(target: string, prompt: string): string {
|
|
1661
|
-
|
|
1662
|
-
const handler = setupSession(false)
|
|
1663
|
-
let reply: string = ""
|
|
178
|
+
setInteractive(false)
|
|
179
|
+
const handler = setupSession(interactive: false)
|
|
1664
180
|
handle {
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
if (result is success(r)) {
|
|
1670
|
-
reply = r
|
|
1671
|
-
} else if (result is failure(f)) {
|
|
1672
|
-
reply = formatTurnFailure("${f.error}")
|
|
181
|
+
const result = try runTurn(target, prompt)
|
|
182
|
+
return match(result) {
|
|
183
|
+
success(r) => r
|
|
184
|
+
failure(f) => formatTurnFailure("${f.error}")
|
|
1673
185
|
}
|
|
1674
|
-
} with
|
|
1675
|
-
return handler(data)
|
|
1676
|
-
}
|
|
1677
|
-
return reply
|
|
186
|
+
} with handler
|
|
1678
187
|
}
|
|
1679
188
|
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
def _runSeedTurn(target: string, msg: string) {
|
|
1684
|
-
pushMessage(color.dim("> ${msg}"))
|
|
1685
|
-
const result = try agentReplyVia(target, msg)
|
|
1686
|
-
if (result is success(reply)) {
|
|
1687
|
-
if (reply != "" && reply != null && reply != undefined) {
|
|
1688
|
-
pushMessage(highlight("${reply}\n", language: "markdown"))
|
|
1689
|
-
} else {
|
|
1690
|
-
pushMessage(color.red("No reply generated."))
|
|
1691
|
-
}
|
|
1692
|
-
} else if (result is failure(f)) {
|
|
1693
|
-
pushMessage(color.red(formatTurnFailure("${f.error}")))
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
// Start the interactive REPL. When `seedPrompt` is non-empty it is run as
|
|
1698
|
-
// the first turn (routed via `seedTarget`) *inside* the handle block so
|
|
1699
|
-
// its interrupts reach the policy `handler`; the user is then left at the
|
|
1700
|
-
// prompt. `seedPrompt == ""` is the plain REPL with no seed. Subsequent
|
|
1701
|
-
// turns always go through `_runTurn` (the coordinator) regardless of
|
|
1702
|
-
// `seedTarget` — the target only kicks off the first turn.
|
|
1703
|
-
def startInteractive(handler: any, seedTarget: string, seedPrompt: string) {
|
|
1704
|
-
handle {
|
|
1705
|
-
if (seedPrompt != "") {
|
|
1706
|
-
_runSeedTurn(seedTarget, seedPrompt)
|
|
1707
|
-
}
|
|
1708
|
-
repl(
|
|
1709
|
-
status: _buildStatus,
|
|
1710
|
-
onSubmit: _runTurn,
|
|
1711
|
-
prompt: "> ",
|
|
1712
|
-
historyFile: HISTORY_PATH,
|
|
1713
|
-
historyMax: 1000,
|
|
1714
|
-
paletteCommands: mergedPalette(),
|
|
1715
|
-
)
|
|
1716
|
-
} with (data) {
|
|
1717
|
-
return handler(data)
|
|
1718
|
-
}
|
|
1719
|
-
print(color.cyan("\nGoodbye!"))
|
|
1720
|
-
}
|
|
189
|
+
/* A seeded turn is if the user invokes the Agency agent with
|
|
190
|
+
an initial prompt – by using the agency doctor command, for example.
|
|
191
|
+
It means that agent starts with an initial prompt already there to respond to. */
|
|
1721
192
|
|
|
1722
193
|
node main() {
|
|
1723
194
|
// Parse CLI flags first — `parseArgs` exits on --help / --version /
|
|
1724
195
|
// usage errors, before any handlers or the TUI are installed.
|
|
1725
|
-
const args =
|
|
1726
|
-
{
|
|
1727
|
-
programName: "agency agent",
|
|
1728
|
-
description: "Agency language assistant — interactive REPL by default; one-shot when piped or passed a query / --print.",
|
|
1729
|
-
version: getVersion(),
|
|
1730
|
-
flags: {
|
|
1731
|
-
print: {
|
|
1732
|
-
type: "boolean",
|
|
1733
|
-
short: "p",
|
|
1734
|
-
description: "Run one-shot: print the reply to stdout and exit (no REPL)"
|
|
1735
|
-
},
|
|
1736
|
-
debug: {
|
|
1737
|
-
type: "boolean",
|
|
1738
|
-
description: "Log tool returns (toolName, result, timing). Same as AGENT_DEBUG=1"
|
|
1739
|
-
},
|
|
1740
|
-
verbose: {
|
|
1741
|
-
type: "boolean",
|
|
1742
|
-
description: "Echo tool-call starts to stdout in non-interactive mode"
|
|
1743
|
-
},
|
|
1744
|
-
model: {
|
|
1745
|
-
type: "string",
|
|
1746
|
-
description: "Model for all LLM calls (overrides provider auto-detection)"
|
|
1747
|
-
},
|
|
1748
|
-
fastmodel: {
|
|
1749
|
-
type: "string",
|
|
1750
|
-
description: "Model for ordinary work (default: per detected provider)"
|
|
1751
|
-
},
|
|
1752
|
-
slowmodel: {
|
|
1753
|
-
type: "string",
|
|
1754
|
-
description: "Model for deep reasoning, e.g. the oracle/explorer subagents"
|
|
1755
|
-
},
|
|
1756
|
-
provider: {
|
|
1757
|
-
type: "string",
|
|
1758
|
-
description: "Force the LLM provider. Given alone (openai/anthropic/google/openrouter) it selects that provider's default models and skips env auto-detection; pair it with --model for any other provider (e.g. litellm, openai-compat, or a custom/local model)"
|
|
1759
|
-
},
|
|
1760
|
-
interactive: {
|
|
1761
|
-
type: "boolean",
|
|
1762
|
-
short: "i",
|
|
1763
|
-
description: "Run the given prompt as the first turn of an interactive session, then hand over the REPL (instead of one-shot)"
|
|
1764
|
-
},
|
|
1765
|
-
agent: {
|
|
1766
|
-
type: "string",
|
|
1767
|
-
description: "Route the starting prompt to a named subagent: code, research, oracle, explorer, review (default: coordinator)"
|
|
1768
|
-
},
|
|
1769
|
-
policy: {
|
|
1770
|
-
type: "string",
|
|
1771
|
-
optional: true,
|
|
1772
|
-
description: "Approval policy for this run: a built-in name (minimal, recommended, with-writes, approve-all) or a path to a policy JSON file. with-writes auto-approves file writes and git changes scoped to the current directory and its children; approve-all approves EVERY interrupt with no scoping (sandbox use only). Overrides the saved policy without persisting it. Pass --policy with no value to list the built-in policies."
|
|
1773
|
-
},
|
|
1774
|
-
"agent-home": {
|
|
1775
|
-
type: "string",
|
|
1776
|
-
description: "Directory to use instead of ~/.agency-agent for settings, policy, and history (equivalent to the AGENCY_AGENT_HOME env var; the flag wins when both are set)"
|
|
1777
|
-
},
|
|
1778
|
-
local: {
|
|
1779
|
-
type: "string",
|
|
1780
|
-
optional: true,
|
|
1781
|
-
description: "Run a local model (downloads if needed): a curated short name, an hf: URI, or a .gguf path. Run without a value for guided setup. Pins all slots to the local model; mutually exclusive with --model/--fastmodel/--slowmodel. Requires: npm i -g smoltalk-llama-cpp"
|
|
1782
|
-
},
|
|
1783
|
-
"local-model": {
|
|
1784
|
-
type: "string",
|
|
1785
|
-
optional: true,
|
|
1786
|
-
description: "Deprecated alias for --local."
|
|
1787
|
-
},
|
|
1788
|
-
trace: {
|
|
1789
|
-
type: "string",
|
|
1790
|
-
optional: true,
|
|
1791
|
-
description: "Write an execution trace to this file for debugging (bare --trace writes <runId>.agencytrace in the current directory)"
|
|
1792
|
-
},
|
|
1793
|
-
"log-file": {
|
|
1794
|
-
type: "string",
|
|
1795
|
-
description: "Append structured statelog events (one JSON object per line) to this file for debugging"
|
|
1796
|
-
},
|
|
1797
|
-
"max-tool-call-rounds": {
|
|
1798
|
-
type: "number",
|
|
1799
|
-
description: "Max LLM tool-call rounds before a tool loop halts (default 10 interactive, 50 in one-shot/-p mode)"
|
|
1800
|
-
},
|
|
1801
|
-
"max-tool-result-chars": {
|
|
1802
|
-
type: "number",
|
|
1803
|
-
description: "Max chars of a single tool result fed back to the model (0 disables; default 100000)"
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
},
|
|
1807
|
-
)
|
|
196
|
+
const args = parseAgentArgs()
|
|
1808
197
|
|
|
1809
|
-
// NOTE: --trace / --log
|
|
198
|
+
// NOTE: --trace / --log / --agent-home are declared here only for
|
|
1810
199
|
// --help and so parseArgs accepts them. runBundledAgent extracts them from
|
|
1811
200
|
// the forwarded args and passes them to this process via env vars
|
|
1812
201
|
// (AGENCY_CONFIG_OVERRIDES for the first two, AGENCY_AGENT_HOME for the
|
|
1813
|
-
// last)
|
|
1814
|
-
// config overrides at construction, and lib/config.agency derives the
|
|
1815
|
-
// settings/policy/history paths from the agent home in its static-const
|
|
1816
|
-
// initializers. Do not re-handle them here.
|
|
202
|
+
// last).
|
|
1817
203
|
|
|
1818
204
|
if (args.flags.debug) {
|
|
1819
|
-
|
|
205
|
+
setDebug(true)
|
|
1820
206
|
}
|
|
1821
207
|
if (args.flags.verbose) {
|
|
1822
|
-
|
|
208
|
+
setVerbose(true)
|
|
1823
209
|
}
|
|
210
|
+
|
|
211
|
+
checkMainPrompts()
|
|
212
|
+
|
|
1824
213
|
// `--policy` is an optional-value flag: a bare `--policy` (no name or
|
|
1825
214
|
// path) prints the usage + the built-in policies and exits, rather than
|
|
1826
215
|
// silently doing nothing.
|
|
@@ -1830,100 +219,7 @@ node main() {
|
|
|
1830
219
|
}
|
|
1831
220
|
_policyArg = args.flags.policy ?? ""
|
|
1832
221
|
|
|
1833
|
-
|
|
1834
|
-
// value flag with three states: absent (null); bare empty-string for guided
|
|
1835
|
-
// setup; a value for that local model. `--local` and the hosted flags
|
|
1836
|
-
// (--model / --fastmodel / --slowmodel) are mutually exclusive -- local and
|
|
1837
|
-
// hosted are different in kind (provider llama-cpp, no embedding endpoint).
|
|
1838
|
-
const localVal = args.flags["local"] ?? args.flags["local-model"]
|
|
1839
|
-
const modelArg = args.flags.model ?? ""
|
|
1840
|
-
const hasModelFlags = modelArg != "" || (args.flags.fastmodel ?? "") != "" || (args.flags.slowmodel ?? "") != ""
|
|
1841
|
-
if (localVal != null && hasModelFlags) {
|
|
1842
|
-
print(
|
|
1843
|
-
color.red("Pass either --model (hosted) or --local (local), not both."),
|
|
1844
|
-
)
|
|
1845
|
-
process.exit(1)
|
|
1846
|
-
}
|
|
1847
|
-
if (localVal == "") {
|
|
1848
|
-
// Bare --local: guided setup. Non-interactive can't prompt, so keep the
|
|
1849
|
-
// print-catalog-and-exit behavior there.
|
|
1850
|
-
if (!isTTY()) {
|
|
1851
|
-
printLocalCatalog()
|
|
1852
|
-
process.exit(0)
|
|
1853
|
-
}
|
|
1854
|
-
if (!localModelsSupported()) {
|
|
1855
|
-
print(color.yellow("Local models need the smoltalk-llama-cpp package."))
|
|
1856
|
-
print("Install it, then re-run: ! npm i -g smoltalk-llama-cpp")
|
|
1857
|
-
process.exit(1)
|
|
1858
|
-
}
|
|
1859
|
-
let items: ChoiceItem[] = []
|
|
1860
|
-
for (modelName in listModelNames()) {
|
|
1861
|
-
items.push({
|
|
1862
|
-
key: modelName.name,
|
|
1863
|
-
label: modelName.name
|
|
1864
|
-
})
|
|
1865
|
-
}
|
|
1866
|
-
const choice = chooseOption(
|
|
1867
|
-
"Local model",
|
|
1868
|
-
"Pick a model, or type an hf: URI / .gguf path (downloads on first use):",
|
|
1869
|
-
items,
|
|
1870
|
-
allowFreeText: true,
|
|
1871
|
-
allowCancel: true,
|
|
1872
|
-
)
|
|
1873
|
-
if (choice == "" || choice == null) {
|
|
1874
|
-
process.exit(0)
|
|
1875
|
-
}
|
|
1876
|
-
configureLocalModel(choice)
|
|
1877
|
-
configureSearch(true)
|
|
1878
|
-
// fall through into the session on the chosen local model
|
|
1879
|
-
} else if (localVal != null) {
|
|
1880
|
-
configureLocalModel(localVal)
|
|
1881
|
-
configureSearch(true)
|
|
1882
|
-
} else {
|
|
1883
|
-
// Hosted path. --model accepts `slot=model` (per-slot) or a bare model
|
|
1884
|
-
// (global pin); explicit --fastmodel/--slowmodel win over a --model slot=.
|
|
1885
|
-
const parsed = parseModelFlag(modelArg)
|
|
1886
|
-
let modelGlobal = ""
|
|
1887
|
-
let fastFlag = ""
|
|
1888
|
-
let slowFlag = ""
|
|
1889
|
-
let embeddingFlag = ""
|
|
1890
|
-
if (modelArg != "") {
|
|
1891
|
-
if (parsed.slot == "") {
|
|
1892
|
-
modelGlobal = parsed.model
|
|
1893
|
-
} else if (parsed.slot == "main") {
|
|
1894
|
-
fastFlag = parsed.model
|
|
1895
|
-
} else if (parsed.slot == "reasoning") {
|
|
1896
|
-
slowFlag = parsed.model
|
|
1897
|
-
} else if (parsed.slot == "embedding") {
|
|
1898
|
-
if (!embeddingSpecHasProvider(parsed.model)) {
|
|
1899
|
-
print(
|
|
1900
|
-
color.red(
|
|
1901
|
-
"Embedding models need the provider/model form, e.g. --model embedding=openai/text-embedding-3-small.",
|
|
1902
|
-
),
|
|
1903
|
-
)
|
|
1904
|
-
process.exit(1)
|
|
1905
|
-
}
|
|
1906
|
-
embeddingFlag = parsed.model
|
|
1907
|
-
} else {
|
|
1908
|
-
print(
|
|
1909
|
-
color.red(
|
|
1910
|
-
"Unknown model slot '${parsed.slot}' in --model. Valid slots: ${SLOTS.join(", ")}.",
|
|
1911
|
-
),
|
|
1912
|
-
)
|
|
1913
|
-
process.exit(1)
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
const fm = args.flags.fastmodel ?? ""
|
|
1917
|
-
const sm = args.flags.slowmodel ?? ""
|
|
1918
|
-
if (fm != "") {
|
|
1919
|
-
fastFlag = fm
|
|
1920
|
-
}
|
|
1921
|
-
if (sm != "") {
|
|
1922
|
-
slowFlag = sm
|
|
1923
|
-
}
|
|
1924
|
-
configureModels(modelGlobal, fastFlag, slowFlag, embeddingFlag, args.flags.provider ?? "")
|
|
1925
|
-
configureSearch(false)
|
|
1926
|
-
}
|
|
222
|
+
pickModelsForAgent(args)
|
|
1927
223
|
|
|
1928
224
|
// Persistent knowledge graph, gated on the capability profile. Must run
|
|
1929
225
|
// before any handler/REPL is installed.
|
|
@@ -1939,83 +235,53 @@ node main() {
|
|
|
1939
235
|
const positionalQuery = args.positionals.join(" ")
|
|
1940
236
|
const hasQuery = positionalQuery != ""
|
|
1941
237
|
const startAgent = args.flags.agent ?? ""
|
|
238
|
+
// Validate the target subagent name up front (empty = coordinator).
|
|
239
|
+
if (startAgent != "" && !START_AGENTS.includes(startAgent)) {
|
|
240
|
+
print(
|
|
241
|
+
color.red(
|
|
242
|
+
"Unknown --agent value: ${startAgent}. Valid: ${START_AGENTS.join(", ")}",
|
|
243
|
+
),
|
|
244
|
+
)
|
|
245
|
+
process.exit(1)
|
|
246
|
+
}
|
|
247
|
+
|
|
1942
248
|
const wantInteractive = args.flags.interactive
|
|
1943
249
|
|
|
1944
250
|
// Seeded interactive: run the prompt as the first turn, then hand over the
|
|
1945
251
|
// REPL (needs a TTY + query, and not --print). Everything else is one-shot.
|
|
1946
252
|
const seededInteractive = wantInteractive && hasQuery && isTTY() && !args.flags.print
|
|
1947
|
-
const
|
|
253
|
+
const isOneShot = !seededInteractive && (args.flags.print || hasQuery || !isTTY())
|
|
1948
254
|
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
// is dispatched, so every (fork-seeded) subagent inherits them. setLlmOptions
|
|
1954
|
-
// merges only present keys, so this never clobbers the model defaults above.
|
|
1955
|
-
// Separate calls, each gated on its own value: setLlmOptions only skips
|
|
1956
|
-
// `undefined`, not `null`, so passing an absent key would clobber the bag.
|
|
1957
|
-
const maxRounds = resolveMaxToolCallRounds(args.flags["max-tool-call-rounds"] ?? null, runningOneShot)
|
|
255
|
+
const maxRounds = resolveMaxToolCallRounds(
|
|
256
|
+
args.flags["max-tool-call-rounds"] ?? null,
|
|
257
|
+
isOneShot,
|
|
258
|
+
)
|
|
1958
259
|
if (maxRounds != null) {
|
|
1959
|
-
setLlmOptions({
|
|
260
|
+
setLlmOptions({
|
|
261
|
+
maxToolCallRounds: maxRounds
|
|
262
|
+
})
|
|
1960
263
|
}
|
|
1961
264
|
const maxResultChars = args.flags["max-tool-result-chars"]
|
|
1962
265
|
if (maxResultChars != null) {
|
|
1963
|
-
setLlmOptions({
|
|
266
|
+
setLlmOptions({
|
|
267
|
+
maxToolResultChars: maxResultChars
|
|
268
|
+
})
|
|
1964
269
|
}
|
|
1965
270
|
|
|
1966
|
-
// Per-model default output cap from the capability profile. The hosted
|
|
1967
|
-
// default of 20000 carries the adaptive-thinking empty-reply fix that
|
|
1968
|
-
// used to live here as a TEMPORARY block. Local profiles cap lower.
|
|
1969
|
-
// Branch-scoped, so every subagent inherits it. A per-call
|
|
1970
|
-
// llm(..., { maxTokens }) still wins, e.g. the summarizer's 256.
|
|
1971
271
|
const capsMaxTokens = getCapabilities().maxTokens
|
|
1972
272
|
if (capsMaxTokens != null) {
|
|
1973
|
-
setLlmOptions({
|
|
273
|
+
setLlmOptions({
|
|
274
|
+
maxTokens: capsMaxTokens
|
|
275
|
+
})
|
|
1974
276
|
}
|
|
1975
277
|
|
|
1976
278
|
// One-shot autonomy: tell the code subagent there is no human to answer
|
|
1977
279
|
// questions and no next turn, so it must drive to a finished artifact.
|
|
1978
280
|
// Set before any dispatch so both the pinned `--agent code` path and the
|
|
1979
281
|
// coordinator (which calls codeAgent as a tool) pick it up.
|
|
1980
|
-
setCodeOneShot(
|
|
282
|
+
setCodeOneShot(isOneShot)
|
|
1981
283
|
|
|
1982
|
-
|
|
1983
|
-
if (startAgent != "" && !START_AGENTS.includes(startAgent)) {
|
|
1984
|
-
print(
|
|
1985
|
-
color.red(
|
|
1986
|
-
"Unknown --agent value: ${startAgent}. Valid: ${START_AGENTS.join(", ")}",
|
|
1987
|
-
),
|
|
1988
|
-
)
|
|
1989
|
-
process.exit(1)
|
|
1990
|
-
}
|
|
1991
|
-
|
|
1992
|
-
// Seeded interactive: run the given prompt as the first turn, then hand
|
|
1993
|
-
// the REPL to the user. Requires a seed prompt and a TTY (the REPL reads
|
|
1994
|
-
// stdin). `--print` wins if both are passed — its whole job is to print
|
|
1995
|
-
// and exit with no REPL. Without a TTY (or with `--print`) we fall
|
|
1996
|
-
// through to one-shot below; `--interactive` with no prompt falls through
|
|
1997
|
-
// to the plain REPL.
|
|
1998
|
-
if (seededInteractive) {
|
|
1999
|
-
setTitle("Agency Agent")
|
|
2000
|
-
clearScreen()
|
|
2001
|
-
printHeader()
|
|
2002
|
-
const seededHandler = setupSession(true)
|
|
2003
|
-
startInteractive(seededHandler, startAgent, positionalQuery)
|
|
2004
|
-
process.exit(0)
|
|
2005
|
-
}
|
|
2006
|
-
|
|
2007
|
-
// One-shot invocation: run one turn through the same agent the REPL uses
|
|
2008
|
-
// and write the reply to stdout. No banner, no REPL. Entered when
|
|
2009
|
-
// `--print` / `-p` is passed, a positional query is given, or stdin is
|
|
2010
|
-
// piped (no TTY) — so the agent behaves like a Unix filter:
|
|
2011
|
-
// `echo "..." | agency agent`. `--interactive` is NOT a one-shot trigger
|
|
2012
|
-
// on its own: with a TTY and no prompt it falls through to the plain
|
|
2013
|
-
// REPL; without a TTY the `!isTTY()` check below routes it here to
|
|
2014
|
-
// degrade gracefully. The prompt comes from the positional when present,
|
|
2015
|
-
// otherwise from stdin. (Title/clearScreen are skipped so piped output
|
|
2016
|
-
// stays free of escape codes.)
|
|
2017
|
-
const forceOneShot = args.flags.print || hasQuery
|
|
2018
|
-
if (forceOneShot || !isTTY()) {
|
|
284
|
+
if (isOneShot) {
|
|
2019
285
|
let prompt = positionalQuery
|
|
2020
286
|
if (!hasQuery) {
|
|
2021
287
|
const fromStdin = readStdin()
|
|
@@ -2025,17 +291,13 @@ node main() {
|
|
|
2025
291
|
prompt = fromStdin
|
|
2026
292
|
}
|
|
2027
293
|
print(oneShotAgent(startAgent, prompt))
|
|
2028
|
-
|
|
294
|
+
const roundedCost = "$${getCost().toFixed(4)}"
|
|
295
|
+
print(color.dim("\nSession cost: ${roundedCost}"))
|
|
296
|
+
} else {
|
|
297
|
+
setTitle("Agency Agent")
|
|
298
|
+
clearScreen()
|
|
299
|
+
print(getHeader())
|
|
300
|
+
const handler = setupSession(interactive: true)
|
|
301
|
+
startInteractive(handler, startAgent, positionalQuery)
|
|
2029
302
|
}
|
|
2030
|
-
|
|
2031
|
-
// Plain interactive REPL (no seed). `startInteractive` owns the runloop;
|
|
2032
|
-
// every Enter dispatches into `_runTurn` which calls `mainAgent`.
|
|
2033
|
-
// Interrupts raised during a turn propagate to the policy handler
|
|
2034
|
-
// installed by the enclosing `handle` block via the AsyncLocalStorage
|
|
2035
|
-
// handler stack.
|
|
2036
|
-
setTitle("Agency Agent")
|
|
2037
|
-
clearScreen()
|
|
2038
|
-
printHeader()
|
|
2039
|
-
const handler = setupSession(true)
|
|
2040
|
-
startInteractive(handler, "", "")
|
|
2041
303
|
}
|