patchwork-os 0.2.0-alpha.9 → 0.2.0-beta.1
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 +318 -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/analyticsAggregator.d.ts +5 -1
- package/dist/analyticsAggregator.js +15 -4
- package/dist/analyticsAggregator.js.map +1 -1
- package/dist/analyticsPrefs.d.ts +11 -0
- package/dist/analyticsPrefs.js +33 -0
- package/dist/analyticsPrefs.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 +194 -153
- 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.d.ts +0 -16
- package/dist/claudeDriver.js +93 -36
- package/dist/claudeDriver.js.map +1 -1
- package/dist/claudeMdPatch.d.ts +9 -3
- package/dist/claudeMdPatch.js +79 -13
- package/dist/claudeMdPatch.js.map +1 -1
- package/dist/claudeOrchestrator.d.ts +13 -1
- package/dist/claudeOrchestrator.js +16 -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/marketplace.d.ts +15 -10
- package/dist/commands/marketplace.js +27 -115
- package/dist/commands/marketplace.js.map +1 -1
- 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/commitIssueLinkLog.d.ts +8 -0
- package/dist/commitIssueLinkLog.js +53 -1
- package/dist/commitIssueLinkLog.js.map +1 -1
- package/dist/config.d.ts +23 -2
- package/dist/config.js +119 -9
- package/dist/config.js.map +1 -1
- package/dist/connectorRoutes.d.ts +43 -0
- package/dist/connectorRoutes.js +1300 -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 +149 -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 +396 -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/claude/subprocess.d.ts +12 -2
- package/dist/drivers/claude/subprocess.js +79 -6
- package/dist/drivers/claude/subprocess.js.map +1 -1
- package/dist/drivers/gemini/api.d.ts +18 -0
- package/dist/drivers/gemini/api.js +29 -0
- package/dist/drivers/gemini/api.js.map +1 -0
- 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 +8 -1
- package/dist/drivers/index.js +10 -2
- package/dist/drivers/index.js.map +1 -1
- package/dist/drivers/local/index.d.ts +26 -0
- package/dist/drivers/local/index.js +41 -0
- package/dist/drivers/local/index.js.map +1 -0
- 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/httpErrorResponse.d.ts +36 -0
- package/dist/httpErrorResponse.js +46 -0
- package/dist/httpErrorResponse.js.map +1 -0
- package/dist/inboxRoutes.d.ts +22 -0
- package/dist/inboxRoutes.js +193 -0
- package/dist/inboxRoutes.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1403 -203
- 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 +20 -1
- package/dist/oauth.js +214 -39
- package/dist/oauth.js.map +1 -1
- package/dist/oauthRoutes.d.ts +32 -0
- package/dist/oauthRoutes.js +119 -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 +29 -0
- package/dist/patchworkConfig.js +100 -5
- 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 +30 -1
- package/dist/preToolUseHook.js.map +1 -1
- package/dist/prompts.js +4 -0
- package/dist/prompts.js.map +1 -1
- package/dist/recipeOrchestration.d.ts +121 -0
- package/dist/recipeOrchestration.js +965 -0
- package/dist/recipeOrchestration.js.map +1 -0
- package/dist/recipeRoutes.d.ts +185 -0
- package/dist/recipeRoutes.js +1369 -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 +38 -0
- package/dist/recipes/agentExecutor.js +50 -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 +451 -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 +130 -2
- package/dist/recipes/yamlRunner.js +1009 -402
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +151 -6
- package/dist/recipesHttp.js +999 -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 +127 -8
- package/dist/server.js +740 -933
- 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/runCommand.js +5 -0
- package/dist/tools/runCommand.js.map +1 -1
- 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/terminal.js +4 -0
- package/dist/tools/terminal.js.map +1 -1
- 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 +6 -0
- package/dist/tools/utils.js +59 -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 +34 -3
- 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/approval-queue-ui-test.yaml +205 -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
package/dist/bridge.js
CHANGED
|
@@ -5,33 +5,38 @@ import path from "node:path";
|
|
|
5
5
|
import { WebSocket } from "ws";
|
|
6
6
|
import { ActivityLog } from "./activityLog.js";
|
|
7
7
|
import { buildSummary } from "./analyticsAggregator.js";
|
|
8
|
-
import { getAnalyticsPref } from "./analyticsPrefs.js";
|
|
8
|
+
import { getAnalyticsPref, getAnalyticsSalt } from "./analyticsPrefs.js";
|
|
9
9
|
import { sendAnalytics } from "./analyticsSend.js";
|
|
10
10
|
import { getApprovalQueue } from "./approvalQueue.js";
|
|
11
11
|
import { AutomationHooks, loadPolicy } from "./automation.js";
|
|
12
12
|
import { loadOrCreateBridgeToken } from "./bridgeToken.js";
|
|
13
13
|
import { repairBridgeToolsRulesIfStale } from "./bridgeToolsRules.js";
|
|
14
|
-
import { createDriver } from "./claudeDriver.js";
|
|
15
14
|
import { ClaudeOrchestrator } from "./claudeOrchestrator.js";
|
|
16
15
|
import { CommitIssueLinkLog } from "./commitIssueLinkLog.js";
|
|
17
16
|
import { DecisionTraceLog } from "./decisionTraceLog.js";
|
|
17
|
+
import { createDriver } from "./drivers/index.js";
|
|
18
18
|
import { ExtensionClient } from "./extensionClient.js";
|
|
19
|
+
import { lockKillSwitchEnv } from "./featureFlags.js";
|
|
19
20
|
import { FileLock } from "./fileLock.js";
|
|
20
21
|
import { buildEnforcementReminder } from "./instructionsUtils.js";
|
|
21
22
|
import { LockFileManager } from "./lockfile.js";
|
|
22
23
|
import { Logger } from "./logger.js";
|
|
23
24
|
import { OAuthServerImpl } from "./oauth.js";
|
|
25
|
+
import { defaultConfigPath, getApiKeysPresent, loadConfig as loadPatchworkConfig, } from "./patchworkConfig.js";
|
|
24
26
|
import { loadPlugins, loadPluginsFull } from "./pluginLoader.js";
|
|
25
27
|
import { PluginWatcher } from "./pluginWatcher.js";
|
|
28
|
+
import { isPreToolUseHookRegistered } from "./preToolUseHook.js";
|
|
26
29
|
import { probeAll } from "./probe.js";
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
30
|
+
import { RecipeOrchestration } from "./recipeOrchestration.js";
|
|
31
|
+
import { warnAboutLegacyPermissionsSidecars } from "./recipes/migrationWarnings.js";
|
|
32
|
+
import { RecipeOrchestrator } from "./recipes/RecipeOrchestrator.js";
|
|
29
33
|
import { classifyTool } from "./riskTier.js";
|
|
30
34
|
import { RecipeRunLog } from "./runLog.js";
|
|
31
35
|
import { Server } from "./server.js";
|
|
32
36
|
import { SessionCheckpoint } from "./sessionCheckpoint.js";
|
|
33
37
|
import { StreamableHttpHandler } from "./streamableHttp.js";
|
|
34
38
|
import { initTelemetry, shutdownTelemetry } from "./telemetry.js";
|
|
39
|
+
import { TokenUsageTracker } from "./tokenUsageTracker.js";
|
|
35
40
|
import { createCtxQueryTracesTool } from "./tools/ctxQueryTraces.js";
|
|
36
41
|
import { readNote, writeNote } from "./tools/handoffNote.js";
|
|
37
42
|
import { registerAllTools } from "./tools/index.js";
|
|
@@ -112,8 +117,10 @@ export class Bridge {
|
|
|
112
117
|
pluginTools = [];
|
|
113
118
|
pluginWatcher = null;
|
|
114
119
|
automationHooks = undefined;
|
|
120
|
+
recipeOrchestration = null;
|
|
115
121
|
recipeScheduler = null;
|
|
116
122
|
recipeRunLog = null;
|
|
123
|
+
recipeOrchestrator = null;
|
|
117
124
|
commitIssueLinkLog = null;
|
|
118
125
|
decisionTraceLog = null;
|
|
119
126
|
/** Pre-computed digest of recent decisions, refreshed on each session connect. */
|
|
@@ -129,6 +136,7 @@ export class Bridge {
|
|
|
129
136
|
/** ISO timestamp of last getProjectContext cache write — drives status-bar "context X min ago". */
|
|
130
137
|
_lastContextCachedAt = null;
|
|
131
138
|
wsHeartbeatInterval = null;
|
|
139
|
+
tokenUsageTracker;
|
|
132
140
|
constructor(config) {
|
|
133
141
|
this.config = config;
|
|
134
142
|
this.logger = new Logger(config.verbose, config.jsonl);
|
|
@@ -136,6 +144,7 @@ export class Bridge {
|
|
|
136
144
|
const configDir = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
|
|
137
145
|
this.authToken = config.fixedToken ?? loadOrCreateBridgeToken(configDir);
|
|
138
146
|
this.server = new Server(this.authToken, this.logger, config.corsOrigins);
|
|
147
|
+
this.server.bridgeConfigPath = config.configFilePath ?? undefined;
|
|
139
148
|
if (config.issuerUrl) {
|
|
140
149
|
this.oauthServer = new OAuthServerImpl(this.authToken, config.issuerUrl, {
|
|
141
150
|
configDir,
|
|
@@ -150,6 +159,10 @@ export class Bridge {
|
|
|
150
159
|
this.logger.info(`Audit log: ${config.auditLogPath}`);
|
|
151
160
|
}
|
|
152
161
|
this.extensionClient = new ExtensionClient(this.logger);
|
|
162
|
+
this.tokenUsageTracker = new TokenUsageTracker({
|
|
163
|
+
workspace: config.workspace,
|
|
164
|
+
logger: { warn: (m) => this.logger.warn(m) },
|
|
165
|
+
});
|
|
153
166
|
// Handle new Claude Code connections
|
|
154
167
|
this.server.on("connection", async (ws) => {
|
|
155
168
|
// Reject connections before probes are ready
|
|
@@ -181,6 +194,15 @@ export class Bridge {
|
|
|
181
194
|
existing.graceTimer = null;
|
|
182
195
|
existing.ws = ws;
|
|
183
196
|
existing.wsAlive = true;
|
|
197
|
+
// Clean up old WS listener + reject stale pending elicitations
|
|
198
|
+
// before attaching the new socket. Without this, the previous
|
|
199
|
+
// listener accumulates and pending elicitations from the old
|
|
200
|
+
// client can resolve against the new connection's `activeWs`,
|
|
201
|
+
// surfacing prompts to a client that didn't request them.
|
|
202
|
+
// Intentionally NOT calling `detach()` — that would abort
|
|
203
|
+
// in-flight tool calls, but grace-period semantics preserve
|
|
204
|
+
// those across the reconnect.
|
|
205
|
+
existing.transport.detachSoft();
|
|
184
206
|
existing.transport.attach(ws);
|
|
185
207
|
ws.on("pong", () => {
|
|
186
208
|
existing.wsAlive = true;
|
|
@@ -239,8 +261,26 @@ export class Bridge {
|
|
|
239
261
|
transport.sessionId = sessionId;
|
|
240
262
|
transport.setActivityLog(this.activityLog);
|
|
241
263
|
transport.setToolRateLimit(this.config.toolRateLimit);
|
|
264
|
+
if (this.config.lazyTools)
|
|
265
|
+
transport.setLazyTools(true);
|
|
242
266
|
if (this.server.approvalGate !== "off") {
|
|
243
267
|
this.logger.info(`[patchwork] approval gate active: ${this.server.approvalGate} tier(s) require dashboard approval`);
|
|
268
|
+
// The approval gate only sees traffic if Claude Code's PreToolUse
|
|
269
|
+
// hook is registered to POST into /approvals. If it isn't, every
|
|
270
|
+
// CC tool call bypasses the bridge entirely — the queue stays
|
|
271
|
+
// empty, no `approval_decision` rows accumulate, and the entire
|
|
272
|
+
// personalSignals catalog has no input data. Silent foot-gun
|
|
273
|
+
// that wasted hours of investigation; surface it loudly.
|
|
274
|
+
try {
|
|
275
|
+
const ccSettingsPath = path.join(process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude"), "settings.json");
|
|
276
|
+
if (!isPreToolUseHookRegistered(ccSettingsPath)) {
|
|
277
|
+
this.logger.warn?.(`[patchwork] WARNING: approval gate is on but no PreToolUse hook found in ${ccSettingsPath}. ` +
|
|
278
|
+
`Claude Code will bypass the approval queue. Run 'patchwork-init' to register the hook.`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
// Best-effort warning — never block startup on a hook check failure.
|
|
283
|
+
}
|
|
244
284
|
transport.setApprovalGate(async ({ toolName, params, sessionId }) => {
|
|
245
285
|
const tier = classifyTool(toolName);
|
|
246
286
|
if (this.server.approvalGate === "off")
|
|
@@ -677,7 +717,11 @@ export class Bridge {
|
|
|
677
717
|
async start() {
|
|
678
718
|
// 0. Initialize OpenTelemetry (no-op when OTEL_EXPORTER_OTLP_ENDPOINT is unset)
|
|
679
719
|
initTelemetry();
|
|
680
|
-
// 0a.
|
|
720
|
+
// 0a. Snapshot env-derived kill-switch flags. After this, plugins or
|
|
721
|
+
// recipe steps mutating `process.env.PATCHWORK_FLAG_*` cannot disable an
|
|
722
|
+
// active emergency stop. Closes MED-2 from the 2026-04-28 audit.
|
|
723
|
+
lockKillSwitchEnv();
|
|
724
|
+
// 0b. Auto-repair .claude/rules/bridge-tools.md if stale (present but missing the
|
|
681
725
|
// current version sentinel). Older package versions write stale files that may
|
|
682
726
|
// lack new tool substitution rules. Repair is silent on success; falls back to
|
|
683
727
|
// warn-only if the template is missing or the write fails.
|
|
@@ -685,6 +729,7 @@ export class Bridge {
|
|
|
685
729
|
// 1. Probe available CLI tools (pass workspace so local node_modules/.bin is checked)
|
|
686
730
|
this.probes = await probeAll(this.config.workspace);
|
|
687
731
|
this.ready = true;
|
|
732
|
+
this.tokenUsageTracker.start();
|
|
688
733
|
// 2. Load plugins (after probes, before accepting sessions)
|
|
689
734
|
this.pluginTools = await loadPlugins(this.config.plugins, this.config, this.logger);
|
|
690
735
|
if (this.config.pluginWatch && this.config.plugins.length > 0) {
|
|
@@ -703,8 +748,21 @@ export class Bridge {
|
|
|
703
748
|
this.logger.info(`Available linters: ${probeList(["tsc", "eslint", "pyright", "ruff", "cargo", "go", "biome"])}`);
|
|
704
749
|
this.logger.info(`Available test runners: ${probeList(["vitest", "jest", "pytest", "cargo", "go"])}`);
|
|
705
750
|
// 2. Initialize Claude driver and orchestrator (if configured)
|
|
706
|
-
if (this.config.
|
|
707
|
-
const driver = createDriver(this.config.
|
|
751
|
+
if (this.config.driver !== "none") {
|
|
752
|
+
const driver = createDriver(this.config.driver, {
|
|
753
|
+
binary: this.config.claudeBinary,
|
|
754
|
+
antBinary: this.config.antBinary,
|
|
755
|
+
// Provided to all subprocess-style drivers (claude, gemini). The
|
|
756
|
+
// claude SubprocessDriver only injects --mcp-config when the spawned
|
|
757
|
+
// task sets providerOptions.mcpAccess=true (per-recipe-step opt-in).
|
|
758
|
+
// Gemini wires it unconditionally into ~/.gemini/settings.json.
|
|
759
|
+
bridgeMcp: () => this.port > 0
|
|
760
|
+
? {
|
|
761
|
+
url: `http://127.0.0.1:${this.port}/mcp`,
|
|
762
|
+
authToken: this.authToken,
|
|
763
|
+
}
|
|
764
|
+
: undefined,
|
|
765
|
+
}, (msg) => this.logger.info(msg));
|
|
708
766
|
// Patchwork: enrichment link log is useful regardless of orchestrator.
|
|
709
767
|
const patchworkDir = path.join(os.homedir(), ".patchwork");
|
|
710
768
|
this.commitIssueLinkLog = new CommitIssueLinkLog({
|
|
@@ -764,17 +822,33 @@ export class Bridge {
|
|
|
764
822
|
},
|
|
765
823
|
});
|
|
766
824
|
this.logger.info(`[bridge] Claude driver: ${driver.name}`);
|
|
767
|
-
//
|
|
825
|
+
// Recipe orchestrator — owns in-flight dedup across all entry paths.
|
|
826
|
+
this.recipeOrchestrator = new RecipeOrchestrator({
|
|
827
|
+
workdir: this.config.workspace,
|
|
828
|
+
});
|
|
829
|
+
// Patchwork: wire recipe server fns + build cron scheduler.
|
|
768
830
|
const recipesDir = path.join(os.homedir(), ".patchwork", "recipes");
|
|
769
|
-
|
|
831
|
+
// One-shot scan for legacy `<name>.permissions.json` sidecars (alpha.36+
|
|
832
|
+
// no longer generates them). Skipped under NODE_ENV=test.
|
|
833
|
+
warnAboutLegacyPermissionsSidecars(recipesDir);
|
|
834
|
+
this.recipeOrchestration = new RecipeOrchestration({
|
|
835
|
+
server: this.server,
|
|
836
|
+
getOrchestrator: () => this.orchestrator,
|
|
837
|
+
recipeOrchestrator: this.recipeOrchestrator,
|
|
838
|
+
recipeRunLog: this.recipeRunLog,
|
|
839
|
+
activityLog: this.activityLog,
|
|
840
|
+
workdir: this.config.workspace,
|
|
841
|
+
logger: this.logger,
|
|
842
|
+
});
|
|
843
|
+
this.recipeOrchestration.wireServerFns();
|
|
844
|
+
this.recipeScheduler = RecipeOrchestration.buildScheduler({
|
|
770
845
|
recipesDir,
|
|
771
|
-
|
|
846
|
+
runRecipeFn: async (name) => this.server.runRecipeFn?.(name),
|
|
847
|
+
enqueue: (opts) => this.orchestrator?.enqueue(opts) ?? "",
|
|
772
848
|
logger: this.logger,
|
|
773
849
|
});
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
this.logger.info(`[patchwork] scheduled ${scheduled.length} cron recipe${scheduled.length === 1 ? "" : "s"}`);
|
|
777
|
-
}
|
|
850
|
+
// scheduler.start() deferred to after this.port is set (see below)
|
|
851
|
+
// so bridgeMcp callback has a valid port when first cron fires.
|
|
778
852
|
}
|
|
779
853
|
}
|
|
780
854
|
if (this.config.automationEnabled) {
|
|
@@ -808,6 +882,7 @@ export class Bridge {
|
|
|
808
882
|
extensionCircuitBreaker: this.extensionClient.getCircuitBreakerState(),
|
|
809
883
|
extensionDisconnectCount: this.extensionDisconnectCount,
|
|
810
884
|
recentActivity: this.activityLog.query({ last: 10 }),
|
|
885
|
+
tokens: this.tokenUsageTracker.getTotals(),
|
|
811
886
|
};
|
|
812
887
|
};
|
|
813
888
|
this.server.metricsFn = () => this.activityLog.toPrometheus({
|
|
@@ -974,6 +1049,37 @@ export class Bridge {
|
|
|
974
1049
|
};
|
|
975
1050
|
};
|
|
976
1051
|
this.server.streamFn = (listener) => this.activityLog.subscribe(listener);
|
|
1052
|
+
this.server.cancelTaskFn = (id) => this.orchestrator?.cancel(id, "user") ?? false;
|
|
1053
|
+
// Wire `/sessions` for the dashboard's Sessions page. The same Map is
|
|
1054
|
+
// already iterated by `statusFn` for the bridge-status payload — exposing
|
|
1055
|
+
// it as a list-only endpoint lets the dashboard render per-session cards
|
|
1056
|
+
// without coupling to the rest of the status payload. Without this the
|
|
1057
|
+
// page returns 404 forever (sessionsFn was declared but never assigned),
|
|
1058
|
+
// even when sessions are connected.
|
|
1059
|
+
this.server.sessionsFn = () => {
|
|
1060
|
+
const approvals = getApprovalQueue().list();
|
|
1061
|
+
const pendingBySession = new Map();
|
|
1062
|
+
for (const a of approvals) {
|
|
1063
|
+
if (!a.sessionId)
|
|
1064
|
+
continue;
|
|
1065
|
+
// Match by 8-char prefix because the dashboard's session id is
|
|
1066
|
+
// the same prefix shape (statusFn emits `s.id.slice(0, 8)`).
|
|
1067
|
+
const prefix = a.sessionId.slice(0, 8);
|
|
1068
|
+
pendingBySession.set(prefix, (pendingBySession.get(prefix) ?? 0) + 1);
|
|
1069
|
+
}
|
|
1070
|
+
const out = [];
|
|
1071
|
+
for (const s of this.sessions.values()) {
|
|
1072
|
+
const id = s.id.slice(0, 8);
|
|
1073
|
+
out.push({
|
|
1074
|
+
id,
|
|
1075
|
+
connectedAt: new Date(s.connectedAt).toISOString(),
|
|
1076
|
+
openedFileCount: s.openedFiles.size,
|
|
1077
|
+
pendingApprovals: pendingBySession.get(id) ?? 0,
|
|
1078
|
+
...(s.remoteAddr ? { remoteAddr: s.remoteAddr } : {}),
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
return out;
|
|
1082
|
+
};
|
|
977
1083
|
this.server.tasksFn = () => ({
|
|
978
1084
|
tasks: (this.orchestrator?.list() ?? []).map((t) => ({
|
|
979
1085
|
taskId: t.id,
|
|
@@ -1000,134 +1106,21 @@ export class Bridge {
|
|
|
1000
1106
|
this.server.approvalWebhookUrl =
|
|
1001
1107
|
this.config.approvalWebhookUrl ?? undefined;
|
|
1002
1108
|
this.server.onApprovalDecision = (event, meta) => this.activityLog.recordEvent(event, meta);
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
}),
|
|
1019
|
-
...(q.status !== undefined && {
|
|
1020
|
-
status: q.status,
|
|
1021
|
-
}),
|
|
1022
|
-
...(q.recipe !== undefined && { recipe: q.recipe }),
|
|
1023
|
-
...(q.after !== undefined && { after: q.after }),
|
|
1024
|
-
});
|
|
1025
|
-
};
|
|
1026
|
-
this.server.sessionsFn = () => [...this.sessions.values()].map((s) => {
|
|
1027
|
-
const tools = this.activityLog.querySessionTools(s.id, 1);
|
|
1028
|
-
return {
|
|
1029
|
-
id: s.id,
|
|
1030
|
-
connectedAt: new Date(s.connectedAt).toISOString(),
|
|
1031
|
-
openedFileCount: s.openedFiles.size,
|
|
1032
|
-
pendingApprovals: getApprovalQueue()
|
|
1033
|
-
.list()
|
|
1034
|
-
.filter((a) => a.sessionId === s.id).length,
|
|
1035
|
-
firstTool: tools[0]?.tool,
|
|
1036
|
-
remoteAddr: s.remoteAddr,
|
|
1037
|
-
};
|
|
1038
|
-
});
|
|
1039
|
-
this.server.sessionDetailFn = (id) => {
|
|
1040
|
-
const s = this.sessions.get(id);
|
|
1041
|
-
const summary = s
|
|
1042
|
-
? {
|
|
1043
|
-
id: s.id,
|
|
1044
|
-
connectedAt: new Date(s.connectedAt).toISOString(),
|
|
1045
|
-
openedFileCount: s.openedFiles.size,
|
|
1046
|
-
pendingApprovals: getApprovalQueue()
|
|
1047
|
-
.list()
|
|
1048
|
-
.filter((a) => a.sessionId === s.id).length,
|
|
1049
|
-
}
|
|
1050
|
-
: null;
|
|
1051
|
-
const lifecycle = this.activityLog.querySessionLifecycle(id, 100);
|
|
1052
|
-
const tools = this.activityLog.querySessionTools(id, 100);
|
|
1053
|
-
const decisions = this.decisionTraceLog?.query({ sessionId: id, limit: 50 }) ?? [];
|
|
1054
|
-
const approvals = getApprovalQueue()
|
|
1055
|
-
.list()
|
|
1056
|
-
.filter((a) => a.sessionId === id);
|
|
1057
|
-
return {
|
|
1058
|
-
summary,
|
|
1059
|
-
lifecycle: lifecycle,
|
|
1060
|
-
tools: tools,
|
|
1061
|
-
decisions: decisions,
|
|
1062
|
-
approvals: approvals,
|
|
1063
|
-
};
|
|
1064
|
-
};
|
|
1065
|
-
this.server.webhookFn = async (hookPath, payload) => {
|
|
1066
|
-
if (!this.orchestrator) {
|
|
1067
|
-
return {
|
|
1068
|
-
ok: false,
|
|
1069
|
-
error: "orchestrator_unavailable",
|
|
1070
|
-
};
|
|
1071
|
-
}
|
|
1072
|
-
const recipesDir = path.join(os.homedir(), ".patchwork", "recipes");
|
|
1073
|
-
const match = findWebhookRecipe(recipesDir, hookPath);
|
|
1074
|
-
if (!match) {
|
|
1075
|
-
return { ok: false, error: "not_found" };
|
|
1076
|
-
}
|
|
1077
|
-
const loaded = loadRecipePrompt(recipesDir, match.name);
|
|
1078
|
-
if (!loaded) {
|
|
1079
|
-
return { ok: false, error: "recipe_file_missing" };
|
|
1080
|
-
}
|
|
1081
|
-
try {
|
|
1082
|
-
const taskId = this.orchestrator.enqueue({
|
|
1083
|
-
prompt: renderWebhookPrompt(loaded.prompt, payload),
|
|
1084
|
-
triggerSource: `webhook:${match.name}`,
|
|
1085
|
-
});
|
|
1086
|
-
return { ok: true, taskId, name: match.name };
|
|
1087
|
-
}
|
|
1088
|
-
catch (err) {
|
|
1089
|
-
return {
|
|
1090
|
-
ok: false,
|
|
1091
|
-
error: err instanceof Error ? err.message : String(err),
|
|
1092
|
-
};
|
|
1093
|
-
}
|
|
1094
|
-
};
|
|
1095
|
-
this.server.runRecipeFn = async (name, vars) => {
|
|
1096
|
-
if (!this.orchestrator) {
|
|
1097
|
-
return {
|
|
1098
|
-
ok: false,
|
|
1099
|
-
error: "Orchestrator unavailable — start bridge with --claude-driver subprocess",
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
const recipesDir = path.join(os.homedir(), ".patchwork", "recipes");
|
|
1103
|
-
const loaded = loadRecipePrompt(recipesDir, name);
|
|
1104
|
-
if (!loaded) {
|
|
1105
|
-
return {
|
|
1106
|
-
ok: false,
|
|
1107
|
-
error: `Recipe "${name}" not found in ${recipesDir}`,
|
|
1108
|
-
};
|
|
1109
|
-
}
|
|
1110
|
-
try {
|
|
1111
|
-
let prompt = loaded.prompt;
|
|
1112
|
-
if (vars && Object.keys(vars).length > 0) {
|
|
1113
|
-
const varLines = Object.entries(vars)
|
|
1114
|
-
.map(([k, v]) => `${k}=${v}`)
|
|
1115
|
-
.join("\n");
|
|
1116
|
-
prompt = `Variables:\n${varLines}\n\n${prompt}`;
|
|
1117
|
-
}
|
|
1118
|
-
const taskId = this.orchestrator.enqueue({
|
|
1119
|
-
prompt,
|
|
1120
|
-
triggerSource: `recipe:${name}`,
|
|
1121
|
-
});
|
|
1122
|
-
return { ok: true, taskId };
|
|
1123
|
-
}
|
|
1124
|
-
catch (err) {
|
|
1125
|
-
return {
|
|
1126
|
-
ok: false,
|
|
1127
|
-
error: err instanceof Error ? err.message : String(err),
|
|
1128
|
-
};
|
|
1129
|
-
}
|
|
1130
|
-
};
|
|
1109
|
+
// Wire activityLog into approvalHttp so passive risk personalization
|
|
1110
|
+
// signals (src/approvalSignals.ts) actually compute against the
|
|
1111
|
+
// user's history. Without this, the personalSignals catalog is
|
|
1112
|
+
// defined but inert — every approval queue entry has
|
|
1113
|
+
// personalSignals: undefined.
|
|
1114
|
+
this.server.activityLog = this.activityLog;
|
|
1115
|
+
// Same wire pattern for h6 (recipe-step trust). recipeRunLog may be
|
|
1116
|
+
// undefined when no orchestrator is configured; that's fine — h6
|
|
1117
|
+
// silently skips and the other 11 heuristics still compute.
|
|
1118
|
+
this.server.recipeRunLog = this.recipeRunLog ?? undefined;
|
|
1119
|
+
// Opt-in switch for personalSignals h10 (time-of-day anomaly).
|
|
1120
|
+
// Default false; user enables via --enable-time-of-day-anomaly or
|
|
1121
|
+
// ~/.patchwork/config.json's enableTimeOfDayAnomaly field.
|
|
1122
|
+
this.server.enableTimeOfDayAnomaly =
|
|
1123
|
+
this.config.enableTimeOfDayAnomaly ?? false;
|
|
1131
1124
|
this.server.readyFn = () => {
|
|
1132
1125
|
// Count tools from the first active session (all sessions share the same tool set)
|
|
1133
1126
|
const anySession = [...this.sessions.values()][0];
|
|
@@ -1165,15 +1158,29 @@ export class Bridge {
|
|
|
1165
1158
|
extension: this.extensionClient.isConnected(),
|
|
1166
1159
|
extensionCircuitBreaker: this.extensionClient.getCircuitBreakerState(),
|
|
1167
1160
|
timeline: this.activityLog.queryTimeline({ last: 50 }),
|
|
1168
|
-
patchwork: {
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1161
|
+
patchwork: (() => {
|
|
1162
|
+
const cfg = loadPatchworkConfig();
|
|
1163
|
+
return {
|
|
1164
|
+
workspace: this.config.workspace,
|
|
1165
|
+
approvalGate: this.server.approvalGate,
|
|
1166
|
+
enableTimeOfDayAnomaly: this.server.enableTimeOfDayAnomaly,
|
|
1167
|
+
fullMode: this.config.fullMode,
|
|
1168
|
+
driver: this.config.driver,
|
|
1169
|
+
model: cfg.model,
|
|
1170
|
+
localEndpoint: cfg.localEndpoint,
|
|
1171
|
+
localModel: cfg.localModel,
|
|
1172
|
+
automationEnabled: this.config.automationEnabled,
|
|
1173
|
+
port: this.port,
|
|
1174
|
+
httpPort: this.port,
|
|
1175
|
+
inboxDir: path.join(os.homedir(), ".patchwork", "inbox"),
|
|
1176
|
+
configPath: defaultConfigPath(),
|
|
1177
|
+
apiKeysPresent: getApiKeysPresent(),
|
|
1178
|
+
webhookUrl: this.server.approvalWebhookUrl ?? null,
|
|
1179
|
+
pushServiceUrl: this.server.pushServiceUrl ?? null,
|
|
1180
|
+
pushServiceToken: this.server.pushServiceToken ? "***" : null,
|
|
1181
|
+
pushServiceBaseUrl: this.server.pushServiceBaseUrl ?? null,
|
|
1182
|
+
};
|
|
1183
|
+
})(),
|
|
1177
1184
|
};
|
|
1178
1185
|
};
|
|
1179
1186
|
// 3b-notify. Wire CC hook notify endpoint
|
|
@@ -1259,6 +1266,31 @@ export class Bridge {
|
|
|
1259
1266
|
: null, async () => {
|
|
1260
1267
|
await this.refreshRecentTracesDigest();
|
|
1261
1268
|
return this.buildInstructions();
|
|
1269
|
+
},
|
|
1270
|
+
// Tail-end deps so `registerAllTools` registers the same tool set
|
|
1271
|
+
// on Streamable-HTTP sessions as on WebSocket. Without this object,
|
|
1272
|
+
// `ctxSaveTrace`, `ctxQueryTraces`, and any tool gated on the
|
|
1273
|
+
// remaining deps silently failed to register over Streamable HTTP
|
|
1274
|
+
// (caught dogfooding `ctx-loop-test` from a remote MCP client).
|
|
1275
|
+
{
|
|
1276
|
+
automationHooks: this.automationHooks,
|
|
1277
|
+
getDisconnectInfo: () => ({
|
|
1278
|
+
at: this.lastDisconnectAt,
|
|
1279
|
+
code: this.lastDisconnectCode,
|
|
1280
|
+
reason: this.lastDisconnectReason,
|
|
1281
|
+
}),
|
|
1282
|
+
onContextCacheUpdated: (generatedAt) => {
|
|
1283
|
+
this._lastContextCachedAt = generatedAt;
|
|
1284
|
+
this._emitLiveState();
|
|
1285
|
+
},
|
|
1286
|
+
getExtensionDisconnectCount: () => this.extensionDisconnectCount,
|
|
1287
|
+
...(this.commitIssueLinkLog && {
|
|
1288
|
+
commitIssueLinkLog: this.commitIssueLinkLog,
|
|
1289
|
+
}),
|
|
1290
|
+
...(this.recipeRunLog && { recipeRunLog: this.recipeRunLog }),
|
|
1291
|
+
...(this.decisionTraceLog && {
|
|
1292
|
+
decisionTraceLog: this.decisionTraceLog,
|
|
1293
|
+
}),
|
|
1262
1294
|
});
|
|
1263
1295
|
this.server.httpMcpHandler = (req, res) => this.httpMcpHandler?.handle(req, res) ?? Promise.resolve();
|
|
1264
1296
|
// 3. Check for stale lock files
|
|
@@ -1275,6 +1307,13 @@ export class Bridge {
|
|
|
1275
1307
|
throw err;
|
|
1276
1308
|
}
|
|
1277
1309
|
this.port = port;
|
|
1310
|
+
// 4a-deferred. Start recipe scheduler now that port is known (bridgeMcp needs a valid port).
|
|
1311
|
+
if (this.recipeScheduler) {
|
|
1312
|
+
const scheduled = this.recipeScheduler.start();
|
|
1313
|
+
if (scheduled.length > 0) {
|
|
1314
|
+
this.logger.info(`[patchwork] scheduled ${scheduled.length} cron recipe${scheduled.length === 1 ? "" : "s"}`);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1278
1317
|
// 4b. Start WebSocket keepalive heartbeat (keeps MCP session alive during long idle periods)
|
|
1279
1318
|
this._startWsHeartbeat();
|
|
1280
1319
|
// 4c. Load persisted tasks from previous sessions (best-effort)
|
|
@@ -1438,6 +1477,7 @@ export class Bridge {
|
|
|
1438
1477
|
this.stopped = true;
|
|
1439
1478
|
this.logger.info("Shutting down...");
|
|
1440
1479
|
this._stopPeriodicSnapshots();
|
|
1480
|
+
this.tokenUsageTracker.stop();
|
|
1441
1481
|
this.automationHooks?.destroy();
|
|
1442
1482
|
this.recipeScheduler?.stop();
|
|
1443
1483
|
this.recipeScheduler = null;
|
|
@@ -1471,7 +1511,7 @@ export class Bridge {
|
|
|
1471
1511
|
if (this.checkpoint && this.port > 0) {
|
|
1472
1512
|
try {
|
|
1473
1513
|
await Promise.race([
|
|
1474
|
-
Promise.resolve().then(() => this.checkpoint
|
|
1514
|
+
Promise.resolve().then(() => this.checkpoint?.write(this._buildCheckpoint(this.port))),
|
|
1475
1515
|
new Promise((resolve) => setTimeout(resolve, 3000)),
|
|
1476
1516
|
]);
|
|
1477
1517
|
}
|
|
@@ -1495,7 +1535,8 @@ export class Bridge {
|
|
|
1495
1535
|
if (analyticsOn === true && totalSessions > 0) {
|
|
1496
1536
|
try {
|
|
1497
1537
|
const entries = this.activityLog.query({ last: 500 });
|
|
1498
|
-
const
|
|
1538
|
+
const salt = getAnalyticsSalt();
|
|
1539
|
+
const summary = buildSummary(entries, maxDurationMs, PACKAGE_VERSION, salt);
|
|
1499
1540
|
await Promise.race([
|
|
1500
1541
|
sendAnalytics(summary),
|
|
1501
1542
|
new Promise((resolve) => setTimeout(resolve, 2000)),
|