@miller-tech/uap 1.0.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/LICENSE +21 -0
- package/README.md +888 -0
- package/dist/analyzers/index.d.ts +3 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +684 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/benchmarks/agents/naive-agent.d.ts +60 -0
- package/dist/benchmarks/agents/naive-agent.d.ts.map +1 -0
- package/dist/benchmarks/agents/naive-agent.js +144 -0
- package/dist/benchmarks/agents/naive-agent.js.map +1 -0
- package/dist/benchmarks/agents/uap-agent.d.ts +167 -0
- package/dist/benchmarks/agents/uap-agent.d.ts.map +1 -0
- package/dist/benchmarks/agents/uap-agent.js +437 -0
- package/dist/benchmarks/agents/uap-agent.js.map +1 -0
- package/dist/benchmarks/benchmark.d.ts +328 -0
- package/dist/benchmarks/benchmark.d.ts.map +1 -0
- package/dist/benchmarks/benchmark.js +112 -0
- package/dist/benchmarks/benchmark.js.map +1 -0
- package/dist/benchmarks/execution-verifier.d.ts +41 -0
- package/dist/benchmarks/execution-verifier.d.ts.map +1 -0
- package/dist/benchmarks/execution-verifier.js +340 -0
- package/dist/benchmarks/execution-verifier.js.map +1 -0
- package/dist/benchmarks/hierarchical-prompting.d.ts +37 -0
- package/dist/benchmarks/hierarchical-prompting.d.ts.map +1 -0
- package/dist/benchmarks/hierarchical-prompting.js +246 -0
- package/dist/benchmarks/hierarchical-prompting.js.map +1 -0
- package/dist/benchmarks/improved-benchmark.d.ts +89 -0
- package/dist/benchmarks/improved-benchmark.d.ts.map +1 -0
- package/dist/benchmarks/improved-benchmark.js +585 -0
- package/dist/benchmarks/improved-benchmark.js.map +1 -0
- package/dist/benchmarks/index.d.ts +11 -0
- package/dist/benchmarks/index.d.ts.map +1 -0
- package/dist/benchmarks/index.js +11 -0
- package/dist/benchmarks/index.js.map +1 -0
- package/dist/benchmarks/model-integration.d.ts +111 -0
- package/dist/benchmarks/model-integration.d.ts.map +1 -0
- package/dist/benchmarks/model-integration.js +904 -0
- package/dist/benchmarks/model-integration.js.map +1 -0
- package/dist/benchmarks/multi-turn-agent.d.ts +44 -0
- package/dist/benchmarks/multi-turn-agent.d.ts.map +1 -0
- package/dist/benchmarks/multi-turn-agent.js +254 -0
- package/dist/benchmarks/multi-turn-agent.js.map +1 -0
- package/dist/benchmarks/multi-turn-loop.d.ts +57 -0
- package/dist/benchmarks/multi-turn-loop.d.ts.map +1 -0
- package/dist/benchmarks/multi-turn-loop.js +167 -0
- package/dist/benchmarks/multi-turn-loop.js.map +1 -0
- package/dist/benchmarks/tasks.d.ts +19 -0
- package/dist/benchmarks/tasks.d.ts.map +1 -0
- package/dist/benchmarks/tasks.js +435 -0
- package/dist/benchmarks/tasks.js.map +1 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +546 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/llama-server-optimize.d.ts +18 -0
- package/dist/bin/llama-server-optimize.d.ts.map +1 -0
- package/dist/bin/llama-server-optimize.js +708 -0
- package/dist/bin/llama-server-optimize.js.map +1 -0
- package/dist/bin/policy.d.ts +3 -0
- package/dist/bin/policy.d.ts.map +1 -0
- package/dist/bin/policy.js +143 -0
- package/dist/bin/policy.js.map +1 -0
- package/dist/bin/tool-calls.d.ts +3 -0
- package/dist/bin/tool-calls.d.ts.map +1 -0
- package/dist/bin/tool-calls.js +4 -0
- package/dist/bin/tool-calls.js.map +1 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/web-browser.d.ts +30 -0
- package/dist/browser/web-browser.d.ts.map +1 -0
- package/dist/browser/web-browser.js +93 -0
- package/dist/browser/web-browser.js.map +1 -0
- package/dist/cli/agent.d.ts +20 -0
- package/dist/cli/agent.d.ts.map +1 -0
- package/dist/cli/agent.js +474 -0
- package/dist/cli/agent.js.map +1 -0
- package/dist/cli/analyze.d.ts +7 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +103 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/completion-gates.d.ts +51 -0
- package/dist/cli/completion-gates.d.ts.map +1 -0
- package/dist/cli/completion-gates.js +201 -0
- package/dist/cli/completion-gates.js.map +1 -0
- package/dist/cli/compliance.d.ts +8 -0
- package/dist/cli/compliance.d.ts.map +1 -0
- package/dist/cli/compliance.js +509 -0
- package/dist/cli/compliance.js.map +1 -0
- package/dist/cli/coord.d.ts +7 -0
- package/dist/cli/coord.d.ts.map +1 -0
- package/dist/cli/coord.js +138 -0
- package/dist/cli/coord.js.map +1 -0
- package/dist/cli/dashboard.d.ts +21 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +1508 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/deploy.d.ts +19 -0
- package/dist/cli/deploy.d.ts.map +1 -0
- package/dist/cli/deploy.js +387 -0
- package/dist/cli/deploy.js.map +1 -0
- package/dist/cli/droids.d.ts +9 -0
- package/dist/cli/droids.d.ts.map +1 -0
- package/dist/cli/droids.js +227 -0
- package/dist/cli/droids.js.map +1 -0
- package/dist/cli/generate.d.ts +17 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +432 -0
- package/dist/cli/generate.js.map +1 -0
- package/dist/cli/hooks.d.ts +9 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +464 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/init.d.ts +12 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +364 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/mcp-router.d.ts +16 -0
- package/dist/cli/mcp-router.d.ts.map +1 -0
- package/dist/cli/mcp-router.js +143 -0
- package/dist/cli/mcp-router.js.map +1 -0
- package/dist/cli/memory.d.ts +24 -0
- package/dist/cli/memory.d.ts.map +1 -0
- package/dist/cli/memory.js +885 -0
- package/dist/cli/memory.js.map +1 -0
- package/dist/cli/model.d.ts +15 -0
- package/dist/cli/model.d.ts.map +1 -0
- package/dist/cli/model.js +290 -0
- package/dist/cli/model.js.map +1 -0
- package/dist/cli/patterns.d.ts +26 -0
- package/dist/cli/patterns.d.ts.map +1 -0
- package/dist/cli/patterns.js +862 -0
- package/dist/cli/patterns.js.map +1 -0
- package/dist/cli/rtk-validation.d.ts +9 -0
- package/dist/cli/rtk-validation.d.ts.map +1 -0
- package/dist/cli/rtk-validation.js +9 -0
- package/dist/cli/rtk-validation.js.map +1 -0
- package/dist/cli/rtk.d.ts +34 -0
- package/dist/cli/rtk.d.ts.map +1 -0
- package/dist/cli/rtk.js +401 -0
- package/dist/cli/rtk.js.map +1 -0
- package/dist/cli/schema-diff.d.ts +7 -0
- package/dist/cli/schema-diff.d.ts.map +1 -0
- package/dist/cli/schema-diff.js +11 -0
- package/dist/cli/schema-diff.js.map +1 -0
- package/dist/cli/setup-mcp-router.d.ts +8 -0
- package/dist/cli/setup-mcp-router.d.ts.map +1 -0
- package/dist/cli/setup-mcp-router.js +163 -0
- package/dist/cli/setup-mcp-router.js.map +1 -0
- package/dist/cli/setup-wizard.d.ts +2 -0
- package/dist/cli/setup-wizard.d.ts.map +1 -0
- package/dist/cli/setup-wizard.js +806 -0
- package/dist/cli/setup-wizard.js.map +1 -0
- package/dist/cli/setup.d.ts +15 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +154 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/sync.d.ts +8 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +395 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/task.d.ts +33 -0
- package/dist/cli/task.d.ts.map +1 -0
- package/dist/cli/task.js +672 -0
- package/dist/cli/task.js.map +1 -0
- package/dist/cli/tool-calls.d.ts +20 -0
- package/dist/cli/tool-calls.d.ts.map +1 -0
- package/dist/cli/tool-calls.js +605 -0
- package/dist/cli/tool-calls.js.map +1 -0
- package/dist/cli/uap.d.ts +10 -0
- package/dist/cli/uap.d.ts.map +1 -0
- package/dist/cli/uap.js +398 -0
- package/dist/cli/uap.js.map +1 -0
- package/dist/cli/update.d.ts +10 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +300 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/visualize.d.ts +77 -0
- package/dist/cli/visualize.d.ts.map +1 -0
- package/dist/cli/visualize.js +287 -0
- package/dist/cli/visualize.js.map +1 -0
- package/dist/cli/worktree.d.ts +9 -0
- package/dist/cli/worktree.d.ts.map +1 -0
- package/dist/cli/worktree.js +213 -0
- package/dist/cli/worktree.js.map +1 -0
- package/dist/coordination/adaptive-patterns.d.ts +65 -0
- package/dist/coordination/adaptive-patterns.d.ts.map +1 -0
- package/dist/coordination/adaptive-patterns.js +108 -0
- package/dist/coordination/adaptive-patterns.js.map +1 -0
- package/dist/coordination/auto-agent.d.ts +82 -0
- package/dist/coordination/auto-agent.d.ts.map +1 -0
- package/dist/coordination/auto-agent.js +145 -0
- package/dist/coordination/auto-agent.js.map +1 -0
- package/dist/coordination/capability-router.d.ts +79 -0
- package/dist/coordination/capability-router.d.ts.map +1 -0
- package/dist/coordination/capability-router.js +334 -0
- package/dist/coordination/capability-router.js.map +1 -0
- package/dist/coordination/database.d.ts +13 -0
- package/dist/coordination/database.d.ts.map +1 -0
- package/dist/coordination/database.js +136 -0
- package/dist/coordination/database.js.map +1 -0
- package/dist/coordination/deploy-batcher.d.ts +122 -0
- package/dist/coordination/deploy-batcher.d.ts.map +1 -0
- package/dist/coordination/deploy-batcher.js +718 -0
- package/dist/coordination/deploy-batcher.js.map +1 -0
- package/dist/coordination/droid-validator.d.ts +59 -0
- package/dist/coordination/droid-validator.d.ts.map +1 -0
- package/dist/coordination/droid-validator.js +142 -0
- package/dist/coordination/droid-validator.js.map +1 -0
- package/dist/coordination/index.d.ts +10 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +10 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/pattern-router.d.ts +50 -0
- package/dist/coordination/pattern-router.d.ts.map +1 -0
- package/dist/coordination/pattern-router.js +118 -0
- package/dist/coordination/pattern-router.js.map +1 -0
- package/dist/coordination/service.d.ts +81 -0
- package/dist/coordination/service.d.ts.map +1 -0
- package/dist/coordination/service.js +619 -0
- package/dist/coordination/service.js.map +1 -0
- package/dist/coordination/worktree-enforcer.d.ts +22 -0
- package/dist/coordination/worktree-enforcer.d.ts.map +1 -0
- package/dist/coordination/worktree-enforcer.js +71 -0
- package/dist/coordination/worktree-enforcer.js.map +1 -0
- package/dist/generators/claude-md.d.ts +3 -0
- package/dist/generators/claude-md.d.ts.map +1 -0
- package/dist/generators/claude-md.js +1020 -0
- package/dist/generators/claude-md.js.map +1 -0
- package/dist/generators/template-loader.d.ts +105 -0
- package/dist/generators/template-loader.d.ts.map +1 -0
- package/dist/generators/template-loader.js +291 -0
- package/dist/generators/template-loader.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-router/config/parser.d.ts +9 -0
- package/dist/mcp-router/config/parser.d.ts.map +1 -0
- package/dist/mcp-router/config/parser.js +174 -0
- package/dist/mcp-router/config/parser.js.map +1 -0
- package/dist/mcp-router/executor/client.d.ts +31 -0
- package/dist/mcp-router/executor/client.d.ts.map +1 -0
- package/dist/mcp-router/executor/client.js +189 -0
- package/dist/mcp-router/executor/client.js.map +1 -0
- package/dist/mcp-router/index.d.ts +22 -0
- package/dist/mcp-router/index.d.ts.map +1 -0
- package/dist/mcp-router/index.js +18 -0
- package/dist/mcp-router/index.js.map +1 -0
- package/dist/mcp-router/output-compressor.d.ts +26 -0
- package/dist/mcp-router/output-compressor.d.ts.map +1 -0
- package/dist/mcp-router/output-compressor.js +236 -0
- package/dist/mcp-router/output-compressor.js.map +1 -0
- package/dist/mcp-router/search/fuzzy.d.ts +26 -0
- package/dist/mcp-router/search/fuzzy.d.ts.map +1 -0
- package/dist/mcp-router/search/fuzzy.js +94 -0
- package/dist/mcp-router/search/fuzzy.js.map +1 -0
- package/dist/mcp-router/server.d.ts +50 -0
- package/dist/mcp-router/server.d.ts.map +1 -0
- package/dist/mcp-router/server.js +229 -0
- package/dist/mcp-router/server.js.map +1 -0
- package/dist/mcp-router/session-stats.d.ts +37 -0
- package/dist/mcp-router/session-stats.d.ts.map +1 -0
- package/dist/mcp-router/session-stats.js +56 -0
- package/dist/mcp-router/session-stats.js.map +1 -0
- package/dist/mcp-router/tools/discover.d.ts +37 -0
- package/dist/mcp-router/tools/discover.d.ts.map +1 -0
- package/dist/mcp-router/tools/discover.js +65 -0
- package/dist/mcp-router/tools/discover.js.map +1 -0
- package/dist/mcp-router/tools/execute.d.ts +43 -0
- package/dist/mcp-router/tools/execute.d.ts.map +1 -0
- package/dist/mcp-router/tools/execute.js +144 -0
- package/dist/mcp-router/tools/execute.js.map +1 -0
- package/dist/mcp-router/types.d.ts +62 -0
- package/dist/mcp-router/types.d.ts.map +1 -0
- package/dist/mcp-router/types.js +6 -0
- package/dist/mcp-router/types.js.map +1 -0
- package/dist/memory/adaptive-context.d.ts +149 -0
- package/dist/memory/adaptive-context.d.ts.map +1 -0
- package/dist/memory/adaptive-context.js +1095 -0
- package/dist/memory/adaptive-context.js.map +1 -0
- package/dist/memory/agent-scoped-memory.d.ts +67 -0
- package/dist/memory/agent-scoped-memory.d.ts.map +1 -0
- package/dist/memory/agent-scoped-memory.js +126 -0
- package/dist/memory/agent-scoped-memory.js.map +1 -0
- package/dist/memory/ambiguity-detector.d.ts +54 -0
- package/dist/memory/ambiguity-detector.d.ts.map +1 -0
- package/dist/memory/ambiguity-detector.js +401 -0
- package/dist/memory/ambiguity-detector.js.map +1 -0
- package/dist/memory/backends/base.d.ts +18 -0
- package/dist/memory/backends/base.d.ts.map +1 -0
- package/dist/memory/backends/base.js +2 -0
- package/dist/memory/backends/base.js.map +1 -0
- package/dist/memory/backends/factory.d.ts +4 -0
- package/dist/memory/backends/factory.d.ts.map +1 -0
- package/dist/memory/backends/factory.js +53 -0
- package/dist/memory/backends/factory.js.map +1 -0
- package/dist/memory/backends/github.d.ts +27 -0
- package/dist/memory/backends/github.d.ts.map +1 -0
- package/dist/memory/backends/github.js +134 -0
- package/dist/memory/backends/github.js.map +1 -0
- package/dist/memory/backends/qdrant-cloud.d.ts +32 -0
- package/dist/memory/backends/qdrant-cloud.d.ts.map +1 -0
- package/dist/memory/backends/qdrant-cloud.js +167 -0
- package/dist/memory/backends/qdrant-cloud.js.map +1 -0
- package/dist/memory/context-compressor.d.ts +116 -0
- package/dist/memory/context-compressor.d.ts.map +1 -0
- package/dist/memory/context-compressor.js +430 -0
- package/dist/memory/context-compressor.js.map +1 -0
- package/dist/memory/context-pruner.d.ts +55 -0
- package/dist/memory/context-pruner.d.ts.map +1 -0
- package/dist/memory/context-pruner.js +85 -0
- package/dist/memory/context-pruner.js.map +1 -0
- package/dist/memory/correction-propagator.d.ts +44 -0
- package/dist/memory/correction-propagator.d.ts.map +1 -0
- package/dist/memory/correction-propagator.js +156 -0
- package/dist/memory/correction-propagator.js.map +1 -0
- package/dist/memory/daily-log.d.ts +67 -0
- package/dist/memory/daily-log.d.ts.map +1 -0
- package/dist/memory/daily-log.js +143 -0
- package/dist/memory/daily-log.js.map +1 -0
- package/dist/memory/dynamic-retrieval.d.ts +112 -0
- package/dist/memory/dynamic-retrieval.d.ts.map +1 -0
- package/dist/memory/dynamic-retrieval.js +908 -0
- package/dist/memory/dynamic-retrieval.js.map +1 -0
- package/dist/memory/embeddings.d.ts +172 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +780 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/generic-uap-patterns.d.ts +7 -0
- package/dist/memory/generic-uap-patterns.d.ts.map +1 -0
- package/dist/memory/generic-uap-patterns.js +43 -0
- package/dist/memory/generic-uap-patterns.js.map +1 -0
- package/dist/memory/hierarchical-memory.d.ts +141 -0
- package/dist/memory/hierarchical-memory.d.ts.map +1 -0
- package/dist/memory/hierarchical-memory.js +485 -0
- package/dist/memory/hierarchical-memory.js.map +1 -0
- package/dist/memory/knowledge-graph.d.ts +98 -0
- package/dist/memory/knowledge-graph.d.ts.map +1 -0
- package/dist/memory/knowledge-graph.js +275 -0
- package/dist/memory/knowledge-graph.js.map +1 -0
- package/dist/memory/memory-consolidator.d.ts +124 -0
- package/dist/memory/memory-consolidator.d.ts.map +1 -0
- package/dist/memory/memory-consolidator.js +514 -0
- package/dist/memory/memory-consolidator.js.map +1 -0
- package/dist/memory/memory-maintenance.d.ts +39 -0
- package/dist/memory/memory-maintenance.d.ts.map +1 -0
- package/dist/memory/memory-maintenance.js +336 -0
- package/dist/memory/memory-maintenance.js.map +1 -0
- package/dist/memory/model-router.d.ts +105 -0
- package/dist/memory/model-router.d.ts.map +1 -0
- package/dist/memory/model-router.js +474 -0
- package/dist/memory/model-router.js.map +1 -0
- package/dist/memory/multi-view-memory.d.ts +134 -0
- package/dist/memory/multi-view-memory.d.ts.map +1 -0
- package/dist/memory/multi-view-memory.js +430 -0
- package/dist/memory/multi-view-memory.js.map +1 -0
- package/dist/memory/predictive-memory.d.ts +79 -0
- package/dist/memory/predictive-memory.d.ts.map +1 -0
- package/dist/memory/predictive-memory.js +294 -0
- package/dist/memory/predictive-memory.js.map +1 -0
- package/dist/memory/prepopulate.d.ts +76 -0
- package/dist/memory/prepopulate.d.ts.map +1 -0
- package/dist/memory/prepopulate.js +832 -0
- package/dist/memory/prepopulate.js.map +1 -0
- package/dist/memory/semantic-compression.d.ts +77 -0
- package/dist/memory/semantic-compression.d.ts.map +1 -0
- package/dist/memory/semantic-compression.js +359 -0
- package/dist/memory/semantic-compression.js.map +1 -0
- package/dist/memory/serverless-qdrant.d.ts +102 -0
- package/dist/memory/serverless-qdrant.d.ts.map +1 -0
- package/dist/memory/serverless-qdrant.js +369 -0
- package/dist/memory/serverless-qdrant.js.map +1 -0
- package/dist/memory/short-term/factory.d.ts +26 -0
- package/dist/memory/short-term/factory.d.ts.map +1 -0
- package/dist/memory/short-term/factory.js +28 -0
- package/dist/memory/short-term/factory.js.map +1 -0
- package/dist/memory/short-term/indexeddb.d.ts +25 -0
- package/dist/memory/short-term/indexeddb.d.ts.map +1 -0
- package/dist/memory/short-term/indexeddb.js +64 -0
- package/dist/memory/short-term/indexeddb.js.map +1 -0
- package/dist/memory/short-term/schema.d.ts +6 -0
- package/dist/memory/short-term/schema.d.ts.map +1 -0
- package/dist/memory/short-term/schema.js +141 -0
- package/dist/memory/short-term/schema.js.map +1 -0
- package/dist/memory/short-term/sqlite.d.ts +64 -0
- package/dist/memory/short-term/sqlite.d.ts.map +1 -0
- package/dist/memory/short-term/sqlite.js +274 -0
- package/dist/memory/short-term/sqlite.js.map +1 -0
- package/dist/memory/speculative-cache.d.ts +111 -0
- package/dist/memory/speculative-cache.d.ts.map +1 -0
- package/dist/memory/speculative-cache.js +457 -0
- package/dist/memory/speculative-cache.js.map +1 -0
- package/dist/memory/task-classifier.d.ts +40 -0
- package/dist/memory/task-classifier.d.ts.map +1 -0
- package/dist/memory/task-classifier.js +342 -0
- package/dist/memory/task-classifier.js.map +1 -0
- package/dist/memory/terminal-bench-knowledge.d.ts +48 -0
- package/dist/memory/terminal-bench-knowledge.d.ts.map +1 -0
- package/dist/memory/terminal-bench-knowledge.js +622 -0
- package/dist/memory/terminal-bench-knowledge.js.map +1 -0
- package/dist/memory/write-gate.d.ts +39 -0
- package/dist/memory/write-gate.d.ts.map +1 -0
- package/dist/memory/write-gate.js +190 -0
- package/dist/memory/write-gate.js.map +1 -0
- package/dist/models/api-client.d.ts +46 -0
- package/dist/models/api-client.d.ts.map +1 -0
- package/dist/models/api-client.js +182 -0
- package/dist/models/api-client.js.map +1 -0
- package/dist/models/execution-profiles.d.ts +64 -0
- package/dist/models/execution-profiles.d.ts.map +1 -0
- package/dist/models/execution-profiles.js +403 -0
- package/dist/models/execution-profiles.js.map +1 -0
- package/dist/models/executor.d.ts +130 -0
- package/dist/models/executor.d.ts.map +1 -0
- package/dist/models/executor.js +382 -0
- package/dist/models/executor.js.map +1 -0
- package/dist/models/index.d.ts +19 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +23 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/plan-validator.d.ts +37 -0
- package/dist/models/plan-validator.d.ts.map +1 -0
- package/dist/models/plan-validator.js +179 -0
- package/dist/models/plan-validator.js.map +1 -0
- package/dist/models/planner.d.ts +73 -0
- package/dist/models/planner.d.ts.map +1 -0
- package/dist/models/planner.js +375 -0
- package/dist/models/planner.js.map +1 -0
- package/dist/models/router.d.ts +96 -0
- package/dist/models/router.d.ts.map +1 -0
- package/dist/models/router.js +523 -0
- package/dist/models/router.js.map +1 -0
- package/dist/models/types.d.ts +370 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +232 -0
- package/dist/models/types.js.map +1 -0
- package/dist/models/unified-router.d.ts +152 -0
- package/dist/models/unified-router.d.ts.map +1 -0
- package/dist/models/unified-router.js +313 -0
- package/dist/models/unified-router.js.map +1 -0
- package/dist/policies/convert-policy-to-claude.d.ts +3 -0
- package/dist/policies/convert-policy-to-claude.d.ts.map +1 -0
- package/dist/policies/convert-policy-to-claude.js +87 -0
- package/dist/policies/convert-policy-to-claude.js.map +1 -0
- package/dist/policies/database-manager.d.ts +27 -0
- package/dist/policies/database-manager.d.ts.map +1 -0
- package/dist/policies/database-manager.js +198 -0
- package/dist/policies/database-manager.js.map +1 -0
- package/dist/policies/enforced-tool-router.d.ts +53 -0
- package/dist/policies/enforced-tool-router.d.ts.map +1 -0
- package/dist/policies/enforced-tool-router.js +80 -0
- package/dist/policies/enforced-tool-router.js.map +1 -0
- package/dist/policies/index.d.ts +10 -0
- package/dist/policies/index.d.ts.map +1 -0
- package/dist/policies/index.js +8 -0
- package/dist/policies/index.js.map +1 -0
- package/dist/policies/policy-gate.d.ts +59 -0
- package/dist/policies/policy-gate.d.ts.map +1 -0
- package/dist/policies/policy-gate.js +171 -0
- package/dist/policies/policy-gate.js.map +1 -0
- package/dist/policies/policy-memory.d.ts +18 -0
- package/dist/policies/policy-memory.d.ts.map +1 -0
- package/dist/policies/policy-memory.js +126 -0
- package/dist/policies/policy-memory.js.map +1 -0
- package/dist/policies/policy-tools.d.ts +11 -0
- package/dist/policies/policy-tools.d.ts.map +1 -0
- package/dist/policies/policy-tools.js +66 -0
- package/dist/policies/policy-tools.js.map +1 -0
- package/dist/policies/schemas/policy.d.ts +69 -0
- package/dist/policies/schemas/policy.d.ts.map +1 -0
- package/dist/policies/schemas/policy.js +31 -0
- package/dist/policies/schemas/policy.js.map +1 -0
- package/dist/tasks/coordination.d.ts +83 -0
- package/dist/tasks/coordination.d.ts.map +1 -0
- package/dist/tasks/coordination.js +291 -0
- package/dist/tasks/coordination.js.map +1 -0
- package/dist/tasks/database.d.ts +19 -0
- package/dist/tasks/database.d.ts.map +1 -0
- package/dist/tasks/database.js +149 -0
- package/dist/tasks/database.js.map +1 -0
- package/dist/tasks/decoder-gate.d.ts +64 -0
- package/dist/tasks/decoder-gate.d.ts.map +1 -0
- package/dist/tasks/decoder-gate.js +268 -0
- package/dist/tasks/decoder-gate.js.map +1 -0
- package/dist/tasks/index.d.ts +6 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +6 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/tasks/service.d.ts +40 -0
- package/dist/tasks/service.d.ts.map +1 -0
- package/dist/tasks/service.js +671 -0
- package/dist/tasks/service.js.map +1 -0
- package/dist/tasks/types.d.ts +238 -0
- package/dist/tasks/types.d.ts.map +1 -0
- package/dist/tasks/types.js +74 -0
- package/dist/tasks/types.js.map +1 -0
- package/dist/telemetry/index.d.ts +2 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +2 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/session-telemetry.d.ts +56 -0
- package/dist/telemetry/session-telemetry.d.ts.map +1 -0
- package/dist/telemetry/session-telemetry.js +807 -0
- package/dist/telemetry/session-telemetry.js.map +1 -0
- package/dist/types/analysis.d.ts +82 -0
- package/dist/types/analysis.d.ts.map +1 -0
- package/dist/types/analysis.js +2 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/types/config.d.ts +3324 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +418 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/coordination.d.ts +240 -0
- package/dist/types/coordination.d.ts.map +1 -0
- package/dist/types/coordination.js +43 -0
- package/dist/types/coordination.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/uap-droids-strict.d.ts +59 -0
- package/dist/uap-droids-strict.d.ts.map +1 -0
- package/dist/uap-droids-strict.js +200 -0
- package/dist/uap-droids-strict.js.map +1 -0
- package/dist/utils/config-manager.d.ts +30 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +41 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/fetch-with-retry.d.ts +5 -0
- package/dist/utils/fetch-with-retry.d.ts.map +1 -0
- package/dist/utils/fetch-with-retry.js +61 -0
- package/dist/utils/fetch-with-retry.js.map +1 -0
- package/dist/utils/merge-claude-md.d.ts +28 -0
- package/dist/utils/merge-claude-md.d.ts.map +1 -0
- package/dist/utils/merge-claude-md.js +342 -0
- package/dist/utils/merge-claude-md.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +58 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +100 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/string-similarity.d.ts +37 -0
- package/dist/utils/string-similarity.d.ts.map +1 -0
- package/dist/utils/string-similarity.js +114 -0
- package/dist/utils/string-similarity.js.map +1 -0
- package/dist/utils/validate-json.d.ts +51 -0
- package/dist/utils/validate-json.d.ts.map +1 -0
- package/dist/utils/validate-json.js +94 -0
- package/dist/utils/validate-json.js.map +1 -0
- package/docs/INDEX.md +66 -0
- package/docs/architecture/MULTI_MODEL.md +224 -0
- package/docs/architecture/SYSTEM_ANALYSIS.md +1117 -0
- package/docs/architecture/UAP_COMPLIANCE.md +217 -0
- package/docs/architecture/UAP_PROTOCOL.md +339 -0
- package/docs/architecture/UAP_STRICT_DROIDS.md +172 -0
- package/docs/archive/BALLS_MODE_SELF_ANALYSIS.md +260 -0
- package/docs/archive/FAILING_TASKS_SOLUTION_PLAN.md +668 -0
- package/docs/archive/JINJA2-SYSTEM-MESSAGE-FIX.md +209 -0
- package/docs/archive/NPM-PUBLISH-V0.9.1.md +240 -0
- package/docs/archive/OPTIMIZATION_OPTIONS.md +334 -0
- package/docs/archive/SETUP_IMPROVEMENTS.md +213 -0
- package/docs/archive/UAP_GENERIC_OPTIMIZATION_PLAN.md +270 -0
- package/docs/archive/UAP_V103_PATTERN_DESIGN.md +315 -0
- package/docs/archive/UAP_V104_COMPLIANCE_DESIGN.md +223 -0
- package/docs/archive/changelog/2026-03-10_uap-100-compliance.md +77 -0
- package/docs/archive/changelog/2026-03-10_uap-full-system-verification.md +109 -0
- package/docs/benchmarks/ACCURACY_ANALYSIS.md +471 -0
- package/docs/benchmarks/TOKEN_OPTIMIZATION.md +572 -0
- package/docs/benchmarks/VALIDATION_PLAN.md +568 -0
- package/docs/benchmarks/VALIDATION_RESULTS.md +161 -0
- package/docs/deployment/DEPLOYMENT.md +895 -0
- package/docs/deployment/DEPLOYMENT_STRATEGIES.md +518 -0
- package/docs/deployment/DEPLOY_BATCHER_ANALYSIS.md +856 -0
- package/docs/deployment/DEPLOY_BATCHING.md +273 -0
- package/docs/deployment/DEPLOY_BUCKETING_ANALYSIS.md +420 -0
- package/docs/deployment/QWEN35_LLAMA_CPP.md +265 -0
- package/docs/getting-started/INTEGRATION.md +449 -0
- package/docs/getting-started/OVERVIEW.md +344 -0
- package/docs/getting-started/SETUP.md +203 -0
- package/docs/integrations/MCP_ROUTER_SETUP.md +445 -0
- package/docs/integrations/RTK_INTEGRATION.md +468 -0
- package/docs/operations/TROUBLESHOOTING.md +660 -0
- package/docs/reference/API_REFERENCE.md +903 -0
- package/docs/reference/FEATURES.md +472 -0
- package/docs/reference/HARNESS-MATRIX.md +318 -0
- package/docs/reference/UAP_CLI_REFERENCE.md +600 -0
- package/docs/research/BEHAVIORAL_PATTERNS.md +228 -0
- package/docs/research/DOMAIN_STRATEGIES.md +316 -0
- package/docs/research/MEMORY_SYSTEMS_COMPARISON.md +812 -0
- package/docs/research/PATTERN_ANALYSIS_2026-01-18.md +436 -0
- package/docs/research/PERFORMANCE_ANALYSIS_2026-01-18.md +209 -0
- package/docs/research/PERFORMANCE_TEST_PLAN.md +383 -0
- package/docs/research/TERMINAL_BENCH_LEARNINGS.md +217 -0
- package/package.json +113 -0
- package/scripts/README.md +161 -0
- package/templates/CLAUDE.template.md +10 -0
- package/templates/CLAUDE_ARCHITECTURE.template.md +103 -0
- package/templates/CLAUDE_CODING.template.md +127 -0
- package/templates/CLAUDE_DROIDS.template.md +109 -0
- package/templates/CLAUDE_MEMORY.template.md +131 -0
- package/templates/CLAUDE_WORKFLOWS.template.md +139 -0
- package/templates/PROJECT.template.md +209 -0
- package/templates/SCHEMA.md +57 -0
- package/templates/archive/CLAUDE.template.root-v6.md +534 -0
- package/templates/archive/CLAUDE.template.v6.md +534 -0
- package/templates/hooks/forgecode/pre-compact.sh +68 -0
- package/templates/hooks/forgecode/session-start.sh +169 -0
- package/templates/hooks/forgecode.plugin.sh +128 -0
- package/templates/hooks/pre-compact.sh +74 -0
- package/templates/hooks/session-start.sh +366 -0
- package/tools/agents/README.md +224 -0
- package/tools/agents/UAP/README.md +386 -0
- package/tools/agents/UAP/__init__.py +9 -0
- package/tools/agents/UAP/cli.py +901 -0
- package/tools/agents/UAP/compliance_verify.sh +108 -0
- package/tools/agents/UAP/full_verification.sh +126 -0
- package/tools/agents/UAP/version.py +32 -0
- package/tools/agents/benchmarks/benchmark_memory_systems.py +730 -0
- package/tools/agents/benchmarks/results/benchmark_20260106_064817.json +170 -0
- package/tools/agents/benchmarks/results/benchmark_20260106_064817.md +51 -0
- package/tools/agents/config/chat_template.jinja +77 -0
- package/tools/agents/config/tool-call-schema.json +19 -0
- package/tools/agents/config/tool-call.gbnf +58 -0
- package/tools/agents/docker/Dockerfile.python +52 -0
- package/tools/agents/docker/Dockerfile.ubuntu +55 -0
- package/tools/agents/docker-compose.qdrant.yml +24 -0
- package/tools/agents/install-opencode-local.sh.j2 +135 -0
- package/tools/agents/migrations/apply.py +256 -0
- package/tools/agents/opencode_uap_agent.py +1505 -0
- package/tools/agents/plugin/README.md +91 -0
- package/tools/agents/plugin/index.ts +46 -0
- package/tools/agents/plugin/pre-compact.sh +68 -0
- package/tools/agents/plugin/session-start.sh +175 -0
- package/tools/agents/plugin/uap-commands.ts +45 -0
- package/tools/agents/plugin/uap-droids.ts +54 -0
- package/tools/agents/plugin/uap-patterns.ts +54 -0
- package/tools/agents/plugin/uap-skills.ts +52 -0
- package/tools/agents/plugins/uap-enforce.ts +314 -0
- package/tools/agents/scripts/__pycache__/tool_call_wrapper.cpython-313.pyc +0 -0
- package/tools/agents/scripts/chat_template_verifier.py +343 -0
- package/tools/agents/scripts/fix-qwen-template.js +38 -0
- package/tools/agents/scripts/fix_qwen_chat_template.py +316 -0
- package/tools/agents/scripts/generate_lora_training_data.py +412 -0
- package/tools/agents/scripts/init_qdrant.py +151 -0
- package/tools/agents/scripts/memory_migration.py +560 -0
- package/tools/agents/scripts/migrate_memory_to_qdrant.py +110 -0
- package/tools/agents/scripts/prepare_lora.sh +512 -0
- package/tools/agents/scripts/query_memory.py +200 -0
- package/tools/agents/scripts/qwen-tool-call-test.js +38 -0
- package/tools/agents/scripts/qwen-tool-call-wrapper.js +38 -0
- package/tools/agents/scripts/qwen_tool_call_test.py +464 -0
- package/tools/agents/scripts/qwen_tool_call_wrapper.py +686 -0
- package/tools/agents/scripts/start-services.sh +96 -0
- package/tools/agents/scripts/tool-choice-proxy.cjs +296 -0
- package/tools/agents/scripts/tool_call_test.py +656 -0
- package/tools/agents/scripts/tool_call_wrapper.py +799 -0
- package/tools/agents/tests/test_uap_compliance.py +257 -0
- package/tools/agents/uap_agent.py +122 -0
- package/tools/agents/uap_agent_install.sh +12 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import type { Plugin } from '@opencode-ai/plugin';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Layer 2: UAP Enforcement Plugin for OpenCode (v1.0.0)
|
|
5
|
+
*
|
|
6
|
+
* ARCHITECTURE: PREPEND-NOT-REPLACE
|
|
7
|
+
* The loop breaker PREPENDS warning messages to commands but NEVER replaces them.
|
|
8
|
+
* This ensures the agent's actual work always executes, even during loop detection.
|
|
9
|
+
* The agent sees the warning in the output and can adjust its approach.
|
|
10
|
+
*
|
|
11
|
+
* 1. Loop Detection (ALL tool types):
|
|
12
|
+
* - Tracks tool calls by full-content fingerprint
|
|
13
|
+
* - bash: prepends warning echo, then runs the actual command
|
|
14
|
+
* - write/edit: lets the write through but prepends warning to next bash call
|
|
15
|
+
* - read: lets the read through but prepends warning to next bash call
|
|
16
|
+
* - Escape hatch: after 3 consecutive warnings, resets fingerprint history
|
|
17
|
+
*
|
|
18
|
+
* 2. Hard Tool-Call Budget:
|
|
19
|
+
* - After 30 tool calls, prepends "WRAP UP NOW" warning
|
|
20
|
+
* - Proxy (Layer 1) handles actual termination at 50 calls
|
|
21
|
+
*
|
|
22
|
+
* 3. Telemetry:
|
|
23
|
+
* - Logs all tool calls to /tmp/uap-telemetry.jsonl
|
|
24
|
+
*/
|
|
25
|
+
export const UapEnforce: Plugin = async ({ $ }) => {
|
|
26
|
+
const recentFingerprints: string[] = [];
|
|
27
|
+
const recentOutputHashes: string[] = [];
|
|
28
|
+
const MAX_HISTORY = 20;
|
|
29
|
+
const LOOP_THRESHOLD = 3;
|
|
30
|
+
|
|
31
|
+
// Escape hatch: track consecutive loop warnings
|
|
32
|
+
let consecutiveLoopWarnings = 0;
|
|
33
|
+
const ESCAPE_HATCH_THRESHOLD = 3;
|
|
34
|
+
|
|
35
|
+
// Pending warning: queued from write/read loops, prepended to next bash call
|
|
36
|
+
let pendingWarning: string | null = null;
|
|
37
|
+
|
|
38
|
+
// Track write content hashes
|
|
39
|
+
const recentWriteHashes: string[] = [];
|
|
40
|
+
|
|
41
|
+
let totalToolCalls = 0;
|
|
42
|
+
const SOFT_BUDGET = 30;
|
|
43
|
+
|
|
44
|
+
const TELEMETRY_PATH = '/tmp/uap-telemetry.jsonl';
|
|
45
|
+
|
|
46
|
+
const simpleHash = (s: string): string => {
|
|
47
|
+
let h = 0;
|
|
48
|
+
for (let i = 0; i < Math.min(s.length, 2000); i++) {
|
|
49
|
+
h = ((h << 5) - h + s.charCodeAt(i)) | 0;
|
|
50
|
+
}
|
|
51
|
+
return String(h);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Write initial telemetry entry
|
|
55
|
+
await $`echo '{"event":"plugin_loaded","version":"1.0.0","ts":"'$(date -Iseconds)'"}' >> ${TELEMETRY_PATH}`
|
|
56
|
+
.quiet()
|
|
57
|
+
.nothrow();
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
'tool.execute.before': async (input, output) => {
|
|
61
|
+
totalToolCalls++;
|
|
62
|
+
|
|
63
|
+
// --- Worktree enforcement (Layer 4) ---
|
|
64
|
+
// Warn when file writes happen outside a worktree
|
|
65
|
+
if ((input.tool === 'write' || input.tool === 'edit') && output.args?.filePath) {
|
|
66
|
+
const filePath = String(output.args.filePath);
|
|
67
|
+
const isInWorktree = filePath.includes('.worktrees/') || filePath.includes('/.worktrees/');
|
|
68
|
+
if (!isInWorktree) {
|
|
69
|
+
try {
|
|
70
|
+
// Check if worktrees are enabled and other agents are active
|
|
71
|
+
const result = await $`bash -c '
|
|
72
|
+
COORD_DB="./agents/data/coordination/coordination.db"
|
|
73
|
+
if [ -f "$COORD_DB" ]; then
|
|
74
|
+
ACTIVE=$(sqlite3 "$COORD_DB" "SELECT COUNT(*) FROM agent_registry WHERE status='"'"'active'"'"';" 2>/dev/null || echo 0)
|
|
75
|
+
if [ "$ACTIVE" -gt 1 ]; then
|
|
76
|
+
echo "MULTI_AGENT"
|
|
77
|
+
fi
|
|
78
|
+
fi
|
|
79
|
+
'`
|
|
80
|
+
.quiet()
|
|
81
|
+
.nothrow();
|
|
82
|
+
|
|
83
|
+
if (result.stdout?.toString().includes('MULTI_AGENT')) {
|
|
84
|
+
await $`echo ${JSON.stringify(
|
|
85
|
+
JSON.stringify({
|
|
86
|
+
event: 'worktree_warning',
|
|
87
|
+
tool: input.tool,
|
|
88
|
+
file: filePath.slice(0, 200),
|
|
89
|
+
reason: 'multi-agent file write outside worktree',
|
|
90
|
+
ts: new Date().toISOString(),
|
|
91
|
+
})
|
|
92
|
+
)} >> ${TELEMETRY_PATH}`
|
|
93
|
+
.quiet()
|
|
94
|
+
.nothrow();
|
|
95
|
+
|
|
96
|
+
// Inject warning into bash tool if the next call is bash
|
|
97
|
+
// For write/edit, we log but don't block (worktree creation is the agent's responsibility)
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
/* fail safely */
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// --- PolicyGate enforcement (Layer 3) ---
|
|
106
|
+
// Check all UAP policies before allowing tool execution.
|
|
107
|
+
// Uses the uap-policy CLI for cross-runtime compatibility.
|
|
108
|
+
try {
|
|
109
|
+
const argsJson = JSON.stringify(output.args || {}).slice(0, 1000);
|
|
110
|
+
const result =
|
|
111
|
+
await $`node dist/bin/policy.js check --operation ${input.tool} --args ${argsJson} 2>/dev/null`
|
|
112
|
+
.quiet()
|
|
113
|
+
.nothrow();
|
|
114
|
+
|
|
115
|
+
if (result.exitCode !== 0) {
|
|
116
|
+
const policyOutput = result.stdout?.toString() || '';
|
|
117
|
+
// Policy blocked this operation
|
|
118
|
+
if (policyOutput.includes('BLOCKED') || policyOutput.includes('blocked')) {
|
|
119
|
+
await $`echo ${JSON.stringify(
|
|
120
|
+
JSON.stringify({
|
|
121
|
+
event: 'policy_blocked',
|
|
122
|
+
tool: input.tool,
|
|
123
|
+
reason: policyOutput.slice(0, 200),
|
|
124
|
+
ts: new Date().toISOString(),
|
|
125
|
+
})
|
|
126
|
+
)} >> ${TELEMETRY_PATH}`
|
|
127
|
+
.quiet()
|
|
128
|
+
.nothrow();
|
|
129
|
+
|
|
130
|
+
if (input.tool === 'bash') {
|
|
131
|
+
output.args.command = [
|
|
132
|
+
`echo "[UAP-POLICY] BLOCKED: Operation '${input.tool}' violated a REQUIRED policy."`,
|
|
133
|
+
`echo "[UAP-POLICY] ${policyOutput.replace(/"/g, '\\"').slice(0, 200)}"`,
|
|
134
|
+
`echo "[UAP-POLICY] You must comply with the policy before retrying."`,
|
|
135
|
+
].join(' && ');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// For non-bash tools, log but allow through (policy gate in MCP router
|
|
139
|
+
// will catch it if the tool goes through the MCP path)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch {
|
|
143
|
+
// Policy check failed (CLI not built, DB not initialized, etc.)
|
|
144
|
+
// Fail open: allow the tool call but log the failure
|
|
145
|
+
await $`echo '{"event":"policy_check_error","tool":"${input.tool}","ts":"'$(date -Iseconds)'"}' >> ${TELEMETRY_PATH}`
|
|
146
|
+
.quiet()
|
|
147
|
+
.nothrow();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// --- Budget enforcement ---
|
|
151
|
+
// NOTE: The proxy (Layer 1) handles the actual budget termination by
|
|
152
|
+
// stripping tools after HARD_BUDGET requests. The plugin just logs warnings.
|
|
153
|
+
// Do NOT replace commands here - that creates infinite loops when
|
|
154
|
+
// tool_choice="required" forces another call.
|
|
155
|
+
if (totalToolCalls === SOFT_BUDGET && input.tool === 'bash') {
|
|
156
|
+
const original = output.args?.command || '';
|
|
157
|
+
output.args.command = [
|
|
158
|
+
'echo "[UAP-ENFORCE] WARNING: 30 tool calls used. WRAP UP your solution NOW."',
|
|
159
|
+
original,
|
|
160
|
+
].join(' && ');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// --- Inject pending warning from write/read loop into this bash call ---
|
|
165
|
+
if (pendingWarning && input.tool === 'bash') {
|
|
166
|
+
const original = output.args?.command || '';
|
|
167
|
+
output.args.command = `echo "${pendingWarning}" && ${original}`;
|
|
168
|
+
pendingWarning = null;
|
|
169
|
+
// Don't return -- still check for loops on this call
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// --- Fingerprint-based loop detection ---
|
|
173
|
+
const argsStr = JSON.stringify(output.args || {});
|
|
174
|
+
const fingerprint = `${input.tool}:${argsStr.length > 500 ? simpleHash(argsStr) : argsStr}`;
|
|
175
|
+
|
|
176
|
+
const matches = recentFingerprints.filter((f) => f === fingerprint);
|
|
177
|
+
if (matches.length >= LOOP_THRESHOLD) {
|
|
178
|
+
const loopCount = matches.length + 1;
|
|
179
|
+
consecutiveLoopWarnings++;
|
|
180
|
+
|
|
181
|
+
// --- ESCAPE HATCH: after N consecutive warnings, reset history ---
|
|
182
|
+
if (consecutiveLoopWarnings >= ESCAPE_HATCH_THRESHOLD) {
|
|
183
|
+
recentFingerprints.length = 0;
|
|
184
|
+
recentWriteHashes.length = 0;
|
|
185
|
+
consecutiveLoopWarnings = 0;
|
|
186
|
+
await $`echo '{"event":"escape_hatch","tool":"${input.tool}","count":${loopCount}}' >> ${TELEMETRY_PATH}`
|
|
187
|
+
.quiet()
|
|
188
|
+
.nothrow();
|
|
189
|
+
// Let this call through completely clean
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (input.tool === 'bash') {
|
|
194
|
+
// PREPEND warning with SEARCH SUGGESTION, then run the ACTUAL command
|
|
195
|
+
const original = output.args?.command || '';
|
|
196
|
+
const warning = [
|
|
197
|
+
`echo "[UAP-ENFORCE] LOOP WARNING (${loopCount}x): Same command repeated."`,
|
|
198
|
+
`echo "[UAP-ENFORCE] Try a DIFFERENT approach. Hints:"`,
|
|
199
|
+
`echo "[UAP-ENFORCE] - SEARCH ONLINE: uap_search 'your error message or question'"`,
|
|
200
|
+
`echo "[UAP-ENFORCE] - If a dep is missing, install it (apt-get, pip, cpan)"`,
|
|
201
|
+
`echo "[UAP-ENFORCE] - If output is wrong, read the test/verifier first"`,
|
|
202
|
+
`echo "[UAP-ENFORCE] - Check /app/tmp/web_research.txt for pre-fetched hints"`,
|
|
203
|
+
].join(' && ');
|
|
204
|
+
output.args.command = `${warning} && ${original}`;
|
|
205
|
+
await $`echo '{"event":"loop_warn_bash","count":${loopCount}}' >> ${TELEMETRY_PATH}`
|
|
206
|
+
.quiet()
|
|
207
|
+
.nothrow();
|
|
208
|
+
} else if (input.tool === 'write' || input.tool === 'edit') {
|
|
209
|
+
// LET THE WRITE THROUGH but queue a warning for the next bash call
|
|
210
|
+
pendingWarning = `[UAP-ENFORCE] WRITE LOOP (${loopCount}x): You wrote identical content. Try a DIFFERENT approach. Read the test/verifier to understand expected format.`;
|
|
211
|
+
await $`echo '{"event":"loop_warn_write","count":${loopCount}}' >> ${TELEMETRY_PATH}`
|
|
212
|
+
.quiet()
|
|
213
|
+
.nothrow();
|
|
214
|
+
// DO NOT modify output -- let the write execute
|
|
215
|
+
} else if (input.tool === 'read') {
|
|
216
|
+
// LET THE READ THROUGH but queue a warning
|
|
217
|
+
pendingWarning = `[UAP-ENFORCE] READ LOOP (${loopCount}x): You read the same file ${loopCount} times. Move on to the next step.`;
|
|
218
|
+
await $`echo '{"event":"loop_warn_read","count":${loopCount}}' >> ${TELEMETRY_PATH}`
|
|
219
|
+
.quiet()
|
|
220
|
+
.nothrow();
|
|
221
|
+
// DO NOT modify output -- let the read execute
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
// Not a loop -- reset consecutive warning counter
|
|
225
|
+
consecutiveLoopWarnings = 0;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// --- Content-aware write dedup ---
|
|
229
|
+
if (input.tool === 'write' && output.args?.content) {
|
|
230
|
+
const contentHash = simpleHash(output.args.content);
|
|
231
|
+
const contentMatches = recentWriteHashes.filter((h) => h === contentHash);
|
|
232
|
+
if (contentMatches.length >= 3) {
|
|
233
|
+
// Queue warning but LET THE WRITE THROUGH
|
|
234
|
+
pendingWarning = `[UAP-ENFORCE] CONTENT DEDUP: Identical content written ${contentMatches.length + 1} times. Your approach is not working. Try something FUNDAMENTALLY different.`;
|
|
235
|
+
await $`echo '{"event":"content_dedup","count":${contentMatches.length + 1}}' >> ${TELEMETRY_PATH}`
|
|
236
|
+
.quiet()
|
|
237
|
+
.nothrow();
|
|
238
|
+
}
|
|
239
|
+
recentWriteHashes.push(contentHash);
|
|
240
|
+
if (recentWriteHashes.length > MAX_HISTORY) {
|
|
241
|
+
recentWriteHashes.shift();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Track fingerprint
|
|
246
|
+
recentFingerprints.push(fingerprint);
|
|
247
|
+
if (recentFingerprints.length > MAX_HISTORY) {
|
|
248
|
+
recentFingerprints.shift();
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
// --- Policy-aware tool descriptions (Layer 3) ---
|
|
253
|
+
// Inject active REQUIRED policy constraints into tool descriptions
|
|
254
|
+
// so the LLM is aware of rules before making tool calls.
|
|
255
|
+
'tool.definition': async (_input, output) => {
|
|
256
|
+
try {
|
|
257
|
+
const result = await $`node dist/bin/policy.js list --category code 2>/dev/null`
|
|
258
|
+
.quiet()
|
|
259
|
+
.nothrow();
|
|
260
|
+
|
|
261
|
+
if (result.exitCode === 0 && result.stdout) {
|
|
262
|
+
const policyText = result.stdout.toString().trim();
|
|
263
|
+
if (policyText && policyText.includes('REQUIRED')) {
|
|
264
|
+
const suffix =
|
|
265
|
+
'\n\n[UAP Policy Constraints: ' +
|
|
266
|
+
policyText
|
|
267
|
+
.split('\n')
|
|
268
|
+
.filter((l: string) => l.includes('REQUIRED'))
|
|
269
|
+
.map((l: string) => l.trim())
|
|
270
|
+
.join('; ')
|
|
271
|
+
.slice(0, 300) +
|
|
272
|
+
']';
|
|
273
|
+
if (output.description) {
|
|
274
|
+
output.description = output.description + suffix;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} catch {
|
|
279
|
+
// Fail silently - policy injection is best-effort
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
'tool.execute.after': async (input, _output) => {
|
|
284
|
+
const outputStr = typeof _output?.output === 'string' ? _output.output : '';
|
|
285
|
+
|
|
286
|
+
// Output-based loop detection
|
|
287
|
+
if (outputStr.length > 0) {
|
|
288
|
+
const hash = simpleHash(outputStr);
|
|
289
|
+
recentOutputHashes.push(hash);
|
|
290
|
+
if (recentOutputHashes.length > MAX_HISTORY) {
|
|
291
|
+
recentOutputHashes.shift();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Telemetry
|
|
296
|
+
const entry = {
|
|
297
|
+
event: 'tool_call',
|
|
298
|
+
tool: input.tool,
|
|
299
|
+
n: totalToolCalls,
|
|
300
|
+
ts: new Date().toISOString(),
|
|
301
|
+
args_preview:
|
|
302
|
+
typeof input.args?.command === 'string'
|
|
303
|
+
? input.args.command.slice(0, 200)
|
|
304
|
+
: typeof input.args?.filePath === 'string'
|
|
305
|
+
? input.args.filePath
|
|
306
|
+
: typeof input.args?.url === 'string'
|
|
307
|
+
? input.args.url.slice(0, 200)
|
|
308
|
+
: '...',
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
await $`echo ${JSON.stringify(JSON.stringify(entry))} >> ${TELEMETRY_PATH}`.quiet().nothrow();
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
};
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
UAP Chat Template Verifier
|
|
4
|
+
|
|
5
|
+
Model-agnostic chat template auto-finder and verifier.
|
|
6
|
+
Validates Jinja2 syntax, renders test data, and checks for
|
|
7
|
+
tool call format support.
|
|
8
|
+
|
|
9
|
+
Works with any chat template format:
|
|
10
|
+
- ChatML (<|im_start|>/<|im_end|>)
|
|
11
|
+
- Llama (<|begin_of_text|>/<|end_of_text|>)
|
|
12
|
+
- Mistral ([INST]/[/INST])
|
|
13
|
+
- Custom formats
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
python3 chat_template_verifier.py [template_path]
|
|
17
|
+
|
|
18
|
+
Auto-detection looks for templates in standard locations relative to project root.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import sys
|
|
22
|
+
import os
|
|
23
|
+
import re
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from datetime import datetime
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def find_project_root():
|
|
29
|
+
"""Find the UAP project root directory."""
|
|
30
|
+
current = Path(__file__).resolve().parent
|
|
31
|
+
|
|
32
|
+
# Walk up from script location until we find package.json or .git
|
|
33
|
+
for parent in [current] + list(current.parents):
|
|
34
|
+
if (parent / "package.json").exists() or (parent / ".git" / "config").exists():
|
|
35
|
+
return parent
|
|
36
|
+
|
|
37
|
+
return current
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def find_chat_templates(project_root=None):
|
|
41
|
+
"""Find all chat template files in project."""
|
|
42
|
+
if not project_root:
|
|
43
|
+
project_root = find_project_root()
|
|
44
|
+
|
|
45
|
+
templates = []
|
|
46
|
+
|
|
47
|
+
# Standard locations to check (in priority order)
|
|
48
|
+
search_paths = [
|
|
49
|
+
project_root / "tools" / "agents" / "config",
|
|
50
|
+
project_root / "config" / "model-profiles",
|
|
51
|
+
project_root,
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
for search_path in search_paths:
|
|
55
|
+
if not search_path.exists():
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
for pattern in ["chat_template.jinja", "*.jinja", "*.jinja2"]:
|
|
59
|
+
for found in search_path.glob(pattern):
|
|
60
|
+
# Skip backup files
|
|
61
|
+
if ".backup." in found.name:
|
|
62
|
+
continue
|
|
63
|
+
templates.append(found)
|
|
64
|
+
|
|
65
|
+
# Deduplicate and sort by path length (prefer deeper/more specific paths)
|
|
66
|
+
seen = set()
|
|
67
|
+
unique = []
|
|
68
|
+
for t in templates:
|
|
69
|
+
resolved = t.resolve()
|
|
70
|
+
if resolved not in seen:
|
|
71
|
+
seen.add(resolved)
|
|
72
|
+
unique.append(t)
|
|
73
|
+
|
|
74
|
+
# Sort: prefer tools/agents/config/ over root
|
|
75
|
+
return sorted(unique, key=lambda x: (0 if "tools" in str(x) else 1, len(str(x))))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def validate_template_syntax(content):
|
|
79
|
+
"""Validate Jinja2 template syntax with correct regex patterns."""
|
|
80
|
+
issues = []
|
|
81
|
+
|
|
82
|
+
# Count balanced blocks using correct Jinja2 syntax
|
|
83
|
+
block_pairs = [
|
|
84
|
+
("if", r"\{%-?\s*if\s+", r"\{%-?\s*endif\s*-?%\}"),
|
|
85
|
+
("for", r"\{%-?\s*for\s+", r"\{%-?\s*endfor\s*-?%\}"),
|
|
86
|
+
("macro", r"\{%-?\s*macro\s+", r"\{%-?\s*endmacro\s*-?%\}"),
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
for tag_name, open_pattern, close_pattern in block_pairs:
|
|
90
|
+
opens = len(re.findall(open_pattern, content))
|
|
91
|
+
closes = len(re.findall(close_pattern, content))
|
|
92
|
+
|
|
93
|
+
if opens != closes:
|
|
94
|
+
issues.append(
|
|
95
|
+
f"Unbalanced {tag_name} blocks: {opens} open vs {closes} close"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Check for broken tag syntax
|
|
99
|
+
broken_tags = re.findall(r"\{-?%[^}]*%\}", content)
|
|
100
|
+
for tag in broken_tags:
|
|
101
|
+
if tag.startswith("{-%") and not tag.startswith("{%-"):
|
|
102
|
+
issues.append(f"Invalid tag syntax: {tag[:40]}...")
|
|
103
|
+
|
|
104
|
+
# Check for double-opened tags like {%- {%- elif %}
|
|
105
|
+
double_opens = re.findall(r"\{%-?\s*\{%-?", content)
|
|
106
|
+
if double_opens:
|
|
107
|
+
issues.append(f"Found {len(double_opens)} double-opened tags")
|
|
108
|
+
|
|
109
|
+
# Check for stray endmacro without macro
|
|
110
|
+
macros = len(re.findall(r"\{%-?\s*macro\s+", content))
|
|
111
|
+
endmacros = len(re.findall(r"\{%-?\s*endmacro\s*-?%\}", content))
|
|
112
|
+
if endmacros > macros:
|
|
113
|
+
issues.append(f"Found {endmacros - macros} stray endmacro tag(s)")
|
|
114
|
+
|
|
115
|
+
return issues
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def verify_template_with_jinja(template_content):
|
|
119
|
+
"""Verify template can be parsed by Jinja2."""
|
|
120
|
+
try:
|
|
121
|
+
from jinja2 import Environment, BaseLoader
|
|
122
|
+
import json
|
|
123
|
+
|
|
124
|
+
env = Environment(loader=BaseLoader())
|
|
125
|
+
|
|
126
|
+
# Try to compile the template
|
|
127
|
+
template = env.from_string(template_content)
|
|
128
|
+
|
|
129
|
+
# Test with minimal valid input
|
|
130
|
+
test_data = {
|
|
131
|
+
"messages": [
|
|
132
|
+
{"role": "system", "content": "Test system message"},
|
|
133
|
+
{"role": "user", "content": "Hello"},
|
|
134
|
+
],
|
|
135
|
+
"add_generation_prompt": True,
|
|
136
|
+
"enable_thinking": False,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
result = template.render(**test_data)
|
|
141
|
+
print(f" [OK] Template compiled and rendered ({len(result)} chars)")
|
|
142
|
+
|
|
143
|
+
# Test tool call round-trip
|
|
144
|
+
test_tool_data = {
|
|
145
|
+
"messages": [
|
|
146
|
+
{"role": "user", "content": "Read file"},
|
|
147
|
+
{
|
|
148
|
+
"role": "assistant",
|
|
149
|
+
"content": "",
|
|
150
|
+
"tool_calls": [
|
|
151
|
+
{
|
|
152
|
+
"function": {
|
|
153
|
+
"name": "read_file",
|
|
154
|
+
"arguments": json.dumps({"path": "/etc/hosts"}),
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"role": "tool",
|
|
161
|
+
"name": "read_file",
|
|
162
|
+
"content": "127.0.0.1 localhost",
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
"add_generation_prompt": True,
|
|
166
|
+
"enable_thinking": False,
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
result2 = template.render(**test_tool_data)
|
|
170
|
+
|
|
171
|
+
# Check for various tool call formats (model-agnostic)
|
|
172
|
+
tool_formats = [
|
|
173
|
+
("<tool_call>", "ChatML/Qwen3 format"),
|
|
174
|
+
("<function_call>", "legacy XML format"),
|
|
175
|
+
("<function=", "function= style"),
|
|
176
|
+
('"name"', "JSON tool call"),
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
found_format = False
|
|
180
|
+
for marker, format_name in tool_formats:
|
|
181
|
+
if marker in result2:
|
|
182
|
+
print(f" [OK] Tool call format verified ({format_name})")
|
|
183
|
+
found_format = True
|
|
184
|
+
break
|
|
185
|
+
|
|
186
|
+
if not found_format:
|
|
187
|
+
print(" [WARN] Tool call tags not found in output")
|
|
188
|
+
|
|
189
|
+
return True
|
|
190
|
+
|
|
191
|
+
except Exception as e:
|
|
192
|
+
error_msg = str(e)
|
|
193
|
+
if "undefined" in error_msg.lower():
|
|
194
|
+
# Variable undefined is expected with minimal test data
|
|
195
|
+
print(f" [OK] Template parsed (expected variable: {error_msg[:60]})")
|
|
196
|
+
return True
|
|
197
|
+
else:
|
|
198
|
+
print(f" [FAIL] Render error: {error_msg[:100]}")
|
|
199
|
+
return False
|
|
200
|
+
|
|
201
|
+
except ImportError:
|
|
202
|
+
print(" [SKIP] Jinja2 not installed (pip install jinja2)")
|
|
203
|
+
return None
|
|
204
|
+
except Exception as e:
|
|
205
|
+
error_msg = str(e)
|
|
206
|
+
line_match = re.search(r"line (\d+)", error_msg)
|
|
207
|
+
|
|
208
|
+
if line_match:
|
|
209
|
+
line_num = int(line_match.group(1))
|
|
210
|
+
lines = template_content.split("\n")
|
|
211
|
+
print(f"\n [FAIL] Error at line {line_num}:")
|
|
212
|
+
start = max(0, line_num - 3)
|
|
213
|
+
for i in range(start, min(line_num + 2, len(lines))):
|
|
214
|
+
marker = ">>>" if i == line_num - 1 else " "
|
|
215
|
+
print(f" {marker} {i + 1}: {lines[i][:80]}")
|
|
216
|
+
else:
|
|
217
|
+
print(f"\n [FAIL] Template parsing error: {error_msg[:200]}")
|
|
218
|
+
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def main():
|
|
223
|
+
"""Main execution with auto-detection."""
|
|
224
|
+
|
|
225
|
+
print("=" * 70)
|
|
226
|
+
print("UAP Chat Template Verifier")
|
|
227
|
+
print("=" * 70)
|
|
228
|
+
|
|
229
|
+
# Get project root
|
|
230
|
+
project_root = find_project_root()
|
|
231
|
+
print(f"\nProject root: {project_root}")
|
|
232
|
+
|
|
233
|
+
# Handle explicit path argument
|
|
234
|
+
if len(sys.argv) > 1:
|
|
235
|
+
target_template = Path(sys.argv[1])
|
|
236
|
+
if not target_template.exists():
|
|
237
|
+
print(f"Error: File not found: {target_template}")
|
|
238
|
+
sys.exit(1)
|
|
239
|
+
else:
|
|
240
|
+
# Find templates automatically
|
|
241
|
+
print("\nSearching for chat templates...")
|
|
242
|
+
templates = find_chat_templates(project_root)
|
|
243
|
+
|
|
244
|
+
if not templates:
|
|
245
|
+
print("Error: No chat template files found!")
|
|
246
|
+
print(
|
|
247
|
+
f"\nExpected at: {project_root / 'tools' / 'agents' / 'config' / 'chat_template.jinja'}"
|
|
248
|
+
)
|
|
249
|
+
sys.exit(1)
|
|
250
|
+
|
|
251
|
+
target_template = templates[0]
|
|
252
|
+
|
|
253
|
+
# Show all found templates
|
|
254
|
+
if len(templates) > 1:
|
|
255
|
+
print(f" Found {len(templates)} template(s):")
|
|
256
|
+
for t in templates:
|
|
257
|
+
try:
|
|
258
|
+
rel = t.relative_to(project_root)
|
|
259
|
+
except ValueError:
|
|
260
|
+
rel = t
|
|
261
|
+
marker = " <-- using" if t == target_template else ""
|
|
262
|
+
print(f" - {rel}{marker}")
|
|
263
|
+
|
|
264
|
+
try:
|
|
265
|
+
rel_path = target_template.relative_to(project_root)
|
|
266
|
+
except ValueError:
|
|
267
|
+
rel_path = target_template
|
|
268
|
+
|
|
269
|
+
print(f"Using: {rel_path}")
|
|
270
|
+
|
|
271
|
+
# Read content
|
|
272
|
+
try:
|
|
273
|
+
with open(target_template, "r", encoding="utf-8") as f:
|
|
274
|
+
content = f.read()
|
|
275
|
+
print(f"Loaded: {len(content)} bytes, {len(content.splitlines())} lines")
|
|
276
|
+
except Exception as e:
|
|
277
|
+
print(f"Error reading {target_template}: {e}")
|
|
278
|
+
sys.exit(1)
|
|
279
|
+
|
|
280
|
+
# Validate syntax
|
|
281
|
+
print("\nValidating template syntax...")
|
|
282
|
+
issues = validate_template_syntax(content)
|
|
283
|
+
|
|
284
|
+
if issues:
|
|
285
|
+
print(f" Found {len(issues)} issue(s):")
|
|
286
|
+
for issue in issues:
|
|
287
|
+
print(f" - {issue}")
|
|
288
|
+
else:
|
|
289
|
+
print(" [OK] No syntax issues detected")
|
|
290
|
+
|
|
291
|
+
# Verify with Jinja2
|
|
292
|
+
print("\nVerifying with Jinja2 parser...")
|
|
293
|
+
jinja_ok = verify_template_with_jinja(content)
|
|
294
|
+
|
|
295
|
+
if jinja_ok is True:
|
|
296
|
+
print("\n[OK] Template is valid and functional")
|
|
297
|
+
elif jinja_ok is False:
|
|
298
|
+
print("\n[FAIL] Template has errors - needs manual review")
|
|
299
|
+
sys.exit(1)
|
|
300
|
+
else:
|
|
301
|
+
print("\n[SKIP] Could not verify (install jinja2: pip install jinja2)")
|
|
302
|
+
|
|
303
|
+
# Show template features (model-agnostic detection)
|
|
304
|
+
print("\nTemplate features:")
|
|
305
|
+
features = [
|
|
306
|
+
("System message handling", "role == 'system'" in content),
|
|
307
|
+
("User message handling", "role == 'user'" in content),
|
|
308
|
+
("Assistant message handling", "role == 'assistant'" in content),
|
|
309
|
+
("Tool call support", "tool_calls" in content or "tool_call" in content),
|
|
310
|
+
("Native tool descriptions", "for tool in tools" in content),
|
|
311
|
+
(
|
|
312
|
+
"Tool response support",
|
|
313
|
+
"role == 'tool'" in content or "tool_response" in content,
|
|
314
|
+
),
|
|
315
|
+
(
|
|
316
|
+
"Thinking/reasoning mode",
|
|
317
|
+
"thinking" in content.lower() or "think" in content.lower(),
|
|
318
|
+
),
|
|
319
|
+
("ChatML format (<|im_start|>)", "<|im_start|>" in content),
|
|
320
|
+
("Llama format (<|begin_of_text|>)", "<|begin_of_text|>" in content),
|
|
321
|
+
("Mistral format ([INST])", "[INST]" in content),
|
|
322
|
+
("Generation prompt", "add_generation_prompt" in content),
|
|
323
|
+
]
|
|
324
|
+
|
|
325
|
+
for feature, has_it in features:
|
|
326
|
+
status = "[OK]" if has_it else "[--]"
|
|
327
|
+
print(f" {status} {feature}")
|
|
328
|
+
|
|
329
|
+
print("\n" + "=" * 70)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
if __name__ == "__main__":
|
|
333
|
+
try:
|
|
334
|
+
main()
|
|
335
|
+
except KeyboardInterrupt:
|
|
336
|
+
print("\nInterrupted")
|
|
337
|
+
sys.exit(130)
|
|
338
|
+
except Exception as e:
|
|
339
|
+
import traceback
|
|
340
|
+
|
|
341
|
+
print(f"\nUnexpected error: {e}")
|
|
342
|
+
traceback.print_exc()
|
|
343
|
+
sys.exit(1)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Fix Qwen Chat Template - Node.js Wrapper
|
|
4
|
+
*
|
|
5
|
+
* Cross-platform shim that finds Python and delegates to the
|
|
6
|
+
* Python template fixer/verifier script in the same directory.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { execFileSync } from 'child_process';
|
|
10
|
+
import { dirname, join } from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import { platform } from 'os';
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
|
|
16
|
+
function getPythonExecutable() {
|
|
17
|
+
if (platform() === 'win32') {
|
|
18
|
+
return 'python';
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
execFileSync('python3', ['--version'], { stdio: 'ignore' });
|
|
22
|
+
return 'python3';
|
|
23
|
+
} catch {
|
|
24
|
+
return 'python';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const pythonScript = join(__dirname, 'fix_qwen_chat_template.py');
|
|
29
|
+
const args = process.argv.slice(2);
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
execFileSync(getPythonExecutable(), [pythonScript, ...args], {
|
|
33
|
+
stdio: 'inherit',
|
|
34
|
+
cwd: process.cwd(),
|
|
35
|
+
});
|
|
36
|
+
} catch (error) {
|
|
37
|
+
process.exit(error.status || 1);
|
|
38
|
+
}
|