ummaya 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/bin/ummaya +10 -1
- package/npm-shrinkwrap.json +253 -2
- package/package.json +5 -1
- package/prompts/manifest.yaml +1 -1
- package/prompts/system_v1.md +1 -0
- package/pyproject.toml +26 -2
- package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
- package/src/ummaya/_canonical/__init__.py +2 -0
- package/src/ummaya/engine/engine.py +29 -132
- package/src/ummaya/evidence/__init__.py +21 -2
- package/src/ummaya/evidence/dataset_contract.py +193 -0
- package/src/ummaya/evidence/document_authoring_cases.py +33 -0
- package/src/ummaya/evidence/document_harness.py +313 -0
- package/src/ummaya/evidence/document_viewer_ux.py +391 -0
- package/src/ummaya/evidence/gates.py +70 -0
- package/src/ummaya/evidence/json_types.py +20 -0
- package/src/ummaya/evidence/models.py +88 -1
- package/src/ummaya/evidence/output_payload.py +89 -0
- package/src/ummaya/evidence/payload_documents.py +233 -0
- package/src/ummaya/evidence/route_contracts.py +224 -0
- package/src/ummaya/evidence/route_helpers.py +150 -0
- package/src/ummaya/evidence/runner.py +81 -212
- package/src/ummaya/evidence/source_provenance.py +246 -0
- package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
- package/src/ummaya/evidence/tool_layer.py +39 -0
- package/src/ummaya/evidence/tool_layer_models.py +151 -0
- package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
- package/src/ummaya/ipc/document_intent_normalization.py +185 -0
- package/src/ummaya/ipc/frame_schema.py +5 -5
- package/src/ummaya/ipc/route_diagnostics.py +73 -0
- package/src/ummaya/ipc/stdio.py +1109 -477
- package/src/ummaya/llm/client.py +102 -3
- package/src/ummaya/llm/config.py +8 -3
- package/src/ummaya/primitives/__init__.py +6 -2
- package/src/ummaya/primitives/delegation.py +1 -1
- package/src/ummaya/primitives/document.py +28 -0
- package/src/ummaya/settings.py +0 -3
- package/src/ummaya/tools/discovery_bridge.py +17 -1
- package/src/ummaya/tools/documents/__init__.py +297 -0
- package/src/ummaya/tools/documents/adapter_registry.py +487 -0
- package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
- package/src/ummaya/tools/documents/artifact_store.py +454 -0
- package/src/ummaya/tools/documents/authoring.py +283 -0
- package/src/ummaya/tools/documents/baselines.py +114 -0
- package/src/ummaya/tools/documents/capability.py +331 -0
- package/src/ummaya/tools/documents/contracts.py +112 -0
- package/src/ummaya/tools/documents/conversion.py +521 -0
- package/src/ummaya/tools/documents/diff.py +275 -0
- package/src/ummaya/tools/documents/engines.py +163 -0
- package/src/ummaya/tools/documents/evaluation.py +291 -0
- package/src/ummaya/tools/documents/explicit_values.py +108 -0
- package/src/ummaya/tools/documents/fixtures.py +174 -0
- package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
- package/src/ummaya/tools/documents/formats/__init__.py +2 -0
- package/src/ummaya/tools/documents/formats/archive.py +528 -0
- package/src/ummaya/tools/documents/formats/base.py +41 -0
- package/src/ummaya/tools/documents/formats/code_file.py +211 -0
- package/src/ummaya/tools/documents/formats/data_file.py +272 -0
- package/src/ummaya/tools/documents/formats/hwp.py +284 -0
- package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
- package/src/ummaya/tools/documents/formats/odf.py +435 -0
- package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
- package/src/ummaya/tools/documents/formats/passive.py +766 -0
- package/src/ummaya/tools/documents/formats/pdf.py +702 -0
- package/src/ummaya/tools/documents/formats/text_web.py +268 -0
- package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
- package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
- package/src/ummaya/tools/documents/inspection.py +289 -0
- package/src/ummaya/tools/documents/intake.py +1079 -0
- package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
- package/src/ummaya/tools/documents/models.py +1598 -0
- package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
- package/src/ummaya/tools/documents/orchestrator.py +96 -0
- package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
- package/src/ummaya/tools/documents/patch.py +170 -0
- package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
- package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
- package/src/ummaya/tools/documents/permissions.py +110 -0
- package/src/ummaya/tools/documents/planner.py +616 -0
- package/src/ummaya/tools/documents/registry.py +2733 -0
- package/src/ummaya/tools/documents/render.py +978 -0
- package/src/ummaya/tools/documents/render_comparison.py +113 -0
- package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
- package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
- package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
- package/src/ummaya/tools/documents/reread.py +157 -0
- package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
- package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
- package/src/ummaya/tools/documents/scorecard.py +184 -0
- package/src/ummaya/tools/documents/socratic_planner.py +193 -0
- package/src/ummaya/tools/documents/style.py +48 -0
- package/src/ummaya/tools/documents/tool_defs.py +523 -0
- package/src/ummaya/tools/documents/validate.py +347 -0
- package/src/ummaya/tools/executor.py +29 -0
- package/src/ummaya/tools/live_proxy.py +0 -3
- package/src/ummaya/tools/models.py +5 -1
- package/src/ummaya/tools/register_all.py +8 -0
- package/src/ummaya/tools/registry.py +10 -1
- package/src/ummaya/tools/routing/__init__.py +59 -0
- package/src/ummaya/tools/routing/builder.py +105 -0
- package/src/ummaya/tools/routing/cards.py +29 -0
- package/src/ummaya/tools/routing/decision_service.py +534 -0
- package/src/ummaya/tools/routing/decision_types.py +74 -0
- package/src/ummaya/tools/routing/feasibility.py +122 -0
- package/src/ummaya/tools/routing/intent.py +17 -0
- package/src/ummaya/tools/routing/intent_extractor.py +207 -0
- package/src/ummaya/tools/routing/intent_patterns.py +160 -0
- package/src/ummaya/tools/routing/intent_public_data.py +150 -0
- package/src/ummaya/tools/routing/intent_types.py +48 -0
- package/src/ummaya/tools/routing/lint.py +78 -0
- package/src/ummaya/tools/routing/metadata.py +174 -0
- package/src/ummaya/tools/routing/projection.py +340 -0
- package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
- package/src/ummaya/tools/routing/schema.py +81 -0
- package/src/ummaya/tools/routing/types.py +96 -0
- package/src/ummaya/tools/routing_index.py +2 -2
- package/src/ummaya/tools/search.py +34 -746
- package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
- package/tui/package.json +1 -1
- package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
- package/tui/src/QueryEngine.ts +12 -8
- package/tui/src/bridge/inboundAttachments.ts +3 -3
- package/tui/src/cli/handlers/auth.ts +3 -12
- package/tui/src/cli/print.ts +7 -7
- package/tui/src/commands/insights.ts +1 -1
- package/tui/src/commands/install-github-app/types.ts +8 -30
- package/tui/src/commands/plugin/types.ts +6 -28
- package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
- package/tui/src/commands/rename/generateSessionName.ts +1 -1
- package/tui/src/components/Feedback.tsx +1 -1
- package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
- package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
- package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
- package/tui/src/components/Spinner/types.ts +6 -28
- package/tui/src/components/agents/generateAgent.ts +1 -1
- package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
- package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
- package/tui/src/components/mcp/types.ts +16 -38
- package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
- package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
- package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
- package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
- package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
- package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
- package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
- package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
- package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
- package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
- package/tui/src/components/primitive/index.tsx +43 -1
- package/tui/src/components/primitive/types.ts +137 -0
- package/tui/src/components/ui/option.ts +4 -26
- package/tui/src/constants/common.ts +0 -2
- package/tui/src/constants/prompts.ts +4 -3
- package/tui/src/constants/querySource.ts +4 -26
- package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
- package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
- package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
- package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
- package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
- package/tui/src/hooks/useApiKeyVerification.ts +1 -1
- package/tui/src/hooks/useVirtualScroll.ts +1 -1
- package/tui/src/ink/ink.tsx +33 -14
- package/tui/src/ink/reconciler.ts +2 -3
- package/tui/src/ink/render-to-screen.ts +30 -10
- package/tui/src/ipc/bridge.ts +62 -15
- package/tui/src/ipc/bridgeSingleton.ts +5 -1
- package/tui/src/ipc/codec.ts +3 -3
- package/tui/src/ipc/frames.generated.ts +12 -12
- package/tui/src/ipc/llmClient.ts +151 -27
- package/tui/src/ipc/schema/frame.schema.json +1 -1
- package/tui/src/keybindings/defaultBindings.ts +4 -0
- package/tui/src/main.tsx +29 -11
- package/tui/src/native-ts/file-index/index.ts +33 -3
- package/tui/src/observability/surface.ts +2 -2
- package/tui/src/probes/toolRegistryProbe.tsx +3 -1
- package/tui/src/projectOnboardingState.ts +7 -6
- package/tui/src/query/chatMessageTypes.ts +18 -0
- package/tui/src/query/chatMessagesBuilder.ts +1 -1
- package/tui/src/query/deps.ts +1 -1
- package/tui/src/query/messageGuards.ts +106 -0
- package/tui/src/query/publicDataTerminalRepair.ts +384 -0
- package/tui/src/query/run.ts +1075 -0
- package/tui/src/query/supportBoundary.ts +168 -0
- package/tui/src/query/toolResultErrors.ts +103 -0
- package/tui/src/query/toolRunner.ts +687 -0
- package/tui/src/query/unavailableToolRepair.ts +118 -0
- package/tui/src/query.ts +9 -2186
- package/tui/src/screens/REPL.tsx +40 -29
- package/tui/src/services/api/adapterManifest.ts +4 -0
- package/tui/src/services/api/backendChat/events.ts +117 -0
- package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
- package/tui/src/services/api/backendChat/frame.ts +9 -0
- package/tui/src/services/api/backendChat/streaming.ts +430 -0
- package/tui/src/services/api/backendChat/types.ts +62 -0
- package/tui/src/services/api/backendChat.ts +1 -0
- package/tui/src/services/api/client.ts +65 -2
- package/tui/src/services/api/errorUtils.ts +5 -5
- package/tui/src/services/api/errors.ts +1 -1
- package/tui/src/services/api/logging.ts +1 -1
- package/tui/src/services/api/ummaya/evidence.ts +194 -0
- package/tui/src/services/api/ummaya/messages.ts +255 -0
- package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
- package/tui/src/services/api/ummaya/provider.ts +200 -0
- package/tui/src/services/api/ummaya/reasoning.ts +24 -0
- package/tui/src/services/api/ummaya/request.ts +200 -0
- package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
- package/tui/src/services/api/ummaya/streaming.ts +365 -0
- package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
- package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
- package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
- package/tui/src/services/api/ummaya/types.ts +110 -0
- package/tui/src/services/api/ummaya/usage.ts +30 -0
- package/tui/src/services/api/ummaya.ts +26 -418
- package/tui/src/services/api/withRetry.ts +1 -1
- package/tui/src/services/awaySummary.ts +2 -2
- package/tui/src/services/claudeAiLimits.ts +1 -1
- package/tui/src/services/compact/autoCompact.ts +1 -1
- package/tui/src/services/compact/compact.ts +1 -1
- package/tui/src/services/lsp/types.ts +8 -30
- package/tui/src/services/tips/types.ts +6 -28
- package/tui/src/services/tokenEstimation.ts +1 -1
- package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
- package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
- package/tui/src/services/tools/toolExecution.ts +94 -1
- package/tui/src/store/pendingPermissionSlot.ts +1 -1
- package/tui/src/store/session-store.ts +10 -36
- package/tui/src/stubs/any-stub.ts +15 -10
- package/tui/src/stubs/color-diff-napi.ts +37 -23
- package/tui/src/stubs/globals.d.ts +3 -3
- package/tui/src/stubs/macro-preload.ts +23 -12
- package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
- package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
- package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
- package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
- package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
- package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
- package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
- package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
- package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
- package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
- package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
- package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
- package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
- package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
- package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
- package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
- package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
- package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
- package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
- package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
- package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
- package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
- package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
- package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
- package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
- package/tui/src/tools/AgentTool/permissions.ts +39 -0
- package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
- package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
- package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
- package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
- package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
- package/tui/src/tools/AgentTool/runAgent.ts +1 -1
- package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
- package/tui/src/tools/AgentTool/schemas.ts +196 -0
- package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
- package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
- package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
- package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
- package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
- package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
- package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
- package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
- package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
- package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
- package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
- package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
- package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
- package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
- package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
- package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
- package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
- package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
- package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
- package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
- package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
- package/tui/src/tools/BashTool/call.ts +202 -0
- package/tui/src/tools/BashTool/callLoader.ts +35 -0
- package/tui/src/tools/BashTool/commandClassification.ts +151 -0
- package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
- package/tui/src/tools/BashTool/cwdReset.ts +33 -0
- package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
- package/tui/src/tools/BashTool/modeValidation.ts +13 -1
- package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
- package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
- package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
- package/tui/src/tools/BashTool/resultLoader.ts +29 -0
- package/tui/src/tools/BashTool/resultMapping.ts +83 -0
- package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
- package/tui/src/tools/BashTool/schemas.ts +65 -0
- package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
- package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
- package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
- package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
- package/tui/src/tools/BashTool/uiLoader.ts +37 -0
- package/tui/src/tools/BriefTool/upload.ts +1 -1
- package/tui/src/tools/CalculatorTool/parser.ts +2 -2
- package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
- package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
- package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
- package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
- package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
- package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
- package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
- package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
- package/tui/src/tools/FileEditTool/call.ts +228 -0
- package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
- package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
- package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
- package/tui/src/tools/FileWriteTool/call.ts +223 -0
- package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
- package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
- package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
- package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
- package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
- package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
- package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
- package/tui/src/tools/NotebookEditTool/call.ts +254 -0
- package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
- package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
- package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
- package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
- package/tui/src/tools/PowerShellTool/call.ts +179 -0
- package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
- package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
- package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
- package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
- package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
- package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
- package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
- package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
- package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
- package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/validation.ts +39 -0
- package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
- package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
- package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
- package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
- package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
- package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
- package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
- package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
- package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
- package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
- package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
- package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
- package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
- package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
- package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
- package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
- package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
- package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
- package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
- package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
- package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
- package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
- package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
- package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
- package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
- package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
- package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
- package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
- package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
- package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
- package/tui/src/tools/WebFetchTool/call.ts +227 -0
- package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
- package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
- package/tui/src/tools/WebFetchTool/types.ts +23 -0
- package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
- package/tui/src/tools/WebFetchTool/utils.ts +1 -1
- package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
- package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
- package/tui/src/tools/WebSearchTool/call.ts +33 -0
- package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
- package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
- package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
- package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
- package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
- package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
- package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
- package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
- package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
- package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
- package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
- package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
- package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
- package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
- package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
- package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
- package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
- package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
- package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
- package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
- package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
- package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
- package/tui/src/tools.ts +39 -190
- package/tui/src/types/fileSuggestion.ts +4 -26
- package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
- package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
- package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
- package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
- package/tui/src/types/message.ts +80 -102
- package/tui/src/types/messageQueueTypes.ts +6 -28
- package/tui/src/types/notebook.ts +16 -38
- package/tui/src/types/statusLine.ts +4 -26
- package/tui/src/types/tools.ts +24 -46
- package/tui/src/types/utils.ts +6 -28
- package/tui/src/upstreamproxy/relay.ts +7 -3
- package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
- package/tui/src/utils/assistantMessageFactories.ts +9 -3
- package/tui/src/utils/auth.ts +129 -139
- package/tui/src/utils/bash/ast.ts +23 -23
- package/tui/src/utils/bash/bashParser.ts +5 -5
- package/tui/src/utils/billing.ts +1 -1
- package/tui/src/utils/collapseReadSearch.ts +3 -3
- package/tui/src/utils/cronTasks.ts +1 -1
- package/tui/src/utils/execFileNoThrow.ts +1 -1
- package/tui/src/utils/filePersistence/types.ts +16 -38
- package/tui/src/utils/forkedAgent.ts +1 -1
- package/tui/src/utils/gracefulShutdown.ts +4 -4
- package/tui/src/utils/heapDumpService.ts +12 -8
- package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
- package/tui/src/utils/hooks/execPromptHook.ts +1 -1
- package/tui/src/utils/hooks/skillImprovement.ts +1 -1
- package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
- package/tui/src/utils/messages.ts +18 -0
- package/tui/src/utils/migrateSessions.ts +3 -3
- package/tui/src/utils/model/model.ts +6 -6
- package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
- package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
- package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
- package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
- package/tui/src/utils/plugins/pluginLoader.ts +8 -8
- package/tui/src/utils/protectedNamespace.ts +5 -3
- package/tui/src/utils/rawJsonToolCall.ts +242 -0
- package/tui/src/utils/ripgrep.ts +16 -7
- package/tui/src/utils/sessionTitle.ts +1 -1
- package/tui/src/utils/settings/permissionValidation.ts +14 -2
- package/tui/src/utils/shell/prefix.ts +1 -1
- package/tui/src/utils/sideQuery.ts +1 -1
- package/tui/src/utils/systemThemeWatcher.ts +13 -3
- package/tui/src/utils/teleport.tsx +1 -1
- package/uv.lock +400 -14
- package/tui/src/services/api/claude.ts +0 -3540
- package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
- package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
- package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
- package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
- package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
- package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto'
|
|
2
|
+
import { APIUserAbortError } from 'src/sdk-compat.js'
|
|
3
|
+
import {
|
|
4
|
+
getOrCreateUmmayaBridge,
|
|
5
|
+
getUmmayaBridgeSessionId,
|
|
6
|
+
} from '../../../ipc/bridgeSingleton.js'
|
|
7
|
+
import type {
|
|
8
|
+
ChatRequestFrame,
|
|
9
|
+
IPCFrame,
|
|
10
|
+
} from '../../../ipc/frames.generated.js'
|
|
11
|
+
import { buildChatMessagesFromTranscript } from '../../../query/chatMessagesBuilder.js'
|
|
12
|
+
import { getToolDefinitionsForFrame } from '../../../query/toolSerialization.js'
|
|
13
|
+
import { assertFriendliApiKeyForUse } from '../../../utils/auth.js'
|
|
14
|
+
import { createAssistantMessage } from '../../../utils/assistantMessageFactories.js'
|
|
15
|
+
import {
|
|
16
|
+
extractTextualToolCallProposals,
|
|
17
|
+
parseTrailingRawJsonToolCallProposal,
|
|
18
|
+
} from '../../../utils/rawJsonToolCall.js'
|
|
19
|
+
import {
|
|
20
|
+
createContentBlockStopEvent,
|
|
21
|
+
createMessageDeltaEvent,
|
|
22
|
+
createMessageStartStreamEvent,
|
|
23
|
+
createMessageStopEvent,
|
|
24
|
+
createTextBlockStartEvent,
|
|
25
|
+
createTextDeltaEvent,
|
|
26
|
+
createThinkingBlockStartEvent,
|
|
27
|
+
createThinkingDeltaEvent,
|
|
28
|
+
createToolUseBlockStartEvent,
|
|
29
|
+
} from './events.js'
|
|
30
|
+
import { createFinalAssistantMessage } from './finalMessage.js'
|
|
31
|
+
import { toNonEmptyMessages } from './frame.js'
|
|
32
|
+
import {
|
|
33
|
+
createBackendChatState,
|
|
34
|
+
hasAssistantPayload,
|
|
35
|
+
type BackendChatParams,
|
|
36
|
+
type BackendChatState,
|
|
37
|
+
} from './types.js'
|
|
38
|
+
|
|
39
|
+
const LLM_STREAM_ERROR_CODE = 'llm_stream_error'
|
|
40
|
+
const STREAM_TIMEOUT_PATTERN = /\b(?:timeout|timed out|idle)\b/iu
|
|
41
|
+
const LLM_STREAM_TIMEOUT_HANDOFF =
|
|
42
|
+
'K-EXAONE 응답이 지연되어 이번 요청을 이어갈 수 없습니다. 잠시 후 다시 시도해 주세요.'
|
|
43
|
+
const DEFAULT_FRAME_IDLE_TIMEOUT_MS = 90_000
|
|
44
|
+
const TEXTUAL_TOOL_CALL_OPEN = '<tool_call>'
|
|
45
|
+
|
|
46
|
+
export async function* queryModelWithStreaming(
|
|
47
|
+
params: BackendChatParams,
|
|
48
|
+
): AsyncGenerator<unknown> {
|
|
49
|
+
const { messages, signal } = params
|
|
50
|
+
assertFriendliApiKeyForUse()
|
|
51
|
+
|
|
52
|
+
const correlationId = randomUUID()
|
|
53
|
+
const messageUuid = randomUUID()
|
|
54
|
+
const innerMessageId = randomUUID()
|
|
55
|
+
const turnStartedAt = performance.now()
|
|
56
|
+
const bridge = getOrCreateUmmayaBridge()
|
|
57
|
+
const requestFrame: ChatRequestFrame = {
|
|
58
|
+
session_id: getUmmayaBridgeSessionId(),
|
|
59
|
+
correlation_id: correlationId,
|
|
60
|
+
ts: new Date().toISOString(),
|
|
61
|
+
role: 'tui',
|
|
62
|
+
kind: 'chat_request',
|
|
63
|
+
messages: toNonEmptyMessages(buildChatMessagesFromTranscript(messages)),
|
|
64
|
+
tools: await getToolDefinitionsForFrame(),
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
yield { type: 'stream_request_start' as const }
|
|
68
|
+
|
|
69
|
+
const sent = bridge.send(requestFrame)
|
|
70
|
+
if (!sent) {
|
|
71
|
+
throw new Error('UMMAYA bridge send failed (backend exited)')
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const persistThinking = process.env.UMMAYA_PERSIST_THINKING === '1'
|
|
75
|
+
const state = createBackendChatState()
|
|
76
|
+
const frameIdleTimeoutMs = getFrameIdleTimeoutMs()
|
|
77
|
+
const frameIterator = bridge.frames()[Symbol.asyncIterator]()
|
|
78
|
+
let correlatedFrameDeadline = performance.now() + frameIdleTimeoutMs
|
|
79
|
+
|
|
80
|
+
while (true) {
|
|
81
|
+
if (signal?.aborted) throw new APIUserAbortError()
|
|
82
|
+
const timeoutMs = correlatedFrameDeadline - performance.now()
|
|
83
|
+
const nextFrame = await readNextFrame(frameIterator, timeoutMs)
|
|
84
|
+
if (nextFrame === 'timeout') {
|
|
85
|
+
yield createAssistantMessage({
|
|
86
|
+
content: LLM_STREAM_TIMEOUT_HANDOFF,
|
|
87
|
+
})
|
|
88
|
+
yield* stopOpenBlocks(state)
|
|
89
|
+
if (state.messageStartEmitted) yield createMessageStopEvent()
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
if (nextFrame.done) break
|
|
93
|
+
const frame = nextFrame.value
|
|
94
|
+
if (frame.correlation_id !== correlationId) continue
|
|
95
|
+
correlatedFrameDeadline = performance.now() + frameIdleTimeoutMs
|
|
96
|
+
|
|
97
|
+
if (frame.kind === 'assistant_chunk') {
|
|
98
|
+
yield* handleAssistantChunk({
|
|
99
|
+
frame,
|
|
100
|
+
state,
|
|
101
|
+
persistThinking,
|
|
102
|
+
turnStartedAt,
|
|
103
|
+
innerMessageId,
|
|
104
|
+
messageUuid,
|
|
105
|
+
})
|
|
106
|
+
if (frame.done) return
|
|
107
|
+
} else if (frame.kind === 'tool_call') {
|
|
108
|
+
yield* handleToolCallFrame({
|
|
109
|
+
frame,
|
|
110
|
+
state,
|
|
111
|
+
persistThinking,
|
|
112
|
+
turnStartedAt,
|
|
113
|
+
innerMessageId,
|
|
114
|
+
messageUuid,
|
|
115
|
+
})
|
|
116
|
+
return
|
|
117
|
+
} else if (frame.kind === 'error') {
|
|
118
|
+
yield createAssistantMessage({
|
|
119
|
+
content: formatBackendErrorMessage(frame),
|
|
120
|
+
})
|
|
121
|
+
yield* stopOpenBlocks(state)
|
|
122
|
+
if (state.messageStartEmitted) yield createMessageStopEvent()
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (hasAssistantPayload(state, persistThinking) || !state.messageStartEmitted) {
|
|
128
|
+
yield createFinalAssistantMessage({
|
|
129
|
+
accumulated: state.accumulated,
|
|
130
|
+
accumulatedThinking: state.accumulatedThinking,
|
|
131
|
+
messageUuid,
|
|
132
|
+
innerMessageId,
|
|
133
|
+
pendingContentBlocks: state.pendingContentBlocks,
|
|
134
|
+
persistThinking,
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
if (state.messageStartEmitted) {
|
|
138
|
+
yield* stopOpenBlocks(state)
|
|
139
|
+
yield createMessageStopEvent()
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function getFrameIdleTimeoutMs(): number {
|
|
144
|
+
const raw = process.env.UMMAYA_TUI_FRAME_IDLE_TIMEOUT_MS
|
|
145
|
+
if (raw === undefined) return DEFAULT_FRAME_IDLE_TIMEOUT_MS
|
|
146
|
+
const parsed = Number.parseInt(raw, 10)
|
|
147
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_FRAME_IDLE_TIMEOUT_MS
|
|
148
|
+
return parsed
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function readNextFrame(
|
|
152
|
+
iterator: AsyncIterator<IPCFrame>,
|
|
153
|
+
timeoutMs: number,
|
|
154
|
+
): Promise<IteratorResult<IPCFrame> | 'timeout'> {
|
|
155
|
+
if (timeoutMs <= 0) return 'timeout'
|
|
156
|
+
let timeoutId: ReturnType<typeof setTimeout> | undefined
|
|
157
|
+
const timeout = new Promise<'timeout'>(resolve => {
|
|
158
|
+
timeoutId = setTimeout(() => resolve('timeout'), timeoutMs)
|
|
159
|
+
})
|
|
160
|
+
const result = await Promise.race([iterator.next(), timeout])
|
|
161
|
+
if (timeoutId !== undefined) clearTimeout(timeoutId)
|
|
162
|
+
if (result === 'timeout') {
|
|
163
|
+
void iterator.return?.()
|
|
164
|
+
}
|
|
165
|
+
return result
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function formatBackendErrorMessage(
|
|
169
|
+
frame: Extract<IPCFrame, { kind?: 'error' }>,
|
|
170
|
+
): string {
|
|
171
|
+
if (
|
|
172
|
+
frame.code === LLM_STREAM_ERROR_CODE &&
|
|
173
|
+
STREAM_TIMEOUT_PATTERN.test(frame.message)
|
|
174
|
+
) {
|
|
175
|
+
return LLM_STREAM_TIMEOUT_HANDOFF
|
|
176
|
+
}
|
|
177
|
+
return `[UMMAYA backend error] ${frame.message}`
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function* handleAssistantChunk({
|
|
181
|
+
frame,
|
|
182
|
+
state,
|
|
183
|
+
persistThinking,
|
|
184
|
+
turnStartedAt,
|
|
185
|
+
innerMessageId,
|
|
186
|
+
messageUuid,
|
|
187
|
+
}: {
|
|
188
|
+
readonly frame: Extract<IPCFrame, { kind?: 'assistant_chunk' }>
|
|
189
|
+
readonly state: BackendChatState
|
|
190
|
+
readonly persistThinking: boolean
|
|
191
|
+
readonly turnStartedAt: number
|
|
192
|
+
readonly innerMessageId: string
|
|
193
|
+
readonly messageUuid: string
|
|
194
|
+
}): Generator<unknown> {
|
|
195
|
+
yield* startMessageIfNeeded(state, innerMessageId, turnStartedAt)
|
|
196
|
+
const thinkingText = frame.thinking ?? ''
|
|
197
|
+
if (thinkingText.length > 0) yield* appendThinking(state, thinkingText, persistThinking)
|
|
198
|
+
|
|
199
|
+
const deltaText = frame.delta ?? ''
|
|
200
|
+
state.accumulated += deltaText
|
|
201
|
+
if (deltaText.length > 0) yield* appendText(state, deltaText)
|
|
202
|
+
|
|
203
|
+
if (!frame.done) return
|
|
204
|
+
const textualToolUse = extractTextualToolCallProposals({
|
|
205
|
+
text: state.accumulated,
|
|
206
|
+
})
|
|
207
|
+
const rawJsonToolUse = textualToolUse === undefined
|
|
208
|
+
? parseTrailingRawJsonToolCallProposal({
|
|
209
|
+
text: state.accumulated,
|
|
210
|
+
})
|
|
211
|
+
: undefined
|
|
212
|
+
if (
|
|
213
|
+
(textualToolUse !== undefined || rawJsonToolUse !== undefined) &&
|
|
214
|
+
state.pendingContentBlocks.length === 0
|
|
215
|
+
) {
|
|
216
|
+
const prelude = textualToolUse?.text ?? rawJsonToolUse?.prelude ?? ''
|
|
217
|
+
yield* flushTextPreludeBeforeRawJsonToolUse(state, prelude)
|
|
218
|
+
yield* stopOpenBlocks(state)
|
|
219
|
+
const proposals = textualToolUse?.proposals ??
|
|
220
|
+
(rawJsonToolUse !== undefined ? [rawJsonToolUse.proposal] : [])
|
|
221
|
+
for (let index = 0; index < proposals.length; index += 1) {
|
|
222
|
+
const proposal = proposals[index]
|
|
223
|
+
if (!proposal) continue
|
|
224
|
+
yield* appendRawJsonToolUseBlock({
|
|
225
|
+
state,
|
|
226
|
+
name: proposal.name,
|
|
227
|
+
input: proposal.input,
|
|
228
|
+
id: textualToolUse !== undefined
|
|
229
|
+
? `call_textual_tool_${index}`
|
|
230
|
+
: 'call_raw_json_tool_0',
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
state.accumulated = prelude
|
|
234
|
+
yield createFinalAssistantMessage({
|
|
235
|
+
accumulated: state.accumulated,
|
|
236
|
+
accumulatedThinking: state.accumulatedThinking,
|
|
237
|
+
messageUuid,
|
|
238
|
+
innerMessageId,
|
|
239
|
+
pendingContentBlocks: state.pendingContentBlocks,
|
|
240
|
+
persistThinking,
|
|
241
|
+
})
|
|
242
|
+
yield createMessageDeltaEvent('tool_use')
|
|
243
|
+
yield createMessageStopEvent()
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
if (state.shouldBufferTextDeltas) {
|
|
247
|
+
yield* flushBufferedText(state)
|
|
248
|
+
}
|
|
249
|
+
yield* stopOpenBlocks(state)
|
|
250
|
+
if (hasAssistantPayload(state, persistThinking) || !state.messageStartEmitted) {
|
|
251
|
+
yield createFinalAssistantMessage({
|
|
252
|
+
accumulated: state.accumulated,
|
|
253
|
+
accumulatedThinking: state.accumulatedThinking,
|
|
254
|
+
messageUuid,
|
|
255
|
+
innerMessageId,
|
|
256
|
+
pendingContentBlocks: state.pendingContentBlocks,
|
|
257
|
+
persistThinking,
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
if (state.messageStartEmitted) {
|
|
261
|
+
yield createMessageDeltaEvent('end_turn')
|
|
262
|
+
yield createMessageStopEvent()
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function* handleToolCallFrame({
|
|
267
|
+
frame,
|
|
268
|
+
state,
|
|
269
|
+
persistThinking,
|
|
270
|
+
turnStartedAt,
|
|
271
|
+
innerMessageId,
|
|
272
|
+
messageUuid,
|
|
273
|
+
}: {
|
|
274
|
+
readonly frame: Extract<IPCFrame, { kind?: 'tool_call' }>
|
|
275
|
+
readonly state: BackendChatState
|
|
276
|
+
readonly persistThinking: boolean
|
|
277
|
+
readonly turnStartedAt: number
|
|
278
|
+
readonly innerMessageId: string
|
|
279
|
+
readonly messageUuid: string
|
|
280
|
+
}): Generator<unknown> {
|
|
281
|
+
yield* startMessageIfNeeded(state, innerMessageId, turnStartedAt)
|
|
282
|
+
if (state.shouldBufferTextDeltas) {
|
|
283
|
+
yield* flushBufferedText(state)
|
|
284
|
+
}
|
|
285
|
+
yield* stopOpenBlocks(state)
|
|
286
|
+
|
|
287
|
+
const toolUseBlock = {
|
|
288
|
+
type: 'tool_use' as const,
|
|
289
|
+
id: frame.call_id,
|
|
290
|
+
name: frame.name,
|
|
291
|
+
input: frame.arguments,
|
|
292
|
+
}
|
|
293
|
+
state.pendingContentBlocks.push(toolUseBlock)
|
|
294
|
+
const toolBlockIndex = state.nextContentBlockIndex
|
|
295
|
+
state.nextContentBlockIndex += 1
|
|
296
|
+
|
|
297
|
+
yield createToolUseBlockStartEvent(toolBlockIndex, toolUseBlock)
|
|
298
|
+
yield createContentBlockStopEvent(toolBlockIndex)
|
|
299
|
+
yield createFinalAssistantMessage({
|
|
300
|
+
accumulated: state.accumulated,
|
|
301
|
+
accumulatedThinking: state.accumulatedThinking,
|
|
302
|
+
messageUuid,
|
|
303
|
+
innerMessageId,
|
|
304
|
+
pendingContentBlocks: state.pendingContentBlocks,
|
|
305
|
+
persistThinking,
|
|
306
|
+
})
|
|
307
|
+
yield createMessageDeltaEvent('tool_use')
|
|
308
|
+
yield createMessageStopEvent()
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function* startMessageIfNeeded(
|
|
312
|
+
state: BackendChatState,
|
|
313
|
+
innerMessageId: string,
|
|
314
|
+
turnStartedAt: number,
|
|
315
|
+
): Generator<unknown> {
|
|
316
|
+
if (state.messageStartEmitted) return
|
|
317
|
+
yield createMessageStartStreamEvent(innerMessageId, performance.now() - turnStartedAt)
|
|
318
|
+
state.messageStartEmitted = true
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function* appendThinking(
|
|
322
|
+
state: BackendChatState,
|
|
323
|
+
text: string,
|
|
324
|
+
persistThinking: boolean,
|
|
325
|
+
): Generator<unknown> {
|
|
326
|
+
if (state.thinkingBlockIndex === null) {
|
|
327
|
+
yield createThinkingBlockStartEvent(state.nextContentBlockIndex)
|
|
328
|
+
state.thinkingBlockIndex = state.nextContentBlockIndex
|
|
329
|
+
state.nextContentBlockIndex += 1
|
|
330
|
+
}
|
|
331
|
+
if (persistThinking) state.accumulatedThinking += text
|
|
332
|
+
yield createThinkingDeltaEvent(state.thinkingBlockIndex, text)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function* appendText(state: BackendChatState, text: string): Generator<unknown> {
|
|
336
|
+
const previousTextLength = state.accumulated.length - text.length
|
|
337
|
+
const bufferOffset = firstToolCallTextOffset(text)
|
|
338
|
+
const startsBuffering = !state.shouldBufferTextDeltas && bufferOffset >= 0
|
|
339
|
+
if (startsBuffering) state.shouldBufferTextDeltas = true
|
|
340
|
+
if (startsBuffering) {
|
|
341
|
+
if (bufferOffset > 0) {
|
|
342
|
+
yield* appendVisibleTextDelta(
|
|
343
|
+
state,
|
|
344
|
+
text.slice(0, bufferOffset),
|
|
345
|
+
previousTextLength,
|
|
346
|
+
)
|
|
347
|
+
}
|
|
348
|
+
return
|
|
349
|
+
}
|
|
350
|
+
if (state.shouldBufferTextDeltas) return
|
|
351
|
+
yield* appendVisibleTextDelta(state, text, previousTextLength)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function* appendVisibleTextDelta(
|
|
355
|
+
state: BackendChatState,
|
|
356
|
+
text: string,
|
|
357
|
+
previousTextLength: number,
|
|
358
|
+
): Generator<unknown> {
|
|
359
|
+
if (text.length === 0) return
|
|
360
|
+
if (state.thinkingBlockIndex !== null && !state.thinkingBlockStopped) {
|
|
361
|
+
yield createContentBlockStopEvent(state.thinkingBlockIndex)
|
|
362
|
+
state.thinkingBlockStopped = true
|
|
363
|
+
}
|
|
364
|
+
if (state.textBlockIndex === null) {
|
|
365
|
+
yield createTextBlockStartEvent(state.nextContentBlockIndex)
|
|
366
|
+
state.textBlockIndex = state.nextContentBlockIndex
|
|
367
|
+
state.nextContentBlockIndex += 1
|
|
368
|
+
}
|
|
369
|
+
yield createTextDeltaEvent(state.textBlockIndex, text)
|
|
370
|
+
state.emittedTextLength = previousTextLength + text.length
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function* flushBufferedText(state: BackendChatState): Generator<unknown> {
|
|
374
|
+
if (state.accumulated.length <= state.emittedTextLength) return
|
|
375
|
+
yield* appendVisibleTextDelta(
|
|
376
|
+
state,
|
|
377
|
+
state.accumulated.slice(state.emittedTextLength),
|
|
378
|
+
state.emittedTextLength,
|
|
379
|
+
)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function* flushTextPreludeBeforeRawJsonToolUse(
|
|
383
|
+
state: BackendChatState,
|
|
384
|
+
prelude: string,
|
|
385
|
+
): Generator<unknown> {
|
|
386
|
+
if (prelude.length <= state.emittedTextLength) return
|
|
387
|
+
yield* appendVisibleTextDelta(
|
|
388
|
+
state,
|
|
389
|
+
prelude.slice(state.emittedTextLength),
|
|
390
|
+
state.emittedTextLength,
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function* appendRawJsonToolUseBlock(params: {
|
|
395
|
+
readonly state: BackendChatState
|
|
396
|
+
readonly name: string
|
|
397
|
+
readonly input: Record<string, unknown>
|
|
398
|
+
readonly id?: string
|
|
399
|
+
}): Generator<unknown> {
|
|
400
|
+
const toolUseBlock = {
|
|
401
|
+
type: 'tool_use' as const,
|
|
402
|
+
id: params.id ?? 'call_raw_json_tool_0',
|
|
403
|
+
name: params.name,
|
|
404
|
+
input: params.input,
|
|
405
|
+
}
|
|
406
|
+
params.state.pendingContentBlocks.push(toolUseBlock)
|
|
407
|
+
const toolBlockIndex = params.state.nextContentBlockIndex
|
|
408
|
+
params.state.nextContentBlockIndex += 1
|
|
409
|
+
yield createToolUseBlockStartEvent(toolBlockIndex, toolUseBlock)
|
|
410
|
+
yield createContentBlockStopEvent(toolBlockIndex)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function firstToolCallTextOffset(text: string): number {
|
|
414
|
+
const braceOffset = text.indexOf('{')
|
|
415
|
+
const tagOffset = text.indexOf(TEXTUAL_TOOL_CALL_OPEN)
|
|
416
|
+
if (braceOffset < 0) return tagOffset
|
|
417
|
+
if (tagOffset < 0) return braceOffset
|
|
418
|
+
return Math.min(braceOffset, tagOffset)
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function* stopOpenBlocks(state: BackendChatState): Generator<unknown> {
|
|
422
|
+
if (state.thinkingBlockIndex !== null && !state.thinkingBlockStopped) {
|
|
423
|
+
yield createContentBlockStopEvent(state.thinkingBlockIndex)
|
|
424
|
+
state.thinkingBlockStopped = true
|
|
425
|
+
}
|
|
426
|
+
if (state.textBlockIndex !== null && !state.textBlockStopped) {
|
|
427
|
+
yield createContentBlockStopEvent(state.textBlockIndex)
|
|
428
|
+
state.textBlockStopped = true
|
|
429
|
+
}
|
|
430
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ToolCallFrame } from '../../../ipc/frames.generated.js'
|
|
2
|
+
|
|
3
|
+
export type BackendChatParams = {
|
|
4
|
+
readonly messages: readonly unknown[]
|
|
5
|
+
readonly systemPrompt: unknown
|
|
6
|
+
readonly thinkingConfig?: unknown
|
|
7
|
+
readonly tools?: unknown
|
|
8
|
+
readonly signal?: AbortSignal
|
|
9
|
+
readonly options?: {
|
|
10
|
+
readonly model?: string
|
|
11
|
+
readonly querySource?: string
|
|
12
|
+
readonly [key: string]: unknown
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type PendingToolUseBlock = {
|
|
17
|
+
readonly type: 'tool_use'
|
|
18
|
+
readonly id: string
|
|
19
|
+
readonly name: string
|
|
20
|
+
readonly input: ToolCallFrame['arguments']
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type BackendChatState = {
|
|
24
|
+
accumulated: string
|
|
25
|
+
accumulatedThinking: string
|
|
26
|
+
emittedTextLength: number
|
|
27
|
+
messageStartEmitted: boolean
|
|
28
|
+
nextContentBlockIndex: number
|
|
29
|
+
shouldBufferTextDeltas: boolean
|
|
30
|
+
textBlockIndex: number | null
|
|
31
|
+
textBlockStopped: boolean
|
|
32
|
+
thinkingBlockIndex: number | null
|
|
33
|
+
thinkingBlockStopped: boolean
|
|
34
|
+
readonly pendingContentBlocks: PendingToolUseBlock[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function createBackendChatState(): BackendChatState {
|
|
38
|
+
return {
|
|
39
|
+
accumulated: '',
|
|
40
|
+
accumulatedThinking: '',
|
|
41
|
+
emittedTextLength: 0,
|
|
42
|
+
messageStartEmitted: false,
|
|
43
|
+
nextContentBlockIndex: 0,
|
|
44
|
+
shouldBufferTextDeltas: false,
|
|
45
|
+
textBlockIndex: null,
|
|
46
|
+
textBlockStopped: false,
|
|
47
|
+
thinkingBlockIndex: null,
|
|
48
|
+
thinkingBlockStopped: false,
|
|
49
|
+
pendingContentBlocks: [],
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function hasAssistantPayload(
|
|
54
|
+
state: BackendChatState,
|
|
55
|
+
persistThinking: boolean,
|
|
56
|
+
): boolean {
|
|
57
|
+
return (
|
|
58
|
+
state.accumulated.trimStart().length > 0 ||
|
|
59
|
+
state.pendingContentBlocks.length > 0 ||
|
|
60
|
+
(persistThinking && state.accumulatedThinking.length > 0)
|
|
61
|
+
)
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { queryModelWithStreaming } from './backendChat/streaming.js'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// UMMAYA FriendliAI client shim for the CC-restored provider.
|
|
3
3
|
//
|
|
4
|
-
// services/api/
|
|
4
|
+
// services/api/ummaya.ts is the Claude Code streaming provider shape. This
|
|
5
5
|
// module supplies the one sanctioned swap: Anthropic SDK transport becomes
|
|
6
6
|
// FriendliAI's OpenAI-compatible /chat/completions endpoint. query.ts still
|
|
7
7
|
// owns the agentic loop; backend stdio remains only the tool executor for
|
|
@@ -601,7 +601,7 @@ function convertToolChoice(
|
|
|
601
601
|
}
|
|
602
602
|
|
|
603
603
|
function sanitizeSchema(schema: Record<string, unknown>): Record<string, unknown> {
|
|
604
|
-
const clone =
|
|
604
|
+
const clone = inlineLocalJsonSchemaRefs(schema)
|
|
605
605
|
delete clone.cache_control
|
|
606
606
|
delete clone.defer_loading
|
|
607
607
|
delete clone.eager_input_streaming
|
|
@@ -609,6 +609,69 @@ function sanitizeSchema(schema: Record<string, unknown>): Record<string, unknown
|
|
|
609
609
|
return clone
|
|
610
610
|
}
|
|
611
611
|
|
|
612
|
+
function inlineLocalJsonSchemaRefs(schema: Record<string, unknown>): Record<string, unknown> {
|
|
613
|
+
const defs = isRecord(schema.$defs) ? schema.$defs : {}
|
|
614
|
+
const inlined = inlineSchemaNode(schema, defs, [])
|
|
615
|
+
if (!isRecord(inlined)) {
|
|
616
|
+
throw new Error('OpenAI tool parameters schema must be a JSON object')
|
|
617
|
+
}
|
|
618
|
+
return inlined
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function inlineSchemaNode(
|
|
622
|
+
node: unknown,
|
|
623
|
+
defs: Record<string, unknown>,
|
|
624
|
+
stack: string[],
|
|
625
|
+
): unknown {
|
|
626
|
+
if (Array.isArray(node)) {
|
|
627
|
+
return node.map(item => inlineSchemaNode(item, defs, stack))
|
|
628
|
+
}
|
|
629
|
+
if (!isRecord(node)) return node
|
|
630
|
+
|
|
631
|
+
const refName = localDefRefName(node.$ref)
|
|
632
|
+
if (refName) {
|
|
633
|
+
if (stack.includes(refName)) {
|
|
634
|
+
throw new Error(`Cyclic JSON Schema reference is not supported: #/$defs/${refName}`)
|
|
635
|
+
}
|
|
636
|
+
if (!Object.prototype.hasOwnProperty.call(defs, refName)) {
|
|
637
|
+
throw new Error(`Unknown JSON Schema reference: #/$defs/${refName}`)
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const expanded = inlineSchemaNode(defs[refName], defs, [...stack, refName])
|
|
641
|
+
const siblings = Object.fromEntries(
|
|
642
|
+
Object.entries(node).filter(([key]) => key !== '$ref' && key !== '$defs'),
|
|
643
|
+
)
|
|
644
|
+
if (Object.keys(siblings).length === 0) return expanded
|
|
645
|
+
if (!isRecord(expanded)) {
|
|
646
|
+
throw new Error(`JSON Schema reference target must be an object: #/$defs/${refName}`)
|
|
647
|
+
}
|
|
648
|
+
return {
|
|
649
|
+
...expanded,
|
|
650
|
+
...Object.fromEntries(
|
|
651
|
+
Object.entries(siblings).map(([key, value]) => [
|
|
652
|
+
key,
|
|
653
|
+
inlineSchemaNode(value, defs, stack),
|
|
654
|
+
]),
|
|
655
|
+
),
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
return Object.fromEntries(
|
|
660
|
+
Object.entries(node)
|
|
661
|
+
.filter(([key]) => key !== '$defs')
|
|
662
|
+
.map(([key, value]) => [key, inlineSchemaNode(value, defs, stack)]),
|
|
663
|
+
)
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function localDefRefName(ref: unknown): string | null {
|
|
667
|
+
if (typeof ref !== 'string' || !ref.startsWith('#/$defs/')) return null
|
|
668
|
+
return ref.slice('#/$defs/'.length).replace(/~1/g, '/').replace(/~0/g, '~')
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
672
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
673
|
+
}
|
|
674
|
+
|
|
612
675
|
function systemToText(system: BetaMessageStreamParams['system']): string {
|
|
613
676
|
if (!system) return ''
|
|
614
677
|
if (typeof system === 'string') return system
|
|
@@ -36,7 +36,7 @@ export type ConnectionErrorDetails = {
|
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Extracts connection error details from the error cause chain.
|
|
39
|
-
* The
|
|
39
|
+
* The legacy SDK wraps underlying errors in the `cause` property.
|
|
40
40
|
* This function walks the cause chain to find the root error code/message.
|
|
41
41
|
*/
|
|
42
42
|
export function extractConnectionErrorDetails(
|
|
@@ -96,7 +96,7 @@ export function getSSLErrorHint(error: unknown): string | null {
|
|
|
96
96
|
if (!details?.isSSLError) {
|
|
97
97
|
return null
|
|
98
98
|
}
|
|
99
|
-
return `SSL certificate error (${details.code}). If you are behind a corporate proxy or TLS-intercepting firewall, set NODE_EXTRA_CA_CERTS to your CA bundle path, or ask IT to allowlist
|
|
99
|
+
return `SSL certificate error (${details.code}). If you are behind a corporate proxy or TLS-intercepting firewall, set NODE_EXTRA_CA_CERTS to your CA bundle path, or ask IT to allowlist the configured UMMAYA provider endpoint. Run /doctor for details.`
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
@@ -136,7 +136,7 @@ export function sanitizeAPIError(apiError: APIError): string {
|
|
|
136
136
|
* The actual message lives at different nesting levels depending on the provider:
|
|
137
137
|
*
|
|
138
138
|
* - Bedrock/proxy: `{ error: { message: "..." } }`
|
|
139
|
-
* -
|
|
139
|
+
* - Provider API: `{ error: { error: { message: "..." } } }`
|
|
140
140
|
* (the outer `.error` is the response body, the inner `.error` is the API error)
|
|
141
141
|
*
|
|
142
142
|
* See also: `getErrorMessage` in `logging.ts` which handles the same shapes.
|
|
@@ -163,7 +163,7 @@ function hasNestedError(value: unknown): value is NestedAPIError {
|
|
|
163
163
|
* a top-level `.message`.
|
|
164
164
|
*
|
|
165
165
|
* Checks two nesting levels (deeper first for specificity):
|
|
166
|
-
* 1. `error.error.error.message` —
|
|
166
|
+
* 1. `error.error.error.message` — provider API shape
|
|
167
167
|
* 2. `error.error.message` — Bedrock shape
|
|
168
168
|
*/
|
|
169
169
|
function extractNestedErrorMessage(error: APIError): string | null {
|
|
@@ -176,7 +176,7 @@ function extractNestedErrorMessage(error: APIError): string | null {
|
|
|
176
176
|
const narrowed: NestedAPIError = error
|
|
177
177
|
const nested = narrowed.error
|
|
178
178
|
|
|
179
|
-
//
|
|
179
|
+
// Provider API shape: { error: { error: { message } } }
|
|
180
180
|
const deepMsg = nested?.error?.message
|
|
181
181
|
if (typeof deepMsg === 'string' && deepMsg.length > 0) {
|
|
182
182
|
const sanitized = sanitizeMessageHTML(deepMsg)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SWAP/anti-anthropic-1p(2521): minimal stub for the byte-copied
|
|
3
|
-
// services/api/
|
|
3
|
+
// services/api/ummaya.ts which references CC's Anthropic-API error envelopes.
|
|
4
4
|
// UMMAYA surfaces errors via the IPC ErrorFrame (Spec 032) and never reaches
|
|
5
5
|
// these helpers. Stubs preserve the import shape only.
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SWAP/anti-anthropic-1p(2521): minimal stub for the byte-copied
|
|
3
|
-
// services/api/
|
|
3
|
+
// services/api/ummaya.ts which references CC's Anthropic-API request/response
|
|
4
4
|
// telemetry. UMMAYA uses OTEL spans (Spec 021) and audit ledger (Spec 024)
|
|
5
5
|
// instead. Stubs preserve the import shape; functions are no-ops because the
|
|
6
6
|
// byte-copy has zero callers in UMMAYA.
|