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.
Files changed (477) hide show
  1. package/README.md +15 -2
  2. package/bin/ummaya +10 -1
  3. package/npm-shrinkwrap.json +253 -2
  4. package/package.json +5 -1
  5. package/prompts/manifest.yaml +1 -1
  6. package/prompts/system_v1.md +1 -0
  7. package/pyproject.toml +26 -2
  8. package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
  9. package/src/ummaya/_canonical/__init__.py +2 -0
  10. package/src/ummaya/engine/engine.py +29 -132
  11. package/src/ummaya/evidence/__init__.py +21 -2
  12. package/src/ummaya/evidence/dataset_contract.py +193 -0
  13. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  14. package/src/ummaya/evidence/document_harness.py +313 -0
  15. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  16. package/src/ummaya/evidence/gates.py +70 -0
  17. package/src/ummaya/evidence/json_types.py +20 -0
  18. package/src/ummaya/evidence/models.py +88 -1
  19. package/src/ummaya/evidence/output_payload.py +89 -0
  20. package/src/ummaya/evidence/payload_documents.py +233 -0
  21. package/src/ummaya/evidence/route_contracts.py +224 -0
  22. package/src/ummaya/evidence/route_helpers.py +150 -0
  23. package/src/ummaya/evidence/runner.py +81 -212
  24. package/src/ummaya/evidence/source_provenance.py +246 -0
  25. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  26. package/src/ummaya/evidence/tool_layer.py +39 -0
  27. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  28. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  29. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  30. package/src/ummaya/ipc/frame_schema.py +5 -5
  31. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  32. package/src/ummaya/ipc/stdio.py +1109 -477
  33. package/src/ummaya/llm/client.py +102 -3
  34. package/src/ummaya/llm/config.py +8 -3
  35. package/src/ummaya/primitives/__init__.py +6 -2
  36. package/src/ummaya/primitives/delegation.py +1 -1
  37. package/src/ummaya/primitives/document.py +28 -0
  38. package/src/ummaya/settings.py +0 -3
  39. package/src/ummaya/tools/discovery_bridge.py +17 -1
  40. package/src/ummaya/tools/documents/__init__.py +297 -0
  41. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  42. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  43. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  44. package/src/ummaya/tools/documents/authoring.py +283 -0
  45. package/src/ummaya/tools/documents/baselines.py +114 -0
  46. package/src/ummaya/tools/documents/capability.py +331 -0
  47. package/src/ummaya/tools/documents/contracts.py +112 -0
  48. package/src/ummaya/tools/documents/conversion.py +521 -0
  49. package/src/ummaya/tools/documents/diff.py +275 -0
  50. package/src/ummaya/tools/documents/engines.py +163 -0
  51. package/src/ummaya/tools/documents/evaluation.py +291 -0
  52. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  53. package/src/ummaya/tools/documents/fixtures.py +174 -0
  54. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  55. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  56. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  57. package/src/ummaya/tools/documents/formats/base.py +41 -0
  58. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  59. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  60. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  61. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  62. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  63. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  64. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  65. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  66. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  67. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  68. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  69. package/src/ummaya/tools/documents/inspection.py +289 -0
  70. package/src/ummaya/tools/documents/intake.py +1079 -0
  71. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  72. package/src/ummaya/tools/documents/models.py +1598 -0
  73. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  74. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  75. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  76. package/src/ummaya/tools/documents/patch.py +170 -0
  77. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  78. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  79. package/src/ummaya/tools/documents/permissions.py +110 -0
  80. package/src/ummaya/tools/documents/planner.py +616 -0
  81. package/src/ummaya/tools/documents/registry.py +2733 -0
  82. package/src/ummaya/tools/documents/render.py +978 -0
  83. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  84. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  85. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  86. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  87. package/src/ummaya/tools/documents/reread.py +157 -0
  88. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  89. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  90. package/src/ummaya/tools/documents/scorecard.py +184 -0
  91. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  92. package/src/ummaya/tools/documents/style.py +48 -0
  93. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  94. package/src/ummaya/tools/documents/validate.py +347 -0
  95. package/src/ummaya/tools/executor.py +29 -0
  96. package/src/ummaya/tools/live_proxy.py +0 -3
  97. package/src/ummaya/tools/models.py +5 -1
  98. package/src/ummaya/tools/register_all.py +8 -0
  99. package/src/ummaya/tools/registry.py +10 -1
  100. package/src/ummaya/tools/routing/__init__.py +59 -0
  101. package/src/ummaya/tools/routing/builder.py +105 -0
  102. package/src/ummaya/tools/routing/cards.py +29 -0
  103. package/src/ummaya/tools/routing/decision_service.py +534 -0
  104. package/src/ummaya/tools/routing/decision_types.py +74 -0
  105. package/src/ummaya/tools/routing/feasibility.py +122 -0
  106. package/src/ummaya/tools/routing/intent.py +17 -0
  107. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  108. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  109. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  110. package/src/ummaya/tools/routing/intent_types.py +48 -0
  111. package/src/ummaya/tools/routing/lint.py +78 -0
  112. package/src/ummaya/tools/routing/metadata.py +174 -0
  113. package/src/ummaya/tools/routing/projection.py +340 -0
  114. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  115. package/src/ummaya/tools/routing/schema.py +81 -0
  116. package/src/ummaya/tools/routing/types.py +96 -0
  117. package/src/ummaya/tools/routing_index.py +2 -2
  118. package/src/ummaya/tools/search.py +34 -746
  119. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  120. package/tui/package.json +1 -1
  121. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  122. package/tui/src/QueryEngine.ts +12 -8
  123. package/tui/src/bridge/inboundAttachments.ts +3 -3
  124. package/tui/src/cli/handlers/auth.ts +3 -12
  125. package/tui/src/cli/print.ts +7 -7
  126. package/tui/src/commands/insights.ts +1 -1
  127. package/tui/src/commands/install-github-app/types.ts +8 -30
  128. package/tui/src/commands/plugin/types.ts +6 -28
  129. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  130. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  131. package/tui/src/components/Feedback.tsx +1 -1
  132. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  133. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  134. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  135. package/tui/src/components/Spinner/types.ts +6 -28
  136. package/tui/src/components/agents/generateAgent.ts +1 -1
  137. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  138. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  139. package/tui/src/components/mcp/types.ts +16 -38
  140. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  141. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  142. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  143. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  144. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  145. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  146. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  147. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  148. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  149. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  150. package/tui/src/components/primitive/index.tsx +43 -1
  151. package/tui/src/components/primitive/types.ts +137 -0
  152. package/tui/src/components/ui/option.ts +4 -26
  153. package/tui/src/constants/common.ts +0 -2
  154. package/tui/src/constants/prompts.ts +4 -3
  155. package/tui/src/constants/querySource.ts +4 -26
  156. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  157. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  158. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  159. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  160. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  161. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  162. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  163. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  164. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  165. package/tui/src/ink/ink.tsx +33 -14
  166. package/tui/src/ink/reconciler.ts +2 -3
  167. package/tui/src/ink/render-to-screen.ts +30 -10
  168. package/tui/src/ipc/bridge.ts +62 -15
  169. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  170. package/tui/src/ipc/codec.ts +3 -3
  171. package/tui/src/ipc/frames.generated.ts +12 -12
  172. package/tui/src/ipc/llmClient.ts +151 -27
  173. package/tui/src/ipc/schema/frame.schema.json +1 -1
  174. package/tui/src/keybindings/defaultBindings.ts +4 -0
  175. package/tui/src/main.tsx +29 -11
  176. package/tui/src/native-ts/file-index/index.ts +33 -3
  177. package/tui/src/observability/surface.ts +2 -2
  178. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  179. package/tui/src/projectOnboardingState.ts +7 -6
  180. package/tui/src/query/chatMessageTypes.ts +18 -0
  181. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  182. package/tui/src/query/deps.ts +1 -1
  183. package/tui/src/query/messageGuards.ts +106 -0
  184. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  185. package/tui/src/query/run.ts +1075 -0
  186. package/tui/src/query/supportBoundary.ts +168 -0
  187. package/tui/src/query/toolResultErrors.ts +103 -0
  188. package/tui/src/query/toolRunner.ts +687 -0
  189. package/tui/src/query/unavailableToolRepair.ts +118 -0
  190. package/tui/src/query.ts +9 -2186
  191. package/tui/src/screens/REPL.tsx +40 -29
  192. package/tui/src/services/api/adapterManifest.ts +4 -0
  193. package/tui/src/services/api/backendChat/events.ts +117 -0
  194. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  195. package/tui/src/services/api/backendChat/frame.ts +9 -0
  196. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  197. package/tui/src/services/api/backendChat/types.ts +62 -0
  198. package/tui/src/services/api/backendChat.ts +1 -0
  199. package/tui/src/services/api/client.ts +65 -2
  200. package/tui/src/services/api/errorUtils.ts +5 -5
  201. package/tui/src/services/api/errors.ts +1 -1
  202. package/tui/src/services/api/logging.ts +1 -1
  203. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  204. package/tui/src/services/api/ummaya/messages.ts +255 -0
  205. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  206. package/tui/src/services/api/ummaya/provider.ts +200 -0
  207. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  208. package/tui/src/services/api/ummaya/request.ts +200 -0
  209. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  210. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  211. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  212. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  213. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  214. package/tui/src/services/api/ummaya/types.ts +110 -0
  215. package/tui/src/services/api/ummaya/usage.ts +30 -0
  216. package/tui/src/services/api/ummaya.ts +26 -418
  217. package/tui/src/services/api/withRetry.ts +1 -1
  218. package/tui/src/services/awaySummary.ts +2 -2
  219. package/tui/src/services/claudeAiLimits.ts +1 -1
  220. package/tui/src/services/compact/autoCompact.ts +1 -1
  221. package/tui/src/services/compact/compact.ts +1 -1
  222. package/tui/src/services/lsp/types.ts +8 -30
  223. package/tui/src/services/tips/types.ts +6 -28
  224. package/tui/src/services/tokenEstimation.ts +1 -1
  225. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  226. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  227. package/tui/src/services/tools/toolExecution.ts +94 -1
  228. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  229. package/tui/src/store/session-store.ts +10 -36
  230. package/tui/src/stubs/any-stub.ts +15 -10
  231. package/tui/src/stubs/color-diff-napi.ts +37 -23
  232. package/tui/src/stubs/globals.d.ts +3 -3
  233. package/tui/src/stubs/macro-preload.ts +23 -12
  234. package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
  235. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  236. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  237. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  238. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  239. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  240. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  241. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  242. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  243. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  244. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  245. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  246. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  247. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  248. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  249. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  250. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  251. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  252. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  253. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  254. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  255. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  256. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  257. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  258. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  259. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  260. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  261. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  262. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  263. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  264. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  265. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  266. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  267. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  268. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  269. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  270. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  271. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  272. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  273. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  274. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  275. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  276. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  277. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  278. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  279. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  280. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  281. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  282. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  283. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  284. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  285. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  286. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  287. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  288. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  289. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  290. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  291. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  292. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  293. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  294. package/tui/src/tools/BashTool/call.ts +202 -0
  295. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  296. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  297. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  298. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  299. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  300. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  301. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  302. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  303. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  304. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  305. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  306. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  307. package/tui/src/tools/BashTool/schemas.ts +65 -0
  308. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  309. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  310. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  311. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  312. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  313. package/tui/src/tools/BriefTool/upload.ts +1 -1
  314. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  315. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  316. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  317. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  318. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  319. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  320. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  321. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  322. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  323. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  324. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  325. package/tui/src/tools/FileEditTool/call.ts +228 -0
  326. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  327. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  328. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  329. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  330. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  331. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  332. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
  333. package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
  334. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  335. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  336. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  337. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  338. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  339. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  340. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  341. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  342. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  343. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  344. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  345. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  346. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  347. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  348. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  349. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  350. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  351. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  352. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  353. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  354. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  355. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  356. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
  357. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  358. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  359. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
  360. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  361. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  362. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  363. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  364. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  365. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  366. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  367. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  368. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  369. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  370. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  371. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  372. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  373. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  374. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  375. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  376. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  377. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  378. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  379. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  380. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  381. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  382. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  383. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  384. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  385. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
  386. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  387. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  388. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  389. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  390. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  391. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  392. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  393. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  394. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  395. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  396. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  397. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  398. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  399. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  400. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  401. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  402. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  403. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  404. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  405. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  406. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  407. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  408. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  409. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  410. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  411. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  412. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  413. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  414. package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
  415. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  416. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  417. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  418. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  419. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  420. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  421. package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
  422. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  423. package/tui/src/tools.ts +39 -190
  424. package/tui/src/types/fileSuggestion.ts +4 -26
  425. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  426. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  427. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  428. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  429. package/tui/src/types/message.ts +80 -102
  430. package/tui/src/types/messageQueueTypes.ts +6 -28
  431. package/tui/src/types/notebook.ts +16 -38
  432. package/tui/src/types/statusLine.ts +4 -26
  433. package/tui/src/types/tools.ts +24 -46
  434. package/tui/src/types/utils.ts +6 -28
  435. package/tui/src/upstreamproxy/relay.ts +7 -3
  436. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  437. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  438. package/tui/src/utils/auth.ts +129 -139
  439. package/tui/src/utils/bash/ast.ts +23 -23
  440. package/tui/src/utils/bash/bashParser.ts +5 -5
  441. package/tui/src/utils/billing.ts +1 -1
  442. package/tui/src/utils/collapseReadSearch.ts +3 -3
  443. package/tui/src/utils/cronTasks.ts +1 -1
  444. package/tui/src/utils/execFileNoThrow.ts +1 -1
  445. package/tui/src/utils/filePersistence/types.ts +16 -38
  446. package/tui/src/utils/forkedAgent.ts +1 -1
  447. package/tui/src/utils/gracefulShutdown.ts +4 -4
  448. package/tui/src/utils/heapDumpService.ts +12 -8
  449. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  450. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  451. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  452. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  453. package/tui/src/utils/messages.ts +18 -0
  454. package/tui/src/utils/migrateSessions.ts +3 -3
  455. package/tui/src/utils/model/model.ts +6 -6
  456. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  457. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  458. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  459. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  460. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  461. package/tui/src/utils/protectedNamespace.ts +5 -3
  462. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  463. package/tui/src/utils/ripgrep.ts +16 -7
  464. package/tui/src/utils/sessionTitle.ts +1 -1
  465. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  466. package/tui/src/utils/shell/prefix.ts +1 -1
  467. package/tui/src/utils/sideQuery.ts +1 -1
  468. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  469. package/tui/src/utils/teleport.tsx +1 -1
  470. package/uv.lock +400 -14
  471. package/tui/src/services/api/claude.ts +0 -3540
  472. package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
  473. package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
  474. package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
  475. package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
  476. package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
  477. 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("&", "&amp;").replace('"', "&quot;").replace("<", "&lt;").replace(">", "&gt;")
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"