@oscharko-dev/keiko-server 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -0
- package/dist/assistant-response.d.ts +6 -0
- package/dist/assistant-response.d.ts.map +1 -0
- package/dist/assistant-response.js +12 -0
- package/dist/browser.d.ts +11 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +245 -0
- package/dist/chat-handlers.d.ts +48 -0
- package/dist/chat-handlers.d.ts.map +1 -0
- package/dist/chat-handlers.js +821 -0
- package/dist/chat-stream-handlers.d.ts +4 -0
- package/dist/chat-stream-handlers.d.ts.map +1 -0
- package/dist/chat-stream-handlers.js +136 -0
- package/dist/conversation-prompt.d.ts +8 -0
- package/dist/conversation-prompt.d.ts.map +1 -0
- package/dist/conversation-prompt.js +36 -0
- package/dist/conversation-validation.d.ts +26 -0
- package/dist/conversation-validation.d.ts.map +1 -0
- package/dist/conversation-validation.js +125 -0
- package/dist/credentialPersistence.d.ts +23 -0
- package/dist/credentialPersistence.d.ts.map +1 -0
- package/dist/credentialPersistence.js +93 -0
- package/dist/credentialVault.d.ts +30 -0
- package/dist/credentialVault.d.ts.map +1 -0
- package/dist/credentialVault.js +206 -0
- package/dist/csp.d.ts +3 -0
- package/dist/csp.d.ts.map +1 -0
- package/dist/csp.js +75 -0
- package/dist/deps.d.ts +78 -0
- package/dist/deps.d.ts.map +1 -0
- package/dist/deps.js +457 -0
- package/dist/editor/agentRoutes.d.ts +7 -0
- package/dist/editor/agentRoutes.d.ts.map +1 -0
- package/dist/editor/agentRoutes.js +197 -0
- package/dist/editor/assuredGateRunner.d.ts +36 -0
- package/dist/editor/assuredGateRunner.d.ts.map +1 -0
- package/dist/editor/assuredGateRunner.js +100 -0
- package/dist/editor/assuredPreFilter.d.ts +34 -0
- package/dist/editor/assuredPreFilter.d.ts.map +1 -0
- package/dist/editor/assuredPreFilter.js +134 -0
- package/dist/editor/assuredPreFilterRunner.d.ts +31 -0
- package/dist/editor/assuredPreFilterRunner.d.ts.map +1 -0
- package/dist/editor/assuredPreFilterRunner.js +312 -0
- package/dist/editor/builtinLanguageProviders.d.ts +6 -0
- package/dist/editor/builtinLanguageProviders.d.ts.map +1 -0
- package/dist/editor/builtinLanguageProviders.js +221 -0
- package/dist/editor/codingContext.d.ts +12 -0
- package/dist/editor/codingContext.d.ts.map +1 -0
- package/dist/editor/codingContext.js +121 -0
- package/dist/editor/codingContextEvidence.d.ts +7 -0
- package/dist/editor/codingContextEvidence.d.ts.map +1 -0
- package/dist/editor/codingContextEvidence.js +52 -0
- package/dist/editor/codingContextProviders.d.ts +36 -0
- package/dist/editor/codingContextProviders.d.ts.map +1 -0
- package/dist/editor/codingContextProviders.js +348 -0
- package/dist/editor/completionModelEvidence.d.ts +16 -0
- package/dist/editor/completionModelEvidence.d.ts.map +1 -0
- package/dist/editor/completionModelEvidence.js +50 -0
- package/dist/editor/completionRoutes.d.ts +37 -0
- package/dist/editor/completionRoutes.d.ts.map +1 -0
- package/dist/editor/completionRoutes.js +411 -0
- package/dist/editor/contextRoutes.d.ts +6 -0
- package/dist/editor/contextRoutes.d.ts.map +1 -0
- package/dist/editor/contextRoutes.js +411 -0
- package/dist/editor/disposableAssuredExecution.d.ts +22 -0
- package/dist/editor/disposableAssuredExecution.d.ts.map +1 -0
- package/dist/editor/disposableAssuredExecution.js +57 -0
- package/dist/editor/editorCompletionModel.d.ts +47 -0
- package/dist/editor/editorCompletionModel.d.ts.map +1 -0
- package/dist/editor/editorCompletionModel.js +156 -0
- package/dist/editor/editorInlineCompletionModel.d.ts +34 -0
- package/dist/editor/editorInlineCompletionModel.d.ts.map +1 -0
- package/dist/editor/editorInlineCompletionModel.js +112 -0
- package/dist/editor/editorModelTokenBudget.d.ts +46 -0
- package/dist/editor/editorModelTokenBudget.d.ts.map +1 -0
- package/dist/editor/editorModelTokenBudget.js +121 -0
- package/dist/editor/inlineCompletionRateLimiter.d.ts +19 -0
- package/dist/editor/inlineCompletionRateLimiter.d.ts.map +1 -0
- package/dist/editor/inlineCompletionRateLimiter.js +46 -0
- package/dist/editor/inlineCompletionRoutes.d.ts +26 -0
- package/dist/editor/inlineCompletionRoutes.d.ts.map +1 -0
- package/dist/editor/inlineCompletionRoutes.js +404 -0
- package/dist/editor/inlineCompletionTelemetryEvidence.d.ts +5 -0
- package/dist/editor/inlineCompletionTelemetryEvidence.d.ts.map +1 -0
- package/dist/editor/inlineCompletionTelemetryEvidence.js +42 -0
- package/dist/editor/languageCancellation.d.ts +19 -0
- package/dist/editor/languageCancellation.d.ts.map +1 -0
- package/dist/editor/languageCancellation.js +48 -0
- package/dist/editor/languageProvider.d.ts +39 -0
- package/dist/editor/languageProvider.d.ts.map +1 -0
- package/dist/editor/languageProvider.js +11 -0
- package/dist/editor/languageRoutes.d.ts +15 -0
- package/dist/editor/languageRoutes.d.ts.map +1 -0
- package/dist/editor/languageRoutes.js +106 -0
- package/dist/editor/languageSanitize.d.ts +8 -0
- package/dist/editor/languageSanitize.d.ts.map +1 -0
- package/dist/editor/languageSanitize.js +101 -0
- package/dist/editor/languageService.d.ts +36 -0
- package/dist/editor/languageService.d.ts.map +1 -0
- package/dist/editor/languageService.js +93 -0
- package/dist/editor/languageServiceHost.d.ts +14 -0
- package/dist/editor/languageServiceHost.d.ts.map +1 -0
- package/dist/editor/languageServiceHost.js +242 -0
- package/dist/editor/localKnowledgeRetrieval.d.ts +21 -0
- package/dist/editor/localKnowledgeRetrieval.d.ts.map +1 -0
- package/dist/editor/localKnowledgeRetrieval.js +44 -0
- package/dist/editor/patchApplyEvidence.d.ts +21 -0
- package/dist/editor/patchApplyEvidence.d.ts.map +1 -0
- package/dist/editor/patchApplyEvidence.js +87 -0
- package/dist/editor/patchApplyRoutes.d.ts +16 -0
- package/dist/editor/patchApplyRoutes.d.ts.map +1 -0
- package/dist/editor/patchApplyRoutes.js +307 -0
- package/dist/editor/postApplyVerification.d.ts +42 -0
- package/dist/editor/postApplyVerification.d.ts.map +1 -0
- package/dist/editor/postApplyVerification.js +177 -0
- package/dist/editor/testGenerationEvidence.d.ts +6 -0
- package/dist/editor/testGenerationEvidence.d.ts.map +1 -0
- package/dist/editor/testGenerationEvidence.js +72 -0
- package/dist/editor/testGenerationPatch.d.ts +10 -0
- package/dist/editor/testGenerationPatch.d.ts.map +1 -0
- package/dist/editor/testGenerationPatch.js +66 -0
- package/dist/editor/testGenerationRoutes.d.ts +21 -0
- package/dist/editor/testGenerationRoutes.d.ts.map +1 -0
- package/dist/editor/testGenerationRoutes.js +254 -0
- package/dist/editor/testGenerationRunner.d.ts +23 -0
- package/dist/editor/testGenerationRunner.d.ts.map +1 -0
- package/dist/editor/testGenerationRunner.js +120 -0
- package/dist/editor/textOffsets.d.ts +6 -0
- package/dist/editor/textOffsets.d.ts.map +1 -0
- package/dist/editor/textOffsets.js +82 -0
- package/dist/editor/typescriptLanguageProvider.d.ts +3 -0
- package/dist/editor/typescriptLanguageProvider.d.ts.map +1 -0
- package/dist/editor/typescriptLanguageProvider.js +217 -0
- package/dist/evidence.d.ts +28 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +145 -0
- package/dist/files-deny.d.ts +3 -0
- package/dist/files-deny.d.ts.map +1 -0
- package/dist/files-deny.js +12 -0
- package/dist/files.d.ts +97 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +733 -0
- package/dist/gateway-setup.d.ts +10 -0
- package/dist/gateway-setup.d.ts.map +1 -0
- package/dist/gateway-setup.js +896 -0
- package/dist/governed-workflow.d.ts +17 -0
- package/dist/governed-workflow.d.ts.map +1 -0
- package/dist/governed-workflow.js +147 -0
- package/dist/grounded-answer.d.ts +12 -0
- package/dist/grounded-answer.d.ts.map +1 -0
- package/dist/grounded-answer.js +69 -0
- package/dist/grounded-context-index.d.ts +25 -0
- package/dist/grounded-context-index.d.ts.map +1 -0
- package/dist/grounded-context-index.js +169 -0
- package/dist/grounded-document-evidence.d.ts +28 -0
- package/dist/grounded-document-evidence.d.ts.map +1 -0
- package/dist/grounded-document-evidence.js +430 -0
- package/dist/grounded-handoff.d.ts +4 -0
- package/dist/grounded-handoff.d.ts.map +1 -0
- package/dist/grounded-handoff.js +445 -0
- package/dist/grounded-orchestrator.d.ts +43 -0
- package/dist/grounded-orchestrator.d.ts.map +1 -0
- package/dist/grounded-orchestrator.js +1445 -0
- package/dist/grounded-prompt.d.ts +2 -0
- package/dist/grounded-prompt.d.ts.map +1 -0
- package/dist/grounded-prompt.js +17 -0
- package/dist/grounded-qa-hybrid.d.ts +36 -0
- package/dist/grounded-qa-hybrid.d.ts.map +1 -0
- package/dist/grounded-qa-hybrid.js +762 -0
- package/dist/grounded-qa-multi-source.d.ts +38 -0
- package/dist/grounded-qa-multi-source.d.ts.map +1 -0
- package/dist/grounded-qa-multi-source.js +461 -0
- package/dist/grounded-qa.d.ts +45 -0
- package/dist/grounded-qa.d.ts.map +1 -0
- package/dist/grounded-qa.js +877 -0
- package/dist/grounded-rerank.d.ts +26 -0
- package/dist/grounded-rerank.d.ts.map +1 -0
- package/dist/grounded-rerank.js +72 -0
- package/dist/grounded-turn-registry.d.ts +23 -0
- package/dist/grounded-turn-registry.d.ts.map +1 -0
- package/dist/grounded-turn-registry.js +102 -0
- package/dist/headers.d.ts +3 -0
- package/dist/headers.d.ts.map +1 -0
- package/dist/headers.js +22 -0
- package/dist/host-check.d.ts +3 -0
- package/dist/host-check.d.ts.map +1 -0
- package/dist/host-check.js +58 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/load-csp.d.ts +3 -0
- package/dist/load-csp.d.ts.map +1 -0
- package/dist/load-csp.js +100 -0
- package/dist/local-knowledge-grounded-qa.d.ts +42 -0
- package/dist/local-knowledge-grounded-qa.d.ts.map +1 -0
- package/dist/local-knowledge-grounded-qa.js +678 -0
- package/dist/local-knowledge-handlers.d.ts +24 -0
- package/dist/local-knowledge-handlers.d.ts.map +1 -0
- package/dist/local-knowledge-handlers.js +1285 -0
- package/dist/local-knowledge-indexing-registry.d.ts +13 -0
- package/dist/local-knowledge-indexing-registry.d.ts.map +1 -0
- package/dist/local-knowledge-indexing-registry.js +53 -0
- package/dist/localKnowledgeKeyProvider.d.ts +11 -0
- package/dist/localKnowledgeKeyProvider.d.ts.map +1 -0
- package/dist/localKnowledgeKeyProvider.js +48 -0
- package/dist/memory-audit-event-builders.d.ts +21 -0
- package/dist/memory-audit-event-builders.d.ts.map +1 -0
- package/dist/memory-audit-event-builders.js +187 -0
- package/dist/memory-audit-handler.d.ts +23 -0
- package/dist/memory-audit-handler.d.ts.map +1 -0
- package/dist/memory-audit-handler.js +191 -0
- package/dist/memory-capture-policy.d.ts +10 -0
- package/dist/memory-capture-policy.d.ts.map +1 -0
- package/dist/memory-capture-policy.js +44 -0
- package/dist/memory-consolidation-handlers.d.ts +6 -0
- package/dist/memory-consolidation-handlers.d.ts.map +1 -0
- package/dist/memory-consolidation-handlers.js +491 -0
- package/dist/memory-consolidation-registry.d.ts +47 -0
- package/dist/memory-consolidation-registry.d.ts.map +1 -0
- package/dist/memory-consolidation-registry.js +106 -0
- package/dist/memory-conv-handlers.d.ts +8 -0
- package/dist/memory-conv-handlers.d.ts.map +1 -0
- package/dist/memory-conv-handlers.js +369 -0
- package/dist/memory-conversation-context.d.ts +13 -0
- package/dist/memory-conversation-context.d.ts.map +1 -0
- package/dist/memory-conversation-context.js +22 -0
- package/dist/memory-diagnostics.d.ts +29 -0
- package/dist/memory-diagnostics.d.ts.map +1 -0
- package/dist/memory-diagnostics.js +122 -0
- package/dist/memory-embedding.d.ts +21 -0
- package/dist/memory-embedding.d.ts.map +1 -0
- package/dist/memory-embedding.js +264 -0
- package/dist/memory-handlers.d.ts +19 -0
- package/dist/memory-handlers.d.ts.map +1 -0
- package/dist/memory-handlers.js +1204 -0
- package/dist/memory-maintenance-handlers.d.ts +35 -0
- package/dist/memory-maintenance-handlers.d.ts.map +1 -0
- package/dist/memory-maintenance-handlers.js +219 -0
- package/dist/memory-record-builders.d.ts +4 -0
- package/dist/memory-record-builders.d.ts.map +1 -0
- package/dist/memory-record-builders.js +19 -0
- package/dist/memory-retention.d.ts +31 -0
- package/dist/memory-retention.d.ts.map +1 -0
- package/dist/memory-retention.js +151 -0
- package/dist/memory-retrieval-signals.d.ts +12 -0
- package/dist/memory-retrieval-signals.d.ts.map +1 -0
- package/dist/memory-retrieval-signals.js +100 -0
- package/dist/memory-salience.d.ts +12 -0
- package/dist/memory-salience.d.ts.map +1 -0
- package/dist/memory-salience.js +154 -0
- package/dist/memory-scope-sanitizer.d.ts +6 -0
- package/dist/memory-scope-sanitizer.d.ts.map +1 -0
- package/dist/memory-scope-sanitizer.js +106 -0
- package/dist/memory-target-resolver.d.ts +4 -0
- package/dist/memory-target-resolver.d.ts.map +1 -0
- package/dist/memory-target-resolver.js +73 -0
- package/dist/memory-workflow-port.d.ts +14 -0
- package/dist/memory-workflow-port.d.ts.map +1 -0
- package/dist/memory-workflow-port.js +186 -0
- package/dist/private-json.d.ts +3 -0
- package/dist/private-json.d.ts.map +1 -0
- package/dist/private-json.js +62 -0
- package/dist/promptEnhancer/index.d.ts +3 -0
- package/dist/promptEnhancer/index.d.ts.map +1 -0
- package/dist/promptEnhancer/index.js +5 -0
- package/dist/promptEnhancer/orchestrate.d.ts +2 -0
- package/dist/promptEnhancer/orchestrate.d.ts.map +1 -0
- package/dist/promptEnhancer/orchestrate.js +5 -0
- package/dist/promptEnhancer/routes.d.ts +9 -0
- package/dist/promptEnhancer/routes.d.ts.map +1 -0
- package/dist/promptEnhancer/routes.js +205 -0
- package/dist/qualityIntelligence/capsuleAdapter.d.ts +27 -0
- package/dist/qualityIntelligence/capsuleAdapter.d.ts.map +1 -0
- package/dist/qualityIntelligence/capsuleAdapter.js +57 -0
- package/dist/qualityIntelligence/connectorAuthorization.d.ts +22 -0
- package/dist/qualityIntelligence/connectorAuthorization.d.ts.map +1 -0
- package/dist/qualityIntelligence/connectorAuthorization.js +35 -0
- package/dist/qualityIntelligence/connectorErrors.d.ts +16 -0
- package/dist/qualityIntelligence/connectorErrors.d.ts.map +1 -0
- package/dist/qualityIntelligence/connectorErrors.js +56 -0
- package/dist/qualityIntelligence/connectorRoutes.d.ts +7 -0
- package/dist/qualityIntelligence/connectorRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/connectorRoutes.js +167 -0
- package/dist/qualityIntelligence/editRoutes.d.ts +5 -0
- package/dist/qualityIntelligence/editRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/editRoutes.js +293 -0
- package/dist/qualityIntelligence/exportAssembly.d.ts +22 -0
- package/dist/qualityIntelligence/exportAssembly.d.ts.map +1 -0
- package/dist/qualityIntelligence/exportAssembly.js +352 -0
- package/dist/qualityIntelligence/exportRoutes.d.ts +5 -0
- package/dist/qualityIntelligence/exportRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/exportRoutes.js +320 -0
- package/dist/qualityIntelligence/figma/figmaConcurrency.d.ts +8 -0
- package/dist/qualityIntelligence/figma/figmaConcurrency.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaConcurrency.js +34 -0
- package/dist/qualityIntelligence/figma/figmaConnector.d.ts +65 -0
- package/dist/qualityIntelligence/figma/figmaConnector.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaConnector.js +184 -0
- package/dist/qualityIntelligence/figma/figmaConnectorAudit.d.ts +52 -0
- package/dist/qualityIntelligence/figma/figmaConnectorAudit.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaConnectorAudit.js +63 -0
- package/dist/qualityIntelligence/figma/figmaConnectorErrors.d.ts +31 -0
- package/dist/qualityIntelligence/figma/figmaConnectorErrors.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaConnectorErrors.js +220 -0
- package/dist/qualityIntelligence/figma/figmaConnectorMetrics.d.ts +44 -0
- package/dist/qualityIntelligence/figma/figmaConnectorMetrics.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaConnectorMetrics.js +49 -0
- package/dist/qualityIntelligence/figma/figmaConsent.d.ts +39 -0
- package/dist/qualityIntelligence/figma/figmaConsent.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaConsent.js +62 -0
- package/dist/qualityIntelligence/figma/figmaHttpPort.d.ts +28 -0
- package/dist/qualityIntelligence/figma/figmaHttpPort.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaHttpPort.js +70 -0
- package/dist/qualityIntelligence/figma/figmaObservedActions.d.ts +49 -0
- package/dist/qualityIntelligence/figma/figmaObservedActions.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaObservedActions.js +89 -0
- package/dist/qualityIntelligence/figma/figmaReadiness.d.ts +32 -0
- package/dist/qualityIntelligence/figma/figmaReadiness.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaReadiness.js +67 -0
- package/dist/qualityIntelligence/figma/figmaRenderPort.d.ts +29 -0
- package/dist/qualityIntelligence/figma/figmaRenderPort.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaRenderPort.js +93 -0
- package/dist/qualityIntelligence/figma/figmaResnapshot.d.ts +28 -0
- package/dist/qualityIntelligence/figma/figmaResnapshot.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaResnapshot.js +38 -0
- package/dist/qualityIntelligence/figma/figmaRetry.d.ts +31 -0
- package/dist/qualityIntelligence/figma/figmaRetry.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaRetry.js +62 -0
- package/dist/qualityIntelligence/figma/figmaScopeRef.d.ts +9 -0
- package/dist/qualityIntelligence/figma/figmaScopeRef.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaScopeRef.js +18 -0
- package/dist/qualityIntelligence/figma/figmaScopedPagination.d.ts +86 -0
- package/dist/qualityIntelligence/figma/figmaScopedPagination.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaScopedPagination.js +308 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotBuilder.d.ts +31 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotBuilder.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotBuilder.js +314 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotHash.d.ts +18 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotHash.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotHash.js +63 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotTypes.d.ts +65 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotTypes.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaSnapshotTypes.js +13 -0
- package/dist/qualityIntelligence/figma/figmaTokenSource.d.ts +9 -0
- package/dist/qualityIntelligence/figma/figmaTokenSource.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaTokenSource.js +61 -0
- package/dist/qualityIntelligence/figma/figmaTokenStore.d.ts +19 -0
- package/dist/qualityIntelligence/figma/figmaTokenStore.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaTokenStore.js +156 -0
- package/dist/qualityIntelligence/figma/figmaUrl.d.ts +6 -0
- package/dist/qualityIntelligence/figma/figmaUrl.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/figmaUrl.js +36 -0
- package/dist/qualityIntelligence/figma/index.d.ts +20 -0
- package/dist/qualityIntelligence/figma/index.d.ts.map +1 -0
- package/dist/qualityIntelligence/figma/index.js +26 -0
- package/dist/qualityIntelligence/figmaCodegenRoutes.d.ts +28 -0
- package/dist/qualityIntelligence/figmaCodegenRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/figmaCodegenRoutes.js +165 -0
- package/dist/qualityIntelligence/figmaSnapshotAdapter.d.ts +55 -0
- package/dist/qualityIntelligence/figmaSnapshotAdapter.d.ts.map +1 -0
- package/dist/qualityIntelligence/figmaSnapshotAdapter.js +219 -0
- package/dist/qualityIntelligence/figmaSnapshotOrchestration.d.ts +64 -0
- package/dist/qualityIntelligence/figmaSnapshotOrchestration.d.ts.map +1 -0
- package/dist/qualityIntelligence/figmaSnapshotOrchestration.js +203 -0
- package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts +112 -0
- package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/figmaSnapshotRoutes.js +1063 -0
- package/dist/qualityIntelligence/figmaSnapshotScreenIds.d.ts +19 -0
- package/dist/qualityIntelligence/figmaSnapshotScreenIds.d.ts.map +1 -0
- package/dist/qualityIntelligence/figmaSnapshotScreenIds.js +75 -0
- package/dist/qualityIntelligence/generationPort.d.ts +15 -0
- package/dist/qualityIntelligence/generationPort.d.ts.map +1 -0
- package/dist/qualityIntelligence/generationPort.js +185 -0
- package/dist/qualityIntelligence/handoffErrors.d.ts +9 -0
- package/dist/qualityIntelligence/handoffErrors.d.ts.map +1 -0
- package/dist/qualityIntelligence/handoffErrors.js +21 -0
- package/dist/qualityIntelligence/handoffRoutes.d.ts +15 -0
- package/dist/qualityIntelligence/handoffRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/handoffRoutes.js +341 -0
- package/dist/qualityIntelligence/index.d.ts +17 -0
- package/dist/qualityIntelligence/index.d.ts.map +1 -0
- package/dist/qualityIntelligence/index.js +36 -0
- package/dist/qualityIntelligence/judgePort.d.ts +30 -0
- package/dist/qualityIntelligence/judgePort.d.ts.map +1 -0
- package/dist/qualityIntelligence/judgePort.js +326 -0
- package/dist/qualityIntelligence/modelSelection.d.ts +58 -0
- package/dist/qualityIntelligence/modelSelection.d.ts.map +1 -0
- package/dist/qualityIntelligence/modelSelection.js +148 -0
- package/dist/qualityIntelligence/reCheckRoutes.d.ts +6 -0
- package/dist/qualityIntelligence/reCheckRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/reCheckRoutes.js +1157 -0
- package/dist/qualityIntelligence/retentionEnforcement.d.ts +13 -0
- package/dist/qualityIntelligence/retentionEnforcement.d.ts.map +1 -0
- package/dist/qualityIntelligence/retentionEnforcement.js +47 -0
- package/dist/qualityIntelligence/retentionRoutes.d.ts +8 -0
- package/dist/qualityIntelligence/retentionRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/retentionRoutes.js +74 -0
- package/dist/qualityIntelligence/reviewRoutes.d.ts +5 -0
- package/dist/qualityIntelligence/reviewRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/reviewRoutes.js +145 -0
- package/dist/qualityIntelligence/reviewStore.d.ts +75 -0
- package/dist/qualityIntelligence/reviewStore.d.ts.map +1 -0
- package/dist/qualityIntelligence/reviewStore.js +170 -0
- package/dist/qualityIntelligence/runExecution.d.ts +36 -0
- package/dist/qualityIntelligence/runExecution.d.ts.map +1 -0
- package/dist/qualityIntelligence/runExecution.js +180 -0
- package/dist/qualityIntelligence/runIngestion.d.ts +70 -0
- package/dist/qualityIntelligence/runIngestion.d.ts.map +1 -0
- package/dist/qualityIntelligence/runIngestion.js +1235 -0
- package/dist/qualityIntelligence/runRegistry.d.ts +31 -0
- package/dist/qualityIntelligence/runRegistry.d.ts.map +1 -0
- package/dist/qualityIntelligence/runRegistry.js +66 -0
- package/dist/qualityIntelligence/runRoutes.d.ts +16 -0
- package/dist/qualityIntelligence/runRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/runRoutes.js +357 -0
- package/dist/qualityIntelligence/traceabilityRoutes.d.ts +5 -0
- package/dist/qualityIntelligence/traceabilityRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/traceabilityRoutes.js +173 -0
- package/dist/qualityIntelligence/uiRoutes.d.ts +7 -0
- package/dist/qualityIntelligence/uiRoutes.d.ts.map +1 -0
- package/dist/qualityIntelligence/uiRoutes.js +336 -0
- package/dist/read-handlers.d.ts +9 -0
- package/dist/read-handlers.d.ts.map +1 -0
- package/dist/read-handlers.js +265 -0
- package/dist/relationship-handlers.d.ts +191 -0
- package/dist/relationship-handlers.d.ts.map +1 -0
- package/dist/relationship-handlers.js +0 -0
- package/dist/routes.d.ts +37 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +507 -0
- package/dist/run-engine.d.ts +25 -0
- package/dist/run-engine.d.ts.map +1 -0
- package/dist/run-engine.js +385 -0
- package/dist/run-handlers.d.ts +9 -0
- package/dist/run-handlers.d.ts.map +1 -0
- package/dist/run-handlers.js +465 -0
- package/dist/run-request.d.ts +17 -0
- package/dist/run-request.d.ts.map +1 -0
- package/dist/run-request.js +219 -0
- package/dist/runs.d.ts +47 -0
- package/dist/runs.d.ts.map +1 -0
- package/dist/runs.js +100 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +152 -0
- package/dist/sink.d.ts +28 -0
- package/dist/sink.d.ts.map +1 -0
- package/dist/sink.js +80 -0
- package/dist/sse-write.d.ts +9 -0
- package/dist/sse-write.d.ts.map +1 -0
- package/dist/sse-write.js +26 -0
- package/dist/sse.d.ts +8 -0
- package/dist/sse.d.ts.map +1 -0
- package/dist/sse.js +27 -0
- package/dist/static.d.ts +5 -0
- package/dist/static.d.ts.map +1 -0
- package/dist/static.js +76 -0
- package/dist/store/chats.d.ts +17 -0
- package/dist/store/chats.d.ts.map +1 -0
- package/dist/store/chats.js +624 -0
- package/dist/store/db.d.ts +11 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +203 -0
- package/dist/store/errors.d.ts +13 -0
- package/dist/store/errors.d.ts.map +1 -0
- package/dist/store/errors.js +30 -0
- package/dist/store/index.d.ts +7 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +6 -0
- package/dist/store/messages.d.ts +8 -0
- package/dist/store/messages.d.ts.map +1 -0
- package/dist/store/messages.js +149 -0
- package/dist/store/paths.d.ts +5 -0
- package/dist/store/paths.d.ts.map +1 -0
- package/dist/store/paths.js +84 -0
- package/dist/store/projects.d.ts +8 -0
- package/dist/store/projects.d.ts.map +1 -0
- package/dist/store/projects.js +59 -0
- package/dist/store/relationship-audit.d.ts +42 -0
- package/dist/store/relationship-audit.d.ts.map +1 -0
- package/dist/store/relationship-audit.js +155 -0
- package/dist/store/relationships.d.ts +191 -0
- package/dist/store/relationships.d.ts.map +1 -0
- package/dist/store/relationships.js +724 -0
- package/dist/store/schema.d.ts +4 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +220 -0
- package/dist/store/types.d.ts +29 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +8 -0
- package/dist/store/validation.d.ts +7 -0
- package/dist/store/validation.d.ts.map +1 -0
- package/dist/store/validation.js +117 -0
- package/dist/store-handlers.d.ts +17 -0
- package/dist/store-handlers.d.ts.map +1 -0
- package/dist/store-handlers.js +872 -0
- package/dist/terminal-errors.d.ts +22 -0
- package/dist/terminal-errors.d.ts.map +1 -0
- package/dist/terminal-errors.js +45 -0
- package/dist/terminal-evidence.d.ts +21 -0
- package/dist/terminal-evidence.d.ts.map +1 -0
- package/dist/terminal-evidence.js +65 -0
- package/dist/terminal-routes.d.ts +10 -0
- package/dist/terminal-routes.d.ts.map +1 -0
- package/dist/terminal-routes.js +219 -0
- package/dist/terminal.d.ts +68 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +855 -0
- package/package.json +52 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// Parsing + validation of the `POST /api/runs` request body (ADR-0011 D5 route 5). The body arrives
|
|
2
|
+
// as untyped JSON; this module narrows it (no `any`) into a typed `RunRequest` or a typed validation
|
|
3
|
+
// error. It performs SHAPE validation only — exactly one of workflowId/taskType, a present input
|
|
4
|
+
// object, a non-empty modelId, and a selected project workspaceRoot. The create route is ALWAYS
|
|
5
|
+
// dry-run: `apply` is forced false here regardless of the body, so applying is reachable only via
|
|
6
|
+
// the gated apply route (D8). The deeper guards (`isSensitivePath`, patch limits, target validation)
|
|
7
|
+
// are enforced by the workflow/harness entry points the engine calls; the BFF never reimplements
|
|
8
|
+
// them.
|
|
9
|
+
function isRecord(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
function resolveKind(body) {
|
|
13
|
+
const workflowId = body.workflowId;
|
|
14
|
+
const taskType = body.taskType;
|
|
15
|
+
const hasWorkflow = workflowId !== undefined;
|
|
16
|
+
const hasTask = taskType !== undefined;
|
|
17
|
+
if (hasWorkflow === hasTask) {
|
|
18
|
+
return { code: "BAD_REQUEST", message: "Provide exactly one of workflowId or taskType." };
|
|
19
|
+
}
|
|
20
|
+
if (hasWorkflow) {
|
|
21
|
+
if (workflowId === "unit-test-generation") {
|
|
22
|
+
return "unit-tests";
|
|
23
|
+
}
|
|
24
|
+
if (workflowId === "bug-investigation") {
|
|
25
|
+
return "bug-investigation";
|
|
26
|
+
}
|
|
27
|
+
return { code: "BAD_REQUEST", message: "Unknown workflowId." };
|
|
28
|
+
}
|
|
29
|
+
if (taskType === "explain-plan") {
|
|
30
|
+
return "explain-plan";
|
|
31
|
+
}
|
|
32
|
+
if (taskType === "verify") {
|
|
33
|
+
return "verify";
|
|
34
|
+
}
|
|
35
|
+
return { code: "BAD_REQUEST", message: "Unsupported taskType." };
|
|
36
|
+
}
|
|
37
|
+
function validateWorkspaceRoot(input) {
|
|
38
|
+
const workspaceRoot = input.workspaceRoot;
|
|
39
|
+
if (typeof workspaceRoot !== "string" || workspaceRoot.length === 0) {
|
|
40
|
+
return { code: "BAD_REQUEST", message: "A non-empty workspaceRoot is required." };
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
function validateStringField(input, name, label) {
|
|
45
|
+
const value = input[name];
|
|
46
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
47
|
+
return { code: "BAD_REQUEST", message: `${label} must be a non-empty string.` };
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function validateOptionalStringField(input, name, label) {
|
|
52
|
+
const value = input[name];
|
|
53
|
+
if (value === undefined) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
if (typeof value !== "string") {
|
|
57
|
+
return { code: "BAD_REQUEST", message: `${label} must be a string.` };
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function validateStringArray(value, label, options = {
|
|
62
|
+
required: false,
|
|
63
|
+
allowEmpty: true,
|
|
64
|
+
}) {
|
|
65
|
+
if (value === undefined) {
|
|
66
|
+
return options.required
|
|
67
|
+
? { code: "BAD_REQUEST", message: `${label} must be a string array.` }
|
|
68
|
+
: null;
|
|
69
|
+
}
|
|
70
|
+
if (!Array.isArray(value)) {
|
|
71
|
+
return { code: "BAD_REQUEST", message: `${label} must be a string array.` };
|
|
72
|
+
}
|
|
73
|
+
if (!options.allowEmpty && value.length === 0) {
|
|
74
|
+
return { code: "BAD_REQUEST", message: `${label} must contain at least one entry.` };
|
|
75
|
+
}
|
|
76
|
+
for (const entry of value) {
|
|
77
|
+
if (typeof entry !== "string" || entry.length === 0) {
|
|
78
|
+
return { code: "BAD_REQUEST", message: `${label} must contain non-empty strings.` };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
// Verify shape: targetFiles (when present) must be a string[] of non-empty entries. The deeper
|
|
84
|
+
// guards (path containment, script detection) run inside the verification orchestrator; the BFF
|
|
85
|
+
// only validates shape here.
|
|
86
|
+
function validateVerifyInput(input) {
|
|
87
|
+
return validateStringArray(input.targetFiles, "verify targetFiles");
|
|
88
|
+
}
|
|
89
|
+
function validateExplainPlanInput(input) {
|
|
90
|
+
return (validateStringField(input, "filePath", "explain-plan filePath") ??
|
|
91
|
+
validateOptionalStringField(input, "question", "explain-plan question"));
|
|
92
|
+
}
|
|
93
|
+
function validateUnitTestTarget(target) {
|
|
94
|
+
const kind = target.kind;
|
|
95
|
+
if (kind === "file") {
|
|
96
|
+
return (validateStringField(target, "filePath", "unit-test target.filePath") ??
|
|
97
|
+
validateOptionalStringField(target, "targetFunction", "unit-test target.targetFunction"));
|
|
98
|
+
}
|
|
99
|
+
if (kind === "module") {
|
|
100
|
+
return validateStringField(target, "moduleDir", "unit-test target.moduleDir");
|
|
101
|
+
}
|
|
102
|
+
if (kind === "changedFiles") {
|
|
103
|
+
return validateStringArray(target.filePaths, "unit-test target.filePaths", {
|
|
104
|
+
required: true,
|
|
105
|
+
allowEmpty: false,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
code: "BAD_REQUEST",
|
|
110
|
+
message: "unit-test target.kind must be one of file, module, changedFiles.",
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function validateUnitTestsInput(input) {
|
|
114
|
+
const target = input.target;
|
|
115
|
+
if (!isRecord(target)) {
|
|
116
|
+
return { code: "BAD_REQUEST", message: "unit-test target must be an object." };
|
|
117
|
+
}
|
|
118
|
+
return validateUnitTestTarget(target);
|
|
119
|
+
}
|
|
120
|
+
function validateBugReport(report) {
|
|
121
|
+
const descriptionError = validateOptionalStringField(report, "description", "bug report.description");
|
|
122
|
+
if (descriptionError !== null) {
|
|
123
|
+
return descriptionError;
|
|
124
|
+
}
|
|
125
|
+
const failingOutputError = validateOptionalStringField(report, "failingOutput", "bug report.failingOutput");
|
|
126
|
+
if (failingOutputError !== null) {
|
|
127
|
+
return failingOutputError;
|
|
128
|
+
}
|
|
129
|
+
const stackTraceError = validateOptionalStringField(report, "stackTrace", "bug report.stackTrace");
|
|
130
|
+
if (stackTraceError !== null) {
|
|
131
|
+
return stackTraceError;
|
|
132
|
+
}
|
|
133
|
+
const targetFilesError = validateStringArray(report.targetFiles, "bug report.targetFiles");
|
|
134
|
+
if (targetFilesError !== null) {
|
|
135
|
+
return targetFilesError;
|
|
136
|
+
}
|
|
137
|
+
return hasBugEvidence(report)
|
|
138
|
+
? null
|
|
139
|
+
: {
|
|
140
|
+
code: "BAD_REQUEST",
|
|
141
|
+
message: "bug report requires at least one of description, failingOutput, stackTrace, or targetFiles.",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function hasNonEmptyString(value) {
|
|
145
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
146
|
+
}
|
|
147
|
+
function hasNonEmptyStringEntry(value) {
|
|
148
|
+
return Array.isArray(value) && value.some(hasNonEmptyString);
|
|
149
|
+
}
|
|
150
|
+
function hasBugEvidence(report) {
|
|
151
|
+
return (hasNonEmptyString(report.description) ||
|
|
152
|
+
hasNonEmptyString(report.failingOutput) ||
|
|
153
|
+
hasNonEmptyString(report.stackTrace) ||
|
|
154
|
+
hasNonEmptyStringEntry(report.targetFiles));
|
|
155
|
+
}
|
|
156
|
+
function validateBugInvestigationInput(input) {
|
|
157
|
+
const report = input.report;
|
|
158
|
+
if (!isRecord(report)) {
|
|
159
|
+
return { code: "BAD_REQUEST", message: "bug report must be an object." };
|
|
160
|
+
}
|
|
161
|
+
return validateBugReport(report);
|
|
162
|
+
}
|
|
163
|
+
function validateRunInput(kind, input) {
|
|
164
|
+
const workspaceRootError = validateWorkspaceRoot(input);
|
|
165
|
+
if (workspaceRootError !== null) {
|
|
166
|
+
return workspaceRootError;
|
|
167
|
+
}
|
|
168
|
+
if (kind === "verify") {
|
|
169
|
+
return validateVerifyInput(input);
|
|
170
|
+
}
|
|
171
|
+
if (kind === "explain-plan") {
|
|
172
|
+
return validateExplainPlanInput(input);
|
|
173
|
+
}
|
|
174
|
+
if (kind === "unit-tests") {
|
|
175
|
+
return validateUnitTestsInput(input);
|
|
176
|
+
}
|
|
177
|
+
return validateBugInvestigationInput(input);
|
|
178
|
+
}
|
|
179
|
+
// Parses the raw JSON text into a validated RunRequest, or a typed BAD_REQUEST error.
|
|
180
|
+
export function parseRunRequest(raw) {
|
|
181
|
+
let parsed;
|
|
182
|
+
try {
|
|
183
|
+
parsed = JSON.parse(raw);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return { code: "BAD_REQUEST", message: "Request body is not valid JSON." };
|
|
187
|
+
}
|
|
188
|
+
if (!isRecord(parsed)) {
|
|
189
|
+
return { code: "BAD_REQUEST", message: "Request body must be a JSON object." };
|
|
190
|
+
}
|
|
191
|
+
const kind = resolveKind(parsed);
|
|
192
|
+
if (typeof kind !== "string") {
|
|
193
|
+
return kind;
|
|
194
|
+
}
|
|
195
|
+
const modelId = parsed.modelId;
|
|
196
|
+
if (typeof modelId !== "string" || modelId.length === 0) {
|
|
197
|
+
return { code: "BAD_REQUEST", message: "A non-empty modelId is required." };
|
|
198
|
+
}
|
|
199
|
+
const input = parsed.input;
|
|
200
|
+
if (!isRecord(input)) {
|
|
201
|
+
return { code: "BAD_REQUEST", message: "An input object is required." };
|
|
202
|
+
}
|
|
203
|
+
const inputError = validateRunInput(kind, input);
|
|
204
|
+
if (inputError !== null) {
|
|
205
|
+
return inputError;
|
|
206
|
+
}
|
|
207
|
+
const limits = parsed.limits;
|
|
208
|
+
return {
|
|
209
|
+
kind,
|
|
210
|
+
modelId,
|
|
211
|
+
// Dry-run-first (ADR-0011 D8 / security M1): the create route NEVER applies, even if the client
|
|
212
|
+
// body carries `apply:true`. Applying is the sole responsibility of POST /api/runs/:runId/apply
|
|
213
|
+
// (route 9), which re-invokes the workflow through the gated path. A one-shot create-with-apply
|
|
214
|
+
// would bypass the explicit review→apply step, so the body flag is deliberately ignored here.
|
|
215
|
+
apply: false,
|
|
216
|
+
input,
|
|
217
|
+
...(isRecord(limits) ? { limits } : { limits: undefined }),
|
|
218
|
+
};
|
|
219
|
+
}
|
package/dist/runs.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { WorkflowHandoffRequest } from "@oscharko-dev/keiko-contracts/workflow-handoff";
|
|
2
|
+
import type { QueueEventSink } from "./sink.js";
|
|
3
|
+
export type RunStatus = "running" | "completed" | "cancelled" | "failed";
|
|
4
|
+
export interface AppliableSnapshot {
|
|
5
|
+
readonly kind: "unit-tests" | "bug-investigation";
|
|
6
|
+
readonly payload: unknown;
|
|
7
|
+
readonly limits: Record<string, unknown> | undefined;
|
|
8
|
+
readonly governedHandoff?: WorkflowHandoffRequest | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface RunRecord {
|
|
11
|
+
readonly runId: string;
|
|
12
|
+
readonly fingerprint: string;
|
|
13
|
+
readonly modelId: string;
|
|
14
|
+
readonly sink: QueueEventSink;
|
|
15
|
+
status: RunStatus;
|
|
16
|
+
report: unknown;
|
|
17
|
+
readonly cancel: (reason?: string) => void;
|
|
18
|
+
appliable: AppliableSnapshot | undefined;
|
|
19
|
+
applyReport: unknown;
|
|
20
|
+
appliedAt: number | undefined;
|
|
21
|
+
terminatedAt: number | undefined;
|
|
22
|
+
}
|
|
23
|
+
export interface RegisterRunInput {
|
|
24
|
+
readonly runId: string;
|
|
25
|
+
readonly fingerprint: string;
|
|
26
|
+
readonly modelId: string;
|
|
27
|
+
readonly sink: QueueEventSink;
|
|
28
|
+
readonly cancel: (reason?: string) => void;
|
|
29
|
+
}
|
|
30
|
+
export interface RunRegistryOptions {
|
|
31
|
+
readonly maxActiveRuns?: number | undefined;
|
|
32
|
+
readonly terminatedTtlMs?: number | undefined;
|
|
33
|
+
readonly now?: (() => number) | undefined;
|
|
34
|
+
}
|
|
35
|
+
export declare class ActiveRunLimitError extends Error {
|
|
36
|
+
constructor(limit: number);
|
|
37
|
+
}
|
|
38
|
+
export interface RunRegistry {
|
|
39
|
+
register: (input: RegisterRunInput) => RunRecord;
|
|
40
|
+
get: (runId: string) => RunRecord | undefined;
|
|
41
|
+
snapshot?: (limit?: number) => readonly RunRecord[];
|
|
42
|
+
complete: (runId: string, status: Exclude<RunStatus, "running">, report: unknown, appliable: AppliableSnapshot | undefined) => void;
|
|
43
|
+
activeCount: () => number;
|
|
44
|
+
size: () => number;
|
|
45
|
+
}
|
|
46
|
+
export declare function createRunRegistry(options?: RunRegistryOptions): RunRegistry;
|
|
47
|
+
//# sourceMappingURL=runs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../src/runs.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,QAAQ,CAAC;AAMzE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACrD,QAAQ,CAAC,eAAe,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAC/D;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAG7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,MAAM,EAAE,SAAS,CAAC;IAElB,MAAM,EAAE,OAAO,CAAC;IAEhB,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAE3C,SAAS,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAEzC,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAE9B,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,kBAAkB;IAEjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE9C,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;CAC3C;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,KAAK,EAAE,MAAM;CAI1B;AAKD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,SAAS,CAAC;IACjD,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IAE9C,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,SAAS,SAAS,EAAE,CAAC;IAEpD,QAAQ,EAAE,CACR,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,EACrC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,iBAAiB,GAAG,SAAS,KACrC,IAAI,CAAC;IAEV,WAAW,EAAE,MAAM,MAAM,CAAC;IAE1B,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB;AAuED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAiC/E"}
|
package/dist/runs.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// The in-memory run registry (ADR-0011 D7). It maps a runId to a live run record (the streaming
|
|
2
|
+
// sink, the run status, the captured final report, and a cancel handle). It is BOUNDED on two axes:
|
|
3
|
+
// a cap on simultaneously-active runs (a new run is refused past the cap) and a TTL after which a
|
|
4
|
+
// TERMINATED run's record — including its event ring buffer — is evicted to reclaim memory (D7's
|
|
5
|
+
// documented retention: buffers are dropped once the run terminates and its TTL elapses). The
|
|
6
|
+
// registry is created via `createRunRegistry` and hung off the handler deps, never a module global,
|
|
7
|
+
// so each server instance (and each test) owns an isolated registry with no cross-talk.
|
|
8
|
+
export class ActiveRunLimitError extends Error {
|
|
9
|
+
constructor(limit) {
|
|
10
|
+
super(`active run limit reached (${String(limit)})`);
|
|
11
|
+
this.name = "ActiveRunLimitError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const DEFAULT_MAX_ACTIVE_RUNS = 16;
|
|
15
|
+
const DEFAULT_TERMINATED_TTL_MS = 600_000;
|
|
16
|
+
function isTerminal(status) {
|
|
17
|
+
return status !== "running";
|
|
18
|
+
}
|
|
19
|
+
function evictExpired(state) {
|
|
20
|
+
const cutoff = state.now();
|
|
21
|
+
for (const [runId, record] of state.records) {
|
|
22
|
+
if (record.terminatedAt !== undefined && cutoff - record.terminatedAt >= state.ttlMs) {
|
|
23
|
+
state.records.delete(runId);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function countActive(state) {
|
|
28
|
+
let count = 0;
|
|
29
|
+
for (const record of state.records.values()) {
|
|
30
|
+
if (!isTerminal(record.status)) {
|
|
31
|
+
count += 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return count;
|
|
35
|
+
}
|
|
36
|
+
function registerRun(state, input) {
|
|
37
|
+
evictExpired(state);
|
|
38
|
+
if (countActive(state) >= state.maxActive) {
|
|
39
|
+
throw new ActiveRunLimitError(state.maxActive);
|
|
40
|
+
}
|
|
41
|
+
const record = {
|
|
42
|
+
runId: input.runId,
|
|
43
|
+
fingerprint: input.fingerprint,
|
|
44
|
+
modelId: input.modelId,
|
|
45
|
+
sink: input.sink,
|
|
46
|
+
status: "running",
|
|
47
|
+
report: undefined,
|
|
48
|
+
cancel: input.cancel,
|
|
49
|
+
appliable: undefined,
|
|
50
|
+
applyReport: undefined,
|
|
51
|
+
appliedAt: undefined,
|
|
52
|
+
terminatedAt: undefined,
|
|
53
|
+
};
|
|
54
|
+
state.records.set(input.runId, record);
|
|
55
|
+
return record;
|
|
56
|
+
}
|
|
57
|
+
function completeRun(state, runId, status, report, appliable) {
|
|
58
|
+
const record = state.records.get(runId);
|
|
59
|
+
if (record === undefined) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
record.status = status;
|
|
63
|
+
record.report = report;
|
|
64
|
+
record.appliable = appliable;
|
|
65
|
+
record.terminatedAt = state.now();
|
|
66
|
+
}
|
|
67
|
+
export function createRunRegistry(options = {}) {
|
|
68
|
+
const state = {
|
|
69
|
+
records: new Map(),
|
|
70
|
+
maxActive: options.maxActiveRuns ?? DEFAULT_MAX_ACTIVE_RUNS,
|
|
71
|
+
ttlMs: options.terminatedTtlMs ?? DEFAULT_TERMINATED_TTL_MS,
|
|
72
|
+
now: options.now ?? Date.now,
|
|
73
|
+
};
|
|
74
|
+
return {
|
|
75
|
+
register: (input) => registerRun(state, input),
|
|
76
|
+
get: (runId) => {
|
|
77
|
+
evictExpired(state);
|
|
78
|
+
return state.records.get(runId);
|
|
79
|
+
},
|
|
80
|
+
complete: (runId, status, report, appliable) => {
|
|
81
|
+
completeRun(state, runId, status, report, appliable);
|
|
82
|
+
},
|
|
83
|
+
snapshot: (limit) => {
|
|
84
|
+
evictExpired(state);
|
|
85
|
+
const records = Array.from(state.records.values());
|
|
86
|
+
if (limit === undefined || limit >= records.length) {
|
|
87
|
+
return records;
|
|
88
|
+
}
|
|
89
|
+
return records.slice(Math.max(0, records.length - limit));
|
|
90
|
+
},
|
|
91
|
+
activeCount: () => {
|
|
92
|
+
evictExpired(state);
|
|
93
|
+
return countActive(state);
|
|
94
|
+
},
|
|
95
|
+
size: () => {
|
|
96
|
+
evictExpired(state);
|
|
97
|
+
return state.records.size;
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Server } from "node:http";
|
|
2
|
+
import { type UiHandlerDeps } from "./deps.js";
|
|
3
|
+
export declare const DEFAULT_UI_PORT = 1983;
|
|
4
|
+
export declare const UI_HOST = "127.0.0.1";
|
|
5
|
+
export interface UiServerDeps {
|
|
6
|
+
readonly staticRoot: string;
|
|
7
|
+
readonly csp: string;
|
|
8
|
+
readonly cspProvider?: (() => string | Promise<string>) | undefined;
|
|
9
|
+
readonly port: number;
|
|
10
|
+
readonly handlerDeps?: UiHandlerDeps | undefined;
|
|
11
|
+
}
|
|
12
|
+
export declare function createUiServer(deps: UiServerDeps): Server;
|
|
13
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAejG,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAI9D,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,OAAO,cAAc,CAAC;AAEnC,MAAM,WAAW,YAAY;IAE3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAGrB,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IAEpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAGtB,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAClD;AA0JD,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAgBzD"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// The local UI BFF binds 127.0.0.1 only, applies security headers and CSP to every response,
|
|
2
|
+
// rejects non-loopback Host/Origin headers, dispatches API routes through injected handlers,
|
|
3
|
+
// and serves the static export from a contained root.
|
|
4
|
+
import { createServer } from "node:http";
|
|
5
|
+
import { extname, join } from "node:path";
|
|
6
|
+
import { applySecurityHeaders } from "./headers.js";
|
|
7
|
+
import { isAllowedHost } from "./host-check.js";
|
|
8
|
+
import { resolveContainedPath, serveFile } from "./static.js";
|
|
9
|
+
import { errorBody, isApiPath, matchRoute, methodNotAllowedBody, notFoundBody, STREAMING, } from "./routes.js";
|
|
10
|
+
import { buildRedactor } from "./deps.js";
|
|
11
|
+
import { createRunRegistry } from "./runs.js";
|
|
12
|
+
import { createInMemoryUiStore } from "./store/index.js";
|
|
13
|
+
export const DEFAULT_UI_PORT = 1983;
|
|
14
|
+
export const UI_HOST = "127.0.0.1";
|
|
15
|
+
function writeJson(res, status, body) {
|
|
16
|
+
res.statusCode = status;
|
|
17
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
18
|
+
res.end(JSON.stringify(body));
|
|
19
|
+
}
|
|
20
|
+
function isJsonRequest(req) {
|
|
21
|
+
const header = req.headers["content-type"];
|
|
22
|
+
const value = typeof header === "string" ? header : header?.[0];
|
|
23
|
+
return value?.split(";", 1)[0]?.trim().toLowerCase() === "application/json";
|
|
24
|
+
}
|
|
25
|
+
function hasCsrfHeader(req) {
|
|
26
|
+
const header = req.headers["x-keiko-csrf"];
|
|
27
|
+
const value = Array.isArray(header) ? header[0] : header;
|
|
28
|
+
return value === "1";
|
|
29
|
+
}
|
|
30
|
+
function rejectUnsupportedMediaType(res) {
|
|
31
|
+
writeJson(res, 415, errorBody("UNSUPPORTED_MEDIA_TYPE", "State-changing API requests must use JSON."));
|
|
32
|
+
}
|
|
33
|
+
function rejectCsrf(res) {
|
|
34
|
+
writeJson(res, 403, errorBody("FORBIDDEN_CSRF", "Missing state-changing request guard."));
|
|
35
|
+
}
|
|
36
|
+
// A minimal default deps object so a 3-arg server can still serve the deps-bound read routes (e.g.
|
|
37
|
+
// `/api/models` and `/api/workspace`, which need no config) without a config or evidence dir. The
|
|
38
|
+
// fallback UI store is in-memory: a 3-arg server is used by the Wave 1 host smoke and by tests that
|
|
39
|
+
// never exercise the store routes, so an ephemeral in-memory store is the safe degraded shape.
|
|
40
|
+
function fallbackDeps() {
|
|
41
|
+
return {
|
|
42
|
+
config: undefined,
|
|
43
|
+
configPresent: false,
|
|
44
|
+
evidenceStore: { put: () => "", list: () => [], get: () => undefined, delete: () => undefined },
|
|
45
|
+
env: {},
|
|
46
|
+
redactor: buildRedactor({}),
|
|
47
|
+
registry: createRunRegistry(),
|
|
48
|
+
modelPortFactory: () => undefined,
|
|
49
|
+
store: createInMemoryUiStore(),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function isStateChangingMethod(method) {
|
|
53
|
+
return method === "POST" || method === "PATCH" || method === "PUT" || method === "DELETE";
|
|
54
|
+
}
|
|
55
|
+
// Returns true when the request was rejected (caller should return immediately).
|
|
56
|
+
function rejectIfInvalidStateChange(req, res) {
|
|
57
|
+
if (!isJsonRequest(req)) {
|
|
58
|
+
rejectUnsupportedMediaType(res);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
if (!hasCsrfHeader(req)) {
|
|
62
|
+
rejectCsrf(res);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
async function dispatchApi(handlerDeps, req, res, method, url) {
|
|
68
|
+
const match = matchRoute(method, url.pathname);
|
|
69
|
+
if (match === undefined) {
|
|
70
|
+
writeJson(res, 404, notFoundBody());
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (match === "method-not-allowed") {
|
|
74
|
+
writeJson(res, 405, methodNotAllowedBody());
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (isStateChangingMethod(method) && rejectIfInvalidStateChange(req, res)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const ctx = { req, res, params: match.params, url };
|
|
81
|
+
const outcome = await match.definition.handler(ctx, handlerDeps);
|
|
82
|
+
if (outcome === STREAMING) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
writeJson(res, outcome.status, outcome.body);
|
|
86
|
+
}
|
|
87
|
+
async function serveStatic(res, staticRoot, pathname) {
|
|
88
|
+
const targets = pathname === "/"
|
|
89
|
+
? ["/index.html"]
|
|
90
|
+
: extname(pathname) === ""
|
|
91
|
+
? [pathname, `${pathname}.html`, `${pathname}/index.html`]
|
|
92
|
+
: [pathname];
|
|
93
|
+
for (const target of targets) {
|
|
94
|
+
const resolved = resolveContainedPath(staticRoot, target);
|
|
95
|
+
if (resolved !== undefined && (await serveFile(res, resolved))) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const indexPath = join(staticRoot, "index.html");
|
|
100
|
+
if (await serveFile(res, indexPath)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
writeJson(res, 404, errorBody("NOT_FOUND", "The requested resource was not found."));
|
|
104
|
+
}
|
|
105
|
+
function rejectForbiddenHost(res) {
|
|
106
|
+
const body = errorBody("FORBIDDEN_HOST", "Request host is not the local interface.");
|
|
107
|
+
writeJson(res, 403, body);
|
|
108
|
+
}
|
|
109
|
+
async function resolveCsp(deps) {
|
|
110
|
+
try {
|
|
111
|
+
return (await deps.cspProvider?.()) ?? deps.csp;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return deps.csp;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function handle(deps, handlerDeps, req, res) {
|
|
118
|
+
const url = new URL(req.url ?? "/", `http://${UI_HOST}`);
|
|
119
|
+
const apiPath = isApiPath(url.pathname);
|
|
120
|
+
applySecurityHeaders(res, await resolveCsp(deps), apiPath);
|
|
121
|
+
if (!isAllowedHost(req, deps.port)) {
|
|
122
|
+
rejectForbiddenHost(res);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
126
|
+
if (apiPath) {
|
|
127
|
+
await dispatchApi(handlerDeps, req, res, method, url);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
await serveStatic(res, deps.staticRoot, url.pathname);
|
|
131
|
+
}
|
|
132
|
+
// Creates the BFF server. The caller binds it with `server.listen(deps.port, UI_HOST)` so it never
|
|
133
|
+
// listens on a non-loopback interface. The previous PTY WebSocket upgrade handler is removed —
|
|
134
|
+
// the terminal tool is now bounded-exec over plain HTTP (ADR-0018 D1/D8).
|
|
135
|
+
export function createUiServer(deps) {
|
|
136
|
+
const handlerDeps = deps.handlerDeps ?? fallbackDeps();
|
|
137
|
+
const server = createServer((req, res) => {
|
|
138
|
+
void handle(deps, handlerDeps, req, res).catch(() => {
|
|
139
|
+
if (!res.headersSent) {
|
|
140
|
+
writeJson(res, 500, errorBody("INTERNAL", "An unexpected error occurred."));
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
res.end();
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
server.on("upgrade", (_req, socket) => {
|
|
148
|
+
socket.write("HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n");
|
|
149
|
+
socket.destroy();
|
|
150
|
+
});
|
|
151
|
+
return server;
|
|
152
|
+
}
|
package/dist/sink.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface StreamEvent {
|
|
2
|
+
readonly schemaVersion: "1";
|
|
3
|
+
readonly runId: string;
|
|
4
|
+
readonly fingerprint: string;
|
|
5
|
+
readonly seq: number;
|
|
6
|
+
readonly ts: number;
|
|
7
|
+
readonly type: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SseWriter {
|
|
10
|
+
readonly write: (event: StreamEvent) => boolean | undefined;
|
|
11
|
+
readonly close: () => void;
|
|
12
|
+
}
|
|
13
|
+
export interface QueueEventSinkOptions {
|
|
14
|
+
readonly bufferCapacity?: number | undefined;
|
|
15
|
+
}
|
|
16
|
+
export declare class QueueEventSink {
|
|
17
|
+
private readonly buffer;
|
|
18
|
+
private readonly capacity;
|
|
19
|
+
private readonly writers;
|
|
20
|
+
private terminated;
|
|
21
|
+
readonly emit: (event: StreamEvent) => void;
|
|
22
|
+
constructor(options?: QueueEventSinkOptions);
|
|
23
|
+
attach(writer: SseWriter, afterSeq: number): () => void;
|
|
24
|
+
closeAll(): void;
|
|
25
|
+
isTerminated(): boolean;
|
|
26
|
+
buffered(afterSeq?: number): readonly StreamEvent[];
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=sink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sink.d.ts","sourceRoot":"","sources":["../src/sink.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,GAAG,SAAS,CAAC;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;CAC5B;AAID,MAAM,WAAW,qBAAqB;IAEpC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9C;AAED,qBAAa,cAAc;IAEzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,UAAU,CAAS;IAG3B,QAAQ,CAAC,IAAI,GAAI,OAAO,WAAW,KAAG,IAAI,CAiBxC;gBAEU,OAAO,GAAE,qBAA0B;IAO/C,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,IAAI;IAkBvD,QAAQ,IAAI,IAAI;IAWhB,YAAY,IAAI,OAAO;IAKvB,QAAQ,CAAC,QAAQ,SAAK,GAAG,SAAS,WAAW,EAAE;CAGhD"}
|
package/dist/sink.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// The QueueEventSink bridges the harness's push-only, synchronous EventSink (and the structurally
|
|
2
|
+
// identical workflow WorkflowEventSink / BugWorkflowEventSink) to Server-Sent Events (ADR-0011 D7).
|
|
3
|
+
// It satisfies all three sink shapes — each is `{ emit(event): void }` over an event that carries
|
|
4
|
+
// the `{ schemaVersion, runId, fingerprint, seq, ts, type }` envelope — with one `emit` typed over
|
|
5
|
+
// that structural envelope (no `any`; the concrete unions are assignable to it).
|
|
6
|
+
//
|
|
7
|
+
// It deliberately does NOT set `retainsRawContent`, so the harness emitter redacts every SENSITIVE
|
|
8
|
+
// field before this sink ever receives an event (the browser only sees redacted events). Internally
|
|
9
|
+
// it (a) appends each received event to a per-run BOUNDED ring buffer for replay-on-connect (oldest
|
|
10
|
+
// dropped past the cap), and (b) fans the event out to any currently-attached SSE writers. A late or
|
|
11
|
+
// reconnecting subscriber replays the buffer (respecting Last-Event-ID = the harness `seq`), then
|
|
12
|
+
// receives live events, then a close after the terminal event.
|
|
13
|
+
const DEFAULT_BUFFER_CAPACITY = 512;
|
|
14
|
+
export class QueueEventSink {
|
|
15
|
+
// retainsRawContent is intentionally absent (never true): the harness must redact before emit.
|
|
16
|
+
buffer = [];
|
|
17
|
+
capacity;
|
|
18
|
+
writers = new Set();
|
|
19
|
+
terminated = false;
|
|
20
|
+
// Bound so the sink can be passed directly as an `EventSink`/`WorkflowEventSink`/`BugWorkflowEventSink`.
|
|
21
|
+
emit = (event) => {
|
|
22
|
+
this.buffer.push(event);
|
|
23
|
+
if (this.buffer.length > this.capacity) {
|
|
24
|
+
this.buffer.shift();
|
|
25
|
+
}
|
|
26
|
+
for (const writer of [...this.writers]) {
|
|
27
|
+
try {
|
|
28
|
+
const accepted = writer.write(event);
|
|
29
|
+
if (accepted === false) {
|
|
30
|
+
this.writers.delete(writer);
|
|
31
|
+
writer.close();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
this.writers.delete(writer);
|
|
36
|
+
writer.close();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.capacity = options.bufferCapacity ?? DEFAULT_BUFFER_CAPACITY;
|
|
42
|
+
}
|
|
43
|
+
// Attaches an SSE writer: replays the buffered events with `seq` strictly greater than
|
|
44
|
+
// `afterSeq` (Last-Event-ID resume), then keeps the writer attached for live fan-out. Returns a
|
|
45
|
+
// detach function the caller invokes on client disconnect to stop fan-out and avoid leaks.
|
|
46
|
+
attach(writer, afterSeq) {
|
|
47
|
+
for (const event of this.buffer) {
|
|
48
|
+
if (event.seq > afterSeq) {
|
|
49
|
+
const accepted = writer.write(event);
|
|
50
|
+
if (accepted === false) {
|
|
51
|
+
writer.close();
|
|
52
|
+
return () => undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
this.writers.add(writer);
|
|
57
|
+
return () => {
|
|
58
|
+
this.writers.delete(writer);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Closes and clears every attached writer (called once the run terminates). The ring buffer is
|
|
62
|
+
// retained for the registry TTL so a late subscriber can still replay history before eviction.
|
|
63
|
+
closeAll() {
|
|
64
|
+
if (this.terminated) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.terminated = true;
|
|
68
|
+
for (const writer of this.writers) {
|
|
69
|
+
writer.close();
|
|
70
|
+
}
|
|
71
|
+
this.writers.clear();
|
|
72
|
+
}
|
|
73
|
+
isTerminated() {
|
|
74
|
+
return this.terminated;
|
|
75
|
+
}
|
|
76
|
+
// Snapshot of buffered events with `seq` strictly greater than `afterSeq` (inspection/replay aid).
|
|
77
|
+
buffered(afterSeq = -1) {
|
|
78
|
+
return this.buffer.filter((event) => event.seq > afterSeq);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ServerResponse } from "node:http";
|
|
2
|
+
/**
|
|
3
|
+
* Writes `frame` to `res`. When `res.write` returns false (TCP send-buffer full / slow client),
|
|
4
|
+
* aborts `controller` (stops the upstream producer) and destroys the socket.
|
|
5
|
+
*
|
|
6
|
+
* Returns the raw boolean from `res.write` so callers can short-circuit if needed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function writeOrDestroy(res: ServerResponse, frame: string, controller: AbortController): boolean;
|
|
9
|
+
//# sourceMappingURL=sse-write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-write.d.ts","sourceRoot":"","sources":["../src/sse-write.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,GAC1B,OAAO,CAOT"}
|