ummaya 0.2.3 → 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 (534) hide show
  1. package/README.md +17 -3
  2. package/bin/ummaya +10 -1
  3. package/npm-shrinkwrap.json +253 -2
  4. package/package.json +5 -1
  5. package/prompts/manifest.yaml +2 -2
  6. package/prompts/session_guidance_v1.md +3 -1
  7. package/prompts/system_v1.md +9 -7
  8. package/pyproject.toml +26 -7
  9. package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
  10. package/src/ummaya/_canonical/__init__.py +2 -0
  11. package/src/ummaya/context/builder.py +17 -11
  12. package/src/ummaya/engine/engine.py +30 -113
  13. package/src/ummaya/engine/query.py +20 -0
  14. package/src/ummaya/evidence/__init__.py +44 -0
  15. package/src/ummaya/evidence/__main__.py +7 -0
  16. package/src/ummaya/evidence/dataset_contract.py +193 -0
  17. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  18. package/src/ummaya/evidence/document_harness.py +313 -0
  19. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  20. package/src/ummaya/evidence/gates.py +70 -0
  21. package/src/ummaya/evidence/json_types.py +20 -0
  22. package/src/ummaya/evidence/models.py +145 -0
  23. package/src/ummaya/evidence/output_payload.py +89 -0
  24. package/src/ummaya/evidence/payload_documents.py +233 -0
  25. package/src/ummaya/evidence/route_contracts.py +224 -0
  26. package/src/ummaya/evidence/route_helpers.py +150 -0
  27. package/src/ummaya/evidence/runner.py +177 -0
  28. package/src/ummaya/evidence/source_provenance.py +246 -0
  29. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  30. package/src/ummaya/evidence/task_registry.py +264 -0
  31. package/src/ummaya/evidence/tool_layer.py +39 -0
  32. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  33. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  34. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  35. package/src/ummaya/ipc/frame_schema.py +52 -5
  36. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  37. package/src/ummaya/ipc/stdio.py +2282 -417
  38. package/src/ummaya/llm/client.py +234 -59
  39. package/src/ummaya/llm/config.py +8 -3
  40. package/src/ummaya/llm/reasoning.py +84 -0
  41. package/src/ummaya/primitives/__init__.py +6 -2
  42. package/src/ummaya/primitives/delegation.py +1 -1
  43. package/src/ummaya/primitives/document.py +28 -0
  44. package/src/ummaya/settings.py +0 -3
  45. package/src/ummaya/tools/discovery_bridge.py +34 -2
  46. package/src/ummaya/tools/documents/__init__.py +297 -0
  47. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  48. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  49. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  50. package/src/ummaya/tools/documents/authoring.py +283 -0
  51. package/src/ummaya/tools/documents/baselines.py +114 -0
  52. package/src/ummaya/tools/documents/capability.py +331 -0
  53. package/src/ummaya/tools/documents/contracts.py +112 -0
  54. package/src/ummaya/tools/documents/conversion.py +521 -0
  55. package/src/ummaya/tools/documents/diff.py +275 -0
  56. package/src/ummaya/tools/documents/engines.py +163 -0
  57. package/src/ummaya/tools/documents/evaluation.py +291 -0
  58. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  59. package/src/ummaya/tools/documents/fixtures.py +174 -0
  60. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  61. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  62. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  63. package/src/ummaya/tools/documents/formats/base.py +41 -0
  64. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  65. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  66. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  67. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  68. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  69. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  70. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  71. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  72. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  73. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  74. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  75. package/src/ummaya/tools/documents/inspection.py +289 -0
  76. package/src/ummaya/tools/documents/intake.py +1079 -0
  77. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  78. package/src/ummaya/tools/documents/models.py +1598 -0
  79. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  80. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  81. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  82. package/src/ummaya/tools/documents/patch.py +170 -0
  83. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  84. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  85. package/src/ummaya/tools/documents/permissions.py +110 -0
  86. package/src/ummaya/tools/documents/planner.py +616 -0
  87. package/src/ummaya/tools/documents/registry.py +2733 -0
  88. package/src/ummaya/tools/documents/render.py +978 -0
  89. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  90. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  91. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  92. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  93. package/src/ummaya/tools/documents/reread.py +157 -0
  94. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  95. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  96. package/src/ummaya/tools/documents/scorecard.py +184 -0
  97. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  98. package/src/ummaya/tools/documents/style.py +48 -0
  99. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  100. package/src/ummaya/tools/documents/validate.py +347 -0
  101. package/src/ummaya/tools/executor.py +61 -12
  102. package/src/ummaya/tools/geocoding/kakao_client.py +1 -2
  103. package/src/ummaya/tools/kma/apihub_catalog.py +984 -1
  104. package/src/ummaya/tools/kma/apihub_structured_adapter.py +86 -6
  105. package/src/ummaya/tools/kma/apihub_url_adapter.py +593 -0
  106. package/src/ummaya/tools/kma/apihub_url_catalog.py +296 -0
  107. package/src/ummaya/tools/live_proxy.py +0 -3
  108. package/src/ummaya/tools/location_adapters.py +8 -6
  109. package/src/ummaya/tools/manifest_metadata.py +16 -3
  110. package/src/ummaya/tools/models.py +5 -1
  111. package/src/ummaya/tools/mvp_surface.py +2 -2
  112. package/src/ummaya/tools/nmc/emergency_search.py +8 -6
  113. package/src/ummaya/tools/register_all.py +17 -0
  114. package/src/ummaya/tools/registry.py +10 -1
  115. package/src/ummaya/tools/resolve_location.py +4 -4
  116. package/src/ummaya/tools/routing/__init__.py +59 -0
  117. package/src/ummaya/tools/routing/builder.py +105 -0
  118. package/src/ummaya/tools/routing/cards.py +29 -0
  119. package/src/ummaya/tools/routing/decision_service.py +534 -0
  120. package/src/ummaya/tools/routing/decision_types.py +74 -0
  121. package/src/ummaya/tools/routing/feasibility.py +122 -0
  122. package/src/ummaya/tools/routing/intent.py +17 -0
  123. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  124. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  125. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  126. package/src/ummaya/tools/routing/intent_types.py +48 -0
  127. package/src/ummaya/tools/routing/lint.py +78 -0
  128. package/src/ummaya/tools/routing/metadata.py +174 -0
  129. package/src/ummaya/tools/routing/projection.py +340 -0
  130. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  131. package/src/ummaya/tools/routing/schema.py +81 -0
  132. package/src/ummaya/tools/routing/types.py +96 -0
  133. package/src/ummaya/tools/routing_index.py +2 -2
  134. package/src/ummaya/tools/search.py +40 -106
  135. package/src/ummaya/tools/verified_data_go_kr/_manifest.py +115 -25
  136. package/src/ummaya/tools/verified_data_go_kr/airkorea_air_quality.py +109 -4
  137. package/src/ummaya/tools/verified_data_go_kr/nmc_aed_site.py +108 -2
  138. package/src/ummaya/tools/verified_data_go_kr/pps_bid_public_info.py +174 -9
  139. package/src/ummaya/tools/verified_data_go_kr/tago_bus_arrival.py +66 -3
  140. package/src/ummaya/tools/verified_data_go_kr/tago_bus_location.py +12 -2
  141. package/src/ummaya/tools/verified_data_go_kr/tago_bus_route.py +8 -2
  142. package/src/ummaya/tools/verified_data_go_kr/tago_bus_route_station.py +114 -0
  143. package/src/ummaya/tools/verified_data_go_kr/tago_bus_station.py +14 -3
  144. package/src/ummaya/tools/verify_canonical_map.py +21 -0
  145. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  146. package/tui/package.json +1 -2
  147. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  148. package/tui/src/QueryEngine.ts +12 -4
  149. package/tui/src/bridge/inboundAttachments.ts +3 -3
  150. package/tui/src/cli/handlers/auth.ts +4 -13
  151. package/tui/src/cli/handlers/mcp.tsx +3 -3
  152. package/tui/src/cli/print.ts +69 -18
  153. package/tui/src/cli/update.ts +13 -13
  154. package/tui/src/commands/copy/index.ts +1 -1
  155. package/tui/src/commands/cost/cost.ts +2 -2
  156. package/tui/src/commands/init-verifiers.ts +5 -5
  157. package/tui/src/commands/init.ts +30 -30
  158. package/tui/src/commands/insights.ts +44 -44
  159. package/tui/src/commands/install-github-app/install-github-app.tsx +2 -2
  160. package/tui/src/commands/install-github-app/setupGitHubActions.ts +3 -3
  161. package/tui/src/commands/install-github-app/types.ts +8 -30
  162. package/tui/src/commands/install.tsx +5 -5
  163. package/tui/src/commands/mcp/addCommand.ts +5 -5
  164. package/tui/src/commands/mcp/xaaIdpCommand.ts +2 -2
  165. package/tui/src/commands/plugin/ManageMarketplaces.tsx +2 -2
  166. package/tui/src/commands/plugin/types.ts +6 -28
  167. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  168. package/tui/src/commands/reasoning/index.ts +13 -0
  169. package/tui/src/commands/reasoning/reasoning.tsx +177 -0
  170. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  171. package/tui/src/commands/thinkback/thinkback.tsx +3 -3
  172. package/tui/src/commands.ts +2 -0
  173. package/tui/src/components/Feedback.tsx +1 -1
  174. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  175. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  176. package/tui/src/components/Messages.tsx +2 -1
  177. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  178. package/tui/src/components/Spinner/types.ts +6 -28
  179. package/tui/src/components/Spinner.tsx +2 -2
  180. package/tui/src/components/agents/generateAgent.ts +1 -1
  181. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  182. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  183. package/tui/src/components/design-system/LoadingState.tsx +2 -2
  184. package/tui/src/components/mcp/types.ts +16 -38
  185. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  186. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  187. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  188. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  189. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  190. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  191. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  192. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  193. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  194. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  195. package/tui/src/components/primitive/index.tsx +43 -1
  196. package/tui/src/components/primitive/types.ts +137 -0
  197. package/tui/src/components/ui/option.ts +4 -26
  198. package/tui/src/constants/common.ts +0 -2
  199. package/tui/src/constants/prompts.ts +4 -3
  200. package/tui/src/constants/querySource.ts +4 -26
  201. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  202. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  203. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  204. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  205. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  206. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  207. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  208. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  209. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  210. package/tui/src/ink/ink.tsx +33 -14
  211. package/tui/src/ink/reconciler.ts +2 -3
  212. package/tui/src/ink/render-to-screen.ts +30 -10
  213. package/tui/src/ipc/bridge.ts +62 -15
  214. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  215. package/tui/src/ipc/codec.ts +29 -3
  216. package/tui/src/ipc/frames.generated.ts +407 -312
  217. package/tui/src/ipc/llmClient.ts +279 -76
  218. package/tui/src/ipc/llmTypes.ts +16 -1
  219. package/tui/src/ipc/schema/frame.schema.json +1 -3475
  220. package/tui/src/keybindings/defaultBindings.ts +4 -0
  221. package/tui/src/main.tsx +32 -11
  222. package/tui/src/native-ts/file-index/index.ts +33 -3
  223. package/tui/src/observability/surface.ts +2 -2
  224. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  225. package/tui/src/projectOnboardingState.ts +7 -6
  226. package/tui/src/query/chatMessageTypes.ts +18 -0
  227. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  228. package/tui/src/query/deps.ts +1 -1
  229. package/tui/src/query/messageGuards.ts +106 -0
  230. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  231. package/tui/src/query/run.ts +1075 -0
  232. package/tui/src/query/supportBoundary.ts +168 -0
  233. package/tui/src/query/toolResultErrors.ts +103 -0
  234. package/tui/src/query/toolRunner.ts +687 -0
  235. package/tui/src/query/unavailableToolRepair.ts +118 -0
  236. package/tui/src/query.ts +9 -1721
  237. package/tui/src/screens/REPL.tsx +42 -31
  238. package/tui/src/services/api/adapterManifest.ts +4 -0
  239. package/tui/src/services/api/backendChat/events.ts +117 -0
  240. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  241. package/tui/src/services/api/backendChat/frame.ts +9 -0
  242. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  243. package/tui/src/services/api/backendChat/types.ts +62 -0
  244. package/tui/src/services/api/backendChat.ts +1 -0
  245. package/tui/src/services/api/client.ts +98 -14
  246. package/tui/src/services/api/errorUtils.ts +5 -5
  247. package/tui/src/services/api/errors.ts +1 -1
  248. package/tui/src/services/api/logging.ts +1 -1
  249. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  250. package/tui/src/services/api/ummaya/messages.ts +255 -0
  251. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  252. package/tui/src/services/api/ummaya/provider.ts +200 -0
  253. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  254. package/tui/src/services/api/ummaya/request.ts +200 -0
  255. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  256. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  257. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  258. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  259. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  260. package/tui/src/services/api/ummaya/types.ts +110 -0
  261. package/tui/src/services/api/ummaya/usage.ts +30 -0
  262. package/tui/src/services/api/ummaya.ts +26 -364
  263. package/tui/src/services/api/withRetry.ts +1 -1
  264. package/tui/src/services/awaySummary.ts +2 -2
  265. package/tui/src/services/claudeAiLimits.ts +1 -1
  266. package/tui/src/services/compact/autoCompact.ts +1 -1
  267. package/tui/src/services/compact/compact.ts +1 -1
  268. package/tui/src/services/lsp/types.ts +8 -30
  269. package/tui/src/services/tips/types.ts +6 -28
  270. package/tui/src/services/tokenEstimation.ts +1 -1
  271. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  272. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  273. package/tui/src/services/tools/toolExecution.ts +94 -1
  274. package/tui/src/skills/bundled/stuck.ts +12 -12
  275. package/tui/src/state/AppStateStore.ts +7 -0
  276. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  277. package/tui/src/store/session-store.ts +10 -36
  278. package/tui/src/stubs/any-stub.ts +15 -10
  279. package/tui/src/stubs/color-diff-napi.ts +37 -23
  280. package/tui/src/stubs/globals.d.ts +3 -3
  281. package/tui/src/stubs/macro-preload.ts +23 -12
  282. package/tui/src/tools/AdapterTool/AdapterTool.ts +1239 -163
  283. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  284. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  285. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  286. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  287. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  288. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  289. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  290. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  291. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  292. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  293. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  294. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  295. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  296. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  297. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  298. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  299. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  300. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  301. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  302. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  303. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  304. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  305. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  306. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  307. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  308. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  309. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  310. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  311. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  312. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  313. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  314. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  315. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  316. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  317. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  318. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  319. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  320. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  321. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  322. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  323. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  324. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  325. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  326. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  327. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  328. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  329. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  330. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  331. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  332. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  333. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  334. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  335. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  336. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  337. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  338. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  339. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  340. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  341. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  342. package/tui/src/tools/BashTool/call.ts +202 -0
  343. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  344. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  345. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  346. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  347. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  348. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  349. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  350. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  351. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  352. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  353. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  354. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  355. package/tui/src/tools/BashTool/schemas.ts +65 -0
  356. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  357. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  358. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  359. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  360. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  361. package/tui/src/tools/BriefTool/upload.ts +1 -1
  362. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  363. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  364. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  365. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  366. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  367. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  368. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  369. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  370. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  371. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  372. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  373. package/tui/src/tools/FileEditTool/call.ts +228 -0
  374. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  375. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  376. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  377. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  378. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  379. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  380. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +48 -29
  381. package/tui/src/tools/LookupPrimitive/prompt.ts +6 -7
  382. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  383. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  384. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  385. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  386. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  387. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  388. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  389. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  390. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  391. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  392. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  393. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  394. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  395. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  396. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  397. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  398. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  399. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  400. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  401. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  402. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  403. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  404. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +30 -19
  405. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  406. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  407. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +51 -18
  408. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  409. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  410. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  411. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  412. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  413. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  414. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  415. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  416. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  417. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  418. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  419. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  420. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  421. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  422. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  423. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  424. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  425. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  426. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  427. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  428. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  429. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  430. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  431. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  432. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  433. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +27 -10
  434. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  435. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  436. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  437. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  438. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  439. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  440. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  441. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  442. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  443. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  444. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  445. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  446. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  447. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  448. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  449. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  450. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  451. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  452. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  453. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  454. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  455. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  456. package/tui/src/tools/_shared/citizenUserText.ts +49 -0
  457. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  458. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  459. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  460. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  461. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  462. package/tui/src/tools/_shared/locationInputRepair.ts +112 -0
  463. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  464. package/tui/src/tools/_shared/rootPrimitiveInput.ts +68 -0
  465. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  466. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  467. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  468. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  469. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  470. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  471. package/tui/src/tools/_shared/toolChoiceRepair.ts +61 -0
  472. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  473. package/tui/src/tools.ts +39 -190
  474. package/tui/src/types/fileSuggestion.ts +4 -26
  475. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  476. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  477. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  478. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  479. package/tui/src/types/message.ts +80 -102
  480. package/tui/src/types/messageQueueTypes.ts +6 -28
  481. package/tui/src/types/notebook.ts +16 -38
  482. package/tui/src/types/statusLine.ts +4 -26
  483. package/tui/src/types/tools.ts +24 -46
  484. package/tui/src/types/utils.ts +6 -28
  485. package/tui/src/upstreamproxy/relay.ts +7 -3
  486. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  487. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  488. package/tui/src/utils/attachments.ts +1 -1
  489. package/tui/src/utils/auth.ts +129 -139
  490. package/tui/src/utils/bash/ast.ts +23 -23
  491. package/tui/src/utils/bash/bashParser.ts +5 -5
  492. package/tui/src/utils/billing.ts +1 -1
  493. package/tui/src/utils/collapseReadSearch.ts +3 -3
  494. package/tui/src/utils/cronTasks.ts +1 -1
  495. package/tui/src/utils/execFileNoThrow.ts +1 -1
  496. package/tui/src/utils/filePersistence/types.ts +16 -38
  497. package/tui/src/utils/forkedAgent.ts +1 -1
  498. package/tui/src/utils/gracefulShutdown.ts +4 -4
  499. package/tui/src/utils/heapDumpService.ts +12 -8
  500. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  501. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  502. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  503. package/tui/src/utils/kExaoneReasoning.ts +138 -0
  504. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  505. package/tui/src/utils/messages.ts +19 -0
  506. package/tui/src/utils/migrateSessions.ts +3 -3
  507. package/tui/src/utils/model/model.ts +6 -6
  508. package/tui/src/utils/multiToolLayout.ts +13 -0
  509. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  510. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  511. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  512. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  513. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  514. package/tui/src/utils/processUserInput/processSlashCommand.tsx +2 -2
  515. package/tui/src/utils/processUserInput/processUserInput.ts +26 -0
  516. package/tui/src/utils/protectedNamespace.ts +5 -3
  517. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  518. package/tui/src/utils/ripgrep.ts +16 -7
  519. package/tui/src/utils/sessionTitle.ts +1 -1
  520. package/tui/src/utils/settings/applySettingsChange.ts +4 -0
  521. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  522. package/tui/src/utils/settings/types.ts +9 -3
  523. package/tui/src/utils/shell/prefix.ts +1 -1
  524. package/tui/src/utils/sideQuery.ts +1 -1
  525. package/tui/src/utils/stats.ts +1 -1
  526. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  527. package/tui/src/utils/teleport.tsx +1 -1
  528. package/uv.lock +394 -22
  529. package/assets/copilot-gate-logo.svg +0 -58
  530. package/assets/govon-logo.svg +0 -40
  531. package/src/ummaya/eval/__init__.py +0 -5
  532. package/src/ummaya/eval/retrieval.py +0 -713
  533. package/tui/src/services/api/claude.ts +0 -3510
  534. package/tui/src/utils/messageStream.ts +0 -186
@@ -0,0 +1,616 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Deterministic autonomous-fill planning over document IR."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import re
7
+ from collections.abc import Mapping
8
+ from datetime import date, datetime, timedelta
9
+ from decimal import Decimal
10
+ from hashlib import sha256
11
+ from pathlib import Path
12
+
13
+ from ummaya.tools.documents.explicit_values import explicit_keyed_value_for_label
14
+ from ummaya.tools.documents.models import (
15
+ AutonomousFillPlan,
16
+ AutonomousSaveIntent,
17
+ AutonomousStyleIntent,
18
+ DocumentIntent,
19
+ DocumentIR,
20
+ DocumentProtectedRange,
21
+ FormSlot,
22
+ ScalarValue,
23
+ StyleAlignment,
24
+ StyleDescriptor,
25
+ )
26
+ from ummaya.tools.documents.socratic_planner import (
27
+ apply_socratic_fill_gate,
28
+ socratic_slot_requires_input,
29
+ )
30
+
31
+ _WEEK_LABEL_RE = re.compile(r"(?P<week>[0-9]{1,3})\s*주\s*차")
32
+ _DATE_RANGE_RE = re.compile(
33
+ r"(?P<start>[0-9]{4}\.[0-9]{2}\.[0-9]{2})\s*(?:~|〜|-)\s*"
34
+ r"(?P<end>[0-9]{4}\.[0-9]{2}\.[0-9]{2})"
35
+ )
36
+ _SAVE_PATH_RE = re.compile(
37
+ r"(?:저장|내보내|export|save)\s*(?:은|는|:|=)?\s*"
38
+ r"(?P<path>(?:~|/|[A-Za-z]:)[^\s,;]+?\.(?:docx|hwpx|hwp|pdf|xlsx|pptx))",
39
+ re.IGNORECASE,
40
+ )
41
+ _HEX_COLOR_RE = re.compile(r"\b(?P<hex>[0-9A-Fa-f]{6})\b")
42
+ _FONT_SIZE_RE = re.compile(r"(?P<size>[0-9]{1,2}(?:\.[0-9]+)?)\s*(?:pt|포인트)", re.IGNORECASE)
43
+ _PROTECTED_TERMS = (
44
+ "서명",
45
+ "signature",
46
+ "동의",
47
+ "consent",
48
+ "주민등록",
49
+ "성명",
50
+ "이름",
51
+ "신청인",
52
+ "applicant",
53
+ "계좌",
54
+ "전화",
55
+ "주소",
56
+ "인감",
57
+ "날인",
58
+ )
59
+ _LEGAL_ACTION_TERMS = (
60
+ "서명",
61
+ "signature",
62
+ "동의",
63
+ "consent",
64
+ "인감",
65
+ "날인",
66
+ )
67
+
68
+
69
+ def plan_autonomous_fill(
70
+ document_ir: DocumentIR,
71
+ *,
72
+ instruction: str,
73
+ session_context: Mapping[str, ScalarValue] | None = None,
74
+ ) -> AutonomousFillPlan:
75
+ """Build a deterministic fill plan from document IR and user intent."""
76
+ intent = DocumentIntent(
77
+ intent_id=f"intent-{document_ir.artifact_id}",
78
+ operation="fill",
79
+ instruction=instruction,
80
+ confidence=_intent_confidence(instruction),
81
+ )
82
+ planned_slots = _planned_slots(
83
+ document_ir,
84
+ instruction=instruction,
85
+ session_context=session_context or {},
86
+ )
87
+ blocked_slot_ids = tuple(
88
+ slot.slot_id
89
+ for slot in planned_slots
90
+ if (
91
+ slot.protected
92
+ or _missing_required_slot(slot, instruction)
93
+ or socratic_slot_requires_input(slot)
94
+ )
95
+ )
96
+ style_intents = _style_intents_from_instruction(
97
+ instruction,
98
+ planned_slots=planned_slots,
99
+ blocked_slot_ids=blocked_slot_ids,
100
+ )
101
+ return AutonomousFillPlan(
102
+ plan_id=f"plan-{document_ir.artifact_id}",
103
+ artifact_id=document_ir.artifact_id,
104
+ intent=intent,
105
+ slots=planned_slots,
106
+ style_intents=style_intents,
107
+ save_intent=_save_intent_from_instruction(instruction),
108
+ blocked_slot_ids=blocked_slot_ids,
109
+ requires_human_review=bool(blocked_slot_ids),
110
+ confidence=_plan_confidence(planned_slots, intent.confidence),
111
+ )
112
+
113
+
114
+ def public_document_writing_profile() -> tuple[str, ...]:
115
+ """Return public-form writing constraints used by autonomous fill planning."""
116
+ return (
117
+ "clear_subject_predicate",
118
+ "plain_public_korean",
119
+ "standard_numbering_ladder",
120
+ "simple_tables_no_complex_merges",
121
+ "protected_legal_text_preserved",
122
+ )
123
+
124
+
125
+ def _planned_slots(
126
+ document_ir: DocumentIR,
127
+ *,
128
+ instruction: str,
129
+ session_context: Mapping[str, ScalarValue],
130
+ ) -> tuple[FormSlot, ...]:
131
+ slots: list[FormSlot] = []
132
+ seen_slot_ids: set[str] = set()
133
+ seen_slot_paths: set[str] = set()
134
+ seen_explicit_label_keys: set[str] = set()
135
+ for slot in document_ir.form_slots:
136
+ protected_range = _protected_range_for_slot(document_ir, slot)
137
+ protected_slot_requested = _protected_slot_requested(slot, instruction)
138
+ broad_autonomous_fill = _instruction_requests_broad_autonomous_fill(instruction)
139
+ explicit_value = _explicit_keyed_value(slot, instruction)
140
+ context_value = _session_context_value(slot, session_context)
141
+ planned_slot = _planned_slot(
142
+ slot,
143
+ instruction=instruction,
144
+ session_context=session_context,
145
+ protected_range=protected_range,
146
+ )
147
+ planned_slot = apply_socratic_fill_gate(
148
+ planned_slot,
149
+ instruction=instruction,
150
+ session_context=session_context,
151
+ explicit_value_provided=explicit_value is not None,
152
+ context_value_provided=context_value is not None,
153
+ broad_autonomous_fill=broad_autonomous_fill,
154
+ )
155
+ protected_requested = protected_range is not None and (
156
+ broad_autonomous_fill or protected_slot_requested
157
+ )
158
+ missing_required = _missing_required_slot(
159
+ planned_slot,
160
+ instruction,
161
+ ) or socratic_slot_requires_input(planned_slot)
162
+ slot_is_protected_context = (
163
+ slot.protected or protected_range is not None or _slot_has_protected_semantics(slot)
164
+ )
165
+ if (
166
+ slot_is_protected_context
167
+ and not broad_autonomous_fill
168
+ and not protected_slot_requested
169
+ and planned_slot.candidate_value is None
170
+ ):
171
+ missing_required = False
172
+ explicit_label_key = (
173
+ _explicit_slot_label_key(slot, instruction)
174
+ if planned_slot.candidate_value is not None
175
+ else None
176
+ )
177
+ if explicit_label_key is not None:
178
+ if explicit_label_key in seen_explicit_label_keys:
179
+ continue
180
+ seen_explicit_label_keys.add(explicit_label_key)
181
+ if (
182
+ planned_slot.candidate_value is not None
183
+ or protected_slot_requested
184
+ or protected_requested
185
+ or missing_required
186
+ ):
187
+ _append_planned_slot(
188
+ slots,
189
+ planned_slot,
190
+ seen_slot_ids=seen_slot_ids,
191
+ seen_slot_paths=seen_slot_paths,
192
+ )
193
+ return tuple(slots)
194
+
195
+
196
+ def _append_planned_slot(
197
+ slots: list[FormSlot],
198
+ planned_slot: FormSlot,
199
+ *,
200
+ seen_slot_ids: set[str],
201
+ seen_slot_paths: set[str],
202
+ ) -> None:
203
+ source_path = planned_slot.source_anchor.format_path
204
+ if source_path in seen_slot_paths:
205
+ return
206
+ unique_slot = planned_slot
207
+ if planned_slot.slot_id in seen_slot_ids:
208
+ unique_slot = planned_slot.model_copy(
209
+ update={
210
+ "slot_id": _unique_planned_slot_id(
211
+ planned_slot.slot_id,
212
+ source_path=source_path,
213
+ seen_slot_ids=seen_slot_ids,
214
+ )
215
+ }
216
+ )
217
+ seen_slot_ids.add(unique_slot.slot_id)
218
+ seen_slot_paths.add(source_path)
219
+ slots.append(unique_slot)
220
+
221
+
222
+ def _unique_planned_slot_id(
223
+ slot_id: str,
224
+ *,
225
+ source_path: str,
226
+ seen_slot_ids: set[str],
227
+ ) -> str:
228
+ suffix = sha256(source_path.encode("utf-8")).hexdigest()[:8]
229
+ candidate = f"{slot_id}__{suffix}"
230
+ counter = 2
231
+ while candidate in seen_slot_ids:
232
+ candidate = f"{slot_id}__{suffix}_{counter}"
233
+ counter += 1
234
+ return candidate
235
+
236
+
237
+ def _planned_slot(
238
+ slot: FormSlot,
239
+ *,
240
+ instruction: str,
241
+ session_context: Mapping[str, ScalarValue],
242
+ protected_range: DocumentProtectedRange | None,
243
+ ) -> FormSlot:
244
+ if slot.protected or protected_range is not None or _slot_has_protected_semantics(slot):
245
+ explicit_value = _explicit_keyed_value(slot, instruction)
246
+ if explicit_value is not None and not _slot_has_legal_action_semantics(slot):
247
+ return slot.model_copy(
248
+ update={
249
+ "candidate_value": explicit_value,
250
+ "protected": False,
251
+ "evidence_text": "user_provided_explicit_value",
252
+ }
253
+ )
254
+ return slot.model_copy(
255
+ update={
256
+ "candidate_value": _protected_candidate(slot, instruction),
257
+ "protected": True,
258
+ "evidence_text": protected_range.reason if protected_range is not None else None,
259
+ }
260
+ )
261
+ candidate = _candidate_value_for_slot(
262
+ slot,
263
+ instruction=instruction,
264
+ session_context=session_context,
265
+ )
266
+ return slot.model_copy(update={"candidate_value": candidate})
267
+
268
+
269
+ def _protected_range_for_slot(
270
+ document_ir: DocumentIR,
271
+ slot: FormSlot,
272
+ ) -> DocumentProtectedRange | None:
273
+ for protected_range in document_ir.protected_ranges:
274
+ if "autonomous_fill" not in protected_range.blocked_operations:
275
+ continue
276
+ if protected_range.source_anchor.format_path == slot.source_anchor.format_path:
277
+ return protected_range
278
+ return None
279
+
280
+
281
+ def _candidate_value_for_slot(
282
+ slot: FormSlot,
283
+ *,
284
+ instruction: str,
285
+ session_context: Mapping[str, ScalarValue],
286
+ ) -> ScalarValue:
287
+ slot_key = _slot_key(slot)
288
+ if _is_week_slot(slot_key):
289
+ return _explicit_week_value(instruction) or _next_week_value(slot.current_value)
290
+ if _is_activity_period_slot(slot_key):
291
+ return _explicit_date_range(instruction) or _next_date_range(slot.current_value)
292
+ explicit_value = _explicit_keyed_value(slot, instruction)
293
+ if explicit_value is not None:
294
+ return explicit_value
295
+ context_value = _session_context_value(slot, session_context)
296
+ if context_value is not None:
297
+ return context_value
298
+ if _instruction_requests_broad_autonomous_fill(instruction) and _slot_is_empty(slot):
299
+ return _autonomous_draft_value_for_slot(slot)
300
+ return None
301
+
302
+
303
+ def _protected_candidate(slot: FormSlot, instruction: str) -> ScalarValue:
304
+ if not _protected_slot_requested(slot, instruction):
305
+ return None
306
+ return None
307
+
308
+
309
+ def _slot_is_empty(slot: FormSlot) -> bool:
310
+ value = slot.current_value
311
+ return value is None or (isinstance(value, str) and value.strip() == "")
312
+
313
+
314
+ def _autonomous_draft_value_for_slot(slot: FormSlot) -> ScalarValue:
315
+ slot_key = _slot_key(slot)
316
+ if "코드" in slot_key or "code" in slot_key:
317
+ return None
318
+ if "상호" in slot_key or "단체명" in slot_key or "법인명" in slot_key:
319
+ return "공공AX 테스트"
320
+ if "주업태" in slot_key or slot_key.endswith("업태") or "업종" in slot_key:
321
+ return "서비스업"
322
+ if "주종목" in slot_key or slot_key.endswith("종목"):
323
+ return "소프트웨어 개발 및 공급업"
324
+ if "개업일" in slot_key or "작성일" in slot_key or "신청일" in slot_key:
325
+ return f"{date.today():%Y.%m.%d}"
326
+ if "사업장구분" in slot_key:
327
+ return "자가"
328
+ return None
329
+
330
+
331
+ def _protected_slot_requested(slot: FormSlot, instruction: str) -> bool:
332
+ instruction_key = _normalize_key(instruction)
333
+ return _slot_has_protected_semantics(slot) and (
334
+ _instruction_requests_broad_autonomous_fill(instruction)
335
+ or any(term in instruction_key for term in _PROTECTED_TERMS)
336
+ )
337
+
338
+
339
+ def _slot_has_protected_semantics(slot: FormSlot) -> bool:
340
+ slot_key = _slot_key(slot)
341
+ return any(term in slot_key for term in _PROTECTED_TERMS)
342
+
343
+
344
+ def _slot_has_legal_action_semantics(slot: FormSlot) -> bool:
345
+ slot_key = _slot_key(slot)
346
+ return any(term in slot_key for term in _LEGAL_ACTION_TERMS)
347
+
348
+
349
+ def _explicit_keyed_value(slot: FormSlot, instruction: str) -> str | None:
350
+ labels = (slot.label, slot.slot_id)
351
+ for label in labels:
352
+ value = explicit_keyed_value_for_label(label, instruction)
353
+ if value is not None:
354
+ return value
355
+ return None
356
+
357
+
358
+ def _explicit_slot_label_key(slot: FormSlot, instruction: str) -> str | None:
359
+ for label in (slot.label, slot.slot_id):
360
+ if explicit_keyed_value_for_label(label, instruction) is not None:
361
+ return _normalize_key(label)
362
+ return None
363
+
364
+
365
+ def _style_intents_from_instruction(
366
+ instruction: str,
367
+ *,
368
+ planned_slots: tuple[FormSlot, ...],
369
+ blocked_slot_ids: tuple[str, ...],
370
+ ) -> tuple[AutonomousStyleIntent, ...]:
371
+ blocked = set(blocked_slot_ids)
372
+ style_intents: list[AutonomousStyleIntent] = []
373
+ for slot in planned_slots:
374
+ if slot.slot_id in blocked or slot.protected or slot.candidate_value is None:
375
+ continue
376
+ style = _style_descriptor_from_instruction(
377
+ instruction,
378
+ target_path=slot.source_anchor.format_path,
379
+ )
380
+ if style is None:
381
+ continue
382
+ style_intents.append(
383
+ AutonomousStyleIntent(
384
+ intent_id=f"style-{slot.slot_id}",
385
+ source_slot_id=slot.slot_id,
386
+ target_path=slot.source_anchor.format_path,
387
+ style=style,
388
+ confidence=Decimal("0.70"),
389
+ )
390
+ )
391
+ return tuple(style_intents)
392
+
393
+
394
+ def _style_descriptor_from_instruction(
395
+ instruction: str,
396
+ *,
397
+ target_path: str,
398
+ ) -> StyleDescriptor | None:
399
+ font_family = _font_family_from_instruction(instruction)
400
+ font_size_pt = _font_size_from_instruction(instruction)
401
+ bold = _bold_from_instruction(instruction)
402
+ font_color_rgb = _hex_after_terms(instruction, ("글자색", "font color", "text color"))
403
+ fill_color_rgb = _hex_after_terms(instruction, ("배경색", "채우기", "fill"))
404
+ alignment = _alignment_from_instruction(instruction)
405
+ if all(
406
+ value is None
407
+ for value in (
408
+ font_family,
409
+ font_size_pt,
410
+ bold,
411
+ font_color_rgb,
412
+ fill_color_rgb,
413
+ alignment,
414
+ )
415
+ ):
416
+ return None
417
+ return StyleDescriptor(
418
+ style_id=f"style-{sha256(target_path.encode('utf-8')).hexdigest()[:8]}",
419
+ target_path=target_path,
420
+ font_family=font_family,
421
+ font_size_pt=font_size_pt,
422
+ bold=bold,
423
+ font_color_rgb=font_color_rgb,
424
+ fill_color_rgb=fill_color_rgb,
425
+ alignment=alignment,
426
+ )
427
+
428
+
429
+ def _font_family_from_instruction(instruction: str) -> str | None:
430
+ if re.search(r"malgun\s*gothic|맑은\s*고딕", instruction, flags=re.IGNORECASE):
431
+ return "Malgun Gothic"
432
+ return None
433
+
434
+
435
+ def _font_size_from_instruction(instruction: str) -> Decimal | None:
436
+ match = _FONT_SIZE_RE.search(instruction)
437
+ if match is None:
438
+ return None
439
+ return Decimal(match.group("size"))
440
+
441
+
442
+ def _bold_from_instruction(instruction: str) -> bool | None:
443
+ instruction_key = _normalize_key(instruction)
444
+ if "bold" in instruction.casefold() or "굵게" in instruction_key or "진하게" in instruction_key:
445
+ return True
446
+ return None
447
+
448
+
449
+ def _hex_after_terms(instruction: str, terms: tuple[str, ...]) -> str | None:
450
+ for term in terms:
451
+ match = re.search(
452
+ rf"{re.escape(term)}\s*(?P<hex>[0-9A-Fa-f]{{6}})",
453
+ instruction,
454
+ flags=re.IGNORECASE,
455
+ )
456
+ if match is not None:
457
+ return match.group("hex").upper()
458
+ if len(terms) == 1:
459
+ match = _HEX_COLOR_RE.search(instruction)
460
+ if match is not None:
461
+ return match.group("hex").upper()
462
+ return None
463
+
464
+
465
+ def _alignment_from_instruction(instruction: str) -> StyleAlignment | None:
466
+ instruction_key = _normalize_key(instruction)
467
+ instruction_casefold = instruction.casefold()
468
+ if "center" in instruction_casefold or "가운데" in instruction_key or "중앙" in instruction_key:
469
+ return "center"
470
+ if (
471
+ "right" in instruction_casefold
472
+ or "오른쪽정렬" in instruction_key
473
+ or "우측정렬" in instruction_key
474
+ ):
475
+ return "right"
476
+ if (
477
+ "left" in instruction_casefold
478
+ or "왼쪽정렬" in instruction_key
479
+ or "좌측정렬" in instruction_key
480
+ ):
481
+ return "left"
482
+ return None
483
+
484
+
485
+ def _save_intent_from_instruction(instruction: str) -> AutonomousSaveIntent | None:
486
+ match = _SAVE_PATH_RE.search(instruction)
487
+ if match is None:
488
+ return None
489
+ destination_path = match.group("path")
490
+ return AutonomousSaveIntent(
491
+ destination_path=destination_path,
492
+ destination_display_name=Path(destination_path).name,
493
+ confidence=Decimal("0.75"),
494
+ )
495
+
496
+
497
+ def _session_context_value(
498
+ slot: FormSlot,
499
+ session_context: Mapping[str, ScalarValue],
500
+ ) -> ScalarValue:
501
+ slot_keys = {
502
+ _normalize_key(slot.slot_id),
503
+ _normalize_key(slot.label),
504
+ _normalize_key(slot.source_anchor.format_path),
505
+ }
506
+ for key, value in session_context.items():
507
+ normalized_key = _normalize_key(str(key))
508
+ if normalized_key not in slot_keys:
509
+ continue
510
+ return _scalar_context_value(value)
511
+ return None
512
+
513
+
514
+ def _scalar_context_value(value: ScalarValue) -> ScalarValue:
515
+ if value is None or isinstance(value, str | int | Decimal | bool | date | datetime):
516
+ return value
517
+ return None
518
+
519
+
520
+ def _missing_required_slot(slot: FormSlot, instruction: str) -> bool:
521
+ return (
522
+ slot.required
523
+ and slot.candidate_value is None
524
+ and (
525
+ _instruction_requests_broad_autonomous_fill(instruction)
526
+ or slot.protected
527
+ or socratic_slot_requires_input(slot)
528
+ )
529
+ )
530
+
531
+
532
+ def _explicit_week_value(instruction: str) -> str | None:
533
+ match = _WEEK_LABEL_RE.search(instruction)
534
+ if match is None:
535
+ return None
536
+ return f"{int(match.group('week'))}주차"
537
+
538
+
539
+ def _next_week_value(value: object) -> str | None:
540
+ if not isinstance(value, str):
541
+ return None
542
+ match = _WEEK_LABEL_RE.search(value)
543
+ if match is None:
544
+ return None
545
+ return f"{int(match.group('week')) + 1}주차"
546
+
547
+
548
+ def _explicit_date_range(instruction: str) -> str | None:
549
+ match = _DATE_RANGE_RE.search(instruction)
550
+ if match is None:
551
+ return None
552
+ return f"{match.group('start')}~{match.group('end')}"
553
+
554
+
555
+ def _next_date_range(value: object) -> str | None:
556
+ if not isinstance(value, str):
557
+ return None
558
+ match = _DATE_RANGE_RE.search(value)
559
+ if match is None:
560
+ return None
561
+ start = datetime.strptime(match.group("start"), "%Y.%m.%d").date()
562
+ end = datetime.strptime(match.group("end"), "%Y.%m.%d").date()
563
+ return f"{start + timedelta(days=7):%Y.%m.%d}~{end + timedelta(days=7):%Y.%m.%d}"
564
+
565
+
566
+ def _slot_key(slot: FormSlot) -> str:
567
+ return _normalize_key(f"{slot.slot_id} {slot.label} {slot.source_anchor.format_path}")
568
+
569
+
570
+ def _normalize_key(value: str) -> str:
571
+ return re.sub(r"[^0-9a-z가-힣]+", "", value.casefold())
572
+
573
+
574
+ def _is_week_slot(slot_key: str) -> bool:
575
+ return "주차" in slot_key or "week" in slot_key
576
+
577
+
578
+ def _is_activity_period_slot(slot_key: str) -> bool:
579
+ return "활동기간" in slot_key or "활동일시" in slot_key or "period" in slot_key
580
+
581
+
582
+ def _intent_confidence(instruction: str) -> Decimal:
583
+ if _is_autonomous_instruction(instruction):
584
+ return Decimal("0.70")
585
+ return Decimal("0.60")
586
+
587
+
588
+ def _is_autonomous_instruction(instruction: str) -> bool:
589
+ instruction_key = _normalize_key(instruction)
590
+ return "알아서" in instruction_key or "파악" in instruction_key
591
+
592
+
593
+ def _instruction_requests_broad_autonomous_fill(instruction: str) -> bool:
594
+ instruction_key = _normalize_key(instruction)
595
+ return any(
596
+ term in instruction_key
597
+ for term in (
598
+ "알아서",
599
+ "자동작성",
600
+ "자동으로작성",
601
+ "전체작성",
602
+ "전체를작성",
603
+ "모든빈칸",
604
+ "빈칸모두",
605
+ "빈칸전체",
606
+ "비어있는칸모두",
607
+ "비어있는항목모두",
608
+ )
609
+ )
610
+
611
+
612
+ def _plan_confidence(slots: tuple[FormSlot, ...], intent_confidence: Decimal) -> Decimal:
613
+ if not slots:
614
+ return Decimal("0")
615
+ slot_confidence = min(slot.confidence for slot in slots)
616
+ return min(intent_confidence, slot_confidence)