@polymorphism-tech/morph-spec 8.38.0 → 8.41.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 +20 -9
- package/README.md +2 -2
- package/bin/morph-spec.js +60 -43
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +4 -3
- package/framework/MORPH.md +10 -9
- package/framework/agents.json +43 -26
- package/framework/docs/CLI.md +7 -5
- package/framework/evals/rubrics/code-quality.md +4 -4
- package/framework/evals/rubrics/condensed.md +2 -2
- package/framework/hooks/README.md +1 -1
- package/framework/hooks/claude-code/core/telemetry-log.js +39 -8
- package/framework/hooks/claude-code/core/worktree-create.js +22 -6
- package/framework/hooks/shared/git-paths.js +38 -5
- package/framework/mcp/registry.json +58 -66
- package/framework/rules/infrastructure-standards.md +0 -1
- package/framework/rules/morph-workflow.md +9 -4
- 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 +59 -25
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +2 -2
- package/framework/skills/core/morph-implement/SKILL.md +48 -24
- package/framework/skills/core/morph-media/SKILL.md +2 -2
- package/framework/skills/core/morph-plan/SKILL.md +10 -3
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +1 -1
- 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 +7 -6
- package/framework/standards/PROVENANCE.json +4 -4
- package/framework/standards/STANDARDS.json +9 -9
- 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/architecture/code-comments.md +52 -16
- package/framework/standards/backend/dotnet/testing.md +4 -2
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +63 -50
- package/framework/standards/frontend/design-system/ai-image-generation.md +42 -28
- package/framework/standards/frontend/design-system/ai-video-generation.md +24 -9
- package/framework/standards/frontend/nextjs/testing.md +4 -2
- package/framework/standards/integration/mcp/mcp-tools.md +64 -126
- 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/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/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/mcp/mcp-setup.js +37 -9
- package/src/commands/project/doctor.js +12 -6
- package/src/commands/project/init.js +6 -3
- package/src/commands/project/install-plugin-cmd.js +1 -1
- package/src/commands/project/update.js +5 -0
- package/src/commands/project/worktree.js +60 -4
- package/src/commands/state/gate-check.js +5 -0
- package/src/commands/tasks/dag.js +27 -4
- package/src/commands/validation/verify.js +22 -38
- 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 +59 -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/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 +2 -0
- package/src/dashboard/vite-plugin-morph-data.js +134 -17
- package/src/lib/detectors/claude-config-detector.js +2 -7
- package/src/lib/detectors/index.js +5 -1
- package/src/lib/evaluator-report.js +22 -0
- package/src/lib/generators/settings-generator.js +208 -209
- 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 +13 -0
- package/src/lib/tasks/tasks-json-parser.js +21 -0
- package/src/lib/validators/code-budget/code-budget-validator.js +32 -4
- package/src/lib/worktree/env-allocator.js +9 -3
- package/src/scripts/install-plugin.js +1 -1
- package/src/scripts/setup-infra.js +2 -4
- package/src/utils/agents-installer.js +108 -13
- package/src/utils/banner.js +1 -1
- 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
|
@@ -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
|
}
|
|
@@ -2,135 +2,37 @@ using Microsoft.Extensions.AI;
|
|
|
2
2
|
|
|
3
3
|
namespace Morph.AiKit.Agents;
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
/// UM UNICO bag de opcoes do agente — a forma copiada do <c>AgentFrameworkToolkit</c>
|
|
7
|
-
/// sem o pacote (decisao D2). Em vez de N objetos de configuracao espalhados por
|
|
8
|
-
/// camadas, tudo o que um agente pode ajustar vive aqui, como dado.
|
|
9
|
-
/// </summary>
|
|
10
|
-
/// <remarks>
|
|
11
|
-
/// <para>
|
|
12
|
-
/// <b>Regra estrutural, e a razao de o tipo existir:</b> toda propriedade e nula por
|
|
13
|
-
/// padrao, e <b>nulo significa "nao envia ao provider"</b> — nunca "envia o default do
|
|
14
|
-
/// framework". E isso que impede o kit de mudar, por omissao, o comportamento de um
|
|
15
|
-
/// modelo. O canario da regra e
|
|
16
|
-
/// <c>AgentSpecTests.FreshOptionsProduceChatOptionsIndistinguishableFromPristine</c>:
|
|
17
|
-
/// uma <see cref="AgentSpecOptions"/> recem-construida produz um <see cref="ChatOptions"/>
|
|
18
|
-
/// indistinguivel de <c>new ChatOptions()</c>, propriedade por propriedade, por reflexao.
|
|
19
|
-
/// </para>
|
|
20
|
-
/// <para><b>Duas familias de opcao convivem aqui, e a fronteira e explicita:</b></para>
|
|
21
|
-
/// <list type="table">
|
|
22
|
-
/// <listheader><term>Familia</term><description>Para onde vai</description></listheader>
|
|
23
|
-
/// <item>
|
|
24
|
-
/// <term>Nivel de requisicao</term>
|
|
25
|
-
/// <description>
|
|
26
|
-
/// <see cref="Temperature"/>, <see cref="TopP"/>, <see cref="MaxOutputTokens"/>,
|
|
27
|
-
/// <see cref="Seed"/>, <see cref="StopSequences"/>, <see cref="ToolMode"/>,
|
|
28
|
-
/// <see cref="ReasoningEffort"/> e <see cref="ServiceTier"/> viram
|
|
29
|
-
/// <see cref="ChatOptions"/> em <see cref="ApplyTo"/>.
|
|
30
|
-
/// </description>
|
|
31
|
-
/// </item>
|
|
32
|
-
/// <item>
|
|
33
|
-
/// <term>Nivel de agente / pipeline</term>
|
|
34
|
-
/// <description>
|
|
35
|
-
/// <see cref="MaxToolIterations"/>, <see cref="AllowConcurrentToolInvocation"/>,
|
|
36
|
-
/// <see cref="TimeoutSeconds"/> e <see cref="EnableSensitiveTelemetry"/> NAO existem
|
|
37
|
-
/// em <see cref="ChatOptions"/>. Sao lidas diretamente pela <c>AgentFactory</c> (T10)
|
|
38
|
-
/// ao montar o pipeline e pela telemetria (T12). O teste
|
|
39
|
-
/// <c>AgentLevelKnobsNeverLeakIntoChatOptions</c> pina essa fronteira.
|
|
40
|
-
/// </description>
|
|
41
|
-
/// </item>
|
|
42
|
-
/// </list>
|
|
43
|
-
/// </remarks>
|
|
5
|
+
// Nulo significa "nao envia ao provider", nunca "envia o default do framework".
|
|
44
6
|
public sealed record AgentSpecOptions
|
|
45
7
|
{
|
|
46
|
-
/// <summary>
|
|
47
|
-
/// Chave usada em <see cref="ChatOptions.AdditionalProperties"/> para transportar
|
|
48
|
-
/// <see cref="ServiceTier"/>. Ver a nota de fato em <see cref="ServiceTier"/>.
|
|
49
|
-
/// </summary>
|
|
50
8
|
public const string ServiceTierPropertyName = "service_tier";
|
|
51
9
|
|
|
52
|
-
/// <summary>Amostragem. Nulo = o provider decide.</summary>
|
|
53
10
|
public float? Temperature { get; init; }
|
|
54
11
|
|
|
55
|
-
/// <summary>Nucleus sampling. Nulo = o provider decide.</summary>
|
|
56
12
|
public float? TopP { get; init; }
|
|
57
13
|
|
|
58
|
-
/// <summary>Teto de tokens de saida. Nulo = o provider decide.</summary>
|
|
59
14
|
public int? MaxOutputTokens { get; init; }
|
|
60
15
|
|
|
61
|
-
/// <summary>Semente de amostragem, quando o provider suporta. Nulo = nao envia.</summary>
|
|
62
16
|
public long? Seed { get; init; }
|
|
63
17
|
|
|
64
|
-
/// <summary>
|
|
65
|
-
/// Sequencias de parada. Nulo = nao envia. Lista vazia NAO e tratada como nulo: e
|
|
66
|
-
/// enviada como veio. "Nulo nao envia; nao-nulo envia o que voce escreveu" e a regra
|
|
67
|
-
/// inteira, sem excecao escondida.
|
|
68
|
-
/// </summary>
|
|
69
18
|
public IReadOnlyList<string>? StopSequences { get; init; }
|
|
70
19
|
|
|
71
|
-
/// <summary>Modo de tool calling (<c>Auto</c>, <c>None</c>, <c>RequireAny</c>...). Nulo = nao envia.</summary>
|
|
72
20
|
public ChatToolMode? ToolMode { get; init; }
|
|
73
21
|
|
|
74
|
-
/// <summary>
|
|
75
|
-
/// Esforco de raciocinio. Tipado com o enum de primeira classe do
|
|
76
|
-
/// <c>Microsoft.Extensions.AI</c> 10.9.0 (<c>None/Low/Medium/High/ExtraHigh</c>) em vez
|
|
77
|
-
/// de string, porque e exatamente esse valor que o limite de tool calling da Chat
|
|
78
|
-
/// Completions cita — ver <c>ModelAliasConstraints.ToolCallingRequiresReasoningEffortNone</c>.
|
|
79
|
-
/// Nulo = nao envia: vale o default do provider, e qual e ele o kit NAO afirma saber.
|
|
80
|
-
/// </summary>
|
|
81
22
|
public Microsoft.Extensions.AI.ReasoningEffort? ReasoningEffort { get; init; }
|
|
82
23
|
|
|
83
|
-
/// <summary>
|
|
84
|
-
/// Tier de servico (ex.: <c>"flex"</c>, <c>"priority"</c>).
|
|
85
|
-
/// <b>Nota de fato, nao de gosto:</b> o <see cref="ChatOptions"/> do
|
|
86
|
-
/// <c>Microsoft.Extensions.AI</c> 10.9.0 NAO tem propriedade de service tier — apurado
|
|
87
|
-
/// por reflexao sobre o assembly do pin, nao por memoria. Quando definido, o valor
|
|
88
|
-
/// viaja em <see cref="ChatOptions.AdditionalProperties"/> sob a chave
|
|
89
|
-
/// <see cref="ServiceTierPropertyName"/>, e so chega ao fio se o adaptador do provider
|
|
90
|
-
/// ler dali ou se a <c>AgentFactory</c> montar um
|
|
91
|
-
/// <see cref="ChatOptions.RawRepresentationFactory"/>. Nulo = nao envia.
|
|
92
|
-
/// </summary>
|
|
93
24
|
public string? ServiceTier { get; init; }
|
|
94
25
|
|
|
95
|
-
/// <summary>
|
|
96
|
-
/// Teto de voltas de tool calling. <b>Nivel de agente</b>: vira
|
|
97
|
-
/// <c>FunctionInvokingChatClient.MaximumIterationsPerRequest</c> na T10, nunca
|
|
98
|
-
/// <see cref="ChatOptions"/>. Nulo = default do pipeline.
|
|
99
|
-
/// </summary>
|
|
100
26
|
public int? MaxToolIterations { get; init; }
|
|
101
27
|
|
|
102
|
-
/// <summary>
|
|
103
|
-
/// Permite invocar tools concorrentemente numa mesma volta. <b>Nivel de agente</b>
|
|
104
|
-
/// (<c>FunctionInvokingChatClient.AllowConcurrentInvocation</c>). Nulo = default do pipeline.
|
|
105
|
-
/// </summary>
|
|
106
28
|
public bool? AllowConcurrentToolInvocation { get; init; }
|
|
107
29
|
|
|
108
|
-
/// <summary>
|
|
109
|
-
/// Timeout da invocacao, em segundos. <b>Nivel de agente</b>: vira
|
|
110
|
-
/// <c>CancellationToken</c> na T10. Nulo = sem timeout proprio.
|
|
111
|
-
/// </summary>
|
|
112
30
|
public int? TimeoutSeconds { get; init; }
|
|
113
31
|
|
|
114
|
-
/// <summary>
|
|
115
|
-
/// Liga a captura de conteudo sensivel (prompt e resposta) nos spans.
|
|
116
|
-
/// <b>Nivel de agente</b> — insumo da T12. A diferenca entre nulo e <c>false</c> e
|
|
117
|
-
/// preservada de proposito: nulo e "nao opinei", <c>false</c> e "decidi que nao".
|
|
118
|
-
/// </summary>
|
|
119
32
|
public bool? EnableSensitiveTelemetry { get; init; }
|
|
120
33
|
|
|
121
|
-
/// <summary>
|
|
122
|
-
/// Produz um <see cref="ChatOptions"/> novo com — e SOMENTE com — as opcoes de nivel
|
|
123
|
-
/// de requisicao que foram definidas.
|
|
124
|
-
/// </summary>
|
|
125
34
|
public ChatOptions ToChatOptions() => ApplyTo(new ChatOptions());
|
|
126
35
|
|
|
127
|
-
/// <summary>
|
|
128
|
-
/// Aplica as opcoes de nivel de requisicao sobre um <see cref="ChatOptions"/> existente.
|
|
129
|
-
/// Propriedade nula aqui NAO toca no destino, o que permite a <c>AgentFactory</c>
|
|
130
|
-
/// preencher <c>Tools</c> e <c>ResponseFormat</c> antes ou depois sem risco de perde-los.
|
|
131
|
-
/// </summary>
|
|
132
|
-
/// <param name="options">Destino. Nao pode ser nulo.</param>
|
|
133
|
-
/// <returns>O proprio <paramref name="options"/>, para encadeamento.</returns>
|
|
134
36
|
public ChatOptions ApplyTo(ChatOptions options)
|
|
135
37
|
{
|
|
136
38
|
ArgumentNullException.ThrowIfNull(options);
|
|
@@ -170,6 +72,7 @@ public sealed record AgentSpecOptions
|
|
|
170
72
|
options.Reasoning = new ReasoningOptions { Effort = effort };
|
|
171
73
|
}
|
|
172
74
|
|
|
75
|
+
// ChatOptions do Microsoft.Extensions.AI 10.9.0 nao tem service tier (apurado por reflexao).
|
|
173
76
|
if (ServiceTier is not null)
|
|
174
77
|
{
|
|
175
78
|
options.AdditionalProperties ??= new AdditionalPropertiesDictionary();
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
namespace Morph.AiKit;
|
|
2
2
|
|
|
3
|
-
/// <summary>
|
|
4
|
-
/// Ancora de tipo do assembly. Existe para que o esqueleto tenha uma superficie
|
|
5
|
-
/// publica verificavel antes das tasks T7-T14 — e para que qualquer consumidor
|
|
6
|
-
/// (teste, DI, reflexao) tenha um <c>typeof</c> estavel para apontar ao assembly
|
|
7
|
-
/// sem depender de um tipo de dominio que ainda nao existe.
|
|
8
|
-
/// </summary>
|
|
9
3
|
public sealed class AiKitAssemblyMarker
|
|
10
4
|
{
|
|
11
5
|
private AiKitAssemblyMarker()
|