patchwork-os 0.2.0-beta.1 → 0.2.0-beta.10.canary.100
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 +201 -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.js +1 -1
- 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 +38 -2
- package/dist/analyticsPrefs.js +148 -23
- 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 +219 -35
- 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.js +23 -8
- package/dist/claudeDriver.js.map +1 -1
- package/dist/claudeOrchestrator.d.ts +1 -1
- package/dist/claudeOrchestrator.js +87 -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/connect.d.ts +47 -0
- package/dist/commands/connect.js +419 -0
- package/dist/commands/connect.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 +151 -0
- package/dist/commands/recipe.js +649 -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.d.ts +25 -0
- package/dist/commands/task.js +62 -42
- 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/tracesExport.d.ts +15 -1
- package/dist/commands/tracesExport.js +39 -5
- package/dist/commands/tracesExport.js.map +1 -1
- package/dist/commands/tracesImport.js +21 -4
- package/dist/commands/tracesImport.js.map +1 -1
- package/dist/commitIssueLinkLog.d.ts +16 -0
- package/dist/commitIssueLinkLog.js +110 -24
- 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 +47 -3
- package/dist/config.js +111 -21
- package/dist/config.js.map +1 -1
- package/dist/connectorRoutes.js +1422 -57
- 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 +60 -0
- package/dist/connectors/connectorRegistry.js +354 -0
- package/dist/connectors/connectorRegistry.js.map +1 -0
- package/dist/connectors/datadog.js +41 -5
- 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 +234 -3
- 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/mcpClient.js +37 -23
- package/dist/connectors/mcpClient.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/notion.d.ts +1 -1
- package/dist/connectors/notion.js +13 -4
- package/dist/connectors/notion.js.map +1 -1
- 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 +579 -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 +633 -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.d.ts +8 -6
- package/dist/decisionReplay.js +50 -17
- 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 +33 -9
- 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.js +69 -16
- package/dist/drivers/claude/subprocess.js.map +1 -1
- 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/local/index.d.ts +2 -0
- package/dist/drivers/local/index.js +12 -0
- package/dist/drivers/local/index.js.map +1 -1
- 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 +267 -87
- 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 +34 -2
- 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/inboxRoutes.d.ts +22 -0
- package/dist/inboxRoutes.js +61 -1
- package/dist/inboxRoutes.js.map +1 -1
- package/dist/index.js +1206 -158
- package/dist/index.js.map +1 -1
- package/dist/installGuard.js +6 -2
- package/dist/installGuard.js.map +1 -1
- package/dist/localEndpointGuard.d.ts +25 -0
- package/dist/localEndpointGuard.js +101 -0
- package/dist/localEndpointGuard.js.map +1 -0
- package/dist/lockfile.js +31 -4
- package/dist/lockfile.js.map +1 -1
- package/dist/oauth.d.ts +9 -0
- package/dist/oauth.js +33 -0
- package/dist/oauth.js.map +1 -1
- package/dist/oauthRoutes.d.ts +1 -1
- package/dist/oauthRoutes.js +5 -3
- package/dist/oauthRoutes.js.map +1 -1
- package/dist/orchestrator/childBridgeClient.d.ts +5 -0
- package/dist/orchestrator/childBridgeClient.js +28 -1
- package/dist/orchestrator/childBridgeClient.js.map +1 -1
- package/dist/orchestrator/childBridgeRegistry.js +29 -11
- package/dist/orchestrator/childBridgeRegistry.js.map +1 -1
- package/dist/orchestrator/orchestratorBridge.d.ts +33 -0
- package/dist/orchestrator/orchestratorBridge.js +70 -9
- package/dist/orchestrator/orchestratorBridge.js.map +1 -1
- package/dist/patchworkConfig.d.ts +44 -1
- package/dist/patchworkConfig.js +28 -3
- 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 +3 -2
- 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 +3 -3
- package/dist/prompts.js.map +1 -1
- package/dist/recipeOrchestration.d.ts +9 -0
- package/dist/recipeOrchestration.js +341 -24
- package/dist/recipeOrchestration.js.map +1 -1
- package/dist/recipeRoutes.d.ts +58 -2
- package/dist/recipeRoutes.js +744 -115
- 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 +25 -5
- package/dist/recipes/agentExecutor.js.map +1 -1
- package/dist/recipes/chainedRunner.d.ts +2 -0
- package/dist/recipes/chainedRunner.js +156 -9
- package/dist/recipes/chainedRunner.js.map +1 -1
- package/dist/recipes/compiler.js +9 -5
- package/dist/recipes/compiler.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.d.ts +9 -0
- package/dist/recipes/dependencyGraph.js +32 -7
- package/dist/recipes/dependencyGraph.js.map +1 -1
- package/dist/recipes/githubInstallSource.d.ts +135 -0
- package/dist/recipes/githubInstallSource.js +236 -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 +154 -0
- package/dist/recipes/idempotencyKey.js +375 -0
- package/dist/recipes/idempotencyKey.js.map +1 -0
- package/dist/recipes/installer.js +58 -3
- 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 +116 -6
- 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 +65 -2
- package/dist/recipes/schemaGenerator.js +119 -7
- 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 +33 -7
- package/dist/recipes/toolRegistry.js.map +1 -1
- package/dist/recipes/tools/airtable.d.ts +15 -0
- package/dist/recipes/tools/airtable.js +239 -0
- package/dist/recipes/tools/airtable.js.map +1 -0
- 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 +27 -5
- 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 +7 -0
- package/dist/recipes/tools/index.js +7 -0
- package/dist/recipes/tools/index.js.map +1 -1
- package/dist/recipes/tools/resend.d.ts +8 -0
- package/dist/recipes/tools/resend.js +152 -0
- package/dist/recipes/tools/resend.js.map +1 -0
- package/dist/recipes/tools/sendgrid.d.ts +9 -0
- package/dist/recipes/tools/sendgrid.js +174 -0
- package/dist/recipes/tools/sendgrid.js.map +1 -0
- package/dist/recipes/tools/slack.js +1 -1
- package/dist/recipes/tools/twilio.d.ts +11 -0
- package/dist/recipes/tools/twilio.js +179 -0
- package/dist/recipes/tools/twilio.js.map +1 -0
- package/dist/recipes/tools/vercel.d.ts +9 -0
- package/dist/recipes/tools/vercel.js +145 -0
- package/dist/recipes/tools/vercel.js.map +1 -0
- package/dist/recipes/validation.d.ts +17 -0
- package/dist/recipes/validation.js +141 -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 +185 -8
- package/dist/recipes/yamlRunner.js +967 -224
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +19 -3
- package/dist/recipesHttp.js +67 -11
- 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 +887 -198
- package/dist/server.d.ts +160 -3
- package/dist/server.js +1099 -122
- 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 +37 -19
- 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/getGitStatus.js +6 -1
- package/dist/tools/getGitStatus.js.map +1 -1
- 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 +116 -204
- 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 +4 -1
- package/dist/tools/github/composite.js +7 -7
- package/dist/tools/github/composite.js.map +1 -1
- package/dist/tools/github/issues.d.ts +4 -0
- package/dist/tools/github/pr.d.ts +13 -6
- package/dist/tools/github/pr.js +18 -11
- package/dist/tools/github/pr.js.map +1 -1
- 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/index.js +14 -10
- package/dist/tools/index.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 +31 -5
- 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/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 +21 -12
- package/dist/tools/searchAndReplace.js.map +1 -1
- package/dist/tools/searchTools.d.ts +26 -0
- package/dist/tools/searchTools.js +62 -21
- 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/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 +13 -1
- package/dist/tools/transaction.js +63 -5
- package/dist/tools/transaction.js.map +1 -1
- package/dist/tools/typeHierarchy.d.ts +1 -0
- package/dist/tools/utils.d.ts +33 -0
- package/dist/tools/utils.js +122 -18
- 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 +126 -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 +73 -17
- 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 +1 -1
- 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 -16
- package/dist/commands/marketplace.js +0 -32
- 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,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auditEnv — statically scan a recipe YAML for {{env.FOO}} references
|
|
3
|
+
* and verify those vars exist in process.env (or an optional .env file).
|
|
4
|
+
*
|
|
5
|
+
* Fills a gap that `recipe preflight` does NOT cover: preflight checks
|
|
6
|
+
* lint/tools/write-steps but silently produces empty string at runtime
|
|
7
|
+
* for missing {{env.FOO}} references. auditEnv catches that statically.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
10
|
+
import { resolve } from "node:path";
|
|
11
|
+
import { parse as parseYaml } from "yaml";
|
|
12
|
+
import { resolveFilePath } from "../tools/utils.js";
|
|
13
|
+
// ── Pattern ──────────────────────────────────────────────────────────────────
|
|
14
|
+
/** Matches {{env.FOO}} and {{env.foo}} references in template strings. */
|
|
15
|
+
const ENV_REF_RE = /\{\{env\.([A-Za-z_][A-Za-z0-9_]*)\}\}/g;
|
|
16
|
+
/**
|
|
17
|
+
* Walk every string value in an arbitrary JSON/YAML-parsed object and collect
|
|
18
|
+
* all unique env var names referenced via {{env.NAME}}.
|
|
19
|
+
*/
|
|
20
|
+
function collectEnvRefs(value, seen = new Set()) {
|
|
21
|
+
if (typeof value === "string") {
|
|
22
|
+
for (const m of value.matchAll(ENV_REF_RE)) {
|
|
23
|
+
// m[1] is always defined — the regex has exactly one capture group
|
|
24
|
+
seen.add(m[1]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (Array.isArray(value)) {
|
|
28
|
+
for (const item of value) {
|
|
29
|
+
collectEnvRefs(item, seen);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (value !== null && typeof value === "object") {
|
|
33
|
+
for (const v of Object.values(value)) {
|
|
34
|
+
collectEnvRefs(v, seen);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return seen;
|
|
38
|
+
}
|
|
39
|
+
// ── .env file parser ──────────────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Parse a simple KEY=VALUE .env file. Lines starting with # and blank lines
|
|
42
|
+
* are ignored. Values may be optionally quoted with ' or ". Does NOT expand
|
|
43
|
+
* variable references — only static values are relevant for presence checks.
|
|
44
|
+
*/
|
|
45
|
+
function parseDotEnv(content) {
|
|
46
|
+
const map = new Map();
|
|
47
|
+
for (const rawLine of content.split(/\r?\n/)) {
|
|
48
|
+
const line = rawLine.trim();
|
|
49
|
+
if (!line || line.startsWith("#"))
|
|
50
|
+
continue;
|
|
51
|
+
const eqIdx = line.indexOf("=");
|
|
52
|
+
if (eqIdx === -1)
|
|
53
|
+
continue;
|
|
54
|
+
const key = line.slice(0, eqIdx).trim();
|
|
55
|
+
if (!key)
|
|
56
|
+
continue;
|
|
57
|
+
let val = line.slice(eqIdx + 1).trim();
|
|
58
|
+
// Strip surrounding quotes if present
|
|
59
|
+
if ((val.startsWith('"') && val.endsWith('"')) ||
|
|
60
|
+
(val.startsWith("'") && val.endsWith("'"))) {
|
|
61
|
+
val = val.slice(1, -1);
|
|
62
|
+
}
|
|
63
|
+
map.set(key, val);
|
|
64
|
+
}
|
|
65
|
+
return map;
|
|
66
|
+
}
|
|
67
|
+
// ── Placeholder heuristic ─────────────────────────────────────────────────────
|
|
68
|
+
/** Values that look like placeholders rather than real secrets. */
|
|
69
|
+
const PLACEHOLDER_RE = /^(changeme|replace[-_]?me|todo|fixme|<[^>]+>|\[.*\]|your[-_]?.*here|placeholder|example|xxx+|dummy|fake|test)$/i;
|
|
70
|
+
function looksLikePlaceholder(val) {
|
|
71
|
+
return PLACEHOLDER_RE.test(val.trim());
|
|
72
|
+
}
|
|
73
|
+
// ── Public API ────────────────────────────────────────────────────────────────
|
|
74
|
+
/**
|
|
75
|
+
* Scan `recipeRef` (file path or installed recipe name) for {{env.FOO}}
|
|
76
|
+
* references and report which env vars are present / missing.
|
|
77
|
+
*
|
|
78
|
+
* `recipeRef` is resolved exactly like `recipe lint` — absolute/relative file
|
|
79
|
+
* paths are used directly; bare names are looked up under the default recipes
|
|
80
|
+
* dir. We intentionally do NOT re-import the heavy `resolveRecipePath` helper
|
|
81
|
+
* from recipe.ts (would pull in the entire 2 400-line module). Instead we do
|
|
82
|
+
* a minimal two-step: try direct path first, then give a clear error.
|
|
83
|
+
*/
|
|
84
|
+
export async function runAuditEnv(recipeRef, options = {}) {
|
|
85
|
+
// ── 1. Resolve recipe path ─────────────────────────────────────────────────
|
|
86
|
+
const directPath = resolve(recipeRef);
|
|
87
|
+
let recipePath;
|
|
88
|
+
if (existsSync(directPath) && statSync(directPath).isFile()) {
|
|
89
|
+
recipePath = directPath;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
return {
|
|
93
|
+
ok: false,
|
|
94
|
+
recipe: recipeRef,
|
|
95
|
+
missing: [],
|
|
96
|
+
present: [],
|
|
97
|
+
warnings: [`Recipe file not found: ${recipeRef}`],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// ── 2. Load + parse YAML ───────────────────────────────────────────────────
|
|
101
|
+
let raw;
|
|
102
|
+
try {
|
|
103
|
+
const text = readFileSync(recipePath, "utf-8");
|
|
104
|
+
raw = parseYaml(text);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
recipe: recipeRef,
|
|
111
|
+
missing: [],
|
|
112
|
+
present: [],
|
|
113
|
+
warnings: [`Failed to parse recipe YAML: ${msg}`],
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Prefer recipe.name for display; fall back to path.
|
|
117
|
+
const recipeName = raw !== null &&
|
|
118
|
+
typeof raw === "object" &&
|
|
119
|
+
typeof raw.name === "string"
|
|
120
|
+
? raw.name
|
|
121
|
+
: recipeRef;
|
|
122
|
+
// ── 3. Collect {{env.FOO}} references ─────────────────────────────────────
|
|
123
|
+
const refs = collectEnvRefs(raw);
|
|
124
|
+
if (refs.size === 0) {
|
|
125
|
+
return {
|
|
126
|
+
ok: true,
|
|
127
|
+
recipe: recipeName,
|
|
128
|
+
missing: [],
|
|
129
|
+
present: [],
|
|
130
|
+
warnings: [],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
// ── 4. Build env lookup map ────────────────────────────────────────────────
|
|
134
|
+
// Start with process.env as baseline.
|
|
135
|
+
let envMap = new Map(Object.entries(process.env));
|
|
136
|
+
if (options.envFile) {
|
|
137
|
+
// Security: envFile must stay within workspace.
|
|
138
|
+
if (!options.workspace) {
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
recipe: recipeName,
|
|
142
|
+
missing: [],
|
|
143
|
+
present: [],
|
|
144
|
+
warnings: [
|
|
145
|
+
"envFile provided but workspace is required for path validation",
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
resolveFilePath(options.envFile, options.workspace);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
154
|
+
return {
|
|
155
|
+
ok: false,
|
|
156
|
+
recipe: recipeName,
|
|
157
|
+
missing: [],
|
|
158
|
+
present: [],
|
|
159
|
+
warnings: [`envFile path rejected: ${msg}`],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const envFilePath = resolve(options.workspace, options.envFile);
|
|
163
|
+
if (!existsSync(envFilePath)) {
|
|
164
|
+
return {
|
|
165
|
+
ok: false,
|
|
166
|
+
recipe: recipeName,
|
|
167
|
+
missing: [],
|
|
168
|
+
present: [],
|
|
169
|
+
warnings: [`envFile not found: ${options.envFile}`],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const dotEnvContent = readFileSync(envFilePath, "utf-8");
|
|
173
|
+
const dotEnvMap = parseDotEnv(dotEnvContent);
|
|
174
|
+
// envFile entries supplement (and override) process.env entries.
|
|
175
|
+
envMap = new Map([...envMap, ...dotEnvMap]);
|
|
176
|
+
}
|
|
177
|
+
// ── 5. Split refs into present / missing ──────────────────────────────────
|
|
178
|
+
const missing = [];
|
|
179
|
+
const present = [];
|
|
180
|
+
const warnings = [];
|
|
181
|
+
for (const name of Array.from(refs).sort()) {
|
|
182
|
+
const val = envMap.get(name);
|
|
183
|
+
if (val === undefined || val === null) {
|
|
184
|
+
missing.push(name);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
present.push(name);
|
|
188
|
+
// Warn if the value looks like an unfilled placeholder.
|
|
189
|
+
if (looksLikePlaceholder(val)) {
|
|
190
|
+
warnings.push(`${name} is set but value looks like a placeholder ("${val}")`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
ok: missing.length === 0,
|
|
196
|
+
recipe: recipeName,
|
|
197
|
+
missing,
|
|
198
|
+
present,
|
|
199
|
+
warnings,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=auditEnv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditEnv.js","sourceRoot":"","sources":["../../src/commands/auditEnv.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `patchwork connect` — the connector front-door.
|
|
3
|
+
*
|
|
4
|
+
* A thin CLI→HTTP shim over the bridge's already-built `/connections/*`
|
|
5
|
+
* routes (see src/connectorRoutes.ts). 23 connector error messages already
|
|
6
|
+
* tell users to "Run: patchwork connect <vendor>"; this is that command.
|
|
7
|
+
*
|
|
8
|
+
* NO new bridge or connector logic lives here — every verb maps to one
|
|
9
|
+
* existing HTTP route:
|
|
10
|
+
* - list → GET /connections (Bearer)
|
|
11
|
+
* - <vendor> → GET /connections/<id>/auth (OAuth, 302 Location)
|
|
12
|
+
* or POST /connections/<id>/connect (PAT, {token})
|
|
13
|
+
* - test → POST /connections/<id>/test (health probe)
|
|
14
|
+
* - disconnect → DELETE /connections/<id> (revoke)
|
|
15
|
+
*
|
|
16
|
+
* Bridge discovery + Bearer auth mirror src/commands/task.ts. All side
|
|
17
|
+
* effects (lock discovery, fetch, stdout/stderr, exit) are injectable so
|
|
18
|
+
* the command is unit-testable without a live bridge.
|
|
19
|
+
*/
|
|
20
|
+
import { type ConnectorDescriptor } from "../connectors/connectorRegistry.js";
|
|
21
|
+
interface LockInfo {
|
|
22
|
+
port: number;
|
|
23
|
+
authToken: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ConnectDeps {
|
|
26
|
+
/** Resolve a running bridge. `port` selects a specific lock. */
|
|
27
|
+
findBridgeLock: (port?: number) => LockInfo | null;
|
|
28
|
+
/** HTTP transport (defaults to global fetch). */
|
|
29
|
+
fetchFn: typeof fetch;
|
|
30
|
+
/** Connector roster (defaults to the shared registry). */
|
|
31
|
+
connectors: readonly ConnectorDescriptor[];
|
|
32
|
+
/** stdout sink. */
|
|
33
|
+
write: (s: string) => void;
|
|
34
|
+
/** stderr sink. */
|
|
35
|
+
writeErr: (s: string) => void;
|
|
36
|
+
/** Process exit (capture-only in tests). */
|
|
37
|
+
exit: (code: number) => void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `patchwork connect ...` dispatcher.
|
|
41
|
+
*
|
|
42
|
+
* `deps` is fully injectable for tests. In production, callers pass
|
|
43
|
+
* `findBridgeLock` (from src/commands/task.ts's lock helper) plus any
|
|
44
|
+
* overrides; everything else defaults to real process I/O.
|
|
45
|
+
*/
|
|
46
|
+
export declare function runConnect(argv: string[], deps: Partial<ConnectDeps> & Pick<ConnectDeps, "findBridgeLock">): Promise<void>;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `patchwork connect` — the connector front-door.
|
|
3
|
+
*
|
|
4
|
+
* A thin CLI→HTTP shim over the bridge's already-built `/connections/*`
|
|
5
|
+
* routes (see src/connectorRoutes.ts). 23 connector error messages already
|
|
6
|
+
* tell users to "Run: patchwork connect <vendor>"; this is that command.
|
|
7
|
+
*
|
|
8
|
+
* NO new bridge or connector logic lives here — every verb maps to one
|
|
9
|
+
* existing HTTP route:
|
|
10
|
+
* - list → GET /connections (Bearer)
|
|
11
|
+
* - <vendor> → GET /connections/<id>/auth (OAuth, 302 Location)
|
|
12
|
+
* or POST /connections/<id>/connect (PAT, {token})
|
|
13
|
+
* - test → POST /connections/<id>/test (health probe)
|
|
14
|
+
* - disconnect → DELETE /connections/<id> (revoke)
|
|
15
|
+
*
|
|
16
|
+
* Bridge discovery + Bearer auth mirror src/commands/task.ts. All side
|
|
17
|
+
* effects (lock discovery, fetch, stdout/stderr, exit) are injectable so
|
|
18
|
+
* the command is unit-testable without a live bridge.
|
|
19
|
+
*/
|
|
20
|
+
import { CONNECTORS, } from "../connectors/connectorRegistry.js";
|
|
21
|
+
const TIMEOUT_MS = 10_000;
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const out = {
|
|
24
|
+
positional: [],
|
|
25
|
+
json: false,
|
|
26
|
+
urlOnly: false,
|
|
27
|
+
help: false,
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < argv.length; i++) {
|
|
30
|
+
const a = argv[i];
|
|
31
|
+
if (a === undefined)
|
|
32
|
+
continue;
|
|
33
|
+
if (a === "--json")
|
|
34
|
+
out.json = true;
|
|
35
|
+
else if (a === "--url-only")
|
|
36
|
+
out.urlOnly = true;
|
|
37
|
+
else if (a === "--help" || a === "-h")
|
|
38
|
+
out.help = true;
|
|
39
|
+
else if (a === "--token") {
|
|
40
|
+
const next = argv[++i];
|
|
41
|
+
if (next !== undefined)
|
|
42
|
+
out.token = next;
|
|
43
|
+
}
|
|
44
|
+
else if (a === "--port") {
|
|
45
|
+
const next = argv[++i];
|
|
46
|
+
if (next !== undefined)
|
|
47
|
+
out.port = Number(next);
|
|
48
|
+
}
|
|
49
|
+
else if (!a.startsWith("-")) {
|
|
50
|
+
out.positional.push(a);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
56
|
+
function bearer(lock) {
|
|
57
|
+
return { Authorization: `Bearer ${lock.authToken}` };
|
|
58
|
+
}
|
|
59
|
+
function statusGlyph(status) {
|
|
60
|
+
if (status === "connected")
|
|
61
|
+
return "✓ connected";
|
|
62
|
+
if (status === "needs_reauth")
|
|
63
|
+
return "⚠ needs reauth";
|
|
64
|
+
return "✗ not connected";
|
|
65
|
+
}
|
|
66
|
+
function normalizeStatus(raw) {
|
|
67
|
+
if (raw === "connected" || raw === "needs_reauth")
|
|
68
|
+
return raw;
|
|
69
|
+
return "disconnected";
|
|
70
|
+
}
|
|
71
|
+
/** Levenshtein distance for "did you mean" suggestions. */
|
|
72
|
+
function editDistance(a, b) {
|
|
73
|
+
const m = a.length;
|
|
74
|
+
const n = b.length;
|
|
75
|
+
const prev = Array.from({ length: n + 1 }, (_, j) => j);
|
|
76
|
+
const curr = new Array(n + 1).fill(0);
|
|
77
|
+
for (let i = 1; i <= m; i++) {
|
|
78
|
+
curr[0] = i;
|
|
79
|
+
for (let j = 1; j <= n; j++) {
|
|
80
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
81
|
+
const del = (prev[j] ?? 0) + 1;
|
|
82
|
+
const ins = (curr[j - 1] ?? 0) + 1;
|
|
83
|
+
const sub = (prev[j - 1] ?? 0) + cost;
|
|
84
|
+
curr[j] = Math.min(del, ins, sub);
|
|
85
|
+
}
|
|
86
|
+
for (let j = 0; j <= n; j++)
|
|
87
|
+
prev[j] = curr[j] ?? 0;
|
|
88
|
+
}
|
|
89
|
+
return prev[n] ?? 0;
|
|
90
|
+
}
|
|
91
|
+
function suggestVendor(input, connectors) {
|
|
92
|
+
let best;
|
|
93
|
+
for (const c of connectors) {
|
|
94
|
+
const dist = editDistance(input, c.id);
|
|
95
|
+
if (!best || dist < best.dist)
|
|
96
|
+
best = { id: c.id, dist };
|
|
97
|
+
}
|
|
98
|
+
// Only suggest when reasonably close.
|
|
99
|
+
return best && best.dist <= 3 ? best.id : undefined;
|
|
100
|
+
}
|
|
101
|
+
function resolveLock(deps, port) {
|
|
102
|
+
const lock = deps.findBridgeLock(port);
|
|
103
|
+
if (!lock) {
|
|
104
|
+
deps.writeErr("No running bridge — start it with: patchwork start\n" +
|
|
105
|
+
(port !== undefined
|
|
106
|
+
? `(checked port ${port}; lock missing, IDE-owned, or dead)\n`
|
|
107
|
+
: ""));
|
|
108
|
+
deps.exit(1);
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return lock;
|
|
112
|
+
}
|
|
113
|
+
async function readJson(res) {
|
|
114
|
+
const text = await res.text();
|
|
115
|
+
if (!text)
|
|
116
|
+
return null;
|
|
117
|
+
try {
|
|
118
|
+
return JSON.parse(text);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function networkError(deps, err, json) {
|
|
125
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
126
|
+
if (json) {
|
|
127
|
+
deps.write(`${JSON.stringify({ ok: false, error: msg })}\n`);
|
|
128
|
+
}
|
|
129
|
+
deps.writeErr(`Error contacting bridge: ${msg}\n`);
|
|
130
|
+
deps.exit(1);
|
|
131
|
+
}
|
|
132
|
+
// ── verbs ────────────────────────────────────────────────────────────────────
|
|
133
|
+
async function runList(deps, args) {
|
|
134
|
+
const lock = resolveLock(deps, args.port);
|
|
135
|
+
if (!lock)
|
|
136
|
+
return;
|
|
137
|
+
let live;
|
|
138
|
+
try {
|
|
139
|
+
const res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections`, {
|
|
140
|
+
method: "GET",
|
|
141
|
+
headers: bearer(lock),
|
|
142
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
143
|
+
});
|
|
144
|
+
live = await readJson(res);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
networkError(deps, err, args.json);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Join live status onto the full registry roster so connectors absent
|
|
151
|
+
// from the response render as not-connected rather than vanishing.
|
|
152
|
+
const statusById = new Map();
|
|
153
|
+
for (const c of live?.connectors ?? []) {
|
|
154
|
+
if (c.id)
|
|
155
|
+
statusById.set(c.id, normalizeStatus(c.status));
|
|
156
|
+
}
|
|
157
|
+
const rows = deps.connectors.map((c) => ({
|
|
158
|
+
id: c.id,
|
|
159
|
+
label: c.label,
|
|
160
|
+
authKind: c.authKind,
|
|
161
|
+
status: statusById.get(c.id) ?? "disconnected",
|
|
162
|
+
}));
|
|
163
|
+
if (args.json) {
|
|
164
|
+
deps.write(`${JSON.stringify({ connectors: rows })}\n`);
|
|
165
|
+
deps.exit(0);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Connected first, then needs_reauth, then disconnected; stable by label.
|
|
169
|
+
const rank = {
|
|
170
|
+
connected: 0,
|
|
171
|
+
needs_reauth: 1,
|
|
172
|
+
disconnected: 2,
|
|
173
|
+
};
|
|
174
|
+
rows.sort((a, b) => rank[a.status] - rank[b.status] || a.label.localeCompare(b.label));
|
|
175
|
+
const idWidth = Math.max(...rows.map((r) => r.id.length), 2);
|
|
176
|
+
deps.write("Connectors:\n");
|
|
177
|
+
for (const r of rows) {
|
|
178
|
+
deps.write(` ${r.id.padEnd(idWidth)} ${statusGlyph(r.status).padEnd(16)}` +
|
|
179
|
+
`${r.label} (${r.authKind})\n`);
|
|
180
|
+
}
|
|
181
|
+
deps.exit(0);
|
|
182
|
+
}
|
|
183
|
+
async function runOauth(deps, descriptor, args) {
|
|
184
|
+
const lock = resolveLock(deps, args.port);
|
|
185
|
+
if (!lock)
|
|
186
|
+
return;
|
|
187
|
+
let res;
|
|
188
|
+
try {
|
|
189
|
+
res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections/${descriptor.id}/auth`, {
|
|
190
|
+
method: "GET",
|
|
191
|
+
headers: bearer(lock),
|
|
192
|
+
redirect: "manual",
|
|
193
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
networkError(deps, err, args.json);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const location = res.headers.get("location");
|
|
201
|
+
if (res.status === 302 && location) {
|
|
202
|
+
if (args.json) {
|
|
203
|
+
deps.write(`${JSON.stringify({ ok: true, url: location })}\n`);
|
|
204
|
+
}
|
|
205
|
+
else if (args.urlOnly) {
|
|
206
|
+
deps.write(`${location}\n`);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
deps.write(`Open this URL in your browser to authorize ${descriptor.label}:\n` +
|
|
210
|
+
` ${location}\n`);
|
|
211
|
+
}
|
|
212
|
+
deps.exit(0);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
// No redirect — surface the bridge's error body if present.
|
|
216
|
+
const body = await readJson(res);
|
|
217
|
+
const detail = body?.error ?? `HTTP ${res.status}`;
|
|
218
|
+
if (args.json) {
|
|
219
|
+
deps.write(`${JSON.stringify({ ok: false, error: detail })}\n`);
|
|
220
|
+
}
|
|
221
|
+
deps.writeErr(`Could not start ${descriptor.label} authorization: ${detail}\n`);
|
|
222
|
+
deps.exit(1);
|
|
223
|
+
}
|
|
224
|
+
async function runPatConnect(deps, descriptor, args) {
|
|
225
|
+
if (!args.token) {
|
|
226
|
+
// No token supplied — print honest instructions rather than guessing.
|
|
227
|
+
deps.write(`${descriptor.label} is a token (PAT) connector.\n` +
|
|
228
|
+
` Pass a token directly:\n` +
|
|
229
|
+
` patchwork connect ${descriptor.id} --token <TOKEN>\n` +
|
|
230
|
+
` Some connectors need more than one field (e.g. Jira/Confluence/` +
|
|
231
|
+
`Zendesk/Datadog need a URL + email + token).\n` +
|
|
232
|
+
` For those, use the dashboard /connections page to connect.\n`);
|
|
233
|
+
deps.exit(0);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const lock = resolveLock(deps, args.port);
|
|
237
|
+
if (!lock)
|
|
238
|
+
return;
|
|
239
|
+
let res;
|
|
240
|
+
try {
|
|
241
|
+
res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections/${descriptor.id}/connect`, {
|
|
242
|
+
method: "POST",
|
|
243
|
+
headers: { ...bearer(lock), "Content-Type": "application/json" },
|
|
244
|
+
body: JSON.stringify({ token: args.token }),
|
|
245
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
networkError(deps, err, args.json);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const body = await readJson(res);
|
|
253
|
+
const ok = res.status >= 200 && res.status < 300 && body?.ok !== false;
|
|
254
|
+
if (args.json) {
|
|
255
|
+
deps.write(`${JSON.stringify({ ok, ...(body ?? {}) })}\n`);
|
|
256
|
+
}
|
|
257
|
+
else if (ok) {
|
|
258
|
+
const where = body?.workspace ? ` (workspace: ${body.workspace})` : "";
|
|
259
|
+
deps.write(`✓ Connected ${descriptor.label}${where}\n`);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
deps.writeErr(`✗ Failed to connect ${descriptor.label}: ${body?.error ?? `HTTP ${res.status}`}\n`);
|
|
263
|
+
}
|
|
264
|
+
deps.exit(ok ? 0 : 1);
|
|
265
|
+
}
|
|
266
|
+
async function runTest(deps, vendor, args) {
|
|
267
|
+
const descriptor = resolveVendor(deps, vendor);
|
|
268
|
+
if (!descriptor)
|
|
269
|
+
return;
|
|
270
|
+
const lock = resolveLock(deps, args.port);
|
|
271
|
+
if (!lock)
|
|
272
|
+
return;
|
|
273
|
+
let res;
|
|
274
|
+
try {
|
|
275
|
+
res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections/${descriptor.id}/test`, {
|
|
276
|
+
method: "POST",
|
|
277
|
+
headers: bearer(lock),
|
|
278
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
networkError(deps, err, args.json);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const body = await readJson(res);
|
|
286
|
+
const ok = res.status >= 200 && res.status < 300 && body?.ok !== false;
|
|
287
|
+
if (args.json) {
|
|
288
|
+
deps.write(`${JSON.stringify({ ok, ...(body ?? {}) })}\n`);
|
|
289
|
+
}
|
|
290
|
+
else if (ok) {
|
|
291
|
+
deps.write(`✓ ${descriptor.label} is healthy\n`);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
deps.writeErr(`✗ ${descriptor.label} test failed: ${body?.error ?? `HTTP ${res.status}`}\n`);
|
|
295
|
+
}
|
|
296
|
+
deps.exit(ok ? 0 : 1);
|
|
297
|
+
}
|
|
298
|
+
async function runDisconnect(deps, vendor, args) {
|
|
299
|
+
const descriptor = resolveVendor(deps, vendor);
|
|
300
|
+
if (!descriptor)
|
|
301
|
+
return;
|
|
302
|
+
const lock = resolveLock(deps, args.port);
|
|
303
|
+
if (!lock)
|
|
304
|
+
return;
|
|
305
|
+
let res;
|
|
306
|
+
try {
|
|
307
|
+
res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections/${descriptor.id}`, {
|
|
308
|
+
method: "DELETE",
|
|
309
|
+
headers: bearer(lock),
|
|
310
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
catch (err) {
|
|
314
|
+
networkError(deps, err, args.json);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const body = await readJson(res);
|
|
318
|
+
const ok = res.status >= 200 && res.status < 300 && body?.ok !== false;
|
|
319
|
+
if (args.json) {
|
|
320
|
+
deps.write(`${JSON.stringify({ ok, ...(body ?? {}) })}\n`);
|
|
321
|
+
}
|
|
322
|
+
else if (ok) {
|
|
323
|
+
deps.write(`✓ Disconnected ${descriptor.label}\n`);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
deps.writeErr(`✗ Failed to disconnect ${descriptor.label}: ${body?.error ?? `HTTP ${res.status}`}\n`);
|
|
327
|
+
}
|
|
328
|
+
deps.exit(ok ? 0 : 1);
|
|
329
|
+
}
|
|
330
|
+
/** Resolve a vendor id to its descriptor, or emit an error + exit(1). */
|
|
331
|
+
function resolveVendor(deps, vendor) {
|
|
332
|
+
if (!vendor) {
|
|
333
|
+
deps.writeErr("Missing connector id.\n");
|
|
334
|
+
deps.exit(1);
|
|
335
|
+
return undefined;
|
|
336
|
+
}
|
|
337
|
+
const descriptor = deps.connectors.find((c) => c.id === vendor);
|
|
338
|
+
if (!descriptor) {
|
|
339
|
+
const hint = suggestVendor(vendor, deps.connectors);
|
|
340
|
+
const validIds = deps.connectors.map((c) => c.id).join(", ");
|
|
341
|
+
deps.writeErr(`Unknown connector "${vendor}".\n` +
|
|
342
|
+
(hint ? `Did you mean "${hint}"?\n` : "") +
|
|
343
|
+
`Valid ids: ${validIds}\n`);
|
|
344
|
+
deps.exit(1);
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
return descriptor;
|
|
348
|
+
}
|
|
349
|
+
function printHelp(deps) {
|
|
350
|
+
deps.write("Usage: patchwork connect [<vendor>|list|test <vendor>|disconnect <vendor>]\n" +
|
|
351
|
+
"\n" +
|
|
352
|
+
" connect [list] [--json] List connectors + connection status\n" +
|
|
353
|
+
" connect <vendor> [--url-only] OAuth: print the authorize URL to open\n" +
|
|
354
|
+
" connect <vendor> --token <TOKEN> PAT: paste a token to connect\n" +
|
|
355
|
+
" connect test <vendor> [--json] Health-probe a connector\n" +
|
|
356
|
+
" connect disconnect <vendor> Revoke a connector\n" +
|
|
357
|
+
"\n" +
|
|
358
|
+
" --port <n> Target a specific bridge lock\n" +
|
|
359
|
+
" --url-only Print only the OAuth URL (headless/CI)\n" +
|
|
360
|
+
" --json Machine-readable output\n");
|
|
361
|
+
deps.exit(0);
|
|
362
|
+
}
|
|
363
|
+
// ── entrypoint ───────────────────────────────────────────────────────────────
|
|
364
|
+
const DEFAULT_DEPS = {
|
|
365
|
+
fetchFn: globalThis.fetch,
|
|
366
|
+
connectors: CONNECTORS,
|
|
367
|
+
write: (s) => process.stdout.write(s),
|
|
368
|
+
writeErr: (s) => process.stderr.write(s),
|
|
369
|
+
exit: (c) => process.exit(c),
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* `patchwork connect ...` dispatcher.
|
|
373
|
+
*
|
|
374
|
+
* `deps` is fully injectable for tests. In production, callers pass
|
|
375
|
+
* `findBridgeLock` (from src/commands/task.ts's lock helper) plus any
|
|
376
|
+
* overrides; everything else defaults to real process I/O.
|
|
377
|
+
*/
|
|
378
|
+
export async function runConnect(argv, deps) {
|
|
379
|
+
const resolved = { ...DEFAULT_DEPS, ...deps };
|
|
380
|
+
const args = parseArgs(argv);
|
|
381
|
+
if (args.help) {
|
|
382
|
+
printHelp(resolved);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const verb = args.positional[0];
|
|
386
|
+
// Bare `connect` or `connect list` → list.
|
|
387
|
+
if (verb === undefined || verb === "list") {
|
|
388
|
+
await runList(resolved, args);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (verb === "test") {
|
|
392
|
+
await runTest(resolved, args.positional[1], args);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (verb === "disconnect") {
|
|
396
|
+
await runDisconnect(resolved, args.positional[1], args);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
// Otherwise `verb` is a vendor id: OAuth (auth) or PAT (connect).
|
|
400
|
+
const descriptor = resolveVendor(resolved, verb);
|
|
401
|
+
if (!descriptor)
|
|
402
|
+
return;
|
|
403
|
+
if (descriptor.authKind === "oauth" && descriptor.supports.auth) {
|
|
404
|
+
await runOauth(resolved, descriptor, args);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
if (descriptor.supports.connect) {
|
|
408
|
+
await runPatConnect(resolved, descriptor, args);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
// OAuth-capable PAT connectors (auth:true but pat): prefer the token path.
|
|
412
|
+
if (descriptor.supports.auth) {
|
|
413
|
+
await runOauth(resolved, descriptor, args);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
resolved.writeErr(`Connector "${descriptor.id}" does not support an interactive connect flow.\n`);
|
|
417
|
+
resolved.exit(1);
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=connect.js.map
|