patchwork-os 0.2.0-alpha.8 → 0.2.0-beta.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/README.bridge.md +6 -0
- package/README.md +315 -35
- package/deploy/bootstrap-new-vps.sh +12 -12
- package/deploy/bootstrap-vps.sh +187 -0
- package/deploy/deploy-dashboard.sh +174 -0
- package/deploy/deploy-landing.sh +136 -0
- package/dist/activationMetrics.d.ts +67 -0
- package/dist/activationMetrics.js +255 -0
- package/dist/activationMetrics.js.map +1 -0
- package/dist/activityLog.d.ts +49 -0
- package/dist/activityLog.js +78 -0
- package/dist/activityLog.js.map +1 -1
- package/dist/approvalHttp.d.ts +49 -2
- package/dist/approvalHttp.js +217 -21
- package/dist/approvalHttp.js.map +1 -1
- package/dist/approvalInsights.d.ts +49 -0
- package/dist/approvalInsights.js +97 -0
- package/dist/approvalInsights.js.map +1 -0
- package/dist/approvalQueue.d.ts +27 -1
- package/dist/approvalQueue.js +123 -3
- package/dist/approvalQueue.js.map +1 -1
- package/dist/approvalSignals.d.ts +124 -0
- package/dist/approvalSignals.js +512 -0
- package/dist/approvalSignals.js.map +1 -0
- package/dist/automation.d.ts +57 -0
- package/dist/automation.js +156 -59
- package/dist/automation.js.map +1 -1
- package/dist/automationSuggestions.d.ts +79 -0
- package/dist/automationSuggestions.js +150 -0
- package/dist/automationSuggestions.js.map +1 -0
- package/dist/bridge.d.ts +3 -0
- package/dist/bridge.js +174 -143
- package/dist/bridge.js.map +1 -1
- package/dist/bridgeToken.js +57 -19
- package/dist/bridgeToken.js.map +1 -1
- package/dist/ccPermissions.d.ts +15 -0
- package/dist/ccPermissions.js +21 -4
- package/dist/ccPermissions.js.map +1 -1
- package/dist/claudeDriver.js +74 -16
- package/dist/claudeDriver.js.map +1 -1
- package/dist/claudeOrchestrator.d.ts +1 -1
- package/dist/claudeOrchestrator.js +14 -8
- package/dist/claudeOrchestrator.js.map +1 -1
- package/dist/commands/dashboard.js +1 -1
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/launchd.d.ts +2 -0
- package/dist/commands/launchd.js +94 -0
- package/dist/commands/launchd.js.map +1 -0
- package/dist/commands/patchworkInit.d.ts +8 -0
- package/dist/commands/patchworkInit.js +77 -11
- package/dist/commands/patchworkInit.js.map +1 -1
- package/dist/commands/recipe.d.ts +289 -0
- package/dist/commands/recipe.js +1359 -0
- package/dist/commands/recipe.js.map +1 -0
- package/dist/commands/recipeInstall.d.ts +150 -0
- package/dist/commands/recipeInstall.js +647 -0
- package/dist/commands/recipeInstall.js.map +1 -0
- package/dist/commands/tracesExport.d.ts +83 -0
- package/dist/commands/tracesExport.js +269 -0
- package/dist/commands/tracesExport.js.map +1 -0
- package/dist/commands/tracesImport.d.ts +56 -0
- package/dist/commands/tracesImport.js +161 -0
- package/dist/commands/tracesImport.js.map +1 -0
- package/dist/config.d.ts +22 -1
- package/dist/config.js +108 -9
- package/dist/config.js.map +1 -1
- package/dist/connectorRoutes.d.ts +43 -0
- package/dist/connectorRoutes.js +1609 -0
- package/dist/connectorRoutes.js.map +1 -0
- package/dist/connectors/asana.d.ts +198 -0
- package/dist/connectors/asana.js +679 -0
- package/dist/connectors/asana.js.map +1 -0
- package/dist/connectors/baseConnector.d.ts +153 -0
- package/dist/connectors/baseConnector.js +336 -0
- package/dist/connectors/baseConnector.js.map +1 -0
- package/dist/connectors/confluence.d.ts +111 -0
- package/dist/connectors/confluence.js +406 -0
- package/dist/connectors/confluence.js.map +1 -0
- package/dist/connectors/datadog.d.ts +116 -0
- package/dist/connectors/datadog.js +385 -0
- package/dist/connectors/datadog.js.map +1 -0
- package/dist/connectors/discord.d.ts +150 -0
- package/dist/connectors/discord.js +543 -0
- package/dist/connectors/discord.js.map +1 -0
- package/dist/connectors/fixtureLibrary.d.ts +21 -0
- package/dist/connectors/fixtureLibrary.js +70 -0
- package/dist/connectors/fixtureLibrary.js.map +1 -0
- package/dist/connectors/fixtureRecorder.d.ts +1 -0
- package/dist/connectors/fixtureRecorder.js +35 -0
- package/dist/connectors/fixtureRecorder.js.map +1 -0
- package/dist/connectors/github.js +17 -18
- package/dist/connectors/github.js.map +1 -1
- package/dist/connectors/gitlab.d.ts +180 -0
- package/dist/connectors/gitlab.js +582 -0
- package/dist/connectors/gitlab.js.map +1 -0
- package/dist/connectors/gmail.d.ts +4 -1
- package/dist/connectors/gmail.js +157 -27
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleCalendar.d.ts +4 -1
- package/dist/connectors/googleCalendar.js +88 -25
- package/dist/connectors/googleCalendar.js.map +1 -1
- package/dist/connectors/googleDrive.d.ts +34 -0
- package/dist/connectors/googleDrive.js +321 -0
- package/dist/connectors/googleDrive.js.map +1 -0
- package/dist/connectors/htmlEscape.d.ts +5 -0
- package/dist/connectors/htmlEscape.js +13 -0
- package/dist/connectors/htmlEscape.js.map +1 -0
- package/dist/connectors/hubspot.d.ts +112 -0
- package/dist/connectors/hubspot.js +408 -0
- package/dist/connectors/hubspot.js.map +1 -0
- package/dist/connectors/intercom.d.ts +102 -0
- package/dist/connectors/intercom.js +402 -0
- package/dist/connectors/intercom.js.map +1 -0
- package/dist/connectors/jira.d.ts +98 -0
- package/dist/connectors/jira.js +379 -0
- package/dist/connectors/jira.js.map +1 -0
- package/dist/connectors/linear.js +30 -19
- package/dist/connectors/linear.js.map +1 -1
- package/dist/connectors/mcpOAuth.d.ts +3 -0
- package/dist/connectors/mcpOAuth.js +64 -10
- package/dist/connectors/mcpOAuth.js.map +1 -1
- package/dist/connectors/mockConnector.d.ts +28 -0
- package/dist/connectors/mockConnector.js +81 -0
- package/dist/connectors/mockConnector.js.map +1 -0
- package/dist/connectors/notion.d.ts +143 -0
- package/dist/connectors/notion.js +424 -0
- package/dist/connectors/notion.js.map +1 -0
- package/dist/connectors/oauthStateStore.d.ts +31 -0
- package/dist/connectors/oauthStateStore.js +52 -0
- package/dist/connectors/oauthStateStore.js.map +1 -0
- package/dist/connectors/pagerduty.d.ts +160 -0
- package/dist/connectors/pagerduty.js +464 -0
- package/dist/connectors/pagerduty.js.map +1 -0
- package/dist/connectors/sentry.js +5 -13
- package/dist/connectors/sentry.js.map +1 -1
- package/dist/connectors/slack.d.ts +16 -1
- package/dist/connectors/slack.js +155 -32
- package/dist/connectors/slack.js.map +1 -1
- package/dist/connectors/stripe.d.ts +116 -0
- package/dist/connectors/stripe.js +379 -0
- package/dist/connectors/stripe.js.map +1 -0
- package/dist/connectors/tokenStorage.d.ts +35 -0
- package/dist/connectors/tokenStorage.js +484 -0
- package/dist/connectors/tokenStorage.js.map +1 -0
- package/dist/connectors/zendesk.d.ts +104 -0
- package/dist/connectors/zendesk.js +442 -0
- package/dist/connectors/zendesk.js.map +1 -0
- package/dist/cors.d.ts +10 -0
- package/dist/cors.js +29 -0
- package/dist/cors.js.map +1 -0
- package/dist/decisionReplay.d.ts +72 -0
- package/dist/decisionReplay.js +92 -0
- package/dist/decisionReplay.js.map +1 -0
- package/dist/decisionTraceLog.d.ts +6 -0
- package/dist/decisionTraceLog.js +54 -2
- package/dist/decisionTraceLog.js.map +1 -1
- package/dist/drivers/gemini/index.d.ts +5 -1
- package/dist/drivers/gemini/index.js +39 -5
- package/dist/drivers/gemini/index.js.map +1 -1
- package/dist/drivers/index.d.ts +5 -0
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/index.js.map +1 -1
- package/dist/featureFlags.d.ts +79 -0
- package/dist/featureFlags.js +208 -0
- package/dist/featureFlags.js.map +1 -0
- package/dist/fp/automationInterpreter.js +26 -21
- package/dist/fp/automationInterpreter.js.map +1 -1
- package/dist/fp/automationProgram.d.ts +1 -1
- package/dist/fp/automationProgram.js.map +1 -1
- package/dist/fp/automationState.js +4 -1
- package/dist/fp/automationState.js.map +1 -1
- package/dist/fp/policyParser.js +21 -1
- package/dist/fp/policyParser.js.map +1 -1
- package/dist/inboxRoutes.d.ts +22 -0
- package/dist/inboxRoutes.js +114 -0
- package/dist/inboxRoutes.js.map +1 -0
- package/dist/index.js +1400 -201
- package/dist/index.js.map +1 -1
- package/dist/installGuard.d.ts +25 -0
- package/dist/installGuard.js +48 -0
- package/dist/installGuard.js.map +1 -0
- package/dist/mcpRoutes.d.ts +37 -0
- package/dist/mcpRoutes.js +76 -0
- package/dist/mcpRoutes.js.map +1 -0
- package/dist/oauth.d.ts +7 -1
- package/dist/oauth.js +201 -39
- package/dist/oauth.js.map +1 -1
- package/dist/oauthRoutes.d.ts +32 -0
- package/dist/oauthRoutes.js +124 -0
- package/dist/oauthRoutes.js.map +1 -0
- package/dist/orchestrator/orchestratorBridge.js +2 -2
- package/dist/orchestrator/orchestratorBridge.js.map +1 -1
- package/dist/patchworkConfig.d.ts +16 -0
- package/dist/patchworkConfig.js +1 -1
- package/dist/patchworkConfig.js.map +1 -1
- package/dist/pluginLoader.d.ts +28 -0
- package/dist/pluginLoader.js +77 -11
- package/dist/pluginLoader.js.map +1 -1
- package/dist/pluginWatcher.js +8 -3
- package/dist/pluginWatcher.js.map +1 -1
- package/dist/preToolUseHook.d.ts +12 -0
- package/dist/preToolUseHook.js +23 -0
- package/dist/preToolUseHook.js.map +1 -1
- package/dist/recipeOrchestration.d.ts +121 -0
- package/dist/recipeOrchestration.js +955 -0
- package/dist/recipeOrchestration.js.map +1 -0
- package/dist/recipeRoutes.d.ts +180 -0
- package/dist/recipeRoutes.js +1345 -0
- package/dist/recipeRoutes.js.map +1 -0
- package/dist/recipes/RecipeOrchestrator.d.ts +40 -0
- package/dist/recipes/RecipeOrchestrator.js +51 -0
- package/dist/recipes/RecipeOrchestrator.js.map +1 -0
- package/dist/recipes/agentExecutor.d.ts +29 -0
- package/dist/recipes/agentExecutor.js +49 -0
- package/dist/recipes/agentExecutor.js.map +1 -0
- package/dist/recipes/chainedRunner.d.ts +191 -0
- package/dist/recipes/chainedRunner.js +759 -0
- package/dist/recipes/chainedRunner.js.map +1 -0
- package/dist/recipes/compiler.js +3 -3
- package/dist/recipes/compiler.js.map +1 -1
- package/dist/recipes/dependencyGraph.d.ts +39 -0
- package/dist/recipes/dependencyGraph.js +199 -0
- package/dist/recipes/dependencyGraph.js.map +1 -0
- package/dist/recipes/disabledMarkers.d.ts +48 -0
- package/dist/recipes/disabledMarkers.js +52 -0
- package/dist/recipes/disabledMarkers.js.map +1 -0
- package/dist/recipes/installer.js +3 -3
- package/dist/recipes/installer.js.map +1 -1
- package/dist/recipes/legacyRecipeCompat.d.ts +10 -0
- package/dist/recipes/legacyRecipeCompat.js +131 -0
- package/dist/recipes/legacyRecipeCompat.js.map +1 -0
- package/dist/recipes/manifest.d.ts +47 -0
- package/dist/recipes/manifest.js +156 -0
- package/dist/recipes/manifest.js.map +1 -0
- package/dist/recipes/migrationWarnings.d.ts +12 -0
- package/dist/recipes/migrationWarnings.js +44 -0
- package/dist/recipes/migrationWarnings.js.map +1 -0
- package/dist/recipes/migrations/index.d.ts +24 -0
- package/dist/recipes/migrations/index.js +55 -0
- package/dist/recipes/migrations/index.js.map +1 -0
- package/dist/recipes/migrations/types.d.ts +28 -0
- package/dist/recipes/migrations/types.js +2 -0
- package/dist/recipes/migrations/types.js.map +1 -0
- package/dist/recipes/migrations/v1.d.ts +11 -0
- package/dist/recipes/migrations/v1.js +18 -0
- package/dist/recipes/migrations/v1.js.map +1 -0
- package/dist/recipes/names.d.ts +40 -0
- package/dist/recipes/names.js +66 -0
- package/dist/recipes/names.js.map +1 -0
- package/dist/recipes/nestedRecipeStep.d.ts +58 -0
- package/dist/recipes/nestedRecipeStep.js +95 -0
- package/dist/recipes/nestedRecipeStep.js.map +1 -0
- package/dist/recipes/outputRegistry.d.ts +28 -0
- package/dist/recipes/outputRegistry.js +52 -0
- package/dist/recipes/outputRegistry.js.map +1 -0
- package/dist/recipes/parser.js +4 -1
- package/dist/recipes/parser.js.map +1 -1
- package/dist/recipes/replayRun.d.ts +62 -0
- package/dist/recipes/replayRun.js +97 -0
- package/dist/recipes/replayRun.js.map +1 -0
- package/dist/recipes/resolveRecipePath.d.ts +69 -0
- package/dist/recipes/resolveRecipePath.js +202 -0
- package/dist/recipes/resolveRecipePath.js.map +1 -0
- package/dist/recipes/scheduler.d.ts +23 -7
- package/dist/recipes/scheduler.js +225 -45
- package/dist/recipes/scheduler.js.map +1 -1
- package/dist/recipes/schema.d.ts +17 -2
- package/dist/recipes/schemaGenerator.d.ts +28 -0
- package/dist/recipes/schemaGenerator.js +565 -0
- package/dist/recipes/schemaGenerator.js.map +1 -0
- package/dist/recipes/stepObservation.d.ts +44 -0
- package/dist/recipes/stepObservation.js +232 -0
- package/dist/recipes/stepObservation.js.map +1 -0
- package/dist/recipes/templateEngine.d.ts +62 -0
- package/dist/recipes/templateEngine.js +201 -0
- package/dist/recipes/templateEngine.js.map +1 -0
- package/dist/recipes/toolRegistry.d.ts +186 -0
- package/dist/recipes/toolRegistry.js +309 -0
- package/dist/recipes/toolRegistry.js.map +1 -0
- package/dist/recipes/tools/asana.d.ts +16 -0
- package/dist/recipes/tools/asana.js +524 -0
- package/dist/recipes/tools/asana.js.map +1 -0
- package/dist/recipes/tools/calendar.d.ts +6 -0
- package/dist/recipes/tools/calendar.js +61 -0
- package/dist/recipes/tools/calendar.js.map +1 -0
- package/dist/recipes/tools/confluence.d.ts +6 -0
- package/dist/recipes/tools/confluence.js +254 -0
- package/dist/recipes/tools/confluence.js.map +1 -0
- package/dist/recipes/tools/datadog.d.ts +6 -0
- package/dist/recipes/tools/datadog.js +239 -0
- package/dist/recipes/tools/datadog.js.map +1 -0
- package/dist/recipes/tools/diagnostics.d.ts +6 -0
- package/dist/recipes/tools/diagnostics.js +36 -0
- package/dist/recipes/tools/diagnostics.js.map +1 -0
- package/dist/recipes/tools/discord.d.ts +18 -0
- package/dist/recipes/tools/discord.js +254 -0
- package/dist/recipes/tools/discord.js.map +1 -0
- package/dist/recipes/tools/file.d.ts +12 -0
- package/dist/recipes/tools/file.js +174 -0
- package/dist/recipes/tools/file.js.map +1 -0
- package/dist/recipes/tools/git.d.ts +6 -0
- package/dist/recipes/tools/git.js +63 -0
- package/dist/recipes/tools/git.js.map +1 -0
- package/dist/recipes/tools/github.d.ts +6 -0
- package/dist/recipes/tools/github.js +116 -0
- package/dist/recipes/tools/github.js.map +1 -0
- package/dist/recipes/tools/gitlab.d.ts +11 -0
- package/dist/recipes/tools/gitlab.js +285 -0
- package/dist/recipes/tools/gitlab.js.map +1 -0
- package/dist/recipes/tools/gmail.d.ts +6 -0
- package/dist/recipes/tools/gmail.js +434 -0
- package/dist/recipes/tools/gmail.js.map +1 -0
- package/dist/recipes/tools/googleDrive.d.ts +1 -0
- package/dist/recipes/tools/googleDrive.js +55 -0
- package/dist/recipes/tools/googleDrive.js.map +1 -0
- package/dist/recipes/tools/hubspot.d.ts +6 -0
- package/dist/recipes/tools/hubspot.js +232 -0
- package/dist/recipes/tools/hubspot.js.map +1 -0
- package/dist/recipes/tools/index.d.ts +30 -0
- package/dist/recipes/tools/index.js +33 -0
- package/dist/recipes/tools/index.js.map +1 -0
- package/dist/recipes/tools/intercom.d.ts +6 -0
- package/dist/recipes/tools/intercom.js +226 -0
- package/dist/recipes/tools/intercom.js.map +1 -0
- package/dist/recipes/tools/jira.d.ts +14 -0
- package/dist/recipes/tools/jira.js +369 -0
- package/dist/recipes/tools/jira.js.map +1 -0
- package/dist/recipes/tools/linear.d.ts +7 -0
- package/dist/recipes/tools/linear.js +307 -0
- package/dist/recipes/tools/linear.js.map +1 -0
- package/dist/recipes/tools/meetingNotes.d.ts +21 -0
- package/dist/recipes/tools/meetingNotes.js +701 -0
- package/dist/recipes/tools/meetingNotes.js.map +1 -0
- package/dist/recipes/tools/notion.d.ts +6 -0
- package/dist/recipes/tools/notion.js +278 -0
- package/dist/recipes/tools/notion.js.map +1 -0
- package/dist/recipes/tools/pagerduty.d.ts +15 -0
- package/dist/recipes/tools/pagerduty.js +451 -0
- package/dist/recipes/tools/pagerduty.js.map +1 -0
- package/dist/recipes/tools/sentry.d.ts +12 -0
- package/dist/recipes/tools/sentry.js +73 -0
- package/dist/recipes/tools/sentry.js.map +1 -0
- package/dist/recipes/tools/slack.d.ts +6 -0
- package/dist/recipes/tools/slack.js +82 -0
- package/dist/recipes/tools/slack.js.map +1 -0
- package/dist/recipes/tools/stripe.d.ts +6 -0
- package/dist/recipes/tools/stripe.js +265 -0
- package/dist/recipes/tools/stripe.js.map +1 -0
- package/dist/recipes/tools/zendesk.d.ts +6 -0
- package/dist/recipes/tools/zendesk.js +245 -0
- package/dist/recipes/tools/zendesk.js.map +1 -0
- package/dist/recipes/validation.d.ts +13 -0
- package/dist/recipes/validation.js +617 -0
- package/dist/recipes/validation.js.map +1 -0
- package/dist/recipes/yamlRunner.d.ts +116 -1
- package/dist/recipes/yamlRunner.js +1000 -401
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +137 -6
- package/dist/recipesHttp.js +941 -29
- package/dist/recipesHttp.js.map +1 -1
- package/dist/riskTier.js +7 -1
- package/dist/riskTier.js.map +1 -1
- package/dist/runLog.d.ts +100 -1
- package/dist/runLog.js +258 -5
- package/dist/runLog.js.map +1 -1
- package/dist/schemas/dry-run-plan.v1.json +139 -0
- package/dist/schemas/recipe.v1.json +684 -0
- package/dist/server.d.ts +121 -8
- package/dist/server.js +538 -735
- package/dist/server.js.map +1 -1
- package/dist/ssrfGuard.d.ts +54 -0
- package/dist/ssrfGuard.js +122 -0
- package/dist/ssrfGuard.js.map +1 -0
- package/dist/streamableHttp.d.ts +39 -1
- package/dist/streamableHttp.js +128 -17
- package/dist/streamableHttp.js.map +1 -1
- package/dist/tokenUsageTracker.d.ts +33 -0
- package/dist/tokenUsageTracker.js +146 -0
- package/dist/tokenUsageTracker.js.map +1 -0
- package/dist/tools/activityLog.d.ts +2 -0
- package/dist/tools/addLinearComment.d.ts +1 -0
- package/dist/tools/addLinearComment.js +4 -2
- package/dist/tools/addLinearComment.js.map +1 -1
- package/dist/tools/batchLsp.d.ts +3 -0
- package/dist/tools/bridgeDoctor.d.ts +1 -0
- package/dist/tools/bridgeDoctor.js +2 -2
- package/dist/tools/bridgeDoctor.js.map +1 -1
- package/dist/tools/bridgeStatus.d.ts +1 -0
- package/dist/tools/cancelClaudeTask.d.ts +2 -0
- package/dist/tools/cancelClaudeTask.js +1 -0
- package/dist/tools/cancelClaudeTask.js.map +1 -1
- package/dist/tools/checkDocumentDirty.d.ts +1 -0
- package/dist/tools/clipboard.d.ts +2 -0
- package/dist/tools/closeTabs.d.ts +2 -0
- package/dist/tools/codeLens.d.ts +1 -0
- package/dist/tools/contextBundle.d.ts +1 -0
- package/dist/tools/createIssueFromAIComment.d.ts +1 -0
- package/dist/tools/createLinearIssue.d.ts +1 -0
- package/dist/tools/ctxGetTaskContext.d.ts +1 -0
- package/dist/tools/ctxQueryTraces.d.ts +1 -0
- package/dist/tools/ctxSaveTrace.d.ts +1 -0
- package/dist/tools/debug.d.ts +4 -0
- package/dist/tools/decorations.d.ts +2 -0
- package/dist/tools/documentLinks.d.ts +1 -0
- package/dist/tools/editText.d.ts +1 -0
- package/dist/tools/enrichCommit.d.ts +1 -0
- package/dist/tools/enrichStackTrace.d.ts +1 -0
- package/dist/tools/explainDiagnostic.d.ts +1 -0
- package/dist/tools/explainSymbol.d.ts +1 -0
- package/dist/tools/fetchCalendarEvents.d.ts +1 -0
- package/dist/tools/fetchGithubIssue.d.ts +1 -0
- package/dist/tools/fetchGithubPR.d.ts +1 -0
- package/dist/tools/fetchLinearIssue.d.ts +1 -0
- package/dist/tools/fetchSentryIssue.d.ts +1 -0
- package/dist/tools/fetchSlackProfile.d.ts +1 -0
- package/dist/tools/fetchSlackProfile.js +4 -1
- package/dist/tools/fetchSlackProfile.js.map +1 -1
- package/dist/tools/fileOperations.d.ts +3 -0
- package/dist/tools/fileWatcher.d.ts +2 -0
- package/dist/tools/findFiles.d.ts +1 -0
- package/dist/tools/findRelatedTests.d.ts +1 -0
- package/dist/tools/fixAllLintErrors.d.ts +1 -0
- package/dist/tools/foldingRanges.d.ts +1 -0
- package/dist/tools/formatDocument.d.ts +1 -0
- package/dist/tools/generateTests.d.ts +1 -0
- package/dist/tools/getAIComments.d.ts +1 -0
- package/dist/tools/getAnalyticsReport.d.ts +1 -0
- package/dist/tools/getArchitectureContext.d.ts +1 -0
- package/dist/tools/getBufferContent.d.ts +1 -0
- package/dist/tools/getChangeImpact.d.ts +1 -0
- package/dist/tools/getClaudeTaskStatus.d.ts +2 -0
- package/dist/tools/getClaudeTaskStatus.js +1 -0
- package/dist/tools/getClaudeTaskStatus.js.map +1 -1
- package/dist/tools/getCodeCoverage.d.ts +1 -0
- package/dist/tools/getCommitsForIssue.d.ts +1 -0
- package/dist/tools/getConnectorStatus.d.ts +1 -0
- package/dist/tools/getCurrentSelection.d.ts +2 -0
- package/dist/tools/getDebugState.d.ts +1 -0
- package/dist/tools/getDependencyTree.d.ts +1 -0
- package/dist/tools/getDiagnostics.d.ts +1 -0
- package/dist/tools/getDiffFromHandoff.d.ts +1 -0
- package/dist/tools/getDocumentSymbols.d.ts +25 -0
- package/dist/tools/getDocumentSymbols.js +74 -8
- package/dist/tools/getDocumentSymbols.js.map +1 -1
- package/dist/tools/getFileTree.d.ts +1 -0
- package/dist/tools/getGitDiff.d.ts +1 -0
- package/dist/tools/getGitHotspots.d.ts +1 -0
- package/dist/tools/getGitLog.d.ts +1 -0
- package/dist/tools/getGitStatus.d.ts +1 -0
- package/dist/tools/getImportTree.d.ts +1 -0
- package/dist/tools/getImportedSignatures.d.ts +1 -0
- package/dist/tools/getOpenEditors.d.ts +1 -0
- package/dist/tools/getPRTemplate.d.ts +1 -0
- package/dist/tools/getProjectContext.d.ts +1 -0
- package/dist/tools/getProjectInfo.d.ts +1 -0
- package/dist/tools/getSecurityAdvisories.d.ts +1 -0
- package/dist/tools/getSecurityAdvisories.js +10 -1
- package/dist/tools/getSecurityAdvisories.js.map +1 -1
- package/dist/tools/getSessionUsage.d.ts +4 -0
- package/dist/tools/getSessionUsage.js +3 -0
- package/dist/tools/getSessionUsage.js.map +1 -1
- package/dist/tools/getSymbolHistory.d.ts +1 -0
- package/dist/tools/getToolCapabilities.d.ts +1 -0
- package/dist/tools/getTypeSignature.d.ts +1 -0
- package/dist/tools/getWorkspaceFolders.d.ts +1 -0
- package/dist/tools/getWorkspaceSettings.d.ts +1 -0
- package/dist/tools/gitHistory.d.ts +2 -0
- package/dist/tools/gitWrite.d.ts +11 -0
- package/dist/tools/github/actions.d.ts +2 -0
- package/dist/tools/github/actions.js +4 -2
- package/dist/tools/github/actions.js.map +1 -1
- package/dist/tools/github/composite.d.ts +342 -0
- package/dist/tools/github/composite.js +343 -0
- package/dist/tools/github/composite.js.map +1 -0
- package/dist/tools/github/index.d.ts +1 -0
- package/dist/tools/github/index.js +1 -0
- package/dist/tools/github/index.js.map +1 -1
- package/dist/tools/github/issues.d.ts +4 -0
- package/dist/tools/github/issues.js +8 -4
- package/dist/tools/github/issues.js.map +1 -1
- package/dist/tools/github/pr.d.ts +7 -0
- package/dist/tools/github/pr.js +50 -12
- package/dist/tools/github/pr.js.map +1 -1
- package/dist/tools/handoffNote.d.ts +4 -0
- package/dist/tools/handoffNote.js +2 -0
- package/dist/tools/handoffNote.js.map +1 -1
- package/dist/tools/hoverAtCursor.d.ts +1 -0
- package/dist/tools/httpClient.d.ts +2 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +47 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/inlayHints.d.ts +1 -0
- package/dist/tools/launchQuickTask.d.ts +2 -0
- package/dist/tools/launchQuickTask.js +1 -0
- package/dist/tools/launchQuickTask.js.map +1 -1
- package/dist/tools/listClaudeTasks.d.ts +2 -0
- package/dist/tools/listClaudeTasks.js +1 -0
- package/dist/tools/listClaudeTasks.js.map +1 -1
- package/dist/tools/listTerminals.d.ts +1 -0
- package/dist/tools/lsp.d.ts +14 -0
- package/dist/tools/navigateToSymbolByName.d.ts +1 -0
- package/dist/tools/openDiff.d.ts +1 -0
- package/dist/tools/openFile.d.ts +1 -0
- package/dist/tools/openInBrowser.d.ts +1 -0
- package/dist/tools/organizeImports.d.ts +1 -0
- package/dist/tools/performanceReport.d.ts +1 -0
- package/dist/tools/planPersistence.d.ts +5 -0
- package/dist/tools/previewEdit.d.ts +1 -0
- package/dist/tools/refactorAnalyze.d.ts +1 -0
- package/dist/tools/refactorPreview.d.ts +2 -0
- package/dist/tools/refactorPreview.js +1 -0
- package/dist/tools/refactorPreview.js.map +1 -1
- package/dist/tools/replaceBlock.d.ts +1 -0
- package/dist/tools/resumeClaudeTask.d.ts +2 -0
- package/dist/tools/resumeClaudeTask.js +1 -0
- package/dist/tools/resumeClaudeTask.js.map +1 -1
- package/dist/tools/runClaudeTask.d.ts +2 -0
- package/dist/tools/runClaudeTask.js +1 -0
- package/dist/tools/runClaudeTask.js.map +1 -1
- package/dist/tools/runCommand.d.ts +1 -0
- package/dist/tools/runTests.d.ts +1 -0
- package/dist/tools/saveDocument.d.ts +1 -0
- package/dist/tools/screenshotAndAnnotate.d.ts +1 -0
- package/dist/tools/searchAndReplace.d.ts +1 -0
- package/dist/tools/searchTools.d.ts +1 -0
- package/dist/tools/searchTools.js +1 -1
- package/dist/tools/searchTools.js.map +1 -1
- package/dist/tools/searchWorkspace.d.ts +1 -0
- package/dist/tools/selectionRanges.d.ts +1 -0
- package/dist/tools/semanticTokens.d.ts +1 -0
- package/dist/tools/setActiveWorkspaceFolder.d.ts +1 -0
- package/dist/tools/signatureHelp.d.ts +1 -0
- package/dist/tools/slackListChannels.d.ts +1 -0
- package/dist/tools/slackListChannels.js.map +1 -1
- package/dist/tools/slackPostMessage.d.ts +1 -0
- package/dist/tools/slackPostMessage.js +11 -6
- package/dist/tools/slackPostMessage.js.map +1 -1
- package/dist/tools/terminal.d.ts +6 -0
- package/dist/tools/testTraceToSource.d.ts +1 -0
- package/dist/tools/testTraceToSource.js +2 -2
- package/dist/tools/testTraceToSource.js.map +1 -1
- package/dist/tools/transaction.d.ts +23 -0
- package/dist/tools/transaction.js +29 -0
- package/dist/tools/transaction.js.map +1 -1
- package/dist/tools/typeHierarchy.d.ts +1 -0
- package/dist/tools/updateLinearIssue.d.ts +1 -0
- package/dist/tools/updateLinearIssue.js +20 -6
- package/dist/tools/updateLinearIssue.js.map +1 -1
- package/dist/tools/utils.d.ts +2 -0
- package/dist/tools/utils.js.map +1 -1
- package/dist/tools/vscodeCommands.d.ts +2 -0
- package/dist/tools/vscodeTasks.d.ts +2 -0
- package/dist/tools/workspaceSettings.d.ts +1 -0
- package/dist/traceEncryption.d.ts +46 -0
- package/dist/traceEncryption.js +124 -0
- package/dist/traceEncryption.js.map +1 -0
- package/dist/transport.d.ts +46 -1
- package/dist/transport.js +173 -19
- package/dist/transport.js.map +1 -1
- package/package.json +30 -8
- package/scripts/mcp-stdio-shim.cjs +19 -3
- package/scripts/start-all.sh +30 -1
- package/templates/automation-policies/recipe-authoring.json +25 -0
- package/templates/automation-policy.example.json +6 -0
- package/templates/co.patchwork-os.bridge.plist +34 -0
- package/templates/policies/README.md +72 -0
- package/templates/policies/conservative.json +14 -0
- package/templates/policies/developer.json +14 -0
- package/templates/policies/headless-ci.json +24 -0
- package/templates/policies/personal-assistant.json +15 -0
- package/templates/policies/regulated-industry.json +18 -0
- package/templates/recipes/lint-on-save.yaml +1 -2
- package/templates/recipes/morning-brief-slack.yaml +57 -0
- package/templates/recipes/morning-brief.yaml +2 -2
- package/templates/recipes/project-health-check.yaml +50 -0
- package/templates/recipes/webhook/README.md +70 -0
- package/templates/recipes/webhook/capture-thought.yaml +26 -0
- package/templates/recipes/webhook/customer-escalation.yaml +49 -0
- package/templates/recipes/webhook/incident-intake.yaml +46 -0
- package/templates/recipes/webhook/meeting-prep.yaml +48 -0
- package/templates/recipes/webhook/morning-brief.yaml +57 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace bundle encryption/decryption — AES-256-GCM with scrypt KDF.
|
|
3
|
+
*
|
|
4
|
+
* Binary format (all multi-byte values big-endian):
|
|
5
|
+
*
|
|
6
|
+
* Offset Len Field
|
|
7
|
+
* 0 8 Magic: ASCII "PWTRACE\0"
|
|
8
|
+
* 8 1 Version: 0x01
|
|
9
|
+
* 9 16 Salt (random, for scrypt)
|
|
10
|
+
* 25 12 IV / nonce (random, for AES-GCM)
|
|
11
|
+
* 37 16 GCM authentication tag
|
|
12
|
+
* 53 N Ciphertext (the original .jsonl.gz bytes)
|
|
13
|
+
*
|
|
14
|
+
* Key derivation: scrypt(passphrase, salt, N=16384, r=8, p=1, keyLen=32).
|
|
15
|
+
* N=2^14 matches Node's `crypto.scryptSync` default and is safe for
|
|
16
|
+
* interactive use on a modern laptop (~50ms, 16MB RAM). They are stored implicitly
|
|
17
|
+
* (fixed); changing them is a version bump.
|
|
18
|
+
*
|
|
19
|
+
* Security properties:
|
|
20
|
+
* - Unique salt per export → unique key per file even with the same passphrase.
|
|
21
|
+
* - GCM authentication tag → any tamper of ciphertext or header is detected.
|
|
22
|
+
* - scrypt → GPU-resistant brute-force on passphrase.
|
|
23
|
+
* - Buffer.fill(0) on key material after use → minimise in-process lifetime.
|
|
24
|
+
*
|
|
25
|
+
* The encrypted file is NOT gzip-compressed on top (the plaintext already
|
|
26
|
+
* is). Compressing ciphertext adds no size benefit and obscures the magic
|
|
27
|
+
* header used by the import command to auto-detect the format.
|
|
28
|
+
*/
|
|
29
|
+
import { createCipheriv, createDecipheriv, randomBytes, scryptSync, } from "node:crypto";
|
|
30
|
+
export const TRACE_ENCRYPT_MAGIC = Buffer.from("PWTRACE\0", "ascii");
|
|
31
|
+
export const TRACE_ENCRYPT_VERSION = 0x01;
|
|
32
|
+
const SALT_LEN = 16;
|
|
33
|
+
const IV_LEN = 12;
|
|
34
|
+
const TAG_LEN = 16;
|
|
35
|
+
const HEADER_LEN = TRACE_ENCRYPT_MAGIC.length + 1 + SALT_LEN + IV_LEN + TAG_LEN; // 53
|
|
36
|
+
const SCRYPT_N = 16384; // 2^14 — Node scryptSync default; needs 128*N*r = 16MB RAM
|
|
37
|
+
const SCRYPT_R = 8;
|
|
38
|
+
const SCRYPT_P = 1;
|
|
39
|
+
const KEY_LEN = 32;
|
|
40
|
+
function deriveKey(passphrase, salt) {
|
|
41
|
+
return scryptSync(passphrase, salt, KEY_LEN, {
|
|
42
|
+
N: SCRYPT_N,
|
|
43
|
+
r: SCRYPT_R,
|
|
44
|
+
p: SCRYPT_P,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Encrypt a Buffer (the gzip-compressed trace bundle) with a passphrase.
|
|
49
|
+
* Returns a new Buffer in the wire format described above.
|
|
50
|
+
*/
|
|
51
|
+
export function encryptTraceBundle(plaintext, passphrase) {
|
|
52
|
+
const salt = randomBytes(SALT_LEN);
|
|
53
|
+
const iv = randomBytes(IV_LEN);
|
|
54
|
+
const key = deriveKey(passphrase, salt);
|
|
55
|
+
try {
|
|
56
|
+
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
57
|
+
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
58
|
+
const tag = cipher.getAuthTag();
|
|
59
|
+
const header = Buffer.alloc(HEADER_LEN);
|
|
60
|
+
let offset = 0;
|
|
61
|
+
TRACE_ENCRYPT_MAGIC.copy(header, offset);
|
|
62
|
+
offset += TRACE_ENCRYPT_MAGIC.length;
|
|
63
|
+
header[offset++] = TRACE_ENCRYPT_VERSION;
|
|
64
|
+
salt.copy(header, offset);
|
|
65
|
+
offset += SALT_LEN;
|
|
66
|
+
iv.copy(header, offset);
|
|
67
|
+
offset += IV_LEN;
|
|
68
|
+
tag.copy(header, offset);
|
|
69
|
+
return Buffer.concat([header, encrypted]);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
key.fill(0);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Decrypt a Buffer that was produced by `encryptTraceBundle`.
|
|
77
|
+
* Returns the original plaintext (the gzip-compressed trace bundle).
|
|
78
|
+
* Throws if the magic, version, or GCM tag don't match.
|
|
79
|
+
*/
|
|
80
|
+
export function decryptTraceBundle(ciphertext, passphrase) {
|
|
81
|
+
if (ciphertext.length < HEADER_LEN) {
|
|
82
|
+
throw new Error("Trace bundle too short to be a valid encrypted file");
|
|
83
|
+
}
|
|
84
|
+
const magic = ciphertext.subarray(0, TRACE_ENCRYPT_MAGIC.length);
|
|
85
|
+
if (!magic.equals(TRACE_ENCRYPT_MAGIC)) {
|
|
86
|
+
throw new Error("Not an encrypted Patchwork trace bundle (magic mismatch)");
|
|
87
|
+
}
|
|
88
|
+
const version = ciphertext[TRACE_ENCRYPT_MAGIC.length];
|
|
89
|
+
if (version !== TRACE_ENCRYPT_VERSION) {
|
|
90
|
+
throw new Error(`Unsupported encrypted bundle version: 0x${version?.toString(16) ?? "??"} (expected 0x01)`);
|
|
91
|
+
}
|
|
92
|
+
let offset = TRACE_ENCRYPT_MAGIC.length + 1;
|
|
93
|
+
const salt = ciphertext.subarray(offset, offset + SALT_LEN);
|
|
94
|
+
offset += SALT_LEN;
|
|
95
|
+
const iv = ciphertext.subarray(offset, offset + IV_LEN);
|
|
96
|
+
offset += IV_LEN;
|
|
97
|
+
const tag = ciphertext.subarray(offset, offset + TAG_LEN);
|
|
98
|
+
offset += TAG_LEN;
|
|
99
|
+
const encrypted = ciphertext.subarray(offset);
|
|
100
|
+
const key = deriveKey(passphrase, salt);
|
|
101
|
+
try {
|
|
102
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
103
|
+
decipher.setAuthTag(tag);
|
|
104
|
+
return Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new Error("Decryption failed — wrong passphrase or corrupted file");
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
key.fill(0);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Returns true if the buffer starts with the encrypted trace bundle magic.
|
|
115
|
+
* Use this to auto-detect encrypted bundles at import time.
|
|
116
|
+
*/
|
|
117
|
+
export function isEncryptedTraceBundle(buf) {
|
|
118
|
+
if (buf.length < TRACE_ENCRYPT_MAGIC.length)
|
|
119
|
+
return false;
|
|
120
|
+
return buf
|
|
121
|
+
.subarray(0, TRACE_ENCRYPT_MAGIC.length)
|
|
122
|
+
.equals(TRACE_ENCRYPT_MAGIC);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=traceEncryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traceEncryption.js","sourceRoot":"","sources":["../src/traceEncryption.ts"],"names":[],"mappings":"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"}
|
package/dist/transport.d.ts
CHANGED
|
@@ -49,6 +49,15 @@ export declare class McpTransport {
|
|
|
49
49
|
private activeListener;
|
|
50
50
|
private inFlightControllers;
|
|
51
51
|
private inFlightToolNames;
|
|
52
|
+
/**
|
|
53
|
+
* Snapshot of in-flight tool-call ids captured at `detachSoft()` time.
|
|
54
|
+
* Used by the per-call `finally` clause to clean up `inFlightControllers`
|
|
55
|
+
* + `activeToolCalls` even after attach() bumped `this.generation`. Without
|
|
56
|
+
* this set, an old-gen tool that settles after grace-period reattach would
|
|
57
|
+
* leak its slot in inFlightControllers AND its activeToolCalls count,
|
|
58
|
+
* which in turn makes HTTP eviction skip the session forever.
|
|
59
|
+
*/
|
|
60
|
+
private detachSoftInflight;
|
|
52
61
|
/** Pending elicitation/create requests waiting for a client response. */
|
|
53
62
|
private pendingElicitations;
|
|
54
63
|
private initialized;
|
|
@@ -57,6 +66,13 @@ export declare class McpTransport {
|
|
|
57
66
|
private activeToolCalls;
|
|
58
67
|
private callCount;
|
|
59
68
|
private errorCount;
|
|
69
|
+
/**
|
|
70
|
+
* Tool calls rejected/expired by the human approval gate. Tracked
|
|
71
|
+
* separately from errorCount so dashboard stats and getSessionUsage can
|
|
72
|
+
* distinguish "human said no" from "tool blew up". Rejections never
|
|
73
|
+
* increment errorCount and never produce a tool-stats entry.
|
|
74
|
+
*/
|
|
75
|
+
private approvalRejectionCount;
|
|
60
76
|
private generation;
|
|
61
77
|
private readonly sessionStartedAt;
|
|
62
78
|
private readonly resultSizeTracker;
|
|
@@ -78,8 +94,12 @@ export declare class McpTransport {
|
|
|
78
94
|
private readonly ajv;
|
|
79
95
|
private readonly schemaValidators;
|
|
80
96
|
private readonly outputValidators;
|
|
81
|
-
/** Cached wire-schema array for tools/list. Invalidated on any tool registration change. */
|
|
97
|
+
/** Cached wire-schema array for tools/list (full mode). Invalidated on any tool registration change. */
|
|
82
98
|
private wireSchemaCache;
|
|
99
|
+
/** Cached wire-schema array for tools/list in lazy mode (inputSchema stripped). */
|
|
100
|
+
private wireSchemaCacheLazy;
|
|
101
|
+
/** When true, tools/list omits inputSchema. Clients must call tools/schema before tools/call. */
|
|
102
|
+
private lazyTools;
|
|
83
103
|
/** Per-session tool-call rate limit (calls/minute). 0 = disabled. */
|
|
84
104
|
private toolRateLimit;
|
|
85
105
|
/**
|
|
@@ -112,6 +132,8 @@ export declare class McpTransport {
|
|
|
112
132
|
* Called at HTTP session initialize time from X-Bridge-Deny-Tools header.
|
|
113
133
|
*/
|
|
114
134
|
setDenyTools(tools: Set<string>): void;
|
|
135
|
+
/** Enable lazy-tools mode: tools/list omits inputSchema; clients use tools/schema to fetch it. */
|
|
136
|
+
setLazyTools(enabled: boolean): void;
|
|
115
137
|
/** Configure per-session tool call rate limiting (calls/minute, 0 = disabled). */
|
|
116
138
|
setToolRateLimit(limit: number): void;
|
|
117
139
|
/**
|
|
@@ -173,10 +195,33 @@ export declare class McpTransport {
|
|
|
173
195
|
/** Remove all tools whose name starts with `prefix`. Returns count removed. */
|
|
174
196
|
deregisterTool(name: string): boolean;
|
|
175
197
|
deregisterToolsByPrefix(prefix: string): number;
|
|
198
|
+
/**
|
|
199
|
+
* Soft cleanup of stale per-connection state, used by the bridge's
|
|
200
|
+
* grace-period resumption path BEFORE calling `attach(ws)` with a new
|
|
201
|
+
* WebSocket. Unlike `detach()`, this does NOT abort in-flight tool calls
|
|
202
|
+
* or zero `activeToolCalls` — grace-period semantics preserve those
|
|
203
|
+
* across the reconnect. It only:
|
|
204
|
+
*
|
|
205
|
+
* 1. Removes the old WebSocket's "message" listener so it can't fire
|
|
206
|
+
* against the new connection's state.
|
|
207
|
+
* 2. Rejects any pending elicitation requests, because the original
|
|
208
|
+
* client that issued them may not be the one reattaching, and an
|
|
209
|
+
* unrelated client should not be allowed to answer another client's
|
|
210
|
+
* elicitation by id collision.
|
|
211
|
+
*
|
|
212
|
+
* Without this, two leaks survive a resumption:
|
|
213
|
+
* - The old `ws.on("message", ...)` listener accumulates (gen-guarded
|
|
214
|
+
* so it no-ops, but still attached to the now-closed socket).
|
|
215
|
+
* - `pendingElicitations` from the old connection persist in the map;
|
|
216
|
+
* the elicit timer keeps ticking and resolving against the NEW
|
|
217
|
+
* `activeWs`, surfacing prompts to a client that didn't request them.
|
|
218
|
+
*/
|
|
219
|
+
detachSoft(): void;
|
|
176
220
|
detach(): void;
|
|
177
221
|
getStats(): {
|
|
178
222
|
callCount: number;
|
|
179
223
|
errorCount: number;
|
|
224
|
+
approvalRejectionCount: number;
|
|
180
225
|
activeToolCalls: number;
|
|
181
226
|
inFlightTools: string[];
|
|
182
227
|
startedAt: number;
|
package/dist/transport.js
CHANGED
|
@@ -41,6 +41,15 @@ export class McpTransport {
|
|
|
41
41
|
activeListener = null;
|
|
42
42
|
inFlightControllers = new Map();
|
|
43
43
|
inFlightToolNames = new Map();
|
|
44
|
+
/**
|
|
45
|
+
* Snapshot of in-flight tool-call ids captured at `detachSoft()` time.
|
|
46
|
+
* Used by the per-call `finally` clause to clean up `inFlightControllers`
|
|
47
|
+
* + `activeToolCalls` even after attach() bumped `this.generation`. Without
|
|
48
|
+
* this set, an old-gen tool that settles after grace-period reattach would
|
|
49
|
+
* leak its slot in inFlightControllers AND its activeToolCalls count,
|
|
50
|
+
* which in turn makes HTTP eviction skip the session forever.
|
|
51
|
+
*/
|
|
52
|
+
detachSoftInflight = new Set();
|
|
44
53
|
/** Pending elicitation/create requests waiting for a client response. */
|
|
45
54
|
pendingElicitations = new Map();
|
|
46
55
|
initialized = false;
|
|
@@ -49,6 +58,13 @@ export class McpTransport {
|
|
|
49
58
|
activeToolCalls = 0;
|
|
50
59
|
callCount = 0;
|
|
51
60
|
errorCount = 0;
|
|
61
|
+
/**
|
|
62
|
+
* Tool calls rejected/expired by the human approval gate. Tracked
|
|
63
|
+
* separately from errorCount so dashboard stats and getSessionUsage can
|
|
64
|
+
* distinguish "human said no" from "tool blew up". Rejections never
|
|
65
|
+
* increment errorCount and never produce a tool-stats entry.
|
|
66
|
+
*/
|
|
67
|
+
approvalRejectionCount = 0;
|
|
52
68
|
generation = 0; // incremented on each attach; stale handlers check this
|
|
53
69
|
sessionStartedAt = Date.now();
|
|
54
70
|
resultSizeTracker = new Map();
|
|
@@ -72,8 +88,12 @@ export class McpTransport {
|
|
|
72
88
|
ajv = new Ajv({ strict: false, allErrors: true });
|
|
73
89
|
schemaValidators = new Map();
|
|
74
90
|
outputValidators = new Map();
|
|
75
|
-
/** Cached wire-schema array for tools/list. Invalidated on any tool registration change. */
|
|
91
|
+
/** Cached wire-schema array for tools/list (full mode). Invalidated on any tool registration change. */
|
|
76
92
|
wireSchemaCache = null;
|
|
93
|
+
/** Cached wire-schema array for tools/list in lazy mode (inputSchema stripped). */
|
|
94
|
+
wireSchemaCacheLazy = null;
|
|
95
|
+
/** When true, tools/list omits inputSchema. Clients must call tools/schema before tools/call. */
|
|
96
|
+
lazyTools = false;
|
|
77
97
|
/** Per-session tool-call rate limit (calls/minute). 0 = disabled. */
|
|
78
98
|
toolRateLimit = 60;
|
|
79
99
|
/**
|
|
@@ -113,6 +133,10 @@ export class McpTransport {
|
|
|
113
133
|
setDenyTools(tools) {
|
|
114
134
|
this.denyTools = tools;
|
|
115
135
|
}
|
|
136
|
+
/** Enable lazy-tools mode: tools/list omits inputSchema; clients use tools/schema to fetch it. */
|
|
137
|
+
setLazyTools(enabled) {
|
|
138
|
+
this.lazyTools = enabled;
|
|
139
|
+
}
|
|
116
140
|
/** Configure per-session tool call rate limiting (calls/minute, 0 = disabled). */
|
|
117
141
|
setToolRateLimit(limit) {
|
|
118
142
|
this.toolRateLimit = limit;
|
|
@@ -281,6 +305,7 @@ export class McpTransport {
|
|
|
281
305
|
this.schemaValidators.delete(schema.name);
|
|
282
306
|
this.outputValidators.delete(schema.name);
|
|
283
307
|
this.wireSchemaCache = null;
|
|
308
|
+
this.wireSchemaCacheLazy = null;
|
|
284
309
|
this.tools.set(schema.name, {
|
|
285
310
|
schema,
|
|
286
311
|
handler,
|
|
@@ -292,6 +317,7 @@ export class McpTransport {
|
|
|
292
317
|
this.schemaValidators.delete(name);
|
|
293
318
|
this.outputValidators.delete(name);
|
|
294
319
|
this.wireSchemaCache = null;
|
|
320
|
+
this.wireSchemaCacheLazy = null;
|
|
295
321
|
return this.tools.delete(name);
|
|
296
322
|
}
|
|
297
323
|
deregisterToolsByPrefix(prefix) {
|
|
@@ -306,10 +332,51 @@ export class McpTransport {
|
|
|
306
332
|
count++;
|
|
307
333
|
}
|
|
308
334
|
}
|
|
309
|
-
if (count > 0)
|
|
335
|
+
if (count > 0) {
|
|
310
336
|
this.wireSchemaCache = null;
|
|
337
|
+
this.wireSchemaCacheLazy = null;
|
|
338
|
+
}
|
|
311
339
|
return count;
|
|
312
340
|
}
|
|
341
|
+
/**
|
|
342
|
+
* Soft cleanup of stale per-connection state, used by the bridge's
|
|
343
|
+
* grace-period resumption path BEFORE calling `attach(ws)` with a new
|
|
344
|
+
* WebSocket. Unlike `detach()`, this does NOT abort in-flight tool calls
|
|
345
|
+
* or zero `activeToolCalls` — grace-period semantics preserve those
|
|
346
|
+
* across the reconnect. It only:
|
|
347
|
+
*
|
|
348
|
+
* 1. Removes the old WebSocket's "message" listener so it can't fire
|
|
349
|
+
* against the new connection's state.
|
|
350
|
+
* 2. Rejects any pending elicitation requests, because the original
|
|
351
|
+
* client that issued them may not be the one reattaching, and an
|
|
352
|
+
* unrelated client should not be allowed to answer another client's
|
|
353
|
+
* elicitation by id collision.
|
|
354
|
+
*
|
|
355
|
+
* Without this, two leaks survive a resumption:
|
|
356
|
+
* - The old `ws.on("message", ...)` listener accumulates (gen-guarded
|
|
357
|
+
* so it no-ops, but still attached to the now-closed socket).
|
|
358
|
+
* - `pendingElicitations` from the old connection persist in the map;
|
|
359
|
+
* the elicit timer keeps ticking and resolving against the NEW
|
|
360
|
+
* `activeWs`, surfacing prompts to a client that didn't request them.
|
|
361
|
+
*/
|
|
362
|
+
detachSoft() {
|
|
363
|
+
if (this.activeWs && this.activeListener) {
|
|
364
|
+
this.activeWs.removeListener("message", this.activeListener);
|
|
365
|
+
this.activeListener = null;
|
|
366
|
+
}
|
|
367
|
+
for (const [, pending] of this.pendingElicitations) {
|
|
368
|
+
pending.reject(new Error("Client disconnected before responding to elicitation"));
|
|
369
|
+
}
|
|
370
|
+
this.pendingElicitations.clear();
|
|
371
|
+
// Snapshot in-flight ids so the per-call finally can clean them up after
|
|
372
|
+
// attach() flips `this.generation`. Merge into the existing set rather
|
|
373
|
+
// than replacing it — multiple back-to-back grace-period reconnects can
|
|
374
|
+
// leave several "old" generations of tool calls in flight, and a later
|
|
375
|
+
// detachSoft must not lose ids carried over from an earlier one.
|
|
376
|
+
for (const id of this.inFlightControllers.keys()) {
|
|
377
|
+
this.detachSoftInflight.add(id);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
313
380
|
detach() {
|
|
314
381
|
// Remove listener from old WebSocket to prevent accumulation
|
|
315
382
|
if (this.activeWs && this.activeListener) {
|
|
@@ -322,6 +389,9 @@ export class McpTransport {
|
|
|
322
389
|
}
|
|
323
390
|
this.inFlightControllers.clear();
|
|
324
391
|
this.inFlightToolNames.clear();
|
|
392
|
+
// Hard detach also drops any pending detachSoft snapshot — those calls
|
|
393
|
+
// are aborted, their finally clauses can no longer leak.
|
|
394
|
+
this.detachSoftInflight.clear();
|
|
325
395
|
// Reject all pending elicitation requests so callers don't hang after disconnect
|
|
326
396
|
for (const [, pending] of this.pendingElicitations) {
|
|
327
397
|
pending.reject(new Error("Client disconnected before responding to elicitation"));
|
|
@@ -342,6 +412,7 @@ export class McpTransport {
|
|
|
342
412
|
return {
|
|
343
413
|
callCount: this.callCount,
|
|
344
414
|
errorCount: this.errorCount,
|
|
415
|
+
approvalRejectionCount: this.approvalRejectionCount,
|
|
345
416
|
activeToolCalls: this.activeToolCalls,
|
|
346
417
|
inFlightTools: [...this.inFlightToolNames.values()],
|
|
347
418
|
startedAt: this.sessionStartedAt,
|
|
@@ -363,6 +434,7 @@ export class McpTransport {
|
|
|
363
434
|
}
|
|
364
435
|
// Invalidate wire cache — categories are stripped but getToolSchemas reads them
|
|
365
436
|
this.wireSchemaCache = null;
|
|
437
|
+
this.wireSchemaCacheLazy = null;
|
|
366
438
|
}
|
|
367
439
|
/** Returns all registered tool schemas — used by searchTools for keyword/category discovery. */
|
|
368
440
|
getToolSchemas() {
|
|
@@ -608,15 +680,33 @@ export class McpTransport {
|
|
|
608
680
|
};
|
|
609
681
|
break;
|
|
610
682
|
}
|
|
611
|
-
if (
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
683
|
+
if (this.lazyTools) {
|
|
684
|
+
// Lazy mode: strip inputSchema from wire response.
|
|
685
|
+
// Clients must call tools/schema to fetch the full schema before tools/call.
|
|
686
|
+
if (!this.wireSchemaCacheLazy) {
|
|
687
|
+
this.wireSchemaCacheLazy = Array.from(this.tools.values()).map((t) => {
|
|
688
|
+
// Strip internal-only fields AND inputSchema in lazy mode.
|
|
689
|
+
// cache_control is intentionally NOT stripped — it passes through to clients.
|
|
690
|
+
const { extensionRequired: _ext, timeoutMs: _timeout, categories: _cat, outputSchema: _outputSchema, inputSchema: _inputSchema, ...wireSchema } = t.schema;
|
|
691
|
+
return wireSchema;
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
else {
|
|
696
|
+
if (!this.wireSchemaCache) {
|
|
697
|
+
this.wireSchemaCache = Array.from(this.tools.values()).map((t) => {
|
|
698
|
+
// Strip internal-only fields before sending on the wire.
|
|
699
|
+
// cache_control is intentionally NOT stripped — it passes through to clients.
|
|
700
|
+
const { extensionRequired: _ext, timeoutMs: _timeout, categories: _cat, outputSchema: _outputSchema, ...wireSchema } = t.schema;
|
|
701
|
+
return wireSchema;
|
|
702
|
+
});
|
|
703
|
+
}
|
|
618
704
|
}
|
|
619
|
-
const allTools = this.
|
|
705
|
+
const allTools = this.lazyTools
|
|
706
|
+
? // biome-ignore lint/style/noNonNullAssertion: built above
|
|
707
|
+
this.wireSchemaCacheLazy
|
|
708
|
+
: // biome-ignore lint/style/noNonNullAssertion: built above
|
|
709
|
+
this.wireSchemaCache;
|
|
620
710
|
// Parse cursor (opaque base64-encoded decimal offset)
|
|
621
711
|
const listParams = msg.params;
|
|
622
712
|
let offset = 0;
|
|
@@ -649,6 +739,48 @@ export class McpTransport {
|
|
|
649
739
|
};
|
|
650
740
|
break;
|
|
651
741
|
}
|
|
742
|
+
case "tools/schema": {
|
|
743
|
+
// Fetch full schema for a single tool by name.
|
|
744
|
+
// Always available regardless of lazyTools mode.
|
|
745
|
+
// Schema validation uses in-memory schema regardless of lazyTools mode.
|
|
746
|
+
const schemaParams = msg.params;
|
|
747
|
+
if (typeof schemaParams?.name !== "string" || !schemaParams.name) {
|
|
748
|
+
response = {
|
|
749
|
+
jsonrpc: "2.0",
|
|
750
|
+
id: msg.id,
|
|
751
|
+
error: {
|
|
752
|
+
code: ErrorCodes.INVALID_PARAMS,
|
|
753
|
+
message: 'Missing required param: "name"',
|
|
754
|
+
},
|
|
755
|
+
};
|
|
756
|
+
break;
|
|
757
|
+
}
|
|
758
|
+
const toolEntry = this.tools.get(schemaParams.name);
|
|
759
|
+
if (!toolEntry) {
|
|
760
|
+
response = {
|
|
761
|
+
jsonrpc: "2.0",
|
|
762
|
+
id: msg.id,
|
|
763
|
+
error: {
|
|
764
|
+
code: ErrorCodes.METHOD_NOT_FOUND,
|
|
765
|
+
message: `Tool not found: ${schemaParams.name}`,
|
|
766
|
+
},
|
|
767
|
+
};
|
|
768
|
+
break;
|
|
769
|
+
}
|
|
770
|
+
response = {
|
|
771
|
+
jsonrpc: "2.0",
|
|
772
|
+
id: msg.id,
|
|
773
|
+
result: {
|
|
774
|
+
name: toolEntry.schema.name,
|
|
775
|
+
description: toolEntry.schema.description,
|
|
776
|
+
inputSchema: toolEntry.schema.inputSchema,
|
|
777
|
+
...(toolEntry.schema.outputSchema !== undefined && {
|
|
778
|
+
outputSchema: toolEntry.schema.outputSchema,
|
|
779
|
+
}),
|
|
780
|
+
},
|
|
781
|
+
};
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
652
784
|
case "tools/call": {
|
|
653
785
|
if (!this.initialized) {
|
|
654
786
|
response = {
|
|
@@ -832,7 +964,11 @@ export class McpTransport {
|
|
|
832
964
|
};
|
|
833
965
|
}
|
|
834
966
|
else {
|
|
835
|
-
|
|
967
|
+
// startTime is captured AFTER the approval gate (below) so that
|
|
968
|
+
// human-decision wait time is excluded from tool stats. Capturing
|
|
969
|
+
// it here would inflate avgDurationMs / p95 / p99 by the entire
|
|
970
|
+
// approval wait — see fix for approval-gate stats pollution bug.
|
|
971
|
+
let startTime = 0;
|
|
836
972
|
const callId = Math.random().toString(36).slice(2, 10);
|
|
837
973
|
const callLog = this.logger.child({ tool: params.name, callId });
|
|
838
974
|
let timedOut = false;
|
|
@@ -874,7 +1010,8 @@ export class McpTransport {
|
|
|
874
1010
|
// schemas use additionalProperties:false, so leaving it in causes
|
|
875
1011
|
// AJV to reject the call with -32602.
|
|
876
1012
|
const { _meta: _stripped, ...toolArgs } = rawArgs;
|
|
877
|
-
//
|
|
1013
|
+
// Schema validation uses in-memory schema regardless of lazyTools mode.
|
|
1014
|
+
// AJV compiles from tool.schema.inputSchema, not from the wire response.
|
|
878
1015
|
const validate = this.getValidator(params.name);
|
|
879
1016
|
if (validate && !validate(toolArgs)) {
|
|
880
1017
|
this.callCount++;
|
|
@@ -923,8 +1060,15 @@ export class McpTransport {
|
|
|
923
1060
|
this.activeToolCalls--;
|
|
924
1061
|
this.inFlightToolNames.delete(msg.id);
|
|
925
1062
|
this.inFlightControllers.delete(msg.id);
|
|
926
|
-
|
|
927
|
-
|
|
1063
|
+
// Approval rejections/expiries are NOT tool failures — track
|
|
1064
|
+
// them on a dedicated counter and record a lifecycle event
|
|
1065
|
+
// (not a tool entry) so stats() avg/p95/p99 stay clean.
|
|
1066
|
+
this.approvalRejectionCount++;
|
|
1067
|
+
this.activityLog?.recordEvent("approval_rejected", {
|
|
1068
|
+
tool: params.name,
|
|
1069
|
+
decision,
|
|
1070
|
+
sessionId: this.sessionId ?? undefined,
|
|
1071
|
+
});
|
|
928
1072
|
response = {
|
|
929
1073
|
jsonrpc: "2.0",
|
|
930
1074
|
id: msg.id,
|
|
@@ -943,6 +1087,10 @@ export class McpTransport {
|
|
|
943
1087
|
break;
|
|
944
1088
|
}
|
|
945
1089
|
}
|
|
1090
|
+
// Start the duration clock now — AFTER the approval gate has
|
|
1091
|
+
// resolved — so stats reflect actual tool execution time, not
|
|
1092
|
+
// the time the human spent thinking about the approval.
|
|
1093
|
+
startTime = Date.now();
|
|
946
1094
|
try {
|
|
947
1095
|
const effectiveTimeout = tool.timeoutMs ?? TOOL_TIMEOUT_MS;
|
|
948
1096
|
const timeoutPromise = new Promise((_, reject) => {
|
|
@@ -1024,11 +1172,17 @@ export class McpTransport {
|
|
|
1024
1172
|
finally {
|
|
1025
1173
|
if (timeoutHandle !== undefined)
|
|
1026
1174
|
clearTimeout(timeoutHandle);
|
|
1027
|
-
// Only touch shared state if we're still on the same generation
|
|
1028
|
-
//
|
|
1029
|
-
//
|
|
1030
|
-
//
|
|
1031
|
-
|
|
1175
|
+
// Only touch shared state if we're still on the same generation,
|
|
1176
|
+
// OR if this id was snapshotted by detachSoft() (grace-period
|
|
1177
|
+
// resumption). detach() clears inFlightControllers and resets
|
|
1178
|
+
// activeToolCalls for hard reconnects; an orphaned finally
|
|
1179
|
+
// from a previous generation must not delete the new session's
|
|
1180
|
+
// controller or skew its counter — UNLESS detachSoft preserved
|
|
1181
|
+
// this id, in which case its slot in inFlightControllers and
|
|
1182
|
+
// its activeToolCalls count survived the reattach and MUST be
|
|
1183
|
+
// released now that the call has settled.
|
|
1184
|
+
const wasSoftPreserved = this.detachSoftInflight.delete(msg.id);
|
|
1185
|
+
if (gen === this.generation || wasSoftPreserved) {
|
|
1032
1186
|
this.inFlightControllers.delete(msg.id);
|
|
1033
1187
|
this.inFlightToolNames.delete(msg.id);
|
|
1034
1188
|
this.activeToolCalls = Math.max(0, this.activeToolCalls - 1);
|