patchwork-os 0.2.0-beta.1 → 0.2.0-beta.10.canary.95
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 +202 -25
- 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/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 +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 +866 -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 +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 +227 -1
- 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.js +22 -3
- 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 +17 -0
- package/dist/drivers/local/index.js +99 -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 +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/inboxRoutes.d.ts +22 -0
- package/dist/inboxRoutes.js +61 -1
- package/dist/inboxRoutes.js.map +1 -1
- package/dist/index.js +1053 -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 +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/childBridgeRegistry.js +29 -11
- package/dist/orchestrator/childBridgeRegistry.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 +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 +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 +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 +182 -8
- package/dist/recipes/yamlRunner.js +877 -217
- 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 +885 -196
- 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 +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/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/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 +18 -0
- package/dist/tools/utils.js +103 -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 +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 +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 @@
|
|
|
1
|
+
{"version":3,"file":"winShim.js","sourceRoot":"","sources":["../src/winShim.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC;IAChD,wEAAwE;IACxE,6EAA6E;IAC7E,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IACjE,OAAO,GAAG,MAAM,MAAM,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC;IACnD,yDAAyD;IACzD,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,6DAA6D;IAC7D,KAAK;IACL,QAAQ;IACR,OAAO;IACP,UAAU;IACV,MAAM;IACN,OAAO;IACP,UAAU;IACV,sDAAsD;IACtD,QAAQ;IACR,mBAAmB;IACnB,QAAQ;IACR,aAAa;IACb,yEAAyE;IACzE,MAAM;IACN,eAAe;IACf,QAAQ;IACR,UAAU;CACX,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC;IAChD,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IACjE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAChD,OAAO,GAAG,MAAM,MAAM,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscribe to ActivityLog and dispatch a Web Push notification
|
|
3
|
+
* whenever a recipe run completes with status=error.
|
|
4
|
+
*
|
|
5
|
+
* Lives outside the recipe runner so the runner stays push-agnostic
|
|
6
|
+
* (`yamlRunner.ts` already emits `recipe_done` lifecycle events —
|
|
7
|
+
* we just listen). Pushes are fire-and-forget; runner is never
|
|
8
|
+
* blocked or affected by a relay outage.
|
|
9
|
+
*
|
|
10
|
+
* Reads `pushServiceUrl` / `pushServiceToken` from a getter callback
|
|
11
|
+
* (not a captured value) so config edits through `/settings` take
|
|
12
|
+
* effect immediately without a bridge restart.
|
|
13
|
+
*
|
|
14
|
+
* Dedup: a run that is retried / resumed can emit `recipe_done` more
|
|
15
|
+
* than once. A short-window per-runSeq guard collapses those into a
|
|
16
|
+
* single push so a flapping run can't spam every subscribed device.
|
|
17
|
+
*/
|
|
18
|
+
import type { ActivityLog } from "./activityLog.js";
|
|
19
|
+
interface WireHaltPushDispatchDeps {
|
|
20
|
+
activityLog: ActivityLog;
|
|
21
|
+
/** Called per event — returns the current push relay config or null
|
|
22
|
+
* if push isn't configured. Reading from a getter rather than a
|
|
23
|
+
* captured value picks up runtime config changes. */
|
|
24
|
+
getPushConfig: () => {
|
|
25
|
+
url: string;
|
|
26
|
+
token: string;
|
|
27
|
+
} | null;
|
|
28
|
+
logger?: {
|
|
29
|
+
warn?: (msg: string) => void;
|
|
30
|
+
};
|
|
31
|
+
/** Override the dedup window. Default 60_000 ms. Tests pass a small
|
|
32
|
+
* value; production never sets it. */
|
|
33
|
+
dedupWindowMs?: number;
|
|
34
|
+
/** Injectable clock for deterministic tests. Default `Date.now`. */
|
|
35
|
+
now?: () => number;
|
|
36
|
+
}
|
|
37
|
+
export declare function wireHaltPushDispatch(deps: WireHaltPushDispatchDeps): () => void;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscribe to ActivityLog and dispatch a Web Push notification
|
|
3
|
+
* whenever a recipe run completes with status=error.
|
|
4
|
+
*
|
|
5
|
+
* Lives outside the recipe runner so the runner stays push-agnostic
|
|
6
|
+
* (`yamlRunner.ts` already emits `recipe_done` lifecycle events —
|
|
7
|
+
* we just listen). Pushes are fire-and-forget; runner is never
|
|
8
|
+
* blocked or affected by a relay outage.
|
|
9
|
+
*
|
|
10
|
+
* Reads `pushServiceUrl` / `pushServiceToken` from a getter callback
|
|
11
|
+
* (not a captured value) so config edits through `/settings` take
|
|
12
|
+
* effect immediately without a bridge restart.
|
|
13
|
+
*
|
|
14
|
+
* Dedup: a run that is retried / resumed can emit `recipe_done` more
|
|
15
|
+
* than once. A short-window per-runSeq guard collapses those into a
|
|
16
|
+
* single push so a flapping run can't spam every subscribed device.
|
|
17
|
+
*/
|
|
18
|
+
import { dispatchHaltPushNotification } from "./haltPushDispatch.js";
|
|
19
|
+
const DEFAULT_DEDUP_WINDOW_MS = 60_000;
|
|
20
|
+
export function wireHaltPushDispatch(deps) {
|
|
21
|
+
const dedupWindowMs = deps.dedupWindowMs ?? DEFAULT_DEDUP_WINDOW_MS;
|
|
22
|
+
const now = deps.now ?? Date.now;
|
|
23
|
+
// runSeq → last-dispatched epoch ms. Pruned opportunistically on
|
|
24
|
+
// each event so the Map can't grow unbounded on a long-lived bridge.
|
|
25
|
+
const lastDispatched = new Map();
|
|
26
|
+
function prune(cutoff) {
|
|
27
|
+
for (const [seq, at] of lastDispatched) {
|
|
28
|
+
if (at < cutoff)
|
|
29
|
+
lastDispatched.delete(seq);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return deps.activityLog.subscribe((kind, entry) => {
|
|
33
|
+
if (kind !== "lifecycle")
|
|
34
|
+
return;
|
|
35
|
+
const lifecycle = entry;
|
|
36
|
+
if (lifecycle.event !== "recipe_done")
|
|
37
|
+
return;
|
|
38
|
+
const md = lifecycle.metadata ?? {};
|
|
39
|
+
if (md.status !== "error")
|
|
40
|
+
return;
|
|
41
|
+
const cfg = deps.getPushConfig();
|
|
42
|
+
if (!cfg)
|
|
43
|
+
return;
|
|
44
|
+
const recipeName = typeof md.recipeName === "string" ? md.recipeName : "recipe";
|
|
45
|
+
const runSeq = typeof md.runSeq === "number" ? md.runSeq : 0;
|
|
46
|
+
const errorMessage = typeof md.errorMessage === "string" ? md.errorMessage : undefined;
|
|
47
|
+
// Dedup: skip if this runSeq fired a push within the window.
|
|
48
|
+
// runSeq 0 is the "unknown" sentinel — never dedup it, since two
|
|
49
|
+
// genuinely distinct unknown-seq runs would otherwise collide.
|
|
50
|
+
const at = now();
|
|
51
|
+
prune(at - dedupWindowMs);
|
|
52
|
+
if (runSeq !== 0) {
|
|
53
|
+
const last = lastDispatched.get(runSeq);
|
|
54
|
+
if (last !== undefined && at - last < dedupWindowMs)
|
|
55
|
+
return;
|
|
56
|
+
lastDispatched.set(runSeq, at);
|
|
57
|
+
}
|
|
58
|
+
// Best-effort: dispatchHaltPushNotification swallows errors, but
|
|
59
|
+
// a synchronously-thrown URL parse error would still surface here.
|
|
60
|
+
dispatchHaltPushNotification(cfg.url, cfg.token, {
|
|
61
|
+
recipeName,
|
|
62
|
+
runSeq,
|
|
63
|
+
status: "error",
|
|
64
|
+
errorMessage,
|
|
65
|
+
occurredAt: at,
|
|
66
|
+
}).catch((err) => {
|
|
67
|
+
deps.logger?.warn?.(`[halt-push] unexpected dispatcher error: ${err instanceof Error ? err.message : String(err)}`);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=wireHaltPushDispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wireHaltPushDispatch.js","sourceRoot":"","sources":["../src/wireHaltPushDispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAgBrE,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAEvC,MAAM,UAAU,oBAAoB,CAClC,IAA8B;IAE9B,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,uBAAuB,CAAC;IACpE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACjC,iEAAiE;IACjE,qEAAqE;IACrE,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEjD,SAAS,KAAK,CAAC,MAAc;QAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,cAAc,EAAE,CAAC;YACvC,IAAI,EAAE,GAAG,MAAM;gBAAE,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAChD,IAAI,IAAI,KAAK,WAAW;YAAE,OAAO;QACjC,MAAM,SAAS,GAAG,KAGjB,CAAC;QACF,IAAI,SAAS,CAAC,KAAK,KAAK,aAAa;YAAE,OAAO;QAC9C,MAAM,EAAE,GAAG,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC;QACpC,IAAI,EAAE,CAAC,MAAM,KAAK,OAAO;YAAE,OAAO;QAElC,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACjC,IAAI,CAAC,GAAG;YAAE,OAAO;QAEjB,MAAM,UAAU,GACd,OAAO,EAAE,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC/D,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,MAAM,YAAY,GAChB,OAAO,EAAE,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;QAEpE,6DAA6D;QAC7D,iEAAiE;QACjE,+DAA+D;QAC/D,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC;QACjB,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,CAAC;QAC1B,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACxC,IAAI,IAAI,KAAK,SAAS,IAAI,EAAE,GAAG,IAAI,GAAG,aAAa;gBAAE,OAAO;YAC5D,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACjC,CAAC;QAED,iEAAiE;QACjE,mEAAmE;QACnE,4BAA4B,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE;YAC/C,UAAU;YACV,MAAM;YACN,MAAM,EAAE,OAAO;YACf,YAAY;YACZ,UAAU,EAAE,EAAE;SACf,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CACjB,4CAA4C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC/F,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type WriteFileAtomicData = string | NodeJS.ArrayBufferView;
|
|
2
|
+
export interface WriteFileAtomicOptions {
|
|
3
|
+
/** Mode for the final file. Default: 0o644. */
|
|
4
|
+
mode?: number;
|
|
5
|
+
/** Encoding when `data` is a string. Default: utf-8. */
|
|
6
|
+
encoding?: BufferEncoding;
|
|
7
|
+
/**
|
|
8
|
+
* Optional cancellation signal — async variant only. Aborts the
|
|
9
|
+
* underlying `fs.promises.writeFile`; if abort fires after the
|
|
10
|
+
* write completes but before the rename, the target is left
|
|
11
|
+
* unchanged and the temp file is cleaned up.
|
|
12
|
+
*/
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Synchronous atomic write. Throws on failure. Best-effort temp cleanup.
|
|
17
|
+
*/
|
|
18
|
+
export declare function writeFileAtomicSync(target: string, data: WriteFileAtomicData, opts?: WriteFileAtomicOptions): void;
|
|
19
|
+
/**
|
|
20
|
+
* Async atomic write. Returns a Promise; rejects on failure. Best-effort
|
|
21
|
+
* temp cleanup. Uses `fs.promises` end-to-end.
|
|
22
|
+
*/
|
|
23
|
+
export declare function writeFileAtomic(target: string, data: WriteFileAtomicData, opts?: WriteFileAtomicOptions): Promise<void>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
/**
|
|
4
|
+
* Atomic file-write helpers — write to a sibling temp file, then `rename`
|
|
5
|
+
* into the target path. A crash mid-write leaves only the orphan temp
|
|
6
|
+
* file; the target is either the old content or the new content, never
|
|
7
|
+
* truncated.
|
|
8
|
+
*
|
|
9
|
+
* Why a shared helper?
|
|
10
|
+
* The recipe-runner / approval / token-storage paths already use this
|
|
11
|
+
* shape ad-hoc (see runLog.ts, decisionTraceLog.ts, activationMetrics.ts,
|
|
12
|
+
* connectors/tokenStorage.ts). The user-source-file edit tools
|
|
13
|
+
* (`editText`, `replaceBlock`, `searchAndReplace`, `transaction`,
|
|
14
|
+
* `refactorExtractFunction`, `fileOperations` overwrite) were doing
|
|
15
|
+
* direct `writeFile`/`writeFileSync` — a crash mid-write corrupts the
|
|
16
|
+
* user's code. Audit 2026-05-17.
|
|
17
|
+
*
|
|
18
|
+
* Temp-name shape: `${target}.tmp.${pid}.${rand}` — pid + 12 random hex
|
|
19
|
+
* chars so concurrent writes to the same target don't collide on their
|
|
20
|
+
* temp files (the rename is single-threaded at the kernel level; the
|
|
21
|
+
* collision risk is the temp file, not the final state).
|
|
22
|
+
*
|
|
23
|
+
* Cleanup on failure: if `writeFile` succeeds but `rename` fails, we
|
|
24
|
+
* best-effort `unlink` the temp file before re-throwing. If `writeFile`
|
|
25
|
+
* itself fails the temp file may not exist; we ignore unlink errors in
|
|
26
|
+
* both cases.
|
|
27
|
+
*
|
|
28
|
+
* NOT a `fsync` guarantee: Node's `writeFile`/`writeFileSync` does not
|
|
29
|
+
* fsync the file before close, and `rename`/`renameSync` does not fsync
|
|
30
|
+
* the parent dir. On `ext4` data=ordered and `apfs` this is fine in
|
|
31
|
+
* practice — the rename can't make the new contents visible until the
|
|
32
|
+
* data write hits the journal. On power-loss this guarantee weakens;
|
|
33
|
+
* accept that as a separate hardening pass.
|
|
34
|
+
*/
|
|
35
|
+
function tempPathFor(target) {
|
|
36
|
+
const rand = crypto.randomBytes(6).toString("hex");
|
|
37
|
+
return `${target}.tmp.${process.pid}.${rand}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Synchronous atomic write. Throws on failure. Best-effort temp cleanup.
|
|
41
|
+
*/
|
|
42
|
+
export function writeFileAtomicSync(target, data, opts = {}) {
|
|
43
|
+
const tmp = tempPathFor(target);
|
|
44
|
+
const mode = opts.mode ?? 0o644;
|
|
45
|
+
try {
|
|
46
|
+
if (typeof data === "string") {
|
|
47
|
+
fs.writeFileSync(tmp, data, { mode, encoding: opts.encoding ?? "utf-8" });
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
fs.writeFileSync(tmp, data, { mode });
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
fs.renameSync(tmp, target);
|
|
54
|
+
}
|
|
55
|
+
catch (renameErr) {
|
|
56
|
+
// On Windows, renameSync throws EEXIST when the target already exists
|
|
57
|
+
// (unlike POSIX which atomically replaces). Unlink the target and retry.
|
|
58
|
+
if (process.platform === "win32" &&
|
|
59
|
+
renameErr.code === "EEXIST") {
|
|
60
|
+
fs.unlinkSync(target);
|
|
61
|
+
fs.renameSync(tmp, target);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
throw renameErr;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
try {
|
|
70
|
+
fs.unlinkSync(tmp);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// already gone or never created
|
|
74
|
+
}
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Async atomic write. Returns a Promise; rejects on failure. Best-effort
|
|
80
|
+
* temp cleanup. Uses `fs.promises` end-to-end.
|
|
81
|
+
*/
|
|
82
|
+
export async function writeFileAtomic(target, data, opts = {}) {
|
|
83
|
+
const tmp = tempPathFor(target);
|
|
84
|
+
const mode = opts.mode ?? 0o644;
|
|
85
|
+
try {
|
|
86
|
+
if (typeof data === "string") {
|
|
87
|
+
await fs.promises.writeFile(tmp, data, {
|
|
88
|
+
mode,
|
|
89
|
+
encoding: opts.encoding ?? "utf-8",
|
|
90
|
+
signal: opts.signal,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
await fs.promises.writeFile(tmp, data, { mode, signal: opts.signal });
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
await fs.promises.rename(tmp, target);
|
|
98
|
+
}
|
|
99
|
+
catch (renameErr) {
|
|
100
|
+
// Windows: rename throws EEXIST when target exists (unlike POSIX atomic replace).
|
|
101
|
+
if (process.platform === "win32" &&
|
|
102
|
+
renameErr.code === "EEXIST") {
|
|
103
|
+
await fs.promises.unlink(target);
|
|
104
|
+
await fs.promises.rename(tmp, target);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
throw renameErr;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
try {
|
|
113
|
+
await fs.promises.unlink(tmp);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// already gone or never created
|
|
117
|
+
}
|
|
118
|
+
throw err;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=writeFileAtomic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeFileAtomic.js","sourceRoot":"","sources":["../src/writeFileAtomic.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,SAAS,WAAW,CAAC,MAAc;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnD,OAAO,GAAG,MAAM,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;AAChD,CAAC;AAkBD;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAc,EACd,IAAyB,EACzB,OAA+B,EAAE;IAEjC,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;IAChC,IAAI,CAAC;QACH,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,OAAO,EAAE,CAAC,CAAC;QAC5E,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,SAAS,EAAE,CAAC;YACnB,sEAAsE;YACtE,yEAAyE;YACzE,IACE,OAAO,CAAC,QAAQ,KAAK,OAAO;gBAC3B,SAAmC,CAAC,IAAI,KAAK,QAAQ,EACtD,CAAC;gBACD,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBACtB,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,MAAM,SAAS,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,IAAyB,EACzB,OAA+B,EAAE;IAEjC,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;IAChC,IAAI,CAAC;QACH,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE;gBACrC,IAAI;gBACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,OAAO;gBAClC,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,SAAS,EAAE,CAAC;YACnB,kFAAkF;YAClF,IACE,OAAO,CAAC,QAAQ,KAAK,OAAO;gBAC3B,SAAmC,CAAC,IAAI,KAAK,QAAQ,EACtD,CAAC;gBACD,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACjC,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACN,MAAM,SAAS,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "patchwork-os",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.10.canary.95",
|
|
4
4
|
"description": "Your personal AI runtime, local-first. Patchwork OS gives any AI model a consistent set of tools, YAML recipes, a delegation policy with approval queue, and a durable trace memory — all on your machine, all under your policy.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,7 +47,10 @@
|
|
|
47
47
|
"anthropic",
|
|
48
48
|
"ollama",
|
|
49
49
|
"local-first",
|
|
50
|
-
"coding-assistant"
|
|
50
|
+
"coding-assistant",
|
|
51
|
+
"smithery",
|
|
52
|
+
"model-context-protocol",
|
|
53
|
+
"developer-tools"
|
|
51
54
|
],
|
|
52
55
|
"repository": {
|
|
53
56
|
"type": "git",
|
|
@@ -62,14 +65,19 @@
|
|
|
62
65
|
"!dist/__tests__",
|
|
63
66
|
"!dist/**/__tests__",
|
|
64
67
|
"scripts/start-all.sh",
|
|
68
|
+
"scripts/start-all.mjs",
|
|
69
|
+
"scripts/start-all.ps1",
|
|
65
70
|
"scripts/start-orchestrator.sh",
|
|
71
|
+
"scripts/start-orchestrator.ps1",
|
|
66
72
|
"scripts/start-remote.sh",
|
|
73
|
+
"scripts/start-remote.mjs",
|
|
67
74
|
"scripts/install-extension.sh",
|
|
68
75
|
"scripts/gen-mcp-config.sh",
|
|
69
76
|
"scripts/mcp-stdio-shim.cjs",
|
|
70
77
|
"scripts/postinstall.mjs",
|
|
71
78
|
"scripts/start-vps.sh",
|
|
72
79
|
"scripts/gen-claude-desktop-config.sh",
|
|
80
|
+
"scripts/smoke/run-all.mjs",
|
|
73
81
|
"templates",
|
|
74
82
|
"deploy",
|
|
75
83
|
"LICENSE",
|
|
@@ -80,10 +88,12 @@
|
|
|
80
88
|
},
|
|
81
89
|
"scripts": {
|
|
82
90
|
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc && (node scripts/postinstall.mjs || true)",
|
|
91
|
+
"install:global": "node scripts/install-global.mjs",
|
|
83
92
|
"dev": "tsx src/index.ts",
|
|
84
93
|
"start": "node dist/index.js",
|
|
85
94
|
"test": "vitest run",
|
|
86
|
-
"test:smoke": "
|
|
95
|
+
"test:smoke": "node scripts/smoke/run-all.mjs",
|
|
96
|
+
"test:smoke:bash": "bash scripts/smoke/run-all.sh",
|
|
87
97
|
"test:smoke:dashboard": "node scripts/smoke/dashboard-walk.mjs",
|
|
88
98
|
"schema:generate": "node scripts/generate-schemas.mjs",
|
|
89
99
|
"schema:check": "node scripts/audit-schema-changes.mjs",
|
|
@@ -97,25 +107,31 @@
|
|
|
97
107
|
"typecheck:tests": "tsc --noEmit -p tsconfig.tests.json",
|
|
98
108
|
"typecheck:tests:core": "tsc --noEmit -p tsconfig.tests.core.json",
|
|
99
109
|
"postinstall": "node scripts/postinstall.mjs || true",
|
|
100
|
-
"prepublishOnly": "npm run build && node dist/index.js
|
|
110
|
+
"prepublishOnly": "npm run build && node -e \"const h=require('child_process').execFileSync('node',['dist/index.js','--workspace','.','--help'],{encoding:'utf8'});if(!h.includes('issuer-url'))process.exit(1)\" && node scripts/publish-schemas.mjs",
|
|
101
111
|
"smoke": "node smoke-test-v2.mjs",
|
|
102
112
|
"remote": "bash scripts/start-remote.sh",
|
|
113
|
+
"remote:node": "node scripts/start-remote.mjs",
|
|
103
114
|
"vps": "bash scripts/start-vps.sh",
|
|
104
115
|
"vps:stop": "bash scripts/start-vps.sh --stop",
|
|
105
116
|
"start-all": "bash scripts/start-all.sh",
|
|
117
|
+
"start-all:node": "node scripts/start-all.mjs",
|
|
118
|
+
"start-all:win": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-all.ps1",
|
|
106
119
|
"start-orchestrator": "bash scripts/start-orchestrator.sh",
|
|
107
|
-
"start:
|
|
120
|
+
"start-orchestrator:win": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-orchestrator.ps1",
|
|
121
|
+
"start:bridge": "node dist/index.js --workspace .",
|
|
122
|
+
"start:automation": "claude-ide-bridge --workspace . --automation --automation-policy automation-policy.json --driver subprocess --full",
|
|
108
123
|
"prepare": "husky"
|
|
109
124
|
},
|
|
110
125
|
"dependencies": {
|
|
111
126
|
"@opentelemetry/api": "^1.9.0",
|
|
112
127
|
"@opentelemetry/exporter-trace-otlp-http": "^0.213.0",
|
|
113
|
-
"@opentelemetry/
|
|
128
|
+
"@opentelemetry/resources": "^2.6.0",
|
|
129
|
+
"@opentelemetry/sdk-trace-node": "^2.7.1",
|
|
114
130
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
115
131
|
"ajv": "^8.18.0",
|
|
116
132
|
"ipaddr.js": "^2.3.0",
|
|
117
133
|
"minimatch": "^10.0.0",
|
|
118
|
-
"node-cron": "^
|
|
134
|
+
"node-cron": "^4.2.1",
|
|
119
135
|
"undici": "^6.25.0",
|
|
120
136
|
"ws": "^8.18.0",
|
|
121
137
|
"yaml": "^2.8.3"
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* postinstall.mjs — wire up optional local binaries into node_modules/.bin
|
|
4
5
|
* so that probeAll() can discover them via the standard local-bin lookup.
|
|
@@ -7,8 +8,10 @@
|
|
|
7
8
|
* @vscode/ripgrep → node_modules/.bin/rg
|
|
8
9
|
*/
|
|
9
10
|
|
|
11
|
+
import { execFileSync } from "node:child_process";
|
|
10
12
|
import {
|
|
11
13
|
chmodSync,
|
|
14
|
+
copyFileSync,
|
|
12
15
|
existsSync,
|
|
13
16
|
mkdirSync,
|
|
14
17
|
symlinkSync,
|
|
@@ -49,8 +52,19 @@ function linkBin(pkgName, binaryName, linkName = binaryName) {
|
|
|
49
52
|
if (existsSync(dest)) {
|
|
50
53
|
unlinkSync(dest);
|
|
51
54
|
}
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
try {
|
|
56
|
+
symlinkSync(src, dest);
|
|
57
|
+
console.log(` linked ${linkName} → ${path.relative(root, src)}`);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
// Windows non-admin users can't create symlinks without Developer Mode.
|
|
60
|
+
// Fall back to a copy so the binary is still discoverable.
|
|
61
|
+
if (process.platform === "win32") {
|
|
62
|
+
copyFileSync(src, dest);
|
|
63
|
+
console.log(` copied ${linkName} → ${path.relative(root, src)}`);
|
|
64
|
+
} else {
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
54
68
|
} catch {
|
|
55
69
|
// Package not installed — silently skip
|
|
56
70
|
}
|
|
@@ -65,4 +79,30 @@ try {
|
|
|
65
79
|
|
|
66
80
|
console.log("[postinstall] Linking optional local binaries...");
|
|
67
81
|
linkBin("@vscode/ripgrep", "rg");
|
|
82
|
+
|
|
83
|
+
// Auto-install dashboard dependencies on first global install
|
|
84
|
+
const dashboardDir = fileURLToPath(new URL("../dashboard", import.meta.url));
|
|
85
|
+
if (
|
|
86
|
+
existsSync(dashboardDir) &&
|
|
87
|
+
!existsSync(path.join(dashboardDir, "node_modules"))
|
|
88
|
+
) {
|
|
89
|
+
console.log(
|
|
90
|
+
"[postinstall] Installing dashboard dependencies (first-time setup)...",
|
|
91
|
+
);
|
|
92
|
+
try {
|
|
93
|
+
// Use execFileSync instead of execSync to avoid shell invocation
|
|
94
|
+
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
95
|
+
execFileSync(npmCmd, ["install", "--prefer-offline"], {
|
|
96
|
+
cwd: dashboardDir,
|
|
97
|
+
stdio: "inherit",
|
|
98
|
+
});
|
|
99
|
+
console.log("[postinstall] Dashboard dependencies installed.");
|
|
100
|
+
} catch {
|
|
101
|
+
console.warn(
|
|
102
|
+
"[postinstall] Warning: could not install dashboard dependencies automatically.",
|
|
103
|
+
);
|
|
104
|
+
console.warn(` Run manually: cd ${dashboardDir} && npm install`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
68
108
|
console.log("[postinstall] Done.");
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Cross-platform smoke test runner — replaces run-all.sh.
|
|
3
|
+
// Works on Windows (PowerShell/cmd), macOS, and Linux.
|
|
4
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const BRIDGE = process.env.BRIDGE ?? "claude-ide-bridge";
|
|
12
|
+
const PORT = 37210;
|
|
13
|
+
const CAT2_PORT = 37211;
|
|
14
|
+
|
|
15
|
+
// Security: shell metacharacters that could enable command injection.
|
|
16
|
+
// On Windows `\` is the path separator (D:\…\bridge.cmd), not an injection
|
|
17
|
+
// vector. Same fix PR #527 applied to scripts/start-all.mjs.
|
|
18
|
+
const SHELL_METACHARACTERS =
|
|
19
|
+
process.platform === "win32"
|
|
20
|
+
? /[;&|`$(){}[\]<>"'\n\r]/
|
|
21
|
+
: /[;&|`$(){}[\]<>"'\\\n\r]/;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Validate that a binary path is safe to execute.
|
|
25
|
+
* Prevents command injection by checking for shell metacharacters.
|
|
26
|
+
* @throws Error if path contains dangerous characters
|
|
27
|
+
*/
|
|
28
|
+
function validateBinaryPath(binaryPath) {
|
|
29
|
+
if (!binaryPath || typeof binaryPath !== "string") {
|
|
30
|
+
throw new Error("Binary path is empty or invalid");
|
|
31
|
+
}
|
|
32
|
+
if (SHELL_METACHARACTERS.test(binaryPath)) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Binary path contains shell metacharacters (potential injection): ${binaryPath}`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Validate BRIDGE path on startup
|
|
40
|
+
try {
|
|
41
|
+
validateBinaryPath(BRIDGE);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
console.error(`ERROR: ${err.message}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const TMPWS = fs.mkdtempSync(path.join(os.tmpdir(), "patchwork-smoke-ws-"));
|
|
48
|
+
const CLAUDE_CFG = fs.mkdtempSync(
|
|
49
|
+
path.join(os.tmpdir(), "patchwork-smoke-cfg-"),
|
|
50
|
+
);
|
|
51
|
+
fs.mkdirSync(path.join(CLAUDE_CFG, "ide"), { recursive: true });
|
|
52
|
+
|
|
53
|
+
process.env.CLAUDE_CONFIG_DIR = CLAUDE_CFG;
|
|
54
|
+
|
|
55
|
+
let bridgePid = null;
|
|
56
|
+
let cat2Pid = null;
|
|
57
|
+
let cat2Cfg = null;
|
|
58
|
+
|
|
59
|
+
function cleanup() {
|
|
60
|
+
for (const pid of [bridgePid, cat2Pid]) {
|
|
61
|
+
if (pid == null) continue;
|
|
62
|
+
try {
|
|
63
|
+
process.kill(pid);
|
|
64
|
+
} catch {
|
|
65
|
+
/* already gone */
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const dir of [TMPWS, CLAUDE_CFG, cat2Cfg]) {
|
|
69
|
+
if (!dir) continue;
|
|
70
|
+
try {
|
|
71
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
72
|
+
} catch {
|
|
73
|
+
/* best-effort */
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
process.on("exit", cleanup);
|
|
79
|
+
process.on("SIGINT", () => process.exit(1));
|
|
80
|
+
process.on("SIGTERM", () => process.exit(1));
|
|
81
|
+
|
|
82
|
+
// Windows GHA runners are noticeably slower at cold-starting node (signed-
|
|
83
|
+
// binary scan, AV hooks). 10s causes recurring "lock file not written" flakes
|
|
84
|
+
// on main. PR #538 doubled the bound in helpers.mjs for individual smoke
|
|
85
|
+
// scripts; this harness was missed. Match the doubled budget here too.
|
|
86
|
+
const DEFAULT_LOCK_TIMEOUT_MS = process.platform === "win32" ? 30_000 : 10_000;
|
|
87
|
+
|
|
88
|
+
function waitForLock(cfgDir, port, timeoutMs = DEFAULT_LOCK_TIMEOUT_MS) {
|
|
89
|
+
const lockPath = path.join(cfgDir, "ide", `${port}.lock`);
|
|
90
|
+
const deadline = Date.now() + timeoutMs;
|
|
91
|
+
while (!fs.existsSync(lockPath)) {
|
|
92
|
+
if (Date.now() > deadline) return false;
|
|
93
|
+
// busy-wait in 100ms increments — same as the bash script
|
|
94
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100);
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Spawn bridge for the given port and config dir. Captures stderr so a
|
|
100
|
+
// startup failure can be surfaced — `stdio: "ignore"` would swallow it
|
|
101
|
+
// and leave the operator staring at "lock file not written after 10s".
|
|
102
|
+
function startBridge(port, cfgDir, wsDir) {
|
|
103
|
+
// Security: BRIDGE path already validated on startup
|
|
104
|
+
const proc = spawn(BRIDGE, ["--port", String(port), "--workspace", wsDir], {
|
|
105
|
+
env: { ...process.env, CLAUDE_CONFIG_DIR: cfgDir },
|
|
106
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
107
|
+
// On Windows, npm global bins are .cmd wrappers that need shell:true
|
|
108
|
+
// Safe because BRIDGE path is validated for injection chars on startup
|
|
109
|
+
shell: process.platform === "win32",
|
|
110
|
+
});
|
|
111
|
+
proc.stderrBuf = "";
|
|
112
|
+
proc.stderr.on("data", (d) => {
|
|
113
|
+
proc.stderrBuf += d.toString();
|
|
114
|
+
});
|
|
115
|
+
return proc;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ── Start main bridge ─────────────────────────────────────────────────────────
|
|
119
|
+
console.log(`Starting bridge on port ${PORT}...`);
|
|
120
|
+
const bridgeProc = startBridge(PORT, CLAUDE_CFG, TMPWS);
|
|
121
|
+
bridgePid = bridgeProc.pid;
|
|
122
|
+
|
|
123
|
+
if (!waitForLock(CLAUDE_CFG, PORT)) {
|
|
124
|
+
console.error(
|
|
125
|
+
`ERROR: bridge lock file not written after ${DEFAULT_LOCK_TIMEOUT_MS / 1000}s`,
|
|
126
|
+
);
|
|
127
|
+
console.error(
|
|
128
|
+
`Bridge stderr (last 4 KB):\n${(bridgeProc.stderrBuf || "(empty)").slice(-4096)}`,
|
|
129
|
+
);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
// tiny extra buffer for WS listener to bind
|
|
133
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 200);
|
|
134
|
+
|
|
135
|
+
const TOKEN = execFileSync(BRIDGE, ["print-token", "--port", String(PORT)], {
|
|
136
|
+
encoding: "utf-8",
|
|
137
|
+
shell: process.platform === "win32",
|
|
138
|
+
}).trim();
|
|
139
|
+
|
|
140
|
+
console.log(`Bridge ready. Token: ${TOKEN.slice(0, 8)}...\n`);
|
|
141
|
+
|
|
142
|
+
// ── Start CAT-2 bridge (separate instance — CAT-2 kills the bridge it tests) ─
|
|
143
|
+
cat2Cfg = fs.mkdtempSync(path.join(os.tmpdir(), "patchwork-smoke-cat2-"));
|
|
144
|
+
fs.mkdirSync(path.join(cat2Cfg, "ide"), { recursive: true });
|
|
145
|
+
|
|
146
|
+
const cat2Proc = startBridge(CAT2_PORT, cat2Cfg, TMPWS);
|
|
147
|
+
cat2Pid = cat2Proc.pid;
|
|
148
|
+
waitForLock(cat2Cfg, CAT2_PORT);
|
|
149
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 200);
|
|
150
|
+
|
|
151
|
+
// ── Category runner ───────────────────────────────────────────────────────────
|
|
152
|
+
let pass = 0;
|
|
153
|
+
let fail = 0;
|
|
154
|
+
const failures = [];
|
|
155
|
+
|
|
156
|
+
function runCat(label, scriptFile, args = [], extraEnv = {}) {
|
|
157
|
+
try {
|
|
158
|
+
execFileSync(process.execPath, [scriptFile, ...args], {
|
|
159
|
+
env: { ...process.env, ...extraEnv },
|
|
160
|
+
stdio: "inherit",
|
|
161
|
+
});
|
|
162
|
+
console.log(`\x1b[32m[PASS]\x1b[0m ${label}`);
|
|
163
|
+
pass++;
|
|
164
|
+
} catch {
|
|
165
|
+
console.log(`\x1b[31m[FAIL]\x1b[0m ${label}`);
|
|
166
|
+
fail++;
|
|
167
|
+
failures.push(label);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const S = __dirname;
|
|
172
|
+
const P = String(PORT);
|
|
173
|
+
const T = TOKEN;
|
|
174
|
+
|
|
175
|
+
runCat(
|
|
176
|
+
"CAT-2 (lockfile)",
|
|
177
|
+
path.join(S, "cat2-lockfile.mjs"),
|
|
178
|
+
[String(CAT2_PORT), String(cat2Pid)],
|
|
179
|
+
{ CLAUDE_CONFIG_DIR: cat2Cfg },
|
|
180
|
+
);
|
|
181
|
+
fs.rmSync(cat2Cfg, { recursive: true, force: true });
|
|
182
|
+
cat2Cfg = null;
|
|
183
|
+
cat2Pid = null;
|
|
184
|
+
|
|
185
|
+
runCat("CAT-3 (auth)", path.join(S, "cat3-auth.mjs"), [P, T]);
|
|
186
|
+
runCat("CAT-4 (tools)", path.join(S, "cat4-tools.mjs"));
|
|
187
|
+
runCat("CAT-5 (http)", path.join(S, "cat5-http.mjs"), [P, T]);
|
|
188
|
+
runCat("CAT-6 (oauth)", path.join(S, "cat6-oauth.mjs"));
|
|
189
|
+
runCat("CAT-7 (plugin)", path.join(S, "cat7-plugin.mjs"));
|
|
190
|
+
runCat("CAT-8 (ratelimit)", path.join(S, "cat8-ratelimit.mjs"), [P, T]);
|
|
191
|
+
|
|
192
|
+
// Give bridge 1s to reset after CAT-8 saturates the rate limiter
|
|
193
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 1000);
|
|
194
|
+
|
|
195
|
+
runCat("CAT-9 (prompts/res)", path.join(S, "cat9-prompts-resources.mjs"), [
|
|
196
|
+
P,
|
|
197
|
+
T,
|
|
198
|
+
]);
|
|
199
|
+
runCat("CAT-10 (health)", path.join(S, "cat10-health.mjs"), [P, T]);
|
|
200
|
+
runCat("CAT-11 (shutdown)", path.join(S, "cat11-shutdown.mjs"));
|
|
201
|
+
runCat("CAT-12 (automation)", path.join(S, "cat12-automation.mjs"));
|
|
202
|
+
|
|
203
|
+
// ── Summary ───────────────────────────────────────────────────────────────────
|
|
204
|
+
const total = pass + fail;
|
|
205
|
+
console.log("\n═══════════════════════════════════");
|
|
206
|
+
if (fail === 0) {
|
|
207
|
+
console.log(`\x1b[32mALL PASS\x1b[0m (${pass}/${total} categories)`);
|
|
208
|
+
} else {
|
|
209
|
+
console.log(`\x1b[31mFAILURES: ${fail}/${total} categories\x1b[0m`);
|
|
210
|
+
for (const c of failures) console.log(` ✗ ${c}`);
|
|
211
|
+
}
|
|
212
|
+
console.log("═══════════════════════════════════");
|
|
213
|
+
process.exit(fail > 0 ? 1 : 0);
|