ummaya 0.2.4 → 0.2.5
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/README.md +15 -2
- package/bin/ummaya +10 -1
- package/npm-shrinkwrap.json +253 -2
- package/package.json +5 -1
- package/prompts/manifest.yaml +1 -1
- package/prompts/system_v1.md +1 -0
- package/pyproject.toml +26 -2
- package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
- package/src/ummaya/_canonical/__init__.py +2 -0
- package/src/ummaya/engine/engine.py +29 -132
- package/src/ummaya/evidence/__init__.py +21 -2
- package/src/ummaya/evidence/dataset_contract.py +193 -0
- package/src/ummaya/evidence/document_authoring_cases.py +33 -0
- package/src/ummaya/evidence/document_harness.py +313 -0
- package/src/ummaya/evidence/document_viewer_ux.py +391 -0
- package/src/ummaya/evidence/gates.py +70 -0
- package/src/ummaya/evidence/json_types.py +20 -0
- package/src/ummaya/evidence/models.py +88 -1
- package/src/ummaya/evidence/output_payload.py +89 -0
- package/src/ummaya/evidence/payload_documents.py +233 -0
- package/src/ummaya/evidence/route_contracts.py +224 -0
- package/src/ummaya/evidence/route_helpers.py +150 -0
- package/src/ummaya/evidence/runner.py +81 -212
- package/src/ummaya/evidence/source_provenance.py +246 -0
- package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
- package/src/ummaya/evidence/tool_layer.py +39 -0
- package/src/ummaya/evidence/tool_layer_models.py +151 -0
- package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
- package/src/ummaya/ipc/document_intent_normalization.py +185 -0
- package/src/ummaya/ipc/frame_schema.py +5 -5
- package/src/ummaya/ipc/route_diagnostics.py +73 -0
- package/src/ummaya/ipc/stdio.py +1109 -477
- package/src/ummaya/llm/client.py +102 -3
- package/src/ummaya/llm/config.py +8 -3
- package/src/ummaya/primitives/__init__.py +6 -2
- package/src/ummaya/primitives/delegation.py +1 -1
- package/src/ummaya/primitives/document.py +28 -0
- package/src/ummaya/settings.py +0 -3
- package/src/ummaya/tools/discovery_bridge.py +17 -1
- package/src/ummaya/tools/documents/__init__.py +297 -0
- package/src/ummaya/tools/documents/adapter_registry.py +487 -0
- package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
- package/src/ummaya/tools/documents/artifact_store.py +454 -0
- package/src/ummaya/tools/documents/authoring.py +283 -0
- package/src/ummaya/tools/documents/baselines.py +114 -0
- package/src/ummaya/tools/documents/capability.py +331 -0
- package/src/ummaya/tools/documents/contracts.py +112 -0
- package/src/ummaya/tools/documents/conversion.py +521 -0
- package/src/ummaya/tools/documents/diff.py +275 -0
- package/src/ummaya/tools/documents/engines.py +163 -0
- package/src/ummaya/tools/documents/evaluation.py +291 -0
- package/src/ummaya/tools/documents/explicit_values.py +108 -0
- package/src/ummaya/tools/documents/fixtures.py +174 -0
- package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
- package/src/ummaya/tools/documents/formats/__init__.py +2 -0
- package/src/ummaya/tools/documents/formats/archive.py +528 -0
- package/src/ummaya/tools/documents/formats/base.py +41 -0
- package/src/ummaya/tools/documents/formats/code_file.py +211 -0
- package/src/ummaya/tools/documents/formats/data_file.py +272 -0
- package/src/ummaya/tools/documents/formats/hwp.py +284 -0
- package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
- package/src/ummaya/tools/documents/formats/odf.py +435 -0
- package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
- package/src/ummaya/tools/documents/formats/passive.py +766 -0
- package/src/ummaya/tools/documents/formats/pdf.py +702 -0
- package/src/ummaya/tools/documents/formats/text_web.py +268 -0
- package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
- package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
- package/src/ummaya/tools/documents/inspection.py +289 -0
- package/src/ummaya/tools/documents/intake.py +1079 -0
- package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
- package/src/ummaya/tools/documents/models.py +1598 -0
- package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
- package/src/ummaya/tools/documents/orchestrator.py +96 -0
- package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
- package/src/ummaya/tools/documents/patch.py +170 -0
- package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
- package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
- package/src/ummaya/tools/documents/permissions.py +110 -0
- package/src/ummaya/tools/documents/planner.py +616 -0
- package/src/ummaya/tools/documents/registry.py +2733 -0
- package/src/ummaya/tools/documents/render.py +978 -0
- package/src/ummaya/tools/documents/render_comparison.py +113 -0
- package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
- package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
- package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
- package/src/ummaya/tools/documents/reread.py +157 -0
- package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
- package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
- package/src/ummaya/tools/documents/scorecard.py +184 -0
- package/src/ummaya/tools/documents/socratic_planner.py +193 -0
- package/src/ummaya/tools/documents/style.py +48 -0
- package/src/ummaya/tools/documents/tool_defs.py +523 -0
- package/src/ummaya/tools/documents/validate.py +347 -0
- package/src/ummaya/tools/executor.py +29 -0
- package/src/ummaya/tools/live_proxy.py +0 -3
- package/src/ummaya/tools/models.py +5 -1
- package/src/ummaya/tools/register_all.py +8 -0
- package/src/ummaya/tools/registry.py +10 -1
- package/src/ummaya/tools/routing/__init__.py +59 -0
- package/src/ummaya/tools/routing/builder.py +105 -0
- package/src/ummaya/tools/routing/cards.py +29 -0
- package/src/ummaya/tools/routing/decision_service.py +534 -0
- package/src/ummaya/tools/routing/decision_types.py +74 -0
- package/src/ummaya/tools/routing/feasibility.py +122 -0
- package/src/ummaya/tools/routing/intent.py +17 -0
- package/src/ummaya/tools/routing/intent_extractor.py +207 -0
- package/src/ummaya/tools/routing/intent_patterns.py +160 -0
- package/src/ummaya/tools/routing/intent_public_data.py +150 -0
- package/src/ummaya/tools/routing/intent_types.py +48 -0
- package/src/ummaya/tools/routing/lint.py +78 -0
- package/src/ummaya/tools/routing/metadata.py +174 -0
- package/src/ummaya/tools/routing/projection.py +340 -0
- package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
- package/src/ummaya/tools/routing/schema.py +81 -0
- package/src/ummaya/tools/routing/types.py +96 -0
- package/src/ummaya/tools/routing_index.py +2 -2
- package/src/ummaya/tools/search.py +34 -746
- package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
- package/tui/package.json +1 -1
- package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
- package/tui/src/QueryEngine.ts +12 -8
- package/tui/src/bridge/inboundAttachments.ts +3 -3
- package/tui/src/cli/handlers/auth.ts +3 -12
- package/tui/src/cli/print.ts +7 -7
- package/tui/src/commands/insights.ts +1 -1
- package/tui/src/commands/install-github-app/types.ts +8 -30
- package/tui/src/commands/plugin/types.ts +6 -28
- package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
- package/tui/src/commands/rename/generateSessionName.ts +1 -1
- package/tui/src/components/Feedback.tsx +1 -1
- package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
- package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
- package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
- package/tui/src/components/Spinner/types.ts +6 -28
- package/tui/src/components/agents/generateAgent.ts +1 -1
- package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
- package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
- package/tui/src/components/mcp/types.ts +16 -38
- package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
- package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
- package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
- package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
- package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
- package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
- package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
- package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
- package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
- package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
- package/tui/src/components/primitive/index.tsx +43 -1
- package/tui/src/components/primitive/types.ts +137 -0
- package/tui/src/components/ui/option.ts +4 -26
- package/tui/src/constants/common.ts +0 -2
- package/tui/src/constants/prompts.ts +4 -3
- package/tui/src/constants/querySource.ts +4 -26
- package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
- package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
- package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
- package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
- package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
- package/tui/src/hooks/useApiKeyVerification.ts +1 -1
- package/tui/src/hooks/useVirtualScroll.ts +1 -1
- package/tui/src/ink/ink.tsx +33 -14
- package/tui/src/ink/reconciler.ts +2 -3
- package/tui/src/ink/render-to-screen.ts +30 -10
- package/tui/src/ipc/bridge.ts +62 -15
- package/tui/src/ipc/bridgeSingleton.ts +5 -1
- package/tui/src/ipc/codec.ts +3 -3
- package/tui/src/ipc/frames.generated.ts +12 -12
- package/tui/src/ipc/llmClient.ts +151 -27
- package/tui/src/ipc/schema/frame.schema.json +1 -1
- package/tui/src/keybindings/defaultBindings.ts +4 -0
- package/tui/src/main.tsx +29 -11
- package/tui/src/native-ts/file-index/index.ts +33 -3
- package/tui/src/observability/surface.ts +2 -2
- package/tui/src/probes/toolRegistryProbe.tsx +3 -1
- package/tui/src/projectOnboardingState.ts +7 -6
- package/tui/src/query/chatMessageTypes.ts +18 -0
- package/tui/src/query/chatMessagesBuilder.ts +1 -1
- package/tui/src/query/deps.ts +1 -1
- package/tui/src/query/messageGuards.ts +106 -0
- package/tui/src/query/publicDataTerminalRepair.ts +384 -0
- package/tui/src/query/run.ts +1075 -0
- package/tui/src/query/supportBoundary.ts +168 -0
- package/tui/src/query/toolResultErrors.ts +103 -0
- package/tui/src/query/toolRunner.ts +687 -0
- package/tui/src/query/unavailableToolRepair.ts +118 -0
- package/tui/src/query.ts +9 -2186
- package/tui/src/screens/REPL.tsx +40 -29
- package/tui/src/services/api/adapterManifest.ts +4 -0
- package/tui/src/services/api/backendChat/events.ts +117 -0
- package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
- package/tui/src/services/api/backendChat/frame.ts +9 -0
- package/tui/src/services/api/backendChat/streaming.ts +430 -0
- package/tui/src/services/api/backendChat/types.ts +62 -0
- package/tui/src/services/api/backendChat.ts +1 -0
- package/tui/src/services/api/client.ts +65 -2
- package/tui/src/services/api/errorUtils.ts +5 -5
- package/tui/src/services/api/errors.ts +1 -1
- package/tui/src/services/api/logging.ts +1 -1
- package/tui/src/services/api/ummaya/evidence.ts +194 -0
- package/tui/src/services/api/ummaya/messages.ts +255 -0
- package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
- package/tui/src/services/api/ummaya/provider.ts +200 -0
- package/tui/src/services/api/ummaya/reasoning.ts +24 -0
- package/tui/src/services/api/ummaya/request.ts +200 -0
- package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
- package/tui/src/services/api/ummaya/streaming.ts +365 -0
- package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
- package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
- package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
- package/tui/src/services/api/ummaya/types.ts +110 -0
- package/tui/src/services/api/ummaya/usage.ts +30 -0
- package/tui/src/services/api/ummaya.ts +26 -418
- package/tui/src/services/api/withRetry.ts +1 -1
- package/tui/src/services/awaySummary.ts +2 -2
- package/tui/src/services/claudeAiLimits.ts +1 -1
- package/tui/src/services/compact/autoCompact.ts +1 -1
- package/tui/src/services/compact/compact.ts +1 -1
- package/tui/src/services/lsp/types.ts +8 -30
- package/tui/src/services/tips/types.ts +6 -28
- package/tui/src/services/tokenEstimation.ts +1 -1
- package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
- package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
- package/tui/src/services/tools/toolExecution.ts +94 -1
- package/tui/src/store/pendingPermissionSlot.ts +1 -1
- package/tui/src/store/session-store.ts +10 -36
- package/tui/src/stubs/any-stub.ts +15 -10
- package/tui/src/stubs/color-diff-napi.ts +37 -23
- package/tui/src/stubs/globals.d.ts +3 -3
- package/tui/src/stubs/macro-preload.ts +23 -12
- package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
- package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
- package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
- package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
- package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
- package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
- package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
- package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
- package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
- package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
- package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
- package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
- package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
- package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
- package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
- package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
- package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
- package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
- package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
- package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
- package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
- package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
- package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
- package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
- package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
- package/tui/src/tools/AgentTool/permissions.ts +39 -0
- package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
- package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
- package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
- package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
- package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
- package/tui/src/tools/AgentTool/runAgent.ts +1 -1
- package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
- package/tui/src/tools/AgentTool/schemas.ts +196 -0
- package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
- package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
- package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
- package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
- package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
- package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
- package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
- package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
- package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
- package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
- package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
- package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
- package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
- package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
- package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
- package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
- package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
- package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
- package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
- package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
- package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
- package/tui/src/tools/BashTool/call.ts +202 -0
- package/tui/src/tools/BashTool/callLoader.ts +35 -0
- package/tui/src/tools/BashTool/commandClassification.ts +151 -0
- package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
- package/tui/src/tools/BashTool/cwdReset.ts +33 -0
- package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
- package/tui/src/tools/BashTool/modeValidation.ts +13 -1
- package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
- package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
- package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
- package/tui/src/tools/BashTool/resultLoader.ts +29 -0
- package/tui/src/tools/BashTool/resultMapping.ts +83 -0
- package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
- package/tui/src/tools/BashTool/schemas.ts +65 -0
- package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
- package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
- package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
- package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
- package/tui/src/tools/BashTool/uiLoader.ts +37 -0
- package/tui/src/tools/BriefTool/upload.ts +1 -1
- package/tui/src/tools/CalculatorTool/parser.ts +2 -2
- package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
- package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
- package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
- package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
- package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
- package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
- package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
- package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
- package/tui/src/tools/FileEditTool/call.ts +228 -0
- package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
- package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
- package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
- package/tui/src/tools/FileWriteTool/call.ts +223 -0
- package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
- package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
- package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
- package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
- package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
- package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
- package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
- package/tui/src/tools/NotebookEditTool/call.ts +254 -0
- package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
- package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
- package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
- package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
- package/tui/src/tools/PowerShellTool/call.ts +179 -0
- package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
- package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
- package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
- package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
- package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
- package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
- package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
- package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
- package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
- package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/validation.ts +39 -0
- package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
- package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
- package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
- package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
- package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
- package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
- package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
- package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
- package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
- package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
- package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
- package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
- package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
- package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
- package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
- package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
- package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
- package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
- package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
- package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
- package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
- package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
- package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
- package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
- package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
- package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
- package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
- package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
- package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
- package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
- package/tui/src/tools/WebFetchTool/call.ts +227 -0
- package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
- package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
- package/tui/src/tools/WebFetchTool/types.ts +23 -0
- package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
- package/tui/src/tools/WebFetchTool/utils.ts +1 -1
- package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
- package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
- package/tui/src/tools/WebSearchTool/call.ts +33 -0
- package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
- package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
- package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
- package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
- package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
- package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
- package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
- package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
- package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
- package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
- package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
- package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
- package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
- package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
- package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
- package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
- package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
- package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
- package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
- package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
- package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
- package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
- package/tui/src/tools.ts +39 -190
- package/tui/src/types/fileSuggestion.ts +4 -26
- package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
- package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
- package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
- package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
- package/tui/src/types/message.ts +80 -102
- package/tui/src/types/messageQueueTypes.ts +6 -28
- package/tui/src/types/notebook.ts +16 -38
- package/tui/src/types/statusLine.ts +4 -26
- package/tui/src/types/tools.ts +24 -46
- package/tui/src/types/utils.ts +6 -28
- package/tui/src/upstreamproxy/relay.ts +7 -3
- package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
- package/tui/src/utils/assistantMessageFactories.ts +9 -3
- package/tui/src/utils/auth.ts +129 -139
- package/tui/src/utils/bash/ast.ts +23 -23
- package/tui/src/utils/bash/bashParser.ts +5 -5
- package/tui/src/utils/billing.ts +1 -1
- package/tui/src/utils/collapseReadSearch.ts +3 -3
- package/tui/src/utils/cronTasks.ts +1 -1
- package/tui/src/utils/execFileNoThrow.ts +1 -1
- package/tui/src/utils/filePersistence/types.ts +16 -38
- package/tui/src/utils/forkedAgent.ts +1 -1
- package/tui/src/utils/gracefulShutdown.ts +4 -4
- package/tui/src/utils/heapDumpService.ts +12 -8
- package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
- package/tui/src/utils/hooks/execPromptHook.ts +1 -1
- package/tui/src/utils/hooks/skillImprovement.ts +1 -1
- package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
- package/tui/src/utils/messages.ts +18 -0
- package/tui/src/utils/migrateSessions.ts +3 -3
- package/tui/src/utils/model/model.ts +6 -6
- package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
- package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
- package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
- package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
- package/tui/src/utils/plugins/pluginLoader.ts +8 -8
- package/tui/src/utils/protectedNamespace.ts +5 -3
- package/tui/src/utils/rawJsonToolCall.ts +242 -0
- package/tui/src/utils/ripgrep.ts +16 -7
- package/tui/src/utils/sessionTitle.ts +1 -1
- package/tui/src/utils/settings/permissionValidation.ts +14 -2
- package/tui/src/utils/shell/prefix.ts +1 -1
- package/tui/src/utils/sideQuery.ts +1 -1
- package/tui/src/utils/systemThemeWatcher.ts +13 -3
- package/tui/src/utils/teleport.tsx +1 -1
- package/uv.lock +400 -14
- package/tui/src/services/api/claude.ts +0 -3540
- package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
- package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
- package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
- package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
- package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
- package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Final, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
ActivePrimitive = Literal["find", "locate", "send", "check"]
|
|
10
|
+
|
|
11
|
+
ACTIVE_PRIMITIVES: Final[tuple[ActivePrimitive, ...]] = ("find", "locate", "send", "check")
|
|
12
|
+
LEGACY_PRIMITIVE_ALIASES: Final[dict[str, ActivePrimitive]] = {
|
|
13
|
+
"lookup": "find",
|
|
14
|
+
"resolve_location": "locate",
|
|
15
|
+
"submit": "send",
|
|
16
|
+
"verify": "check",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ToolSelectionIntent(BaseModel):
|
|
21
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
22
|
+
|
|
23
|
+
raw_query: str
|
|
24
|
+
normalized_query: str
|
|
25
|
+
intent_verbs: tuple[ActivePrimitive, ...]
|
|
26
|
+
entities: tuple[str, ...]
|
|
27
|
+
document_refs: tuple[str, ...]
|
|
28
|
+
location_refs: tuple[str, ...]
|
|
29
|
+
time_refs: tuple[str, ...]
|
|
30
|
+
public_data_refs: tuple[str, ...]
|
|
31
|
+
credential_refs: tuple[str, ...]
|
|
32
|
+
side_effect_markers: tuple[str, ...]
|
|
33
|
+
explicit_tool_ids: tuple[str, ...]
|
|
34
|
+
explicit_artifact_ids: tuple[str, ...]
|
|
35
|
+
candidate_primitives: tuple[ActivePrimitive, ...]
|
|
36
|
+
missing_slots: tuple[str, ...]
|
|
37
|
+
unsafe_assumptions: tuple[str, ...]
|
|
38
|
+
requires_clarification: bool
|
|
39
|
+
requires_permission: bool
|
|
40
|
+
|
|
41
|
+
def has_location_ref(self, value: str) -> bool:
|
|
42
|
+
return value in self.location_refs
|
|
43
|
+
|
|
44
|
+
def has_public_data_ref(self, value: str) -> bool:
|
|
45
|
+
return value in self.public_data_refs
|
|
46
|
+
|
|
47
|
+
def has_document_ref(self, value: str) -> bool:
|
|
48
|
+
return value in self.document_refs
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ummaya.tools.routing.types import (
|
|
6
|
+
RAW_SCHEMA_MARKERS,
|
|
7
|
+
AdapterCard,
|
|
8
|
+
AdapterCardQualityViolation,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def lint_adapter_card(card: AdapterCard) -> tuple[AdapterCardQualityViolation, ...]:
|
|
13
|
+
violations: list[AdapterCardQualityViolation] = []
|
|
14
|
+
if card.source_mode in ("live", "mock") and not card.policy_authority_url:
|
|
15
|
+
violations.append(
|
|
16
|
+
AdapterCardQualityViolation(
|
|
17
|
+
code="missing_policy_citation",
|
|
18
|
+
message="live/mock adapter cards must cite an agency policy URL",
|
|
19
|
+
)
|
|
20
|
+
)
|
|
21
|
+
if not card.input_schema_summary:
|
|
22
|
+
violations.append(
|
|
23
|
+
AdapterCardQualityViolation(
|
|
24
|
+
code="missing_required_slot_metadata",
|
|
25
|
+
message="adapter cards must summarize input slots",
|
|
26
|
+
)
|
|
27
|
+
)
|
|
28
|
+
if not card.safety_annotations:
|
|
29
|
+
violations.append(
|
|
30
|
+
AdapterCardQualityViolation(
|
|
31
|
+
code="missing_safety_annotations",
|
|
32
|
+
message="adapter cards must expose safety annotations",
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
if not card.credential_requirements:
|
|
36
|
+
violations.append(
|
|
37
|
+
AdapterCardQualityViolation(
|
|
38
|
+
code="missing_credential_requirements",
|
|
39
|
+
message="adapter cards must expose credential requirements",
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
if not card.examples_ko or not card.examples_en:
|
|
43
|
+
violations.append(
|
|
44
|
+
AdapterCardQualityViolation(
|
|
45
|
+
code="missing_examples",
|
|
46
|
+
message="adapter cards must include Korean and English examples",
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
if not card.negative_examples:
|
|
50
|
+
violations.append(
|
|
51
|
+
AdapterCardQualityViolation(
|
|
52
|
+
code="missing_negative_examples",
|
|
53
|
+
message="adapter cards must include negative examples",
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
if not card.limitations:
|
|
57
|
+
violations.append(
|
|
58
|
+
AdapterCardQualityViolation(
|
|
59
|
+
code="missing_limitations",
|
|
60
|
+
message="adapter cards must state routing limitations",
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
if any(marker in card.routing_text for marker in RAW_SCHEMA_MARKERS):
|
|
64
|
+
violations.append(
|
|
65
|
+
AdapterCardQualityViolation(
|
|
66
|
+
code="raw_schema_leakage",
|
|
67
|
+
message="routing_text must not embed raw JSON schema",
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
return tuple(violations)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def assert_adapter_card_quality(card: AdapterCard) -> None:
|
|
74
|
+
violations = lint_adapter_card(card)
|
|
75
|
+
if not violations:
|
|
76
|
+
return
|
|
77
|
+
detail = ", ".join(f"{violation.code}: {violation.message}" for violation in violations)
|
|
78
|
+
raise ValueError(f"AdapterCard quality violations: {detail}")
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from typing import assert_never
|
|
7
|
+
|
|
8
|
+
from ummaya.tools.models import GovAPITool, MockFidelityGrade
|
|
9
|
+
from ummaya.tools.routing.schema import unique
|
|
10
|
+
from ummaya.tools.routing.types import (
|
|
11
|
+
AdapterCardError,
|
|
12
|
+
PrimitiveFamily,
|
|
13
|
+
SchemaFieldSummary,
|
|
14
|
+
SideEffectLevel,
|
|
15
|
+
SourceMode,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def primitive_family(value: str | None) -> PrimitiveFamily:
|
|
20
|
+
match value:
|
|
21
|
+
case "find":
|
|
22
|
+
return "find"
|
|
23
|
+
case "locate":
|
|
24
|
+
return "locate"
|
|
25
|
+
case "send":
|
|
26
|
+
return "send"
|
|
27
|
+
case "check":
|
|
28
|
+
return "check"
|
|
29
|
+
case "document":
|
|
30
|
+
return "document"
|
|
31
|
+
case None:
|
|
32
|
+
raise AdapterCardError("AdapterCard requires GovAPITool.primitive to be declared")
|
|
33
|
+
case _:
|
|
34
|
+
raise AdapterCardError(f"Unsupported adapter primitive for AdapterCard: {value!r}")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def source_mode_for_tool(tool: GovAPITool) -> SourceMode:
|
|
38
|
+
return "mock" if tool.adapter_mode == "mock" else "live"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def side_effect_level_for_tool(
|
|
42
|
+
tool: GovAPITool,
|
|
43
|
+
primitive: PrimitiveFamily,
|
|
44
|
+
) -> SideEffectLevel:
|
|
45
|
+
if tool.policy is not None:
|
|
46
|
+
match tool.policy.citizen_facing_gate:
|
|
47
|
+
case "read-only":
|
|
48
|
+
return "read_only"
|
|
49
|
+
case "login":
|
|
50
|
+
return "login"
|
|
51
|
+
case "action":
|
|
52
|
+
return "action"
|
|
53
|
+
case "sign":
|
|
54
|
+
return "sign"
|
|
55
|
+
case "send":
|
|
56
|
+
return "send"
|
|
57
|
+
case unreachable_gate:
|
|
58
|
+
assert_never(unreachable_gate)
|
|
59
|
+
match primitive:
|
|
60
|
+
case "send":
|
|
61
|
+
return "send"
|
|
62
|
+
case "check":
|
|
63
|
+
return "verify"
|
|
64
|
+
case "find" | "locate" | "document":
|
|
65
|
+
return "read_only"
|
|
66
|
+
case unreachable_primitive:
|
|
67
|
+
assert_never(unreachable_primitive)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def mock_fidelity_grade_for_tool(tool: GovAPITool) -> MockFidelityGrade:
|
|
71
|
+
if tool.adapter_mode != "mock":
|
|
72
|
+
return "not_applicable"
|
|
73
|
+
if tool.mock_fidelity_grade == "not_applicable":
|
|
74
|
+
return "unknown"
|
|
75
|
+
return tool.mock_fidelity_grade
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def credential_requirements_for_tool(tool: GovAPITool) -> tuple[str, ...]:
|
|
79
|
+
requirements: list[str] = [tool.auth_type]
|
|
80
|
+
if tool.published_tier_minimum is not None:
|
|
81
|
+
requirements.append(tool.published_tier_minimum)
|
|
82
|
+
if tool.nist_aal_hint is not None:
|
|
83
|
+
requirements.append(tool.nist_aal_hint)
|
|
84
|
+
return tuple(unique(requirements))
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def capabilities_for_tool(tool: GovAPITool, primitive: PrimitiveFamily) -> tuple[str, ...]:
|
|
88
|
+
return tuple(unique([primitive, *tool.category, tool.name_ko]))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def entity_types_for_tool(
|
|
92
|
+
input_summary: Sequence[SchemaFieldSummary],
|
|
93
|
+
categories: Sequence[str],
|
|
94
|
+
) -> tuple[str, ...]:
|
|
95
|
+
names = [field.name for field in input_summary]
|
|
96
|
+
if names:
|
|
97
|
+
return tuple(names)
|
|
98
|
+
return tuple(unique(categories))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def prerequisite_tools_for_tool(tool: GovAPITool, primitive: PrimitiveFamily) -> tuple[str, ...]:
|
|
102
|
+
description = (tool.llm_description or "").lower()
|
|
103
|
+
if primitive == "send" or "prior check" in description or "delegation" in description:
|
|
104
|
+
return ("check",)
|
|
105
|
+
return ()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def examples_ko_for_tool(tool: GovAPITool) -> tuple[str, ...]:
|
|
109
|
+
if tool.trigger_examples:
|
|
110
|
+
return tuple(tool.trigger_examples)
|
|
111
|
+
return (tool.name_ko,)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def examples_en_for_tool(tool: GovAPITool, primitive: PrimitiveFamily) -> tuple[str, ...]:
|
|
115
|
+
domain = tool.category[0] if tool.category else tool.id
|
|
116
|
+
return (f"Use {tool.id} to {primitive} {domain} information.",)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def limitations_for_tool(
|
|
120
|
+
tool: GovAPITool,
|
|
121
|
+
source_mode: SourceMode,
|
|
122
|
+
policy_authority_url: str | None,
|
|
123
|
+
) -> tuple[str, ...]:
|
|
124
|
+
limitations = [f"Requires registry source_mode {source_mode} and auth_type {tool.auth_type}."]
|
|
125
|
+
if source_mode == "mock":
|
|
126
|
+
limitations.append("Mock output may mirror shape without live upstream freshness.")
|
|
127
|
+
if policy_authority_url is None:
|
|
128
|
+
limitations.append("No agency policy citation is registered for this adapter.")
|
|
129
|
+
return tuple(limitations)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def safety_annotations_for_tool(
|
|
133
|
+
tool: GovAPITool,
|
|
134
|
+
side_effect_level: SideEffectLevel,
|
|
135
|
+
) -> tuple[str, ...]:
|
|
136
|
+
values = [
|
|
137
|
+
f"side_effect_level:{side_effect_level}",
|
|
138
|
+
f"auth_type:{tool.auth_type}",
|
|
139
|
+
f"concurrency_safe:{str(tool.is_concurrency_safe).lower()}",
|
|
140
|
+
]
|
|
141
|
+
if tool.policy is not None:
|
|
142
|
+
values.append(f"citizen_gate:{tool.policy.citizen_facing_gate}")
|
|
143
|
+
return tuple(values)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def domain_for_tool(tool: GovAPITool) -> str:
|
|
147
|
+
if tool.category:
|
|
148
|
+
return tool.category[0]
|
|
149
|
+
return tool.id
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def routing_text(
|
|
153
|
+
*,
|
|
154
|
+
tool_id: str,
|
|
155
|
+
primitive: PrimitiveFamily,
|
|
156
|
+
agency: str,
|
|
157
|
+
domain: str,
|
|
158
|
+
capabilities: Sequence[str],
|
|
159
|
+
required_slots: Sequence[str],
|
|
160
|
+
examples_ko: Sequence[str],
|
|
161
|
+
limitations: Sequence[str],
|
|
162
|
+
) -> str:
|
|
163
|
+
return " | ".join(
|
|
164
|
+
(
|
|
165
|
+
f"tool_id={tool_id}",
|
|
166
|
+
f"primitive={primitive}",
|
|
167
|
+
f"agency={agency}",
|
|
168
|
+
f"domain={domain}",
|
|
169
|
+
f"capabilities={', '.join(capabilities)}",
|
|
170
|
+
f"required_slots={', '.join(required_slots) or 'none'}",
|
|
171
|
+
f"examples_ko={'; '.join(examples_ko)}",
|
|
172
|
+
f"limitations={'; '.join(limitations)}",
|
|
173
|
+
)
|
|
174
|
+
)
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from collections.abc import Iterable, Mapping
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel, ConfigDict
|
|
10
|
+
|
|
11
|
+
from ummaya.tools.errors import ToolNotFoundError
|
|
12
|
+
from ummaya.tools.models import GovAPITool
|
|
13
|
+
from ummaya.tools.routing.decision_types import RouteCandidate, RouteDecision, SchemaProjectionLevel
|
|
14
|
+
from ummaya.tools.routing.schema import model_json_schema
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from ummaya.tools.registry import ToolRegistry
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AvailableAdaptersProjection(BaseModel):
|
|
21
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
22
|
+
|
|
23
|
+
content: str | None
|
|
24
|
+
tool_ids: tuple[str, ...]
|
|
25
|
+
schema_projection_level: SchemaProjectionLevel
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def build_available_adapters_projection(
|
|
29
|
+
decision: RouteDecision,
|
|
30
|
+
registry: ToolRegistry,
|
|
31
|
+
*,
|
|
32
|
+
query: str,
|
|
33
|
+
projection_level: SchemaProjectionLevel | None = None,
|
|
34
|
+
max_visible: int = 5,
|
|
35
|
+
visible_tool_ids: Iterable[str] | None = None,
|
|
36
|
+
exclude_tool_ids: Iterable[str] = (),
|
|
37
|
+
) -> AvailableAdaptersProjection:
|
|
38
|
+
level = projection_level or decision.schema_projection_level
|
|
39
|
+
if level == "none":
|
|
40
|
+
return AvailableAdaptersProjection(
|
|
41
|
+
content=None,
|
|
42
|
+
tool_ids=(),
|
|
43
|
+
schema_projection_level=level,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
visible = _selected_candidates(
|
|
47
|
+
decision,
|
|
48
|
+
max_visible=max_visible,
|
|
49
|
+
visible_tool_ids=visible_tool_ids,
|
|
50
|
+
exclude_tool_ids=exclude_tool_ids,
|
|
51
|
+
)
|
|
52
|
+
if not visible:
|
|
53
|
+
return AvailableAdaptersProjection(
|
|
54
|
+
content=None,
|
|
55
|
+
tool_ids=(),
|
|
56
|
+
schema_projection_level="none",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
tool_ids = tuple(candidate.tool_id for candidate in visible)
|
|
60
|
+
lines: list[str] = [
|
|
61
|
+
(
|
|
62
|
+
f'<available_adapters query="{_xml_attr(query[:120])}" '
|
|
63
|
+
f'decision_id="{decision.decision_id}" '
|
|
64
|
+
f'backend="{_xml_attr(decision.backend_label)}" '
|
|
65
|
+
f'schema_projection="{level}">'
|
|
66
|
+
),
|
|
67
|
+
(
|
|
68
|
+
f"RouteDecision candidates (top {len(visible)}, backend={decision.backend_label}, "
|
|
69
|
+
f"manifest_hash={decision.manifest_hash[:12]})."
|
|
70
|
+
),
|
|
71
|
+
"Use concrete adapter function names when they are present in tools[].",
|
|
72
|
+
]
|
|
73
|
+
if decision.degradation_reason:
|
|
74
|
+
lines.append(f"degradation_reason: {decision.degradation_reason}")
|
|
75
|
+
if decision.permission_gate:
|
|
76
|
+
lines.append("permission_gate: true")
|
|
77
|
+
if level == "name_only":
|
|
78
|
+
lines.extend(f"- {candidate.tool_id}" for candidate in visible)
|
|
79
|
+
lines.append("</available_adapters>")
|
|
80
|
+
return AvailableAdaptersProjection(
|
|
81
|
+
content="\n".join(lines),
|
|
82
|
+
tool_ids=tool_ids,
|
|
83
|
+
schema_projection_level=level,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
for candidate in visible:
|
|
87
|
+
lines.extend(_candidate_lines(candidate, registry, projection_level=level))
|
|
88
|
+
lines.extend(_route_rules(visible))
|
|
89
|
+
lines.append("</available_adapters>")
|
|
90
|
+
return AvailableAdaptersProjection(
|
|
91
|
+
content="\n".join(lines),
|
|
92
|
+
tool_ids=tool_ids,
|
|
93
|
+
schema_projection_level=level,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def selected_concrete_adapter_tools(
|
|
98
|
+
decision: RouteDecision,
|
|
99
|
+
registry: ToolRegistry,
|
|
100
|
+
*,
|
|
101
|
+
exclude_tool_ids: Iterable[str] = (),
|
|
102
|
+
max_tools: int = 5,
|
|
103
|
+
) -> tuple[GovAPITool, ...]:
|
|
104
|
+
excluded = frozenset(exclude_tool_ids)
|
|
105
|
+
tools: list[GovAPITool] = []
|
|
106
|
+
for tool_id in _decision_tool_ids(decision):
|
|
107
|
+
if tool_id in excluded:
|
|
108
|
+
continue
|
|
109
|
+
try:
|
|
110
|
+
tools.append(registry.find(tool_id))
|
|
111
|
+
except ToolNotFoundError:
|
|
112
|
+
continue
|
|
113
|
+
if len(tools) >= max_tools:
|
|
114
|
+
break
|
|
115
|
+
return tuple(tools)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _selected_candidates(
|
|
119
|
+
decision: RouteDecision,
|
|
120
|
+
*,
|
|
121
|
+
max_visible: int,
|
|
122
|
+
visible_tool_ids: Iterable[str] | None = None,
|
|
123
|
+
exclude_tool_ids: Iterable[str] = (),
|
|
124
|
+
) -> tuple[RouteCandidate, ...]:
|
|
125
|
+
excluded = frozenset(exclude_tool_ids)
|
|
126
|
+
selected = (
|
|
127
|
+
tuple(tool_id for tool_id in visible_tool_ids if tool_id not in excluded)
|
|
128
|
+
if visible_tool_ids is not None
|
|
129
|
+
else tuple(tool_id for tool_id in _decision_tool_ids(decision) if tool_id not in excluded)
|
|
130
|
+
)
|
|
131
|
+
selected_rank = {tool_id: index for index, tool_id in enumerate(selected)}
|
|
132
|
+
candidates_by_id = {
|
|
133
|
+
candidate.tool_id: candidate
|
|
134
|
+
for candidate in decision.candidate_set
|
|
135
|
+
if candidate.tool_id in selected_rank
|
|
136
|
+
}
|
|
137
|
+
ordered = tuple(
|
|
138
|
+
candidates_by_id[tool_id] for tool_id in selected if tool_id in candidates_by_id
|
|
139
|
+
)
|
|
140
|
+
return ordered[: max(0, max_visible)]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _decision_tool_ids(decision: RouteDecision) -> tuple[str, ...]:
|
|
144
|
+
if decision.selected_tools:
|
|
145
|
+
return decision.selected_tools
|
|
146
|
+
if (
|
|
147
|
+
decision.clarification is not None
|
|
148
|
+
and decision.clarification.reason == "side_effect_confirmation"
|
|
149
|
+
):
|
|
150
|
+
return ()
|
|
151
|
+
return tuple(candidate.tool_id for candidate in decision.candidate_set)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _candidate_lines(
|
|
155
|
+
candidate: RouteCandidate,
|
|
156
|
+
registry: ToolRegistry,
|
|
157
|
+
*,
|
|
158
|
+
projection_level: SchemaProjectionLevel,
|
|
159
|
+
) -> list[str]:
|
|
160
|
+
card = candidate.card
|
|
161
|
+
lines = [
|
|
162
|
+
f"- tool_id: {card.tool_id}",
|
|
163
|
+
f" primitive: {card.primitive_family}",
|
|
164
|
+
f" source_mode: {card.source_mode}",
|
|
165
|
+
f" agency: {card.agency}",
|
|
166
|
+
f" domain: {card.domain}",
|
|
167
|
+
f" score: {candidate.retrieval_score:.4f}",
|
|
168
|
+
f" description: {_one_line(card.routing_text)}",
|
|
169
|
+
f" required_params: {list(card.required_slots)}",
|
|
170
|
+
f" optional_params: {list(card.optional_slots)}",
|
|
171
|
+
f" call_hint: {card.tool_id}({{...schema fields...}})",
|
|
172
|
+
f" policy_url: {card.policy_authority_url or ''}",
|
|
173
|
+
]
|
|
174
|
+
llm_description = _tool_llm_description(card.tool_id, registry)
|
|
175
|
+
if llm_description:
|
|
176
|
+
lines.append(f" usage: {_one_line(llm_description)}")
|
|
177
|
+
if projection_level in {"summary", "full_schema"}:
|
|
178
|
+
lines.append(" input_schema_summary:")
|
|
179
|
+
lines.extend(_schema_summary_lines(candidate, registry))
|
|
180
|
+
if projection_level == "full_schema":
|
|
181
|
+
try:
|
|
182
|
+
tool = registry.find(card.tool_id)
|
|
183
|
+
schema_json = json.dumps(
|
|
184
|
+
model_json_schema(tool.input_schema),
|
|
185
|
+
ensure_ascii=False,
|
|
186
|
+
sort_keys=True,
|
|
187
|
+
)
|
|
188
|
+
except ToolNotFoundError:
|
|
189
|
+
schema_json = "{}"
|
|
190
|
+
lines.append(f" input_schema_json: {schema_json}")
|
|
191
|
+
return lines
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _tool_llm_description(tool_id: str, registry: ToolRegistry) -> str | None:
|
|
195
|
+
try:
|
|
196
|
+
value = registry.find(tool_id).llm_description
|
|
197
|
+
except ToolNotFoundError:
|
|
198
|
+
return None
|
|
199
|
+
return value if isinstance(value, str) and value.strip() else None
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _schema_summary_lines(candidate: RouteCandidate, registry: ToolRegistry) -> list[str]:
|
|
203
|
+
card = candidate.card
|
|
204
|
+
try:
|
|
205
|
+
schema = model_json_schema(registry.find(card.tool_id).input_schema)
|
|
206
|
+
except ToolNotFoundError:
|
|
207
|
+
schema = {}
|
|
208
|
+
properties = _mapping(schema.get("properties"))
|
|
209
|
+
defs = _mapping(schema.get("$defs"))
|
|
210
|
+
required = frozenset(card.required_slots)
|
|
211
|
+
lines: list[str] = []
|
|
212
|
+
for field in card.input_schema_summary:
|
|
213
|
+
flag = "required" if field.required else "optional"
|
|
214
|
+
description = f" - {_one_line(field.description)}" if field.description else ""
|
|
215
|
+
lines.append(f" - {field.name} ({field.type}, {flag}){description}")
|
|
216
|
+
field_schema = _mapping(properties.get(field.name))
|
|
217
|
+
for nested_name, nested_schema in _nested_properties(field.name, field_schema, defs):
|
|
218
|
+
nested_description = _description(nested_schema)
|
|
219
|
+
nested_suffix = f" - {_one_line(nested_description)}" if nested_description else ""
|
|
220
|
+
nested_required = _nested_required(field.name, nested_name, field_schema, defs)
|
|
221
|
+
nested_flag = "required" if field.name in required and nested_required else "optional"
|
|
222
|
+
lines.append(
|
|
223
|
+
f" - {nested_name} ({_schema_type(nested_schema)}, {nested_flag})"
|
|
224
|
+
f"{nested_suffix}"
|
|
225
|
+
)
|
|
226
|
+
return lines
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _route_rules(candidates: tuple[RouteCandidate, ...]) -> tuple[str, ...]:
|
|
230
|
+
primitives = frozenset(candidate.card.primitive_family for candidate in candidates)
|
|
231
|
+
lines = [
|
|
232
|
+
"Rules:",
|
|
233
|
+
(
|
|
234
|
+
" - Concrete adapter functions accept only their own schema fields; "
|
|
235
|
+
"do not wrap tool_id/params inside concrete adapter calls."
|
|
236
|
+
),
|
|
237
|
+
(
|
|
238
|
+
" - Use root primitives find/locate/check/send only when the concrete "
|
|
239
|
+
"adapter function is not loaded."
|
|
240
|
+
),
|
|
241
|
+
(
|
|
242
|
+
" - Preserve explicit citizen constraints such as count, radius, date, "
|
|
243
|
+
"time, category, institution type, and administrative region when a "
|
|
244
|
+
"selected schema exposes the matching field."
|
|
245
|
+
),
|
|
246
|
+
]
|
|
247
|
+
if primitives == {"find"}:
|
|
248
|
+
lines.append(
|
|
249
|
+
" - All selected adapters are read/fetch candidates; do not switch to "
|
|
250
|
+
"check/send unless the citizen explicitly asks for authentication, "
|
|
251
|
+
"consent, submission, payment, report, or filing."
|
|
252
|
+
)
|
|
253
|
+
return tuple(lines)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _one_line(value: str | None, *, limit: int = 900) -> str:
|
|
257
|
+
compact = " ".join((value or "").split())
|
|
258
|
+
if len(compact) <= limit:
|
|
259
|
+
return compact
|
|
260
|
+
return compact[: limit - 3] + "..."
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _xml_attr(value: str) -> str:
|
|
264
|
+
return (
|
|
265
|
+
value.replace("&", "&").replace('"', """).replace("<", "<").replace(">", ">")
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _nested_properties(
|
|
270
|
+
parent_name: str,
|
|
271
|
+
field_schema: Mapping[str, object],
|
|
272
|
+
defs: Mapping[str, object],
|
|
273
|
+
) -> tuple[tuple[str, Mapping[str, object]], ...]:
|
|
274
|
+
target = _resolve_ref(field_schema, defs)
|
|
275
|
+
if target:
|
|
276
|
+
return _properties_with_prefix(parent_name, target)
|
|
277
|
+
raw_items = field_schema.get("items")
|
|
278
|
+
item_schema = _mapping(raw_items)
|
|
279
|
+
item_target = _resolve_ref(item_schema, defs)
|
|
280
|
+
if item_target:
|
|
281
|
+
return _properties_with_prefix(f"{parent_name}[]", item_target)
|
|
282
|
+
return ()
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def _properties_with_prefix(
|
|
286
|
+
prefix: str, schema: Mapping[str, object]
|
|
287
|
+
) -> tuple[tuple[str, Mapping[str, object]], ...]:
|
|
288
|
+
properties = _mapping(schema.get("properties"))
|
|
289
|
+
return tuple(
|
|
290
|
+
(f"{prefix}.{name}", _mapping(spec)) for name, spec in properties.items() if str(name)
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _nested_required(
|
|
295
|
+
parent_name: str,
|
|
296
|
+
nested_name: str,
|
|
297
|
+
field_schema: Mapping[str, object],
|
|
298
|
+
defs: Mapping[str, object],
|
|
299
|
+
) -> bool:
|
|
300
|
+
target = _resolve_ref(field_schema, defs)
|
|
301
|
+
nested_key = nested_name.removeprefix(f"{parent_name}.")
|
|
302
|
+
if not target:
|
|
303
|
+
item_schema = _mapping(field_schema.get("items"))
|
|
304
|
+
target = _resolve_ref(item_schema, defs)
|
|
305
|
+
nested_key = nested_name.removeprefix(f"{parent_name}[].")
|
|
306
|
+
raw_required = target.get("required") if target else None
|
|
307
|
+
if not isinstance(raw_required, list):
|
|
308
|
+
return False
|
|
309
|
+
return nested_key in {str(item) for item in raw_required if isinstance(item, str)}
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def _resolve_ref(schema: Mapping[str, object], defs: Mapping[str, object]) -> Mapping[str, object]:
|
|
313
|
+
ref = schema.get("$ref")
|
|
314
|
+
if not isinstance(ref, str) or not ref.startswith("#/$defs/"):
|
|
315
|
+
return {}
|
|
316
|
+
return _mapping(defs.get(ref.removeprefix("#/$defs/")))
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def _mapping(value: object) -> Mapping[str, object]:
|
|
320
|
+
return value if isinstance(value, Mapping) else {}
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def _description(schema: Mapping[str, object]) -> str | None:
|
|
324
|
+
value = schema.get("description")
|
|
325
|
+
return value if isinstance(value, str) and value.strip() else None
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def _schema_type(schema: Mapping[str, object]) -> str:
|
|
329
|
+
raw_type = schema.get("type")
|
|
330
|
+
if isinstance(raw_type, str):
|
|
331
|
+
return raw_type
|
|
332
|
+
if isinstance(raw_type, list):
|
|
333
|
+
return "|".join(str(item) for item in raw_type)
|
|
334
|
+
if "$ref" in schema:
|
|
335
|
+
return "ref"
|
|
336
|
+
if "anyOf" in schema:
|
|
337
|
+
return "anyOf"
|
|
338
|
+
if "oneOf" in schema:
|
|
339
|
+
return "oneOf"
|
|
340
|
+
return "unknown"
|