@polymorphism-tech/morph-spec 8.37.1 → 8.40.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/CLAUDE.md +37 -13
- package/README.md +2 -2
- package/bin/morph-spec.js +75 -49
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +6 -5
- package/framework/MORPH.md +25 -22
- package/framework/agents.json +96 -36
- package/framework/docs/CLI.md +54 -17
- package/framework/evals/rubrics/code-quality.md +5 -0
- package/framework/evals/rubrics/condensed.md +6 -2
- package/framework/evals/rubrics/contracts.md +20 -0
- package/framework/evals/rubrics/test-coverage.md +17 -6
- package/framework/hooks/README.md +9 -3
- package/framework/hooks/claude-code/core/graph-refresh-kick.js +52 -0
- package/framework/hooks/claude-code/core/telemetry-log.js +172 -87
- package/framework/hooks/claude-code/core/validate-completion.js +16 -90
- package/framework/hooks/claude-code/core/worktree-context.js +10 -0
- package/framework/hooks/shared/command-tokens.js +96 -0
- package/framework/hooks/shared/git-exclude.js +44 -0
- package/framework/hooks/shared/git-paths.js +52 -0
- package/framework/hooks/shared/graph-freshness.js +380 -0
- package/framework/hooks/shared/graph-refresh.js +416 -0
- package/framework/hooks/shared/morph-cli.js +17 -5
- package/framework/hooks/shared/redact-secrets.js +55 -0
- package/framework/hooks/shared/telemetry-logger.js +25 -2
- package/framework/hooks/shared/transcript-usage.js +80 -0
- package/framework/mcp/registry.json +33 -2
- package/framework/rubrics/backend.json +2 -2
- package/framework/rubrics/default.json +2 -2
- package/framework/rubrics/frontend.json +2 -2
- package/framework/rules/csharp-standards.md +1 -0
- package/framework/rules/infrastructure-standards.md +0 -1
- package/framework/rules/morph-workflow.md +10 -4
- package/framework/rules/nextjs-standards.md +1 -0
- package/framework/schemas/config.schema.json +41 -1
- package/framework/schemas/feature.schema.json +5 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +40 -11
- package/framework/skills/core/morph-brainstorming/SKILL.md +16 -7
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
- package/framework/skills/core/morph-implement/SKILL.md +44 -10
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +73 -15
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +51 -13
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +39 -13
- package/framework/standards/STANDARDS.json +189 -14
- package/framework/standards/ai-agents/context-providers.md +16 -26
- package/framework/standards/ai-agents/durable-workflows-hitl.md +15 -21
- package/framework/standards/ai-agents/modalities-image-gen.md +21 -25
- package/framework/standards/ai-agents/modalities-speech-to-text.md +4 -15
- package/framework/standards/ai-agents/modalities-text-to-speech.md +2 -11
- package/framework/standards/ai-agents/modalities-vision.md +1 -18
- package/framework/standards/ai-agents/prompt-sources.md +0 -4
- package/framework/standards/ai-agents/testing-ai.md +2 -1
- package/framework/standards/architecture/code-comments.md +100 -0
- package/framework/standards/backend/dotnet/testing.md +22 -0
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +63 -50
- package/framework/standards/frontend/admin-app/data-table.md +562 -0
- package/framework/standards/frontend/admin-app/feedback.md +236 -0
- package/framework/standards/frontend/admin-app/forms.md +232 -0
- package/framework/standards/frontend/admin-app/page-structure.md +203 -0
- package/framework/standards/frontend/design-system/ai-image-generation.md +5 -5
- package/framework/standards/frontend/nextjs/components.md +37 -58
- package/framework/standards/frontend/nextjs/data-fetching.md +1 -0
- package/framework/standards/frontend/nextjs/forms.md +31 -30
- package/framework/standards/frontend/nextjs/state-management.md +2 -1
- package/framework/standards/frontend/nextjs/testing.md +18 -0
- package/framework/standards/integration/mcp/mcp-tools.md +48 -117
- package/framework/templates/code/dotnet/abstractions/result.cs +0 -2
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +26 -39
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +28 -68
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +99 -117
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +2 -44
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +40 -61
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +54 -107
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +53 -58
- package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +192 -281
- package/framework/templates/code/dotnet/database/migration.cs +49 -83
- package/framework/templates/code/dotnet/database/vector-entity.cs +2 -46
- package/framework/templates/code/dotnet/extensions/result-extensions.cs +0 -2
- package/framework/templates/code/dotnet/feature/validator.cs.hbs +11 -15
- package/framework/templates/code/dotnet/jobs/agent.cs +3 -51
- package/framework/templates/code/dotnet/jobs/job.cs +2 -97
- package/framework/templates/code/dotnet/test.cs +2 -87
- package/framework/templates/code/typescript/contracts.ts +140 -167
- package/framework/templates/context/design-system.md +3 -3
- package/framework/templates/docs/proposal.md +11 -0
- package/framework/templates/docs/spec.md +15 -0
- package/framework/templates/docs/ui-mockups.md +115 -98
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentApi.cs +1 -48
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs +3 -79
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactoryOptions.cs +1 -70
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpec.cs +1 -47
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpecOptions.cs +2 -99
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/AiKitAssemblyMarker.cs +0 -6
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/ConversationStore.cs +3 -88
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/IConversationStore.cs +1 -41
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/InMemoryConversationStore.cs +0 -21
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/CountingChatClient.cs +1 -25
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalAssertion.cs +2 -63
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheMissException.cs +0 -30
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheOptions.cs +1 -52
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheStamp.cs +3 -78
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalFixture.cs +4 -109
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalMode.cs +0 -22
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalQualityEvaluators.cs +1 -36
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalScenario.cs +2 -57
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalSummary.cs +0 -75
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/OfflineChatClient.cs +2 -59
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/ShortPathResponseCache.cs +4 -111
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaGenerator.cs +0 -34
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaProvider.cs +1 -57
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaArtifact.cs +0 -19
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaDisclosure.cs +2 -74
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaGenerator.cs +2 -33
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaIdempotencyKey.cs +1 -43
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJob.cs +1 -96
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobId.cs +0 -13
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobState.cs +0 -27
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaPricing.cs +0 -33
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaProvenance.cs +0 -31
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaRequest.cs +3 -75
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaResult.cs +0 -42
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaReview.cs +0 -39
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaSeams.cs +1 -55
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaStore.cs +3 -59
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MorphMedia.cs +0 -46
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/GoogleImageProvider.cs +3 -28
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs +7 -61
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/VeoVideoProvider.cs +2 -37
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/IUsageCostSink.cs +1 -23
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostMiddleware.cs +2 -82
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostRecord.cs +1 -68
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs +1 -62
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphTelemetryOptions.cs +2 -62
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/IProviderClientFactory.cs +1 -25
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs +0 -124
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs +1 -73
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaIngest.cs +1 -66
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaPlan.cs +0 -41
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentFactoryTests.cs +2 -112
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentSpecTests.cs +2 -43
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ConversationStoreTests.cs +5 -110
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/DeltaIngestTests.cs +7 -103
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalAssertionTests.cs +1 -42
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheMissTests.cs +1 -30
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheStampTests.cs +1 -19
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFailuresTests.cs +0 -48
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFixtureTests.cs +1 -29
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalRefreshTests.cs +2 -38
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalWorkspace.cs +1 -14
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/KitEvals.cs +4 -69
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/OfflineChatClientTests.cs +1 -10
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs +1 -57
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClientTests.cs +0 -26
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeClock.cs +1 -19
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeMediaProvider.cs +0 -32
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeProviderClientFactory.cs +0 -14
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeUsageCostSink.cs +0 -24
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/InMemoryMediaStore.cs +0 -32
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAccessibilityTests.cs +0 -37
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAliasIsNotAnAgentTests.cs +0 -24
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +0 -78
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaGeneratorTests.cs +0 -53
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaIdempotencyKeyTests.cs +0 -44
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaJobStateTests.cs +0 -44
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaReviewTests.cs +0 -19
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaStoreTests.cs +0 -24
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ModelRegistryTests.cs +6 -48
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/SkeletonSmokeTests.cs +1 -13
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/TelemetryTests.cs +2 -71
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/UsageCostMiddlewareTests.cs +5 -100
- package/framework/templates/feature/decisions.md +124 -122
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +39 -43
- package/framework/templates/frontend/nextjs/env.mjs.hbs +29 -32
- package/framework/templates/frontend/nextjs/page.tsx.hbs +21 -22
- package/framework/templates/frontend/nextjs/use-feature.ts.hbs +42 -54
- package/framework/templates/integrations/asaas-client.cs +332 -387
- package/framework/templates/integrations/asaas-webhook.cs +290 -351
- package/framework/templates/integrations/neon-auth-config.cs +9 -105
- package/framework/templates/project/validate.js +97 -120
- package/package.json +2 -2
- package/src/commands/dashboard/dashboard.js +80 -53
- package/src/commands/graph/affected.js +4 -3
- package/src/commands/graph/build.js +109 -18
- package/src/commands/graph/explain.js +8 -5
- package/src/commands/graph/status.js +14 -8
- package/src/commands/mcp/mcp-setup.js +37 -9
- package/src/commands/observability/cost.js +148 -18
- package/src/commands/project/doctor.js +85 -15
- package/src/commands/project/init.js +6 -3
- package/src/commands/project/install-plugin-cmd.js +1 -1
- package/src/commands/project/update.js +30 -0
- package/src/commands/project/worktree.js +73 -90
- package/src/commands/state/advance.js +18 -0
- package/src/commands/state/approve.js +15 -0
- package/src/commands/state/archive.js +62 -9
- package/src/commands/state/finish.js +62 -14
- package/src/commands/state/gate-check.js +8 -1
- package/src/commands/state/gate-decision.js +8 -4
- package/src/commands/state/report-check.js +90 -9
- package/src/commands/state/usecase.js +66 -0
- package/src/commands/tasks/dag.js +17 -2
- package/src/commands/validation/validate-feature.js +6 -1
- package/src/commands/validation/verify.js +20 -1
- package/src/dashboard/app/App.jsx +80 -16
- package/src/dashboard/app/components/ActivityFeed.jsx +172 -0
- package/src/dashboard/app/components/CommandPalette.jsx +155 -0
- package/src/dashboard/app/components/DetailPanel.jsx +47 -11
- package/src/dashboard/app/components/EntityLink.jsx +55 -0
- package/src/dashboard/app/components/ErrorBoundary.jsx +54 -0
- package/src/dashboard/app/components/FlowGraph.jsx +19 -17
- package/src/dashboard/app/components/KnowledgeMarkdown.jsx +53 -0
- package/src/dashboard/app/components/Markdown.jsx +47 -0
- package/src/dashboard/app/components/PhaseRail.jsx +111 -0
- package/src/dashboard/app/components/SearchFilter.jsx +40 -22
- package/src/dashboard/app/components/Sidebar.jsx +146 -37
- package/src/dashboard/app/hooks/useMorphQuery.js +54 -0
- package/src/dashboard/app/hooks/usePref.js +38 -0
- package/src/dashboard/app/lib/format.js +69 -0
- package/src/dashboard/app/lib/phases.js +56 -0
- package/src/dashboard/app/lib/project.js +50 -0
- package/src/dashboard/app/pages/Activity.jsx +24 -0
- package/src/dashboard/app/pages/AgentMap.jsx +371 -370
- package/src/dashboard/app/pages/FeatureDetail.jsx +604 -0
- package/src/dashboard/app/pages/Features.jsx +400 -0
- package/src/dashboard/app/pages/Guide.jsx +146 -0
- package/src/dashboard/app/pages/HookInspector.jsx +357 -322
- package/src/dashboard/app/pages/PhasePipeline.jsx +277 -408
- package/src/dashboard/app/pages/Portfolio.jsx +156 -0
- package/src/dashboard/app/pages/Rubrics.jsx +101 -0
- package/src/dashboard/app/pages/RulesMap.jsx +300 -273
- package/src/dashboard/app/pages/SkillsLibrary.jsx +483 -366
- package/src/dashboard/app/pages/Standards.jsx +407 -332
- package/src/dashboard/app/styles/index.css +187 -47
- package/src/dashboard/index.html +14 -12
- package/src/dashboard/package.json +32 -24
- package/src/dashboard/scanner/activity-scanner.js +351 -0
- package/src/dashboard/scanner/agents-scanner.js +63 -1
- package/src/dashboard/scanner/docs-scanner.js +59 -0
- package/src/dashboard/scanner/feature-status.js +10 -0
- package/src/dashboard/scanner/features-scanner.js +360 -0
- package/src/dashboard/scanner/hooks-scanner.js +8 -1
- package/src/dashboard/scanner/index.js +14 -7
- package/src/dashboard/scanner/phases-scanner.js +14 -15
- package/src/dashboard/scanner/portfolio.js +153 -0
- package/src/dashboard/scanner/project-api.js +195 -0
- package/src/dashboard/scanner/rules-scanner.js +42 -37
- package/src/dashboard/scanner/skills-scanner.js +105 -43
- package/src/dashboard/scanner/standards-scanner.js +4 -1
- package/src/dashboard/vite-plugin-morph-data.js +134 -17
- package/src/lib/ai/comment-stripper.js +101 -4
- package/src/lib/detectors/claude-config-detector.js +2 -7
- package/src/lib/detectors/index.js +5 -1
- package/src/lib/evaluator-report.js +47 -0
- package/src/lib/generators/handoff-generator.js +4 -18
- package/src/lib/generators/settings-generator.js +208 -209
- package/src/lib/git/default-branch.js +52 -0
- package/src/lib/git/tree-fingerprint.js +58 -0
- package/src/lib/git/tree-state.js +167 -0
- package/src/lib/graph/god-nodes.js +12 -3
- package/src/lib/graph/graph-health.js +48 -2
- package/src/lib/graph/graph-loader.js +99 -25
- package/src/lib/graph/graphifyignore.js +145 -28
- package/src/lib/graph/sanitize.js +117 -11
- package/src/lib/installers/mcp-installer.js +724 -719
- package/src/lib/installers/memory-installer.js +1 -2
- package/src/lib/projects/registry.js +154 -0
- package/src/lib/risk-detector.js +90 -0
- package/src/lib/specs/acervo-format.js +70 -0
- package/src/lib/specs/acervo-lifecycle.js +264 -0
- package/src/lib/specs/adr-index.js +169 -0
- package/src/lib/specs/revocations.js +156 -0
- package/src/lib/specs/screen-checklist.js +357 -0
- package/src/lib/specs/usecase-check.js +20 -16
- package/src/lib/specs/usecase-promoter.js +103 -38
- package/src/lib/specs/usecase-registry.js +7 -7
- package/src/lib/tasks/tasks-json-parser.js +2 -3
- package/src/lib/telemetry/metrics.js +386 -0
- package/src/lib/telemetry/telemetry-reader.js +161 -51
- package/src/lib/telemetry/verify-event.js +79 -0
- package/src/lib/validators/code-budget/code-budget-validator.js +200 -0
- package/src/lib/validators/code-budget/comment-scanner.js +75 -0
- package/src/lib/validators/code-budget/index.js +9 -0
- package/src/lib/validators/reuse/reuse-validator.js +4 -2
- package/src/lib/validators/reuse/symbol-scanner.js +27 -22
- package/src/lib/validators/validation-runner.js +21 -5
- package/src/lib/validators/verify-runner.js +11 -0
- package/src/lib/worktree/finish-backup.js +739 -0
- package/src/lib/worktree/ignored-triage.js +15 -8
- package/src/lib/worktree/worktree-audit.js +5 -0
- package/src/scripts/install-plugin.js +1 -1
- package/src/scripts/setup-infra.js +31 -22
- package/src/utils/agents-installer.js +338 -24
- package/src/utils/banner.js +1 -1
- package/src/utils/hooks-installer.js +75 -15
- package/src/commands/index.js +0 -13
- package/src/commands/project/checkpoint.js +0 -209
- package/src/core/state/phase-state-machine.js +0 -197
- package/src/dashboard/app/hooks/useDetailPanel.js +0 -15
- package/src/dashboard/app/pages/LiveState.jsx +0 -206
- package/src/dashboard/scanner/squads-scanner.js +0 -13
- package/src/dashboard/scanner/state-scanner.js +0 -85
- package/src/lib/generators/index.js +0 -10
- package/src/lib/hooks/hook-executor.js +0 -167
- package/src/lib/validators/checkpoint-persistence.js +0 -39
- package/src/lib/validators/shared/emit-validator-dispatch.js +0 -14
- package/src/lib/validators/shared/index.js +0 -12
- package/src/lib/validators/shared/issue-counter.js +0 -14
- package/src/lib/validators/shared/result-formatter.js +0 -124
|
@@ -1,98 +1,115 @@
|
|
|
1
|
-
# UI Mockups & Wireframes: {{titleCase FEATURE_NAME}}
|
|
2
|
-
|
|
3
|
-
| Field | Value |
|
|
4
|
-
|-------|-------|
|
|
5
|
-
| **Feature** | {{FEATURE_NAME}} |
|
|
6
|
-
| **Created** | {{DATE}} |
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## Screen Inventory
|
|
11
|
-
|
|
12
|
-
| Screen ID | Name | Route | Priority |
|
|
13
|
-
|-----------|------|-------|----------|
|
|
14
|
-
| **S001** | {Screen Name} | /path | High |
|
|
15
|
-
| **S002** | {Screen Name} | /path | Medium |
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
### Desktop Layout
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
┌─────────────────────────────────────┐
|
|
25
|
-
│ Header [User ▼] │
|
|
26
|
-
├─────────────────────────────────────┤
|
|
27
|
-
│ │
|
|
28
|
-
│ [Title] │
|
|
29
|
-
│ │
|
|
30
|
-
│ ┌──────────────────────────────┐ │
|
|
31
|
-
│ │ Main Content Area │ │
|
|
32
|
-
│ │ │ │
|
|
33
|
-
│ │ [Card 1] [Card 2] │ │
|
|
34
|
-
│ │ │ │
|
|
35
|
-
│ │ ┌────────────────────────┐ │ │
|
|
36
|
-
│ │ │ Data Table │ │ │
|
|
37
|
-
│ │ │ ... │ │ │
|
|
38
|
-
│ │ └────────────────────────┘ │ │
|
|
39
|
-
│ └──────────────────────────────┘ │
|
|
40
|
-
│ │
|
|
41
|
-
└─────────────────────────────────────┘
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Mobile Layout
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
┌──────────────────────┐
|
|
48
|
-
│ ☰ Title [User ▼]│
|
|
49
|
-
├──────────────────────┤
|
|
50
|
-
│ │
|
|
51
|
-
│ [Card 1] │
|
|
52
|
-
│ │
|
|
53
|
-
│ [Card 2] │
|
|
54
|
-
│ │
|
|
55
|
-
│ [View All Items] │
|
|
56
|
-
│ │
|
|
57
|
-
└──────────────────────┘
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
1
|
+
# UI Mockups & Wireframes: {{titleCase FEATURE_NAME}}
|
|
2
|
+
|
|
3
|
+
| Field | Value |
|
|
4
|
+
|-------|-------|
|
|
5
|
+
| **Feature** | {{FEATURE_NAME}} |
|
|
6
|
+
| **Created** | {{DATE}} |
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Screen Inventory
|
|
11
|
+
|
|
12
|
+
| Screen ID | Name | Route | Priority |
|
|
13
|
+
|-----------|------|-------|----------|
|
|
14
|
+
| **S001** | {Screen Name} | /path | High |
|
|
15
|
+
| **S002** | {Screen Name} | /path | Medium |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Tela: {Primary Screen}
|
|
20
|
+
|
|
21
|
+
### Desktop Layout
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
┌─────────────────────────────────────┐
|
|
25
|
+
│ Header [User ▼] │
|
|
26
|
+
├─────────────────────────────────────┤
|
|
27
|
+
│ │
|
|
28
|
+
│ [Title] │
|
|
29
|
+
│ │
|
|
30
|
+
│ ┌──────────────────────────────┐ │
|
|
31
|
+
│ │ Main Content Area │ │
|
|
32
|
+
│ │ │ │
|
|
33
|
+
│ │ [Card 1] [Card 2] │ │
|
|
34
|
+
│ │ │ │
|
|
35
|
+
│ │ ┌────────────────────────┐ │ │
|
|
36
|
+
│ │ │ Data Table │ │ │
|
|
37
|
+
│ │ │ ... │ │ │
|
|
38
|
+
│ │ └────────────────────────┘ │ │
|
|
39
|
+
│ └──────────────────────────────┘ │
|
|
40
|
+
│ │
|
|
41
|
+
└─────────────────────────────────────┘
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Mobile Layout
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
┌──────────────────────┐
|
|
48
|
+
│ ☰ Title [User ▼]│
|
|
49
|
+
├──────────────────────┤
|
|
50
|
+
│ │
|
|
51
|
+
│ [Card 1] │
|
|
52
|
+
│ │
|
|
53
|
+
│ [Card 2] │
|
|
54
|
+
│ │
|
|
55
|
+
│ [View All Items] │
|
|
56
|
+
│ │
|
|
57
|
+
└──────────────────────┘
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Checklist de tela
|
|
61
|
+
|
|
62
|
+
Troque cada `…` pela decisão — "não se aplica" vale se escrito; `…`, vazio ou "a definir" reprovam o Gate uiux.
|
|
63
|
+
|
|
64
|
+
| Item | Decisão |
|
|
65
|
+
|---|---|
|
|
66
|
+
| Superfície | … |
|
|
67
|
+
| Volume esperado | … |
|
|
68
|
+
| Paginação | … |
|
|
69
|
+
| Ordenação | … |
|
|
70
|
+
| Filtro | … |
|
|
71
|
+
| Estado vazio | … |
|
|
72
|
+
| Estado carregando | … |
|
|
73
|
+
| Estado de erro | … |
|
|
74
|
+
| Mobile | … |
|
|
75
|
+
| Abas | … |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## States
|
|
80
|
+
|
|
81
|
+
### Loading
|
|
82
|
+
- Show skeleton placeholders
|
|
83
|
+
- Spinner for primary content
|
|
84
|
+
|
|
85
|
+
### Empty
|
|
86
|
+
- Icon + message
|
|
87
|
+
- Clear call-to-action button
|
|
88
|
+
|
|
89
|
+
### Error
|
|
90
|
+
- Warning icon
|
|
91
|
+
- User-friendly message
|
|
92
|
+
- Retry button
|
|
93
|
+
|
|
94
|
+
### Success (After Action)
|
|
95
|
+
- Toast notification
|
|
96
|
+
- Auto-dismiss after 3s
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Interactions
|
|
101
|
+
|
|
102
|
+
- **Hover**: Subtle elevation increase
|
|
103
|
+
- **Click**: Scale down (0.98)
|
|
104
|
+
- **Transitions**: Fade-in 200ms
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Accessibility
|
|
109
|
+
- [ ] 44x44px minimum touch targets
|
|
110
|
+
- [ ] Focus indicators visible
|
|
111
|
+
- [ ] Proper heading hierarchy (H1 → H2 → H3)
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
*Generated with MORPH Framework*
|
|
@@ -1,65 +1,18 @@
|
|
|
1
1
|
namespace Morph.AiKit.Agents;
|
|
2
2
|
|
|
3
|
-
/// <summary>
|
|
4
|
-
/// Protocolo pelo qual um modelo e alcancado. E o campo <c>api:</c> por alias que a
|
|
5
|
-
/// issue #92 exige: a MESMA familia de modelos e atendida por dois protocolos
|
|
6
|
-
/// diferentes, e qual deles vale e decisao de configuracao — nunca folclore espalhado
|
|
7
|
-
/// por condicional no meio do codigo.
|
|
8
|
-
/// </summary>
|
|
9
|
-
/// <remarks>
|
|
10
|
-
/// <para>
|
|
11
|
-
/// <see cref="Responses"/> e <b>0 de proposito</b>: <c>default(AgentApi)</c> e a Responses
|
|
12
|
-
/// API porque essa e a decisao da casa (Responses por padrao, Chat Completions como
|
|
13
|
-
/// opt-in explicito por alias). Um alias que omite <c>api:</c> no
|
|
14
|
-
/// <c>model-registry.v2.json</c> cai em Responses; usar Chat Completions exige escrever
|
|
15
|
-
/// <c>"api": "chat"</c> — ou seja, exige alguem assumir a escolha por escrito.
|
|
16
|
-
/// </para>
|
|
17
|
-
/// <para>
|
|
18
|
-
/// O enum descreve a escolha ENTRE OS DOIS PROTOCOLOS DA OpenAI. Provider que expoe um
|
|
19
|
-
/// unico protocolo (Google, Ollama) ignora o campo, e por isso declara — ou omite,
|
|
20
|
-
/// caindo em — <see cref="Responses"/>: escrever <c>chat</c> ali sugeriria uma escolha
|
|
21
|
-
/// que naquele provider nao existe.
|
|
22
|
-
/// </para>
|
|
23
|
-
/// </remarks>
|
|
24
3
|
public enum AgentApi
|
|
25
4
|
{
|
|
26
|
-
|
|
5
|
+
// 0 de proposito: default(AgentApi) e alias sem 'api:' caem em Responses; Chat e opt-in escrito.
|
|
27
6
|
Responses = 0,
|
|
28
7
|
|
|
29
|
-
/// <summary>
|
|
30
|
-
/// Chat Completions — opt-in explicito por alias. Carrega limites que a Responses API
|
|
31
|
-
/// nao tem; ver <c>Morph.AiKit.Providers.ModelAliasConstraints</c>.
|
|
32
|
-
/// </summary>
|
|
33
8
|
Chat = 1,
|
|
34
9
|
|
|
35
|
-
/// <summary>
|
|
36
|
-
/// Images — geracao/edicao de imagem. <b>Nao e um protocolo de conversa</b>: um alias
|
|
37
|
-
/// com este <c>api</c> e recusado pela <c>AgentFactory</c>, com erro nomeado.
|
|
38
|
-
/// </summary>
|
|
39
|
-
/// <remarks>
|
|
40
|
-
/// Um registry so, um vocabulario so de alias: quem procura "qual modelo este projeto
|
|
41
|
-
/// usa" encontra o de imagem no mesmo lugar que o de chat. A alternativa era um
|
|
42
|
-
/// <c>media-registry.json</c> separado — duas verdades sobre o mesmo fato.
|
|
43
|
-
/// </remarks>
|
|
44
10
|
Images = 2,
|
|
45
11
|
|
|
46
|
-
/// <summary>
|
|
47
|
-
/// Videos — geracao de video. Mesma regra de <see cref="Images"/>: alias de midia nao
|
|
48
|
-
/// vira agente.
|
|
49
|
-
/// </summary>
|
|
50
12
|
Videos = 3,
|
|
51
13
|
}
|
|
52
14
|
|
|
53
|
-
/// <summary>Predicados sobre <see cref="AgentApi"/>.</summary>
|
|
54
15
|
public static class AgentApiExtensions
|
|
55
16
|
{
|
|
56
|
-
/// <summary>
|
|
57
|
-
/// Se o protocolo e de MIDIA (imagem ou video) e portanto nao fala conversa.
|
|
58
|
-
/// </summary>
|
|
59
|
-
/// <remarks>
|
|
60
|
-
/// Escrito uma vez, aqui, porque duas copias deste predicado sao como a
|
|
61
|
-
/// <c>AgentFactory</c> e o <c>ModelRegistry</c> passariam a discordar sobre o mesmo
|
|
62
|
-
/// alias.
|
|
63
|
-
/// </remarks>
|
|
64
17
|
public static bool IsMedia(this AgentApi api) => api is AgentApi.Images or AgentApi.Videos;
|
|
65
18
|
}
|
|
@@ -5,48 +5,11 @@ using Morph.AiKit.Providers;
|
|
|
5
5
|
|
|
6
6
|
namespace Morph.AiKit.Agents;
|
|
7
7
|
|
|
8
|
-
/// <summary>
|
|
9
|
-
/// Transforma uma <see cref="AgentSpec"/> (o agente como dado) num
|
|
10
|
-
/// <see cref="AIAgent"/> pronto para rodar. E o unico lugar do kit que conhece a ORDEM do
|
|
11
|
-
/// pipeline.
|
|
12
|
-
/// </summary>
|
|
13
|
-
/// <remarks>
|
|
14
|
-
/// <para><b>A ordem, de fora para dentro, e o contrato desta classe:</b></para>
|
|
15
|
-
/// <code>
|
|
16
|
-
/// OpenTelemetryAgent span invoke_agent — cobre a invocacao inteira (T12)
|
|
17
|
-
/// +- ChatClientAgent UseProvidedChatClientAsIs = true: o pipeline abaixo e nosso
|
|
18
|
-
/// +- timeout TimeoutSeconds vira CancellationToken
|
|
19
|
-
/// +- usage-cost ve UMA resposta com o uso ja somado das voltas (T11)
|
|
20
|
-
/// +- FunctionInvoking MaxToolIterations / AllowConcurrentToolInvocation
|
|
21
|
-
/// +- telemetria de chat span chat, ABAIXO do FICC (T12)
|
|
22
|
-
/// +- cliente do provider memoizado pelo ModelRegistry
|
|
23
|
-
/// </code>
|
|
24
|
-
/// <para>
|
|
25
|
-
/// Cada posicao foi <b>medida</b> contra o pin, nao herdada de folclore. Acima do FICC o
|
|
26
|
-
/// middleware de custo recebe o uso agregado (10/4 + 30/6 chegam como 40/10); abaixo dele
|
|
27
|
-
/// receberia uma resposta por volta, e ainda leria um <c>UsageDetails</c> que o FICC muta
|
|
28
|
-
/// para acumular. A telemetria de chat fica abaixo do FICC porque o MAF 1.20.0 escreve, na
|
|
29
|
-
/// documentacao do proprio slot que ele reserva, que so assim o span de chat fecha antes
|
|
30
|
-
/// das tools e o <c>invoke_agent</c> vira raiz.
|
|
31
|
-
/// </para>
|
|
32
|
-
/// <para>
|
|
33
|
-
/// <b>Por que <c>UseProvidedChatClientAsIs = true</c>:</b> com o default, o
|
|
34
|
-
/// <c>ChatClientAgent</c> monta ele mesmo o FICC — e nao ha onde ajustar
|
|
35
|
-
/// <c>MaximumIterationsPerRequest</c> nem onde encaixar o custo entre o FICC e o cliente.
|
|
36
|
-
/// O preco medido dessa escolha e que o slot de telemetria que o MAF reservaria deixa de
|
|
37
|
-
/// existir: sem a T12 ligada, um agente desta fabrica emite <c>invoke_agent</c> e
|
|
38
|
-
/// <b>nenhum</b> span de chat. E por isso que a telemetria de chat e um encaixe nomeado, e
|
|
39
|
-
/// nao um detalhe opcional.
|
|
40
|
-
/// </para>
|
|
41
|
-
/// </remarks>
|
|
42
8
|
public sealed class AgentFactory
|
|
43
9
|
{
|
|
44
10
|
private readonly ModelRegistry _registry;
|
|
45
11
|
private readonly AgentFactoryOptions _options;
|
|
46
12
|
|
|
47
|
-
/// <summary>Cria a fabrica sobre um registry ja carregado.</summary>
|
|
48
|
-
/// <param name="registry">Fonte unica de alias, protocolo e tarifa.</param>
|
|
49
|
-
/// <param name="options">Infraestrutura e encaixes. Nulo = nenhum encaixe preenchido.</param>
|
|
50
13
|
public AgentFactory(ModelRegistry registry, AgentFactoryOptions? options = null)
|
|
51
14
|
{
|
|
52
15
|
ArgumentNullException.ThrowIfNull(registry);
|
|
@@ -55,15 +18,6 @@ public sealed class AgentFactory
|
|
|
55
18
|
_options = options ?? new AgentFactoryOptions();
|
|
56
19
|
}
|
|
57
20
|
|
|
58
|
-
/// <summary>
|
|
59
|
-
/// Materializa a spec. Alias desconhecido, limite de alias violado ou troca de
|
|
60
|
-
/// protocolo sem seletor sao recusas <b>na construcao</b> — nunca um agente meio certo.
|
|
61
|
-
/// </summary>
|
|
62
|
-
/// <remarks>
|
|
63
|
-
/// Recusar aqui e falha de composicao, nao excecao como fluxo de controle: acontece uma
|
|
64
|
-
/// vez, na montagem, e seguir adiante seria seguir sem regua. Quem quiser inspecionar
|
|
65
|
-
/// antes chama <c>registry.Resolve(alias).CheckRequest(...)</c>, que e Result.
|
|
66
|
-
/// </remarks>
|
|
67
21
|
public AIAgent Create(AgentSpec spec)
|
|
68
22
|
{
|
|
69
23
|
ArgumentNullException.ThrowIfNull(spec);
|
|
@@ -71,11 +25,6 @@ public sealed class AgentFactory
|
|
|
71
25
|
var alias = _registry.Resolve(spec.Alias);
|
|
72
26
|
var api = spec.ResolveApi(alias.Api);
|
|
73
27
|
|
|
74
|
-
// Alias de MIDIA nao vira agente, e a recusa e aqui, na construcao. Sem ela, um
|
|
75
|
-
// alias de imagem passado por engano viraria um agente de chat apontando para um
|
|
76
|
-
// modelo que nao fala chat: a falha apareceria tarde, no primeiro turno, com uma
|
|
77
|
-
// mensagem do provider que nao diz o que aconteceu. E a companheira obrigatoria de
|
|
78
|
-
// AgentApi.Images/Videos existirem — enum novo sem recusa e uma armadilha nova.
|
|
79
28
|
if (alias.Api.IsMedia() || api.IsMedia())
|
|
80
29
|
{
|
|
81
30
|
throw AgentFactoryException.MediaAliasIsNotAnAgent(spec.Alias, alias.Api.IsMedia() ? alias.Api : api);
|
|
@@ -98,6 +47,7 @@ public sealed class AgentFactory
|
|
|
98
47
|
Name = spec.Name,
|
|
99
48
|
Description = spec.Description,
|
|
100
49
|
ChatOptions = BuildChatOptions(spec, alias),
|
|
50
|
+
// Com o default o ChatClientAgent monta o proprio FICC, sem MaximumIterationsPerRequest nem slot para o custo.
|
|
101
51
|
UseProvidedChatClientAsIs = true,
|
|
102
52
|
};
|
|
103
53
|
|
|
@@ -112,12 +62,6 @@ public sealed class AgentFactory
|
|
|
112
62
|
: agent;
|
|
113
63
|
}
|
|
114
64
|
|
|
115
|
-
/// <summary>
|
|
116
|
-
/// As opcoes de requisicao do agente. <c>ModelId</c> vem do alias — a spec nunca cita
|
|
117
|
-
/// modelo. <c>Tools</c> e <c>ResponseFormat</c> entram antes de
|
|
118
|
-
/// <see cref="AgentSpecOptions.ApplyTo"/>, que por contrato nao sobrescreve o que ja
|
|
119
|
-
/// foi definido.
|
|
120
|
-
/// </summary>
|
|
121
65
|
private static ChatOptions BuildChatOptions(AgentSpec spec, ModelAlias alias)
|
|
122
66
|
{
|
|
123
67
|
var options = new ChatOptions
|
|
@@ -151,6 +95,8 @@ public sealed class AgentFactory
|
|
|
151
95
|
: throw AgentFactoryException.ProtocolWithoutSelector(alias.Name, alias.Api, api);
|
|
152
96
|
}
|
|
153
97
|
|
|
98
|
+
// A ordem e o contrato: o custo fica ACIMA do FICC para ver o uso ja somado das voltas, e a
|
|
99
|
+
// telemetria de chat ABAIXO dele porque so assim o span de chat fecha antes das tools (MAF 1.20.0).
|
|
154
100
|
private IChatClient BuildChatPipeline(IChatClient leaf, AgentSpec spec, ModelAlias alias)
|
|
155
101
|
{
|
|
156
102
|
var builder = leaf.AsBuilder();
|
|
@@ -186,11 +132,6 @@ public sealed class AgentFactory
|
|
|
186
132
|
return builder.Build(_options.ServiceProvider);
|
|
187
133
|
}
|
|
188
134
|
|
|
189
|
-
/// <summary>
|
|
190
|
-
/// Realiza <see cref="AgentSpecOptions.TimeoutSeconds"/>. Vive aqui, privado, porque e
|
|
191
|
-
/// a traducao de UMA opcao para o <see cref="CancellationToken"/> que o pipeline ja
|
|
192
|
-
/// carrega — e nao um conceito que alguem deva compor por fora.
|
|
193
|
-
/// </summary>
|
|
194
135
|
private sealed class TimeoutChatClient(IChatClient inner, TimeSpan timeout) : DelegatingChatClient(inner)
|
|
195
136
|
{
|
|
196
137
|
public override async Task<ChatResponse> GetResponseAsync(
|
|
@@ -222,43 +163,31 @@ public sealed class AgentFactory
|
|
|
222
163
|
}
|
|
223
164
|
}
|
|
224
165
|
|
|
225
|
-
/// <summary>Motivo de uma recusa da <see cref="AgentFactory"/>.</summary>
|
|
226
166
|
public enum AgentFactoryError
|
|
227
167
|
{
|
|
228
|
-
/// <summary>A requisicao viola um limite declarado no alias, com procedencia.</summary>
|
|
229
168
|
ConstraintViolated = 0,
|
|
230
169
|
|
|
231
|
-
/// <summary>A spec pede um protocolo diferente do alias e nao ha seletor de cliente.</summary>
|
|
232
170
|
ProtocolWithoutSelector = 1,
|
|
233
171
|
|
|
234
|
-
/// <summary>O seletor de cliente devolveu nulo.</summary>
|
|
235
172
|
NoChatClient = 2,
|
|
236
173
|
|
|
237
|
-
/// <summary>O alias e de midia (<c>api: images</c> ou <c>api: videos</c>) e nao fala conversa.</summary>
|
|
238
174
|
MediaAliasIsNotAnAgent = 3,
|
|
239
175
|
}
|
|
240
176
|
|
|
241
|
-
/// <summary>
|
|
242
|
-
/// Recusa de composicao da <see cref="AgentFactory"/>. <c>sealed</c> e discriminada por
|
|
243
|
-
/// <see cref="Reason"/>: quem trata precisa do motivo, nao de herdar do tipo.
|
|
244
|
-
/// </summary>
|
|
245
177
|
public sealed class AgentFactoryException : InvalidOperationException
|
|
246
178
|
{
|
|
247
179
|
private AgentFactoryException(AgentFactoryError reason, string message)
|
|
248
180
|
: base(message)
|
|
249
181
|
=> Reason = reason;
|
|
250
182
|
|
|
251
|
-
/// <summary>Por que a fabrica recusou.</summary>
|
|
252
183
|
public AgentFactoryError Reason { get; }
|
|
253
184
|
|
|
254
|
-
/// <summary>A requisicao viola limites do alias. A mensagem traz cada violacao com sua procedencia.</summary>
|
|
255
185
|
public static AgentFactoryException ConstraintViolated(string alias, IReadOnlyList<string> violations)
|
|
256
186
|
=> new(
|
|
257
187
|
AgentFactoryError.ConstraintViolated,
|
|
258
188
|
$"alias '{alias}': a spec viola limite(s) declarado(s) do alias e o agente NAO foi criado. " +
|
|
259
189
|
string.Join(" | ", violations));
|
|
260
190
|
|
|
261
|
-
/// <summary>Divergencia de protocolo sem seletor que saiba construir o outro cliente.</summary>
|
|
262
191
|
public static AgentFactoryException ProtocolWithoutSelector(string alias, AgentApi aliasApi, AgentApi specApi)
|
|
263
192
|
=> new(
|
|
264
193
|
AgentFactoryError.ProtocolWithoutSelector,
|
|
@@ -268,10 +197,6 @@ public sealed class AgentFactoryException : InvalidOperationException
|
|
|
268
197
|
"alias com o api pedido no model-registry.v2.json, ou preencha " +
|
|
269
198
|
$"{nameof(AgentFactoryOptions)}.{nameof(AgentFactoryOptions.ChatClientSelector)}.");
|
|
270
199
|
|
|
271
|
-
/// <summary>
|
|
272
|
-
/// O alias e de midia. Recusa nomeada, na construcao — nunca um agente que aponta para
|
|
273
|
-
/// um modelo que nao fala chat.
|
|
274
|
-
/// </summary>
|
|
275
200
|
public static AgentFactoryException MediaAliasIsNotAnAgent(string alias, AgentApi api)
|
|
276
201
|
=> new(
|
|
277
202
|
AgentFactoryError.MediaAliasIsNotAnAgent,
|
|
@@ -280,7 +205,6 @@ public sealed class AgentFactoryException : InvalidOperationException
|
|
|
280
205
|
$"{nameof(Morph.AiKit.Media.IMediaGenerator)}.{nameof(Morph.AiKit.Media.IMediaGenerator.EnqueueAsync)}, " +
|
|
281
206
|
"que devolve um id de job e nunca bytes. Ver ai-agents/media-pipeline.md.");
|
|
282
207
|
|
|
283
|
-
/// <summary>O seletor devolveu nulo — nao ha cliente para o par alias/protocolo.</summary>
|
|
284
208
|
public static AgentFactoryException NoChatClient(string alias, AgentApi api)
|
|
285
209
|
=> new(
|
|
286
210
|
AgentFactoryError.NoChatClient,
|
|
@@ -5,87 +5,18 @@ using Morph.AiKit.Providers;
|
|
|
5
5
|
|
|
6
6
|
namespace Morph.AiKit.Agents;
|
|
7
7
|
|
|
8
|
-
/// <summary>
|
|
9
|
-
/// O que a <see cref="AgentFactory"/> precisa saber que NAO esta na
|
|
10
|
-
/// <see cref="AgentSpec"/>: infraestrutura do processo (log, DI) e os tres encaixes do
|
|
11
|
-
/// pipeline que outras tasks preenchem.
|
|
12
|
-
/// </summary>
|
|
13
|
-
/// <remarks>
|
|
14
|
-
/// <para>
|
|
15
|
-
/// <b>Por que encaixes e nao dependencias diretas:</b> a ORDEM do pipeline e do kit — ela
|
|
16
|
-
/// esta escrita, medida e testada dentro da <see cref="AgentFactory"/>. O CONTEUDO de cada
|
|
17
|
-
/// posicao e de quem tem o tipo: o middleware de custo mora na T11 e a telemetria na T12.
|
|
18
|
-
/// Se a fabrica referenciasse os dois diretamente, ou ela nasceria depois deles, ou eles
|
|
19
|
-
/// nasceriam dentro dela. Com encaixe nomeado, a fabrica continua dona do lugar e cada
|
|
20
|
-
/// task continua dona do que ocupa o lugar.
|
|
21
|
-
/// </para>
|
|
22
|
-
/// <para>
|
|
23
|
-
/// Encaixe nulo = posicao vazia. Um agente sem custo e sem telemetria e um agente valido,
|
|
24
|
-
/// nao um agente pela metade.
|
|
25
|
-
/// </para>
|
|
26
|
-
/// </remarks>
|
|
27
8
|
public sealed record AgentFactoryOptions
|
|
28
9
|
{
|
|
29
|
-
/// <summary>
|
|
30
|
-
/// Fabrica de log repassada ao <c>FunctionInvokingChatClient</c> e ao
|
|
31
|
-
/// <c>ChatClientAgent</c>. Nula = sem log, que e o default do MAF.
|
|
32
|
-
/// </summary>
|
|
33
10
|
public ILoggerFactory? LoggerFactory { get; init; }
|
|
34
11
|
|
|
35
|
-
/// <summary>
|
|
36
|
-
/// Container usado para resolver servicos ao montar os pipelines. Nulo = os builders
|
|
37
|
-
/// do <c>Microsoft.Extensions.AI</c> usam o provider vazio deles.
|
|
38
|
-
/// </summary>
|
|
39
12
|
public IServiceProvider? ServiceProvider { get; init; }
|
|
40
13
|
|
|
41
|
-
/// <summary>
|
|
42
|
-
/// De onde sai o <see cref="IChatClient"/> quando o protocolo efetivo NAO e o do alias.
|
|
43
|
-
/// </summary>
|
|
44
|
-
/// <remarks>
|
|
45
|
-
/// <para>
|
|
46
|
-
/// O <c>ModelRegistry</c> memoiza <b>um</b> cliente por alias, construido pela
|
|
47
|
-
/// <c>IProviderClientFactory</c> a partir do <c>api:</c> daquele alias. Logo, uma spec
|
|
48
|
-
/// que pede Chat Completions num alias declarado <c>responses</c> nao pode ser servida
|
|
49
|
-
/// pelo cliente memoizado — ele fala o outro protocolo. Sem este seletor a fabrica
|
|
50
|
-
/// <b>recusa</b> a combinacao, nomeando os dois protocolos, em vez de devolver um agente
|
|
51
|
-
/// que diz falar um protocolo e fala outro.
|
|
52
|
-
/// </para>
|
|
53
|
-
/// <para>
|
|
54
|
-
/// Nulo (o normal) = todo agente usa o cliente memoizado do alias, e
|
|
55
|
-
/// <see cref="AgentSpec.Api"/> divergente vira recusa. Preenchido, recebe o alias e o
|
|
56
|
-
/// protocolo <b>efetivo</b> (ja resolvido por <see cref="AgentSpec.ResolveApi"/>) e
|
|
57
|
-
/// devolve o cliente correspondente.
|
|
58
|
-
/// </para>
|
|
59
|
-
/// </remarks>
|
|
60
14
|
public Func<ModelAlias, AgentApi, IChatClient>? ChatClientSelector { get; init; }
|
|
61
15
|
|
|
62
|
-
|
|
63
|
-
/// Encaixe do middleware de custo (T11), <b>acima</b> do <c>FunctionInvokingChatClient</c>.
|
|
64
|
-
/// Preencha com <c>(b, _, alias) => b.UseUsageCost(alias, sink)</c>.
|
|
65
|
-
/// </summary>
|
|
66
|
-
/// <remarks>
|
|
67
|
-
/// A posicao e medida, nao opinada: acima do FICC o middleware ve <b>uma</b> resposta
|
|
68
|
-
/// com o uso ja somado de todas as voltas de tool (medido: 40/10 num roteiro de duas
|
|
69
|
-
/// voltas de 10/4 e 30/6); abaixo do FICC ele ve uma resposta por volta. Pior, o FICC
|
|
70
|
-
/// <b>acumula no proprio objeto</b> <c>UsageDetails</c> da primeira volta — um sink que
|
|
71
|
-
/// guardasse a referencia abaixo do FICC leria valores que mudaram depois.
|
|
72
|
-
/// </remarks>
|
|
16
|
+
// Abaixo do FICC um sink veria uma resposta por volta, e o FICC muta o UsageDetails da primeira volta para acumular.
|
|
73
17
|
public Func<ChatClientBuilder, AgentSpec, ModelAlias, ChatClientBuilder>? ConfigureUsageCost { get; init; }
|
|
74
18
|
|
|
75
|
-
/// <summary>
|
|
76
|
-
/// Encaixe da telemetria de chat (T12), <b>abaixo</b> do <c>FunctionInvokingChatClient</c>
|
|
77
|
-
/// e imediatamente acima do cliente do provider.
|
|
78
|
-
/// </summary>
|
|
79
|
-
/// <remarks>
|
|
80
|
-
/// A posicao e exigencia escrita do proprio MAF 1.20.0: com a instrumentacao abaixo do
|
|
81
|
-
/// FICC o span de chat fecha <b>antes</b> de as tools rodarem, o que deixa o
|
|
82
|
-
/// <c>invoke_agent</c> como span raiz e permite ao FICC emitir <c>execute_tool</c>.
|
|
83
|
-
/// </remarks>
|
|
84
19
|
public Func<ChatClientBuilder, AgentSpec, ModelAlias, ChatClientBuilder>? ConfigureChatTelemetry { get; init; }
|
|
85
20
|
|
|
86
|
-
/// <summary>
|
|
87
|
-
/// Encaixe da telemetria de agente (T12) — o span mais externo, que cobre a invocacao
|
|
88
|
-
/// inteira. Preencha com <c>(b, _, _) => b.UseMorphTelemetry(telemetryOptions)</c>.
|
|
89
|
-
/// </summary>
|
|
90
21
|
public Func<AIAgentBuilder, AgentSpec, ModelAlias, AIAgentBuilder>? ConfigureAgentTelemetry { get; init; }
|
|
91
22
|
}
|
|
@@ -3,30 +3,11 @@ using Microsoft.Extensions.AI;
|
|
|
3
3
|
|
|
4
4
|
namespace Morph.AiKit.Agents;
|
|
5
5
|
|
|
6
|
-
/// <summary>
|
|
7
|
-
/// O agente <b>como dado</b>: tudo o que a <c>AgentFactory</c> (T10) precisa para
|
|
8
|
-
/// materializar um <c>AIAgent</c>, e nada mais. Nao tem comportamento de execucao, nao
|
|
9
|
-
/// abre conexao, nao le configuracao — o que permite descrever um agente em teste, em
|
|
10
|
-
/// JSON ou em banco sem arrastar infraestrutura junto.
|
|
11
|
-
/// </summary>
|
|
12
|
-
/// <remarks>
|
|
13
|
-
/// <para>
|
|
14
|
-
/// <b>O modelo nao aparece aqui.</b> So o <see cref="Alias"/>, que e resolvido pelo
|
|
15
|
-
/// <c>ModelRegistry</c>. E a regra do standard <c>ai-agents-providers-model-registry</c>:
|
|
16
|
-
/// agentes referenciam alias, nunca id de modelo — trocar de provider e mudanca de um
|
|
17
|
-
/// arquivo so.
|
|
18
|
-
/// </para>
|
|
19
|
-
/// </remarks>
|
|
20
6
|
public sealed record AgentSpec
|
|
21
7
|
{
|
|
22
8
|
private readonly string _alias = string.Empty;
|
|
23
9
|
private readonly string _instructions = string.Empty;
|
|
24
10
|
|
|
25
|
-
/// <summary>
|
|
26
|
-
/// Chave no <c>ModelRegistry</c>. Nunca um id de modelo.
|
|
27
|
-
/// Vazio ou so espaco e rejeitado na construcao: um alias em branco viraria uma falha
|
|
28
|
-
/// de resolucao ilegivel varias camadas adiante.
|
|
29
|
-
/// </summary>
|
|
30
11
|
public required string Alias
|
|
31
12
|
{
|
|
32
13
|
get => _alias;
|
|
@@ -37,7 +18,6 @@ public sealed record AgentSpec
|
|
|
37
18
|
}
|
|
38
19
|
}
|
|
39
20
|
|
|
40
|
-
/// <summary>Prompt de sistema do agente. Vazio ou so espaco e rejeitado na construcao.</summary>
|
|
41
21
|
public required string Instructions
|
|
42
22
|
{
|
|
43
23
|
get => _instructions;
|
|
@@ -48,44 +28,18 @@ public sealed record AgentSpec
|
|
|
48
28
|
}
|
|
49
29
|
}
|
|
50
30
|
|
|
51
|
-
/// <summary>
|
|
52
|
-
/// Protocolo desta spec. <b>Nulo = usa o <c>api:</c> do alias</b> — o caso normal.
|
|
53
|
-
/// Preenchido, vence o alias (ver <see cref="ResolveApi"/>).
|
|
54
|
-
/// </summary>
|
|
55
31
|
public AgentApi? Api { get; init; }
|
|
56
32
|
|
|
57
|
-
/// <summary>Tools do agente. Vazio por padrao — nunca nulo.</summary>
|
|
58
33
|
public IReadOnlyList<AITool> Tools { get; init; } = [];
|
|
59
34
|
|
|
60
|
-
|
|
61
|
-
/// Schema JSON da saida estruturada. Nulo = saida livre.
|
|
62
|
-
/// <para>
|
|
63
|
-
/// <b>Armadilha de tempo de vida:</b> um <see cref="JsonElement"/> so e valido enquanto
|
|
64
|
-
/// o <see cref="JsonDocument"/> que o originou estiver vivo. Guarde aqui um
|
|
65
|
-
/// <see cref="JsonElement.Clone"/> quando o documento for descartado — senao o schema
|
|
66
|
-
/// morre silenciosamente entre a montagem da spec e o uso dela.
|
|
67
|
-
/// </para>
|
|
68
|
-
/// </summary>
|
|
35
|
+
// Guarde um JsonElement.Clone(): o elemento morre junto com o JsonDocument que o originou.
|
|
69
36
|
public JsonElement? OutputSchema { get; init; }
|
|
70
37
|
|
|
71
|
-
/// <summary>Bag unico de opcoes. Nunca nulo; o default nao envia opcao nenhuma.</summary>
|
|
72
38
|
public AgentSpecOptions Options { get; init; } = new();
|
|
73
39
|
|
|
74
|
-
/// <summary>Nome legivel do agente (telemetria, logs). Nulo = sem nome.</summary>
|
|
75
40
|
public string? Name { get; init; }
|
|
76
41
|
|
|
77
|
-
/// <summary>Descricao legivel do agente. Nulo = sem descricao.</summary>
|
|
78
42
|
public string? Description { get; init; }
|
|
79
43
|
|
|
80
|
-
/// <summary>
|
|
81
|
-
/// Precedencia entre o <c>api:</c> da spec e o <c>api:</c> do alias, num lugar so.
|
|
82
|
-
/// <b>A spec vence quando presente; o alias vence quando a spec e nula.</b>
|
|
83
|
-
/// </summary>
|
|
84
|
-
/// <remarks>
|
|
85
|
-
/// A regra mora aqui, e nao dentro da <c>AgentFactory</c>, porque divergencia silenciosa
|
|
86
|
-
/// entre spec e registry e exatamente o bug que o <c>api:</c> por alias existe para
|
|
87
|
-
/// eliminar — e uma regra copiada em dois lugares e uma regra que ja divergiu.
|
|
88
|
-
/// </remarks>
|
|
89
|
-
/// <param name="aliasApi">O <c>api:</c> declarado no alias resolvido.</param>
|
|
90
44
|
public AgentApi ResolveApi(AgentApi aliasApi) => Api ?? aliasApi;
|
|
91
45
|
}
|