patchwork-os 0.2.0-beta.0 → 0.2.0-beta.10
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 +14 -14
- package/README.md +204 -34
- package/deploy/README.md +1 -1
- package/deploy/bootstrap-vps.sh +14 -9
- package/deploy/deploy-dashboard.sh +25 -1
- package/deploy/macos/README.md +153 -0
- package/deploy/macos/com.patchwork.bridge.plist.template +54 -0
- package/deploy/macos/com.patchwork.tunnel.plist.template +76 -0
- package/deploy/macos/install-mac-bridge.sh +244 -0
- package/deploy/macos/uninstall-mac-bridge.sh +22 -0
- package/dist/activityLog.d.ts +6 -0
- package/dist/activityLog.js +63 -26
- package/dist/activityLog.js.map +1 -1
- package/dist/adapters/claude.js +22 -16
- package/dist/adapters/claude.js.map +1 -1
- package/dist/adapters/gemini.js +15 -11
- package/dist/adapters/gemini.js.map +1 -1
- package/dist/adapters/openai.js +9 -9
- package/dist/adapters/openai.js.map +1 -1
- package/dist/ajv2020.d.ts +25 -0
- package/dist/ajv2020.js +33 -0
- package/dist/ajv2020.js.map +1 -0
- package/dist/analyticsAggregator.d.ts +5 -1
- package/dist/analyticsAggregator.js +16 -5
- package/dist/analyticsAggregator.js.map +1 -1
- package/dist/analyticsConfig.d.ts +29 -0
- package/dist/analyticsConfig.js +102 -0
- package/dist/analyticsConfig.js.map +1 -0
- package/dist/analyticsPrefs.d.ts +49 -2
- package/dist/analyticsPrefs.js +177 -19
- package/dist/analyticsPrefs.js.map +1 -1
- package/dist/analyticsSend.d.ts +17 -1
- package/dist/analyticsSend.js +67 -5
- package/dist/analyticsSend.js.map +1 -1
- package/dist/approvalHttp.d.ts +14 -0
- package/dist/approvalHttp.js +212 -9
- package/dist/approvalHttp.js.map +1 -1
- package/dist/approvalInsights.js +13 -5
- package/dist/approvalInsights.js.map +1 -1
- package/dist/approvalQueue.d.ts +97 -3
- package/dist/approvalQueue.js +193 -19
- package/dist/approvalQueue.js.map +1 -1
- package/dist/approvalSignals.js +19 -11
- package/dist/approvalSignals.js.map +1 -1
- package/dist/automation.d.ts +35 -10
- package/dist/automation.js +133 -37
- package/dist/automation.js.map +1 -1
- package/dist/automationSuggestions.js +10 -8
- package/dist/automationSuggestions.js.map +1 -1
- package/dist/bridge.d.ts +2 -0
- package/dist/bridge.js +238 -51
- package/dist/bridge.js.map +1 -1
- package/dist/bridgeLockDiscovery.d.ts +27 -1
- package/dist/bridgeLockDiscovery.js +38 -11
- package/dist/bridgeLockDiscovery.js.map +1 -1
- package/dist/bridgeToken.js +3 -2
- package/dist/bridgeToken.js.map +1 -1
- package/dist/claudeDriver.d.ts +0 -16
- package/dist/claudeDriver.js +42 -28
- 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 +89 -44
- package/dist/claudeOrchestrator.js.map +1 -1
- package/dist/commands/analytics.d.ts +8 -0
- package/dist/commands/analytics.js +134 -0
- package/dist/commands/analytics.js.map +1 -0
- package/dist/commands/auditEnv.d.ts +36 -0
- package/dist/commands/auditEnv.js +202 -0
- package/dist/commands/auditEnv.js.map +1 -0
- package/dist/commands/dashboard.js +8 -1
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/doctor.d.ts +35 -0
- package/dist/commands/doctor.js +51 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/install.js +3 -0
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/launchd.js +15 -16
- package/dist/commands/launchd.js.map +1 -1
- package/dist/commands/patchworkInit.d.ts +5 -0
- package/dist/commands/patchworkInit.js +89 -7
- package/dist/commands/patchworkInit.js.map +1 -1
- package/dist/commands/recipe.d.ts +110 -0
- package/dist/commands/recipe.js +512 -9
- package/dist/commands/recipe.js.map +1 -1
- package/dist/commands/recipeInstall.js +11 -4
- package/dist/commands/recipeInstall.js.map +1 -1
- package/dist/commands/shadowScan.d.ts +34 -0
- package/dist/commands/shadowScan.js +142 -0
- package/dist/commands/shadowScan.js.map +1 -0
- package/dist/commands/task.js +2 -2
- package/dist/commands/task.js.map +1 -1
- package/dist/commands/tools.d.ts +20 -1
- package/dist/commands/tools.js +112 -3
- package/dist/commands/tools.js.map +1 -1
- package/dist/commands/tracesImport.js +21 -4
- package/dist/commands/tracesImport.js.map +1 -1
- package/dist/commitIssueLinkLog.d.ts +24 -0
- package/dist/commitIssueLinkLog.js +160 -22
- package/dist/commitIssueLinkLog.js.map +1 -1
- package/dist/companions/registry.js +15 -7
- package/dist/companions/registry.js.map +1 -1
- package/dist/config.d.ts +49 -5
- package/dist/config.js +123 -22
- package/dist/config.js.map +1 -1
- package/dist/connectorRoutes.js +913 -413
- package/dist/connectorRoutes.js.map +1 -1
- package/dist/connectors/airtable.d.ts +230 -0
- package/dist/connectors/airtable.js +700 -0
- package/dist/connectors/airtable.js.map +1 -0
- package/dist/connectors/asana.js +13 -9
- package/dist/connectors/asana.js.map +1 -1
- package/dist/connectors/baseConnector.js +25 -3
- package/dist/connectors/baseConnector.js.map +1 -1
- package/dist/connectors/caldiy.d.ts +137 -0
- package/dist/connectors/caldiy.js +424 -0
- package/dist/connectors/caldiy.js.map +1 -0
- package/dist/connectors/circleci.d.ts +162 -0
- package/dist/connectors/circleci.js +576 -0
- package/dist/connectors/circleci.js.map +1 -0
- package/dist/connectors/cloudflare.d.ts +132 -0
- package/dist/connectors/cloudflare.js +622 -0
- package/dist/connectors/cloudflare.js.map +1 -0
- package/dist/connectors/confluence.js +35 -0
- package/dist/connectors/confluence.js.map +1 -1
- package/dist/connectors/connectorRedirectUri.d.ts +30 -0
- package/dist/connectors/connectorRedirectUri.js +38 -0
- package/dist/connectors/connectorRedirectUri.js.map +1 -0
- package/dist/connectors/connectorRegistry.d.ts +63 -0
- package/dist/connectors/connectorRegistry.js +354 -0
- package/dist/connectors/connectorRegistry.js.map +1 -0
- package/dist/connectors/datadog.js +33 -4
- package/dist/connectors/datadog.js.map +1 -1
- package/dist/connectors/discord.js +14 -10
- package/dist/connectors/discord.js.map +1 -1
- package/dist/connectors/elasticsearch.d.ts +141 -0
- package/dist/connectors/elasticsearch.js +601 -0
- package/dist/connectors/elasticsearch.js.map +1 -0
- package/dist/connectors/figma.d.ts +130 -0
- package/dist/connectors/figma.js +387 -0
- package/dist/connectors/figma.js.map +1 -0
- package/dist/connectors/github.d.ts +17 -0
- package/dist/connectors/github.js +53 -2
- package/dist/connectors/github.js.map +1 -1
- package/dist/connectors/gitlab.js +12 -6
- package/dist/connectors/gitlab.js.map +1 -1
- package/dist/connectors/gmail.js +72 -21
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleCalendar.js +8 -8
- package/dist/connectors/googleCalendar.js.map +1 -1
- package/dist/connectors/googleDocs.d.ts +103 -0
- package/dist/connectors/googleDocs.js +409 -0
- package/dist/connectors/googleDocs.js.map +1 -0
- package/dist/connectors/googleDrive.d.ts +12 -0
- package/dist/connectors/googleDrive.js +35 -8
- package/dist/connectors/googleDrive.js.map +1 -1
- package/dist/connectors/grafana.d.ts +133 -0
- package/dist/connectors/grafana.js +478 -0
- package/dist/connectors/grafana.js.map +1 -0
- package/dist/connectors/jira.d.ts +25 -0
- package/dist/connectors/jira.js +245 -2
- package/dist/connectors/jira.js.map +1 -1
- package/dist/connectors/linear.js +1 -1
- package/dist/connectors/linear.js.map +1 -1
- package/dist/connectors/mcpOAuth.js +78 -16
- package/dist/connectors/mcpOAuth.js.map +1 -1
- package/dist/connectors/monday.d.ts +217 -0
- package/dist/connectors/monday.js +655 -0
- package/dist/connectors/monday.js.map +1 -0
- package/dist/connectors/mongodb.d.ts +139 -0
- package/dist/connectors/mongodb.js +455 -0
- package/dist/connectors/mongodb.js.map +1 -0
- package/dist/connectors/oauthStateStore.d.ts +20 -0
- package/dist/connectors/oauthStateStore.js +94 -4
- package/dist/connectors/oauthStateStore.js.map +1 -1
- package/dist/connectors/obsidian.d.ts +83 -0
- package/dist/connectors/obsidian.js +441 -0
- package/dist/connectors/obsidian.js.map +1 -0
- package/dist/connectors/paystack.d.ts +159 -0
- package/dist/connectors/paystack.js +607 -0
- package/dist/connectors/paystack.js.map +1 -0
- package/dist/connectors/pipedrive.d.ts +189 -0
- package/dist/connectors/pipedrive.js +559 -0
- package/dist/connectors/pipedrive.js.map +1 -0
- package/dist/connectors/postgres.d.ts +127 -0
- package/dist/connectors/postgres.js +512 -0
- package/dist/connectors/postgres.js.map +1 -0
- package/dist/connectors/posthog.d.ts +119 -0
- package/dist/connectors/posthog.js +479 -0
- package/dist/connectors/posthog.js.map +1 -0
- package/dist/connectors/redis.d.ts +140 -0
- package/dist/connectors/redis.js +571 -0
- package/dist/connectors/redis.js.map +1 -0
- package/dist/connectors/resend.d.ts +131 -0
- package/dist/connectors/resend.js +529 -0
- package/dist/connectors/resend.js.map +1 -0
- package/dist/connectors/salesforce.d.ts +136 -0
- package/dist/connectors/salesforce.js +603 -0
- package/dist/connectors/salesforce.js.map +1 -0
- package/dist/connectors/secrets.d.ts +51 -0
- package/dist/connectors/secrets.js +102 -0
- package/dist/connectors/secrets.js.map +1 -0
- package/dist/connectors/sendgrid.d.ts +102 -0
- package/dist/connectors/sendgrid.js +423 -0
- package/dist/connectors/sendgrid.js.map +1 -0
- package/dist/connectors/shopify.d.ts +145 -0
- package/dist/connectors/shopify.js +502 -0
- package/dist/connectors/shopify.js.map +1 -0
- package/dist/connectors/slack.d.ts +1 -1
- package/dist/connectors/slack.js +61 -9
- package/dist/connectors/slack.js.map +1 -1
- package/dist/connectors/snowflake.d.ts +119 -0
- package/dist/connectors/snowflake.js +615 -0
- package/dist/connectors/snowflake.js.map +1 -0
- package/dist/connectors/supabase.d.ts +92 -0
- package/dist/connectors/supabase.js +630 -0
- package/dist/connectors/supabase.js.map +1 -0
- package/dist/connectors/todoist.d.ts +117 -0
- package/dist/connectors/todoist.js +485 -0
- package/dist/connectors/todoist.js.map +1 -0
- package/dist/connectors/tokenStorage.js +56 -14
- package/dist/connectors/tokenStorage.js.map +1 -1
- package/dist/connectors/twilio.d.ts +118 -0
- package/dist/connectors/twilio.js +475 -0
- package/dist/connectors/twilio.js.map +1 -0
- package/dist/connectors/vercel.d.ts +110 -0
- package/dist/connectors/vercel.js +479 -0
- package/dist/connectors/vercel.js.map +1 -0
- package/dist/connectors/webflow.d.ts +118 -0
- package/dist/connectors/webflow.js +393 -0
- package/dist/connectors/webflow.js.map +1 -0
- package/dist/connectors/woocommerce.d.ts +220 -0
- package/dist/connectors/woocommerce.js +464 -0
- package/dist/connectors/woocommerce.js.map +1 -0
- package/dist/crypto.js +7 -2
- package/dist/crypto.js.map +1 -1
- package/dist/decisionReplay.js +15 -6
- package/dist/decisionReplay.js.map +1 -1
- package/dist/decisionTraceLog.d.ts +28 -0
- package/dist/decisionTraceLog.js +156 -29
- package/dist/decisionTraceLog.js.map +1 -1
- package/dist/drivers/claude/api.js +5 -4
- package/dist/drivers/claude/api.js.map +1 -1
- package/dist/drivers/claude/envSanitizer.d.ts +0 -6
- package/dist/drivers/claude/envSanitizer.js +17 -2
- package/dist/drivers/claude/envSanitizer.js.map +1 -1
- package/dist/drivers/claude/streamParser.js +5 -4
- package/dist/drivers/claude/streamParser.js.map +1 -1
- package/dist/drivers/claude/subprocess.d.ts +12 -2
- package/dist/drivers/claude/subprocess.js +100 -8
- 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 +22 -0
- package/dist/drivers/gemini/index.js +256 -129
- package/dist/drivers/gemini/index.js.map +1 -1
- package/dist/drivers/index.d.ts +3 -1
- package/dist/drivers/index.js +9 -1
- package/dist/drivers/index.js.map +1 -1
- package/dist/drivers/local/index.d.ts +43 -0
- package/dist/drivers/local/index.js +140 -0
- package/dist/drivers/local/index.js.map +1 -0
- package/dist/drivers/openai/index.js +30 -2
- package/dist/drivers/openai/index.js.map +1 -1
- package/dist/extensionClient.d.ts +37 -4
- package/dist/extensionClient.js +58 -16
- package/dist/extensionClient.js.map +1 -1
- package/dist/featureFlags.d.ts +91 -0
- package/dist/featureFlags.js +174 -3
- package/dist/featureFlags.js.map +1 -1
- package/dist/fileLock.js +21 -12
- package/dist/fileLock.js.map +1 -1
- package/dist/fileLockSync.d.ts +67 -0
- package/dist/fileLockSync.js +126 -0
- package/dist/fileLockSync.js.map +1 -0
- package/dist/fp/activityAnalytics.js +26 -12
- package/dist/fp/activityAnalytics.js.map +1 -1
- package/dist/fp/automationInterpreter.d.ts +15 -1
- package/dist/fp/automationInterpreter.js +217 -82
- package/dist/fp/automationInterpreter.js.map +1 -1
- package/dist/fp/automationProgram.d.ts +30 -0
- package/dist/fp/automationProgram.js.map +1 -1
- package/dist/fp/automationState.d.ts +24 -5
- package/dist/fp/automationState.js +56 -9
- package/dist/fp/automationState.js.map +1 -1
- package/dist/fp/automationUtils.js +1 -1
- package/dist/fp/automationUtils.js.map +1 -1
- package/dist/fp/commandDescription.js +7 -1
- package/dist/fp/commandDescription.js.map +1 -1
- package/dist/fp/extensionSnapshot.js +8 -2
- package/dist/fp/extensionSnapshot.js.map +1 -1
- package/dist/fp/interpreterContext.d.ts +66 -1
- package/dist/fp/interpreterContext.js +91 -1
- package/dist/fp/interpreterContext.js.map +1 -1
- package/dist/fp/policyParser.js +29 -1
- package/dist/fp/policyParser.js.map +1 -1
- package/dist/fsWatchWithFallback.d.ts +36 -0
- package/dist/fsWatchWithFallback.js +128 -0
- package/dist/fsWatchWithFallback.js.map +1 -0
- package/dist/haltPushDispatch.d.ts +33 -0
- package/dist/haltPushDispatch.js +103 -0
- package/dist/haltPushDispatch.js.map +1 -0
- package/dist/httpBodyValidation.d.ts +41 -0
- package/dist/httpBodyValidation.js +45 -0
- package/dist/httpBodyValidation.js.map +1 -0
- 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 +151 -12
- package/dist/inboxRoutes.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1054 -76
- package/dist/index.js.map +1 -1
- package/dist/installGuard.js +6 -2
- package/dist/installGuard.js.map +1 -1
- package/dist/lockfile.js +31 -4
- package/dist/lockfile.js.map +1 -1
- package/dist/oauth.d.ts +22 -0
- package/dist/oauth.js +46 -0
- package/dist/oauth.js.map +1 -1
- package/dist/oauthRoutes.d.ts +1 -1
- package/dist/oauthRoutes.js +8 -11
- package/dist/oauthRoutes.js.map +1 -1
- package/dist/orchestrator/childBridgeRegistry.js +29 -11
- package/dist/orchestrator/childBridgeRegistry.js.map +1 -1
- package/dist/patchworkConfig.d.ts +57 -1
- package/dist/patchworkConfig.js +125 -5
- package/dist/patchworkConfig.js.map +1 -1
- package/dist/pluginLoader.js +10 -1
- package/dist/pluginLoader.js.map +1 -1
- package/dist/pluginWatcher.js +12 -14
- package/dist/pluginWatcher.js.map +1 -1
- package/dist/preToolUseHook.js +10 -3
- package/dist/preToolUseHook.js.map +1 -1
- package/dist/processTree.d.ts +34 -0
- package/dist/processTree.js +105 -0
- package/dist/processTree.js.map +1 -0
- package/dist/prompts.js +7 -3
- package/dist/prompts.js.map +1 -1
- package/dist/recipeOrchestration.d.ts +9 -0
- package/dist/recipeOrchestration.js +354 -27
- package/dist/recipeOrchestration.js.map +1 -1
- package/dist/recipeRoutes.d.ts +63 -2
- package/dist/recipeRoutes.js +790 -137
- package/dist/recipeRoutes.js.map +1 -1
- package/dist/recipes/RecipeOrchestrator.d.ts +2 -0
- package/dist/recipes/RecipeOrchestrator.js +6 -1
- package/dist/recipes/RecipeOrchestrator.js.map +1 -1
- package/dist/recipes/agentExecutor.d.ts +34 -5
- package/dist/recipes/agentExecutor.js +5 -4
- package/dist/recipes/agentExecutor.js.map +1 -1
- package/dist/recipes/chainedRunner.d.ts +2 -0
- package/dist/recipes/chainedRunner.js +142 -5
- package/dist/recipes/chainedRunner.js.map +1 -1
- package/dist/recipes/connectorPreflight.d.ts +66 -0
- package/dist/recipes/connectorPreflight.js +169 -0
- package/dist/recipes/connectorPreflight.js.map +1 -0
- package/dist/recipes/dependencyGraph.js +13 -5
- package/dist/recipes/dependencyGraph.js.map +1 -1
- package/dist/recipes/githubInstallSource.d.ts +128 -0
- package/dist/recipes/githubInstallSource.js +206 -0
- package/dist/recipes/githubInstallSource.js.map +1 -0
- package/dist/recipes/haltCategory.d.ts +119 -0
- package/dist/recipes/haltCategory.js +188 -0
- package/dist/recipes/haltCategory.js.map +1 -0
- package/dist/recipes/idempotencyKey.d.ts +134 -0
- package/dist/recipes/idempotencyKey.js +322 -0
- package/dist/recipes/idempotencyKey.js.map +1 -0
- package/dist/recipes/installer.js +48 -2
- package/dist/recipes/installer.js.map +1 -1
- package/dist/recipes/judgeSummary.d.ts +50 -0
- package/dist/recipes/judgeSummary.js +47 -0
- package/dist/recipes/judgeSummary.js.map +1 -0
- package/dist/recipes/judgeVerdict.d.ts +48 -0
- package/dist/recipes/judgeVerdict.js +174 -0
- package/dist/recipes/judgeVerdict.js.map +1 -0
- package/dist/recipes/migrations/index.d.ts +9 -0
- package/dist/recipes/migrations/index.js +133 -0
- package/dist/recipes/migrations/index.js.map +1 -1
- package/dist/recipes/names.d.ts +20 -0
- package/dist/recipes/names.js +25 -0
- package/dist/recipes/names.js.map +1 -1
- package/dist/recipes/parser.js +88 -5
- package/dist/recipes/parser.js.map +1 -1
- package/dist/recipes/replayRun.js +1 -1
- package/dist/recipes/replayRun.js.map +1 -1
- package/dist/recipes/runBudget.d.ts +70 -0
- package/dist/recipes/runBudget.js +109 -0
- package/dist/recipes/runBudget.js.map +1 -0
- package/dist/recipes/scheduler.d.ts +30 -0
- package/dist/recipes/scheduler.js +69 -19
- package/dist/recipes/scheduler.js.map +1 -1
- package/dist/recipes/schema.d.ts +36 -0
- package/dist/recipes/schemaGenerator.js +103 -5
- package/dist/recipes/schemaGenerator.js.map +1 -1
- package/dist/recipes/stepObservation.js +9 -0
- package/dist/recipes/stepObservation.js.map +1 -1
- package/dist/recipes/toolRegistry.js +20 -3
- package/dist/recipes/toolRegistry.js.map +1 -1
- package/dist/recipes/tools/fanOut.d.ts +20 -0
- package/dist/recipes/tools/fanOut.js +199 -0
- package/dist/recipes/tools/fanOut.js.map +1 -0
- package/dist/recipes/tools/file.js +5 -2
- package/dist/recipes/tools/file.js.map +1 -1
- package/dist/recipes/tools/github.d.ts +1 -1
- package/dist/recipes/tools/github.js +75 -1
- package/dist/recipes/tools/github.js.map +1 -1
- package/dist/recipes/tools/gmail.js +45 -6
- package/dist/recipes/tools/gmail.js.map +1 -1
- package/dist/recipes/tools/googleDrive.js +64 -0
- package/dist/recipes/tools/googleDrive.js.map +1 -1
- package/dist/recipes/tools/http.d.ts +10 -0
- package/dist/recipes/tools/http.js +176 -0
- package/dist/recipes/tools/http.js.map +1 -0
- package/dist/recipes/tools/index.d.ts +2 -0
- package/dist/recipes/tools/index.js +2 -0
- package/dist/recipes/tools/index.js.map +1 -1
- package/dist/recipes/tools/slack.js +1 -1
- package/dist/recipes/validation.d.ts +17 -0
- package/dist/recipes/validation.js +29 -11
- package/dist/recipes/validation.js.map +1 -1
- package/dist/recipes/workspaceRoot.d.ts +37 -0
- package/dist/recipes/workspaceRoot.js +73 -0
- package/dist/recipes/workspaceRoot.js.map +1 -0
- package/dist/recipes/yamlPositions.d.ts +56 -0
- package/dist/recipes/yamlPositions.js +183 -0
- package/dist/recipes/yamlPositions.js.map +1 -0
- package/dist/recipes/yamlRunner.d.ts +195 -8
- package/dist/recipes/yamlRunner.js +877 -209
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +33 -3
- package/dist/recipesHttp.js +126 -12
- package/dist/recipesHttp.js.map +1 -1
- package/dist/resources.js +21 -13
- package/dist/resources.js.map +1 -1
- package/dist/runLog.d.ts +58 -5
- package/dist/runLog.js +98 -21
- package/dist/runLog.js.map +1 -1
- package/dist/sanitizeParsedJson.d.ts +39 -0
- package/dist/sanitizeParsedJson.js +55 -0
- package/dist/sanitizeParsedJson.js.map +1 -0
- package/dist/schemas/recipe.v1.json +885 -196
- package/dist/server.d.ts +166 -3
- package/dist/server.js +1313 -332
- package/dist/server.js.map +1 -1
- package/dist/sessionCheckpoint.d.ts +8 -0
- package/dist/sessionCheckpoint.js +33 -3
- package/dist/sessionCheckpoint.js.map +1 -1
- package/dist/ssrfGuard.d.ts +16 -0
- package/dist/ssrfGuard.js +87 -4
- package/dist/ssrfGuard.js.map +1 -1
- package/dist/streamableHttp.d.ts +9 -4
- package/dist/streamableHttp.js +76 -20
- package/dist/streamableHttp.js.map +1 -1
- package/dist/telemetry.js +19 -12
- package/dist/telemetry.js.map +1 -1
- package/dist/testing/shadowRun.d.ts +52 -0
- package/dist/testing/shadowRun.js +71 -0
- package/dist/testing/shadowRun.js.map +1 -0
- package/dist/tools/batchLsp.d.ts +3 -0
- package/dist/tools/bridgeDoctor.d.ts +11 -0
- package/dist/tools/bridgeDoctor.js +48 -2
- package/dist/tools/bridgeDoctor.js.map +1 -1
- package/dist/tools/bridgeStatus.d.ts +0 -12
- package/dist/tools/bridgeStatus.js +2 -28
- package/dist/tools/bridgeStatus.js.map +1 -1
- package/dist/tools/cancelClaudeTask.d.ts +1 -0
- package/dist/tools/clipboard.d.ts +2 -0
- package/dist/tools/closeTabs.d.ts +1 -0
- package/dist/tools/codeLens.d.ts +1 -0
- package/dist/tools/createIssueFromAIComment.d.ts +1 -0
- package/dist/tools/ctxGetTaskContext.d.ts +9 -0
- package/dist/tools/ctxGetTaskContext.js +50 -2
- package/dist/tools/ctxGetTaskContext.js.map +1 -1
- package/dist/tools/ctxQueryTraces.js +32 -24
- package/dist/tools/ctxQueryTraces.js.map +1 -1
- 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/detectUnusedCode.js +9 -7
- package/dist/tools/detectUnusedCode.js.map +1 -1
- package/dist/tools/documentLinks.d.ts +1 -0
- package/dist/tools/editText.d.ts +1 -0
- package/dist/tools/editText.js +2 -1
- package/dist/tools/editText.js.map +1 -1
- package/dist/tools/enrichCommit.d.ts +1 -0
- package/dist/tools/enrichStackTrace.js +11 -5
- package/dist/tools/enrichStackTrace.js.map +1 -1
- package/dist/tools/explainDiagnostic.d.ts +1 -0
- package/dist/tools/explainSymbol.d.ts +1 -0
- package/dist/tools/fileOperations.d.ts +3 -0
- package/dist/tools/fileOperations.js +2 -1
- package/dist/tools/fileOperations.js.map +1 -1
- package/dist/tools/fileWatcher.d.ts +2 -0
- package/dist/tools/fileWatcher.js +8 -2
- package/dist/tools/fileWatcher.js.map +1 -1
- package/dist/tools/findFiles.d.ts +1 -0
- package/dist/tools/fixAllLintErrors.d.ts +1 -0
- package/dist/tools/fixAllLintErrors.js +10 -5
- package/dist/tools/fixAllLintErrors.js.map +1 -1
- package/dist/tools/foldingRanges.d.ts +1 -0
- package/dist/tools/formatDocument.d.ts +1 -0
- package/dist/tools/formatDocument.js +10 -5
- package/dist/tools/formatDocument.js.map +1 -1
- package/dist/tools/generateTests.d.ts +1 -0
- package/dist/tools/getAIComments.d.ts +1 -0
- package/dist/tools/getAnalyticsReport.js +5 -1
- package/dist/tools/getAnalyticsReport.js.map +1 -1
- package/dist/tools/getBufferContent.d.ts +1 -0
- package/dist/tools/getChangeImpact.d.ts +1 -0
- package/dist/tools/getChangeImpact.js +23 -14
- package/dist/tools/getChangeImpact.js.map +1 -1
- package/dist/tools/getClaudeTaskStatus.d.ts +1 -0
- package/dist/tools/getCodeCoverage.d.ts +1 -0
- package/dist/tools/getCodeCoverage.js +32 -14
- package/dist/tools/getCodeCoverage.js.map +1 -1
- package/dist/tools/getCommitsForIssue.d.ts +1 -0
- package/dist/tools/getDebugState.d.ts +1 -0
- package/dist/tools/getDiagnostics.js +32 -29
- package/dist/tools/getDiagnostics.js.map +1 -1
- package/dist/tools/getDiffFromHandoff.js +8 -2
- package/dist/tools/getDiffFromHandoff.js.map +1 -1
- package/dist/tools/getDocumentSymbols.d.ts +1 -0
- package/dist/tools/getGitHotspots.d.ts +1 -0
- package/dist/tools/getImportedSignatures.d.ts +1 -0
- package/dist/tools/getImportedSignatures.js +18 -14
- package/dist/tools/getImportedSignatures.js.map +1 -1
- package/dist/tools/getPRTemplate.d.ts +1 -0
- package/dist/tools/getProjectContext.js +23 -10
- package/dist/tools/getProjectContext.js.map +1 -1
- package/dist/tools/getSymbolHistory.d.ts +1 -0
- package/dist/tools/getToolCapabilities.d.ts +10 -5
- package/dist/tools/getToolCapabilities.js +79 -202
- package/dist/tools/getToolCapabilities.js.map +1 -1
- package/dist/tools/getTypeSignature.d.ts +1 -0
- package/dist/tools/getWorkspaceSettings.d.ts +1 -0
- package/dist/tools/gitWrite.d.ts +11 -0
- package/dist/tools/github/actions.d.ts +2 -0
- package/dist/tools/github/composite.d.ts +3 -0
- package/dist/tools/github/issues.d.ts +4 -0
- package/dist/tools/github/pr.d.ts +7 -0
- package/dist/tools/handoffNote.d.ts +1 -0
- package/dist/tools/handoffNote.js +2 -1
- package/dist/tools/handoffNote.js.map +1 -1
- package/dist/tools/headless/lspClient.js +3 -0
- package/dist/tools/headless/lspClient.js.map +1 -1
- package/dist/tools/hoverAtCursor.d.ts +1 -0
- package/dist/tools/httpClient.d.ts +2 -0
- package/dist/tools/httpClient.js +38 -71
- package/dist/tools/httpClient.js.map +1 -1
- package/dist/tools/inlayHints.d.ts +1 -0
- package/dist/tools/launchQuickTask.d.ts +1 -0
- package/dist/tools/listClaudeTasks.d.ts +1 -0
- package/dist/tools/listClaudeTasks.js +10 -8
- package/dist/tools/listClaudeTasks.js.map +1 -1
- package/dist/tools/listTerminals.d.ts +1 -0
- package/dist/tools/lsp.d.ts +15 -0
- package/dist/tools/lsp.js +17 -0
- package/dist/tools/lsp.js.map +1 -1
- package/dist/tools/navigateToSymbolByName.d.ts +1 -0
- package/dist/tools/openDiff.d.ts +1 -0
- package/dist/tools/openDiff.js +4 -1
- package/dist/tools/openDiff.js.map +1 -1
- package/dist/tools/openFile.d.ts +1 -0
- package/dist/tools/openFile.js +4 -1
- package/dist/tools/openFile.js.map +1 -1
- package/dist/tools/openInBrowser.js +6 -1
- package/dist/tools/openInBrowser.js.map +1 -1
- package/dist/tools/organizeImports.d.ts +1 -0
- package/dist/tools/organizeImports.js +5 -3
- package/dist/tools/organizeImports.js.map +1 -1
- package/dist/tools/performanceReport.js +5 -3
- package/dist/tools/performanceReport.js.map +1 -1
- package/dist/tools/planPersistence.d.ts +3 -0
- package/dist/tools/planPersistence.js +4 -1
- package/dist/tools/planPersistence.js.map +1 -1
- package/dist/tools/previewEdit.d.ts +1 -0
- package/dist/tools/previewEdit.js +15 -4
- package/dist/tools/previewEdit.js.map +1 -1
- package/dist/tools/recentTracesDigest.js +54 -11
- package/dist/tools/recentTracesDigest.js.map +1 -1
- package/dist/tools/refactorAnalyze.d.ts +1 -0
- package/dist/tools/refactorExtractFunction.js +4 -1
- package/dist/tools/refactorExtractFunction.js.map +1 -1
- package/dist/tools/refactorPreview.d.ts +1 -0
- package/dist/tools/refactorPreview.js +10 -2
- package/dist/tools/refactorPreview.js.map +1 -1
- package/dist/tools/replaceBlock.d.ts +1 -0
- package/dist/tools/replaceBlock.js +2 -1
- package/dist/tools/replaceBlock.js.map +1 -1
- package/dist/tools/resumeClaudeTask.d.ts +1 -0
- package/dist/tools/runClaudeTask.d.ts +1 -0
- package/dist/tools/runCommand.js +5 -0
- package/dist/tools/runCommand.js.map +1 -1
- package/dist/tools/runTests.js +15 -4
- package/dist/tools/runTests.js.map +1 -1
- package/dist/tools/screenshot.d.ts +1 -0
- package/dist/tools/screenshotAndAnnotate.js +6 -2
- package/dist/tools/screenshotAndAnnotate.js.map +1 -1
- package/dist/tools/searchAndReplace.d.ts +1 -0
- package/dist/tools/searchAndReplace.js +17 -7
- package/dist/tools/searchAndReplace.js.map +1 -1
- package/dist/tools/searchTools.js +20 -19
- 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/signatureHelp.d.ts +1 -0
- package/dist/tools/spawnWorkspace.js +15 -7
- package/dist/tools/spawnWorkspace.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/testRunners/pytest.js +6 -2
- package/dist/tools/testRunners/pytest.js.map +1 -1
- package/dist/tools/testRunners/vitestJest.js +3 -1
- package/dist/tools/testRunners/vitestJest.js.map +1 -1
- package/dist/tools/testTraceToSource.d.ts +1 -0
- package/dist/tools/transaction.d.ts +4 -0
- package/dist/tools/transaction.js +4 -1
- package/dist/tools/transaction.js.map +1 -1
- package/dist/tools/typeHierarchy.d.ts +1 -0
- package/dist/tools/utils.d.ts +22 -0
- package/dist/tools/utils.js +158 -14
- 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/transport.d.ts +3 -1
- package/dist/transport.js +103 -52
- package/dist/transport.js.map +1 -1
- package/dist/winShim.d.ts +34 -0
- package/dist/winShim.js +94 -0
- package/dist/winShim.js.map +1 -0
- package/dist/wireHaltPushDispatch.d.ts +38 -0
- package/dist/wireHaltPushDispatch.js +71 -0
- package/dist/wireHaltPushDispatch.js.map +1 -0
- package/dist/writeFileAtomic.d.ts +23 -0
- package/dist/writeFileAtomic.js +121 -0
- package/dist/writeFileAtomic.js.map +1 -0
- package/package.json +23 -7
- package/scripts/postinstall.mjs +42 -2
- package/scripts/smoke/run-all.mjs +213 -0
- package/scripts/start-all.mjs +572 -0
- package/scripts/start-all.ps1 +209 -0
- package/scripts/start-all.sh +77 -19
- package/scripts/start-orchestrator.ps1 +158 -0
- package/scripts/start-remote.mjs +122 -0
- package/templates/automation-policies/recipe-authoring.json +1 -1
- package/templates/automation-policies/security-first.json +1 -1
- package/templates/automation-policies/strict-lint.json +1 -1
- package/templates/automation-policies/test-driven.json +1 -1
- package/templates/automation-policy.example.json +1 -1
- package/templates/co.patchwork-os.bridge.plist +2 -2
- package/templates/recipes/approval-queue-ui-test.yaml +205 -0
- package/templates/recipes/ctx-loop-test.yaml +1 -1
- package/templates/recipes/fix-errors-on-save.yaml +71 -0
- package/templates/recipes/morning-brief.yaml +5 -2
- package/templates/recipes/project-health-check.yaml +4 -1
- package/templates/recipes/sentry-to-linear.yaml +72 -38
- package/templates/recipes/webhook/apple-watch-health-log.yaml +145 -0
- package/templates/recipes/webhook/customer-escalation.yaml +8 -9
- package/templates/recipes/webhook/meeting-prep.yaml +11 -5
- package/dist/commands/marketplace.d.ts +0 -11
- package/dist/commands/marketplace.js +0 -120
- package/dist/commands/marketplace.js.map +0 -1
- package/dist/recipes/legacyRecipeCompat.d.ts +0 -10
- package/dist/recipes/legacyRecipeCompat.js +0 -131
- package/dist/recipes/legacyRecipeCompat.js.map +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch a directory for any change, falling back to mtime polling when
|
|
3
|
+
* `fs.watch` is unavailable or fails.
|
|
4
|
+
*
|
|
5
|
+
* Motivation: `fs.watch` is unreliable on several real-world filesystems —
|
|
6
|
+
* Windows network drives (SMB/CIFS), WSL bind mounts, and macOS volumes
|
|
7
|
+
* mounted from a Linux host all either throw at watch time or stop firing
|
|
8
|
+
* events silently mid-session. The bridge's plugin hot-reload and kill-
|
|
9
|
+
* switch flag watcher silently went dead on those mounts.
|
|
10
|
+
*
|
|
11
|
+
* Behaviour:
|
|
12
|
+
* - First try `fs.watch(dir, { recursive: false })`. If it succeeds, also
|
|
13
|
+
* listen for the watcher's `error` event so a mid-session breakdown
|
|
14
|
+
* swaps to polling without losing change notifications.
|
|
15
|
+
* - If `fs.watch` throws (e.g. ENOENT — the directory doesn't exist yet,
|
|
16
|
+
* or EPERM — the filesystem doesn't support watching), start polling
|
|
17
|
+
* immediately.
|
|
18
|
+
* - Polling: stat the directory every `pollIntervalMs` (default 2000ms)
|
|
19
|
+
* and stat each non-dot file in it. Fire `onChange` if any file's
|
|
20
|
+
* mtime advanced, a file appeared, or a file disappeared. If the
|
|
21
|
+
* directory itself is missing, keep polling — it may appear later.
|
|
22
|
+
*
|
|
23
|
+
* Caller filters changes by re-reading the file(s) of interest. The helper
|
|
24
|
+
* deliberately does NOT expose the changed filename: polling can't reliably
|
|
25
|
+
* provide that, and fs.watch filenames are already null on some platforms
|
|
26
|
+
* (Windows rename events, atomic saves). One source of truth keeps callers
|
|
27
|
+
* platform-agnostic.
|
|
28
|
+
*
|
|
29
|
+
* Returns a `stop()` function that releases both the watcher and the timer.
|
|
30
|
+
*/
|
|
31
|
+
export declare function watchDirectoryWithFallback(dir: string, onChange: () => void, opts?: {
|
|
32
|
+
pollIntervalMs?: number;
|
|
33
|
+
logger?: {
|
|
34
|
+
warn: (msg: string) => void;
|
|
35
|
+
} | undefined;
|
|
36
|
+
}): () => void;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Watch a directory for any change, falling back to mtime polling when
|
|
5
|
+
* `fs.watch` is unavailable or fails.
|
|
6
|
+
*
|
|
7
|
+
* Motivation: `fs.watch` is unreliable on several real-world filesystems —
|
|
8
|
+
* Windows network drives (SMB/CIFS), WSL bind mounts, and macOS volumes
|
|
9
|
+
* mounted from a Linux host all either throw at watch time or stop firing
|
|
10
|
+
* events silently mid-session. The bridge's plugin hot-reload and kill-
|
|
11
|
+
* switch flag watcher silently went dead on those mounts.
|
|
12
|
+
*
|
|
13
|
+
* Behaviour:
|
|
14
|
+
* - First try `fs.watch(dir, { recursive: false })`. If it succeeds, also
|
|
15
|
+
* listen for the watcher's `error` event so a mid-session breakdown
|
|
16
|
+
* swaps to polling without losing change notifications.
|
|
17
|
+
* - If `fs.watch` throws (e.g. ENOENT — the directory doesn't exist yet,
|
|
18
|
+
* or EPERM — the filesystem doesn't support watching), start polling
|
|
19
|
+
* immediately.
|
|
20
|
+
* - Polling: stat the directory every `pollIntervalMs` (default 2000ms)
|
|
21
|
+
* and stat each non-dot file in it. Fire `onChange` if any file's
|
|
22
|
+
* mtime advanced, a file appeared, or a file disappeared. If the
|
|
23
|
+
* directory itself is missing, keep polling — it may appear later.
|
|
24
|
+
*
|
|
25
|
+
* Caller filters changes by re-reading the file(s) of interest. The helper
|
|
26
|
+
* deliberately does NOT expose the changed filename: polling can't reliably
|
|
27
|
+
* provide that, and fs.watch filenames are already null on some platforms
|
|
28
|
+
* (Windows rename events, atomic saves). One source of truth keeps callers
|
|
29
|
+
* platform-agnostic.
|
|
30
|
+
*
|
|
31
|
+
* Returns a `stop()` function that releases both the watcher and the timer.
|
|
32
|
+
*/
|
|
33
|
+
export function watchDirectoryWithFallback(dir, onChange, opts = {}) {
|
|
34
|
+
const pollIntervalMs = opts.pollIntervalMs ?? 2000;
|
|
35
|
+
const logger = opts.logger;
|
|
36
|
+
let watcher = null;
|
|
37
|
+
let pollTimer = null;
|
|
38
|
+
let stopped = false;
|
|
39
|
+
// Snapshot: filename → mtimeMs. Empty Map when directory doesn't exist.
|
|
40
|
+
let snapshot = new Map();
|
|
41
|
+
const snapshotDir = () => {
|
|
42
|
+
const out = new Map();
|
|
43
|
+
try {
|
|
44
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
45
|
+
for (const ent of entries) {
|
|
46
|
+
if (!ent.isFile())
|
|
47
|
+
continue;
|
|
48
|
+
if (ent.name.startsWith("."))
|
|
49
|
+
continue;
|
|
50
|
+
try {
|
|
51
|
+
const st = fs.statSync(path.join(dir, ent.name));
|
|
52
|
+
out.set(ent.name, st.mtimeMs);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
/* file disappeared between readdir and stat — ignore */
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
/* dir missing — empty snapshot */
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
};
|
|
64
|
+
const startPolling = (reason) => {
|
|
65
|
+
if (pollTimer || stopped)
|
|
66
|
+
return;
|
|
67
|
+
if (logger)
|
|
68
|
+
logger.warn(`[fs-watch] falling back to polling: ${reason}`);
|
|
69
|
+
snapshot = snapshotDir();
|
|
70
|
+
pollTimer = setInterval(() => {
|
|
71
|
+
if (stopped)
|
|
72
|
+
return;
|
|
73
|
+
const next = snapshotDir();
|
|
74
|
+
let changed = next.size !== snapshot.size;
|
|
75
|
+
if (!changed) {
|
|
76
|
+
for (const [name, mtime] of next) {
|
|
77
|
+
const prev = snapshot.get(name);
|
|
78
|
+
if (prev === undefined || prev !== mtime) {
|
|
79
|
+
changed = true;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
snapshot = next;
|
|
85
|
+
if (changed)
|
|
86
|
+
onChange();
|
|
87
|
+
}, pollIntervalMs);
|
|
88
|
+
// Don't keep the event loop alive solely for polling.
|
|
89
|
+
pollTimer.unref?.();
|
|
90
|
+
};
|
|
91
|
+
try {
|
|
92
|
+
watcher = fs.watch(dir, { recursive: false }, () => {
|
|
93
|
+
if (!stopped)
|
|
94
|
+
onChange();
|
|
95
|
+
});
|
|
96
|
+
watcher.on("error", (err) => {
|
|
97
|
+
// Watcher broke mid-session. Tear it down, start polling.
|
|
98
|
+
try {
|
|
99
|
+
watcher?.close();
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
/* ignore */
|
|
103
|
+
}
|
|
104
|
+
watcher = null;
|
|
105
|
+
startPolling(`watcher error: ${err.message}`);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
startPolling(`fs.watch threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
110
|
+
}
|
|
111
|
+
return () => {
|
|
112
|
+
stopped = true;
|
|
113
|
+
if (watcher) {
|
|
114
|
+
try {
|
|
115
|
+
watcher.close();
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
/* ignore */
|
|
119
|
+
}
|
|
120
|
+
watcher = null;
|
|
121
|
+
}
|
|
122
|
+
if (pollTimer) {
|
|
123
|
+
clearInterval(pollTimer);
|
|
124
|
+
pollTimer = null;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=fsWatchWithFallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsWatchWithFallback.js","sourceRoot":"","sources":["../src/fsWatchWithFallback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge → push relay dispatch for recipe halt events.
|
|
3
|
+
*
|
|
4
|
+
* Sibling of `dispatchPushNotification` in [src/approvalHttp.ts](./approvalHttp.ts).
|
|
5
|
+
* The bridge POSTs a halt payload to `${pushServiceUrl}/halt`; the relay
|
|
6
|
+
* (a hosted push service or the dashboard's `/api/relay/halt` route)
|
|
7
|
+
* fans it out to every subscribed browser via Web Push.
|
|
8
|
+
*
|
|
9
|
+
* SSRF guard mirrors the approval dispatcher: HTTPS-only, hostname
|
|
10
|
+
* blocklist (localhost / loopback / private IPs after DNS resolve),
|
|
11
|
+
* 5s abort timeout, fire-and-forget so the recipe runner is never
|
|
12
|
+
* blocked on a push relay outage.
|
|
13
|
+
*
|
|
14
|
+
* Wired via `wireHaltPushDispatch` (subscribes to ActivityLog) — keeps
|
|
15
|
+
* the runner itself ignorant of push transport.
|
|
16
|
+
*/
|
|
17
|
+
export interface HaltPushPayload {
|
|
18
|
+
recipeName: string;
|
|
19
|
+
runSeq: number;
|
|
20
|
+
/** Always "error" or "halted" — the runner emits "error" today; the
|
|
21
|
+
* shape leaves room for the dashboard's halted/error distinction. */
|
|
22
|
+
status: "error" | "halted";
|
|
23
|
+
haltReason?: string;
|
|
24
|
+
haltCategory?: string;
|
|
25
|
+
stepId?: string;
|
|
26
|
+
errorMessage?: string;
|
|
27
|
+
occurredAt?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fire-and-forget dispatch. Never throws — caller cannot recover from a
|
|
31
|
+
* push relay outage. Logged via console.warn for ops visibility.
|
|
32
|
+
*/
|
|
33
|
+
export declare function dispatchHaltPushNotification(pushServiceUrl: string, pushServiceToken: string, payload: HaltPushPayload): Promise<void>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge → push relay dispatch for recipe halt events.
|
|
3
|
+
*
|
|
4
|
+
* Sibling of `dispatchPushNotification` in [src/approvalHttp.ts](./approvalHttp.ts).
|
|
5
|
+
* The bridge POSTs a halt payload to `${pushServiceUrl}/halt`; the relay
|
|
6
|
+
* (a hosted push service or the dashboard's `/api/relay/halt` route)
|
|
7
|
+
* fans it out to every subscribed browser via Web Push.
|
|
8
|
+
*
|
|
9
|
+
* SSRF guard mirrors the approval dispatcher: HTTPS-only, hostname
|
|
10
|
+
* blocklist (localhost / loopback / private IPs after DNS resolve),
|
|
11
|
+
* 5s abort timeout, fire-and-forget so the recipe runner is never
|
|
12
|
+
* blocked on a push relay outage.
|
|
13
|
+
*
|
|
14
|
+
* Wired via `wireHaltPushDispatch` (subscribes to ActivityLog) — keeps
|
|
15
|
+
* the runner itself ignorant of push transport.
|
|
16
|
+
*/
|
|
17
|
+
import dns from "node:dns/promises";
|
|
18
|
+
/**
|
|
19
|
+
* Same SSRF blocklist as `dispatchPushNotification` in approvalHttp.ts.
|
|
20
|
+
* Duplicated inline to keep this dispatcher self-contained (the
|
|
21
|
+
* approvalHttp version is module-private and the file is already
|
|
22
|
+
* dense). If a third dispatcher ever lands, extract to a shared
|
|
23
|
+
* `src/sanitizeIp.ts`.
|
|
24
|
+
*/
|
|
25
|
+
function isBlockedIp(ip) {
|
|
26
|
+
if (ip === "::1" || ip === "0:0:0:0:0:0:0:1")
|
|
27
|
+
return true;
|
|
28
|
+
const parts = ip.split(".").map(Number);
|
|
29
|
+
if (parts.length !== 4)
|
|
30
|
+
return false;
|
|
31
|
+
const [a, b] = parts;
|
|
32
|
+
if (a === 127)
|
|
33
|
+
return true;
|
|
34
|
+
if (a === 10)
|
|
35
|
+
return true;
|
|
36
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
37
|
+
return true;
|
|
38
|
+
if (a === 192 && b === 168)
|
|
39
|
+
return true;
|
|
40
|
+
if (a === 169 && b === 254)
|
|
41
|
+
return true;
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Fire-and-forget dispatch. Never throws — caller cannot recover from a
|
|
46
|
+
* push relay outage. Logged via console.warn for ops visibility.
|
|
47
|
+
*/
|
|
48
|
+
export async function dispatchHaltPushNotification(pushServiceUrl, pushServiceToken, payload) {
|
|
49
|
+
if (!pushServiceUrl.startsWith("https://")) {
|
|
50
|
+
console.warn(`[halt-push] Rejected non-HTTPS push service URL`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let hostname;
|
|
54
|
+
try {
|
|
55
|
+
hostname = new URL(pushServiceUrl).hostname;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
console.warn(`[halt-push] Malformed push service URL — skipping`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (hostname === "localhost") {
|
|
62
|
+
console.warn(`[halt-push] Blocked loopback push service hostname`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const resolved = await dns.lookup(hostname);
|
|
67
|
+
if (isBlockedIp(resolved.address)) {
|
|
68
|
+
console.warn(`[halt-push] Blocked private/loopback IP for push service: ${resolved.address}`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
console.warn(`[halt-push] DNS resolution failed for ${hostname}: ${err instanceof Error ? err.message : String(err)}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const controller = new AbortController();
|
|
77
|
+
const timer = setTimeout(() => controller.abort(), 5_000);
|
|
78
|
+
try {
|
|
79
|
+
const res = await fetch(`${pushServiceUrl}/halt`, {
|
|
80
|
+
method: "POST",
|
|
81
|
+
headers: {
|
|
82
|
+
"Content-Type": "application/json",
|
|
83
|
+
Authorization: `Bearer ${pushServiceToken}`,
|
|
84
|
+
},
|
|
85
|
+
body: JSON.stringify(payload),
|
|
86
|
+
signal: controller.signal,
|
|
87
|
+
});
|
|
88
|
+
if (!res.ok) {
|
|
89
|
+
// 404 is informational ("no subscribers yet") — same relay
|
|
90
|
+
// contract as the approval path. Anything else is worth a warn.
|
|
91
|
+
if (res.status !== 404) {
|
|
92
|
+
console.warn(`[halt-push] Non-2xx from push relay: ${res.status} ${res.statusText}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.warn(`[halt-push] Dispatch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
clearTimeout(timer);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=haltPushDispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"haltPushDispatch.js","sourceRoot":"","sources":["../src/haltPushDispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict allow-list validation for HTTP request body keys.
|
|
3
|
+
*
|
|
4
|
+
* `readJsonBody<T>()` is type-erased at runtime — the generic only documents
|
|
5
|
+
* the EXPECTED shape; unknown top-level keys are silently kept on the parsed
|
|
6
|
+
* object and dropped by the handler's destructure. Misspelled fields
|
|
7
|
+
* (`enabledZ`, `targerName`, `vasr`) succeed as a no-op + 200, which masks
|
|
8
|
+
* client bugs and complicates dashboard debugging.
|
|
9
|
+
*
|
|
10
|
+
* This helper closes the silent-failure gap for the highest-value
|
|
11
|
+
* configuration endpoints (settings, telemetry, kill-switch, recipe run /
|
|
12
|
+
* promote / trust). Callers extract the body, run this check, and on
|
|
13
|
+
* failure return a 400 enumerating the unknown keys.
|
|
14
|
+
*
|
|
15
|
+
* Sister module to `httpErrorResponse.ts`; same one-function-one-file style.
|
|
16
|
+
*/
|
|
17
|
+
import type { ServerResponse } from "node:http";
|
|
18
|
+
export type AllowedKeysResult = {
|
|
19
|
+
ok: true;
|
|
20
|
+
} | {
|
|
21
|
+
ok: false;
|
|
22
|
+
unknownKeys: string[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Returns `{ok: true}` when every own enumerable key on `body` is in
|
|
26
|
+
* `allowed`. Otherwise lists the offending keys.
|
|
27
|
+
*
|
|
28
|
+
* Uses `Object.hasOwn` to avoid prototype walk surface (see project memory
|
|
29
|
+
* `feedback_record_string_prototype_walk.md` — 5 prod sites burned by
|
|
30
|
+
* `key in obj` / bare bracket access on attacker-controlled objects).
|
|
31
|
+
*
|
|
32
|
+
* Non-object / null / array bodies short-circuit `{ok: true}` — the
|
|
33
|
+
* handler's own shape-check will reject them with its existing 400.
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateAllowedBodyKeys(body: unknown, allowed: readonly string[]): AllowedKeysResult;
|
|
36
|
+
/**
|
|
37
|
+
* Convenience: writes the canonical 400 response and returns true when the
|
|
38
|
+
* body fails the allow-list check. Returns false on success so callers can
|
|
39
|
+
* `if (respondIfUnknownBodyKeys(...)) return;` and keep flowing.
|
|
40
|
+
*/
|
|
41
|
+
export declare function respondIfUnknownBodyKeys(res: ServerResponse, body: unknown, allowed: readonly string[]): boolean;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns `{ok: true}` when every own enumerable key on `body` is in
|
|
3
|
+
* `allowed`. Otherwise lists the offending keys.
|
|
4
|
+
*
|
|
5
|
+
* Uses `Object.hasOwn` to avoid prototype walk surface (see project memory
|
|
6
|
+
* `feedback_record_string_prototype_walk.md` — 5 prod sites burned by
|
|
7
|
+
* `key in obj` / bare bracket access on attacker-controlled objects).
|
|
8
|
+
*
|
|
9
|
+
* Non-object / null / array bodies short-circuit `{ok: true}` — the
|
|
10
|
+
* handler's own shape-check will reject them with its existing 400.
|
|
11
|
+
*/
|
|
12
|
+
export function validateAllowedBodyKeys(body, allowed) {
|
|
13
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) {
|
|
14
|
+
return { ok: true };
|
|
15
|
+
}
|
|
16
|
+
const allowSet = new Set(allowed);
|
|
17
|
+
const unknownKeys = [];
|
|
18
|
+
for (const key of Object.keys(body)) {
|
|
19
|
+
if (!Object.hasOwn(body, key))
|
|
20
|
+
continue;
|
|
21
|
+
if (!allowSet.has(key))
|
|
22
|
+
unknownKeys.push(key);
|
|
23
|
+
}
|
|
24
|
+
if (unknownKeys.length > 0) {
|
|
25
|
+
return { ok: false, unknownKeys };
|
|
26
|
+
}
|
|
27
|
+
return { ok: true };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convenience: writes the canonical 400 response and returns true when the
|
|
31
|
+
* body fails the allow-list check. Returns false on success so callers can
|
|
32
|
+
* `if (respondIfUnknownBodyKeys(...)) return;` and keep flowing.
|
|
33
|
+
*/
|
|
34
|
+
export function respondIfUnknownBodyKeys(res, body, allowed) {
|
|
35
|
+
const result = validateAllowedBodyKeys(body, allowed);
|
|
36
|
+
if (result.ok)
|
|
37
|
+
return false;
|
|
38
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
39
|
+
res.end(JSON.stringify({
|
|
40
|
+
error: "Unknown body fields",
|
|
41
|
+
unknownKeys: result.unknownKeys,
|
|
42
|
+
}));
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=httpBodyValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpBodyValidation.js","sourceRoot":"","sources":["../src/httpBodyValidation.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAAa,EACb,OAA0B;IAE1B,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAA+B,CAAC,EAAE,CAAC;QAC/D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAc,EAAE,GAAG,CAAC;YAAE,SAAS;QAClD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,GAAmB,EACnB,IAAa,EACb,OAA0B;IAE1B,MAAM,MAAM,GAAG,uBAAuB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAC5B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;QACb,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CACH,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized HTTP error responder for the bridge's plain-`http` route
|
|
3
|
+
* handlers.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the ~96 inline `res.end(JSON.stringify({error: err.message}))`
|
|
6
|
+
* blocks scattered across `server.ts`, `connectorRoutes.ts`,
|
|
7
|
+
* `recipeRoutes.ts`, `inboxRoutes.ts`, and `oauthRoutes.ts` — every one of
|
|
8
|
+
* which leaked the underlying error message (and sometimes a stack frame
|
|
9
|
+
* via `Error.toString`) to the network. CodeQL flagged each as
|
|
10
|
+
* `js/stack-trace-exposure` (89 open alerts at the time of writing).
|
|
11
|
+
*
|
|
12
|
+
* Contract:
|
|
13
|
+
* - Always returns a generic `{error: "Internal server error"}` body, never
|
|
14
|
+
* the underlying error.message — even for non-Error throws.
|
|
15
|
+
* - Logs the full detail (stack preferred, message fallback, String(err)
|
|
16
|
+
* last) to stderr with an optional context label so post-incident
|
|
17
|
+
* debugging is unaffected.
|
|
18
|
+
* - Idempotent on `headersSent` / `writableEnded` so callers nested inside
|
|
19
|
+
* other try/catch blocks can safely call this without re-throwing.
|
|
20
|
+
*
|
|
21
|
+
* Note: the dashboard's Next.js route handlers (`dashboard/src/app/api/**`)
|
|
22
|
+
* are a separate runtime — they use `NextResponse.json(...)` and have their
|
|
23
|
+
* own (smaller) leak surface; this helper is bridge-side only.
|
|
24
|
+
*/
|
|
25
|
+
import type { ServerResponse } from "node:http";
|
|
26
|
+
/**
|
|
27
|
+
* Write a generic 500 response and log the underlying error detail
|
|
28
|
+
* server-side.
|
|
29
|
+
*
|
|
30
|
+
* @param res The Node http response to write to.
|
|
31
|
+
* @param err The thrown value caught by the route handler.
|
|
32
|
+
* @param context Optional short tag identifying the route ("recipes/lint",
|
|
33
|
+
* "connectors/jira/connect", etc.). Surfaces in the server
|
|
34
|
+
* log only — never sent to the client.
|
|
35
|
+
*/
|
|
36
|
+
export declare function respond500(res: ServerResponse, err: unknown, context?: string): void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized HTTP error responder for the bridge's plain-`http` route
|
|
3
|
+
* handlers.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the ~96 inline `res.end(JSON.stringify({error: err.message}))`
|
|
6
|
+
* blocks scattered across `server.ts`, `connectorRoutes.ts`,
|
|
7
|
+
* `recipeRoutes.ts`, `inboxRoutes.ts`, and `oauthRoutes.ts` — every one of
|
|
8
|
+
* which leaked the underlying error message (and sometimes a stack frame
|
|
9
|
+
* via `Error.toString`) to the network. CodeQL flagged each as
|
|
10
|
+
* `js/stack-trace-exposure` (89 open alerts at the time of writing).
|
|
11
|
+
*
|
|
12
|
+
* Contract:
|
|
13
|
+
* - Always returns a generic `{error: "Internal server error"}` body, never
|
|
14
|
+
* the underlying error.message — even for non-Error throws.
|
|
15
|
+
* - Logs the full detail (stack preferred, message fallback, String(err)
|
|
16
|
+
* last) to stderr with an optional context label so post-incident
|
|
17
|
+
* debugging is unaffected.
|
|
18
|
+
* - Idempotent on `headersSent` / `writableEnded` so callers nested inside
|
|
19
|
+
* other try/catch blocks can safely call this without re-throwing.
|
|
20
|
+
*
|
|
21
|
+
* Note: the dashboard's Next.js route handlers (`dashboard/src/app/api/**`)
|
|
22
|
+
* are a separate runtime — they use `NextResponse.json(...)` and have their
|
|
23
|
+
* own (smaller) leak surface; this helper is bridge-side only.
|
|
24
|
+
*/
|
|
25
|
+
const GENERIC_BODY = JSON.stringify({ error: "Internal server error" });
|
|
26
|
+
/**
|
|
27
|
+
* Write a generic 500 response and log the underlying error detail
|
|
28
|
+
* server-side.
|
|
29
|
+
*
|
|
30
|
+
* @param res The Node http response to write to.
|
|
31
|
+
* @param err The thrown value caught by the route handler.
|
|
32
|
+
* @param context Optional short tag identifying the route ("recipes/lint",
|
|
33
|
+
* "connectors/jira/connect", etc.). Surfaces in the server
|
|
34
|
+
* log only — never sent to the client.
|
|
35
|
+
*/
|
|
36
|
+
export function respond500(res, err, context) {
|
|
37
|
+
const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
|
38
|
+
console.error(`[http-500]${context ? ` ${context}` : ""}: ${detail}`);
|
|
39
|
+
if (!res.headersSent) {
|
|
40
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
41
|
+
}
|
|
42
|
+
if (!res.writableEnded) {
|
|
43
|
+
res.end(GENERIC_BODY);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=httpErrorResponse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpErrorResponse.js","sourceRoot":"","sources":["../src/httpErrorResponse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CACxB,GAAmB,EACnB,GAAY,EACZ,OAAgB;IAEhB,MAAM,MAAM,GACV,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAClE,OAAO,CAAC,KAAK,CAAC,aAAa,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QACvB,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
|
package/dist/inboxRoutes.d.ts
CHANGED
|
@@ -14,6 +14,28 @@
|
|
|
14
14
|
* preserved verbatim from the original.
|
|
15
15
|
*/
|
|
16
16
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
17
|
+
/**
|
|
18
|
+
* Phase 0β provenance shape. Optional + additive — files without
|
|
19
|
+
* frontmatter return `provenance: undefined`.
|
|
20
|
+
*/
|
|
21
|
+
export interface InboxProvenance {
|
|
22
|
+
recipe?: string;
|
|
23
|
+
runSeq?: number;
|
|
24
|
+
trigger?: string;
|
|
25
|
+
deliveredAt?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Split a markdown file into its YAML-frontmatter block (parsed as a flat
|
|
29
|
+
* `key: value` map) and the remaining body. Frontmatter is recognised
|
|
30
|
+
* only when the file begins with `---\n` and a closing `---` line is
|
|
31
|
+
* found within the first 30 lines (cap to bound the scan). Returns
|
|
32
|
+
* `{ provenance: undefined, body: content }` for files without
|
|
33
|
+
* frontmatter so callers degrade gracefully on legacy inbox items.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseInboxFile(content: string): {
|
|
36
|
+
provenance: InboxProvenance | undefined;
|
|
37
|
+
body: string;
|
|
38
|
+
};
|
|
17
39
|
/**
|
|
18
40
|
* Try to handle an `/inbox` or `/inbox/<filename>.md` route. Returns true
|
|
19
41
|
* if the route was dispatched (caller should `return` from the request
|