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
|
@@ -14,26 +14,115 @@
|
|
|
14
14
|
* - TTL eviction at access time (consume() or add()) — no per-state timer,
|
|
15
15
|
* so 10k states cost 10k Map slots + 10k longs, nothing more.
|
|
16
16
|
* - `consume()` is single-use; second call with the same state returns false.
|
|
17
|
+
*
|
|
18
|
+
* Persistence (opt-in via `namespace`):
|
|
19
|
+
* - When `namespace` is set, the state map is mirrored to disk at
|
|
20
|
+
* `${PATCHWORK_HOME}/tokens/oauth-state.<namespace>.json` (mode 0600).
|
|
21
|
+
* - The in-memory Map remains the read path; disk is the source of truth
|
|
22
|
+
* so a bridge restart between /authorize and /callback survives.
|
|
23
|
+
* - Each mutation triggers an atomic re-serialise of the namespace's map
|
|
24
|
+
* via `writeFileAtomicSync` (sibling tmp + rename). State payloads are
|
|
25
|
+
* short-lived (≤10 min) and bounded (≤1000 entries × ~80 bytes each),
|
|
26
|
+
* so a full-rewrite-on-mutation is the simplest correct shape.
|
|
27
|
+
* - State values are CSRF nonces, NOT secrets — they're single-use and
|
|
28
|
+
* useless after consume(). Plain JSON storage at 0600 is sufficient;
|
|
29
|
+
* no need to encrypt under the master key like tokenStorage.ts does.
|
|
17
30
|
*/
|
|
31
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
32
|
+
import os from "node:os";
|
|
33
|
+
import { join } from "node:path";
|
|
34
|
+
import { writeFileAtomicSync } from "../writeFileAtomic.js";
|
|
18
35
|
const DEFAULT_TTL_MS = 10 * 60_000;
|
|
19
36
|
const DEFAULT_MAX_ENTRIES = 1000;
|
|
37
|
+
function getStorageDir() {
|
|
38
|
+
const base = process.env.PATCHWORK_HOME ?? join(os.homedir(), ".patchwork");
|
|
39
|
+
return join(base, "tokens");
|
|
40
|
+
}
|
|
41
|
+
function stateFilePath(namespace) {
|
|
42
|
+
return join(getStorageDir(), `oauth-state.${namespace}.json`);
|
|
43
|
+
}
|
|
44
|
+
function loadFromDisk(namespace) {
|
|
45
|
+
const m = new Map();
|
|
46
|
+
const file = stateFilePath(namespace);
|
|
47
|
+
if (!existsSync(file))
|
|
48
|
+
return m;
|
|
49
|
+
try {
|
|
50
|
+
const raw = readFileSync(file, "utf-8");
|
|
51
|
+
const parsed = JSON.parse(raw);
|
|
52
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
53
|
+
const now = Date.now();
|
|
54
|
+
// Use Object.hasOwn to avoid walking the prototype chain — same
|
|
55
|
+
// pattern as the rest of the codebase (see Record<string,T>
|
|
56
|
+
// prototype-walk feedback).
|
|
57
|
+
for (const key of Object.keys(parsed)) {
|
|
58
|
+
if (!Object.hasOwn(parsed, key))
|
|
59
|
+
continue;
|
|
60
|
+
const expiry = parsed[key];
|
|
61
|
+
if (typeof expiry === "number" && expiry >= now) {
|
|
62
|
+
m.set(key, expiry);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Corrupt file → start empty. Next mutation rewrites it.
|
|
69
|
+
}
|
|
70
|
+
return m;
|
|
71
|
+
}
|
|
72
|
+
function persistToDisk(namespace, states) {
|
|
73
|
+
const dir = getStorageDir();
|
|
74
|
+
if (!existsSync(dir)) {
|
|
75
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
76
|
+
}
|
|
77
|
+
const obj = {};
|
|
78
|
+
for (const [k, v] of states)
|
|
79
|
+
obj[k] = v;
|
|
80
|
+
writeFileAtomicSync(stateFilePath(namespace), JSON.stringify(obj), {
|
|
81
|
+
mode: 0o600,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
20
84
|
export function createOAuthStateStore(opts = {}) {
|
|
21
85
|
const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
|
|
22
86
|
const maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
23
|
-
const
|
|
87
|
+
const namespace = opts.namespace;
|
|
88
|
+
const persist = typeof namespace === "string" && namespace.length > 0;
|
|
89
|
+
// Read-through cache. Seeded from disk on construction so a bridge
|
|
90
|
+
// restart preserves in-flight OAuth states.
|
|
91
|
+
const states = persist
|
|
92
|
+
? loadFromDisk(namespace)
|
|
93
|
+
: new Map();
|
|
24
94
|
function pruneExpired(now) {
|
|
95
|
+
let changed = false;
|
|
25
96
|
for (const [s, expiry] of states) {
|
|
26
|
-
if (expiry < now)
|
|
97
|
+
if (expiry < now) {
|
|
27
98
|
states.delete(s);
|
|
99
|
+
changed = true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return changed;
|
|
103
|
+
}
|
|
104
|
+
function flush() {
|
|
105
|
+
if (!persist)
|
|
106
|
+
return;
|
|
107
|
+
try {
|
|
108
|
+
persistToDisk(namespace, states);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Disk failure is non-fatal — the in-memory store still works for
|
|
112
|
+
// the lifetime of this process. A restart loses the unflushed state.
|
|
28
113
|
}
|
|
29
114
|
}
|
|
30
115
|
return {
|
|
31
116
|
add(state) {
|
|
32
117
|
const now = Date.now();
|
|
33
|
-
pruneExpired(now);
|
|
34
|
-
if (states.size >= maxEntries)
|
|
118
|
+
const prunedSomething = pruneExpired(now);
|
|
119
|
+
if (states.size >= maxEntries) {
|
|
120
|
+
if (prunedSomething)
|
|
121
|
+
flush();
|
|
35
122
|
return false;
|
|
123
|
+
}
|
|
36
124
|
states.set(state, now + ttlMs);
|
|
125
|
+
flush();
|
|
37
126
|
return true;
|
|
38
127
|
},
|
|
39
128
|
consume(state) {
|
|
@@ -42,6 +131,7 @@ export function createOAuthStateStore(opts = {}) {
|
|
|
42
131
|
if (expiry === undefined)
|
|
43
132
|
return false;
|
|
44
133
|
states.delete(state);
|
|
134
|
+
flush();
|
|
45
135
|
return expiry >= now;
|
|
46
136
|
},
|
|
47
137
|
size() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthStateStore.js","sourceRoot":"","sources":["../../src/connectors/oauthStateStore.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oauthStateStore.js","sourceRoot":"","sources":["../../src/connectors/oauthStateStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Obsidian connector — read/write notes via the Obsidian Local REST API plugin.
|
|
3
|
+
*
|
|
4
|
+
* Auth: API key (Bearer token) from plugin settings.
|
|
5
|
+
* - Env var: OBSIDIAN_API_KEY overrides stored key for CI/headless use.
|
|
6
|
+
* - Stored: getSecretJsonSync("obsidian") → ObsidianTokens
|
|
7
|
+
*
|
|
8
|
+
* Tools: listVault, readNote, writeNote, deleteNote, searchVault, appendToNote,
|
|
9
|
+
* getActiveNote, openNote, executeCommand, listCommands
|
|
10
|
+
*
|
|
11
|
+
* The plugin runs at https://127.0.0.1:27124 with a self-signed certificate.
|
|
12
|
+
* All fetch calls use an undici Agent with rejectUnauthorized: false.
|
|
13
|
+
*
|
|
14
|
+
* Extends BaseConnector for unified auth, retry, rate-limit, error handling.
|
|
15
|
+
*/
|
|
16
|
+
import { type AuthContext, BaseConnector, type ConnectorError, type ConnectorStatus } from "./baseConnector.js";
|
|
17
|
+
export interface ObsidianTokens {
|
|
18
|
+
apiKey: string;
|
|
19
|
+
baseUrl: string;
|
|
20
|
+
connected_at: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ObsidianVaultEntry {
|
|
23
|
+
path: string;
|
|
24
|
+
type: "file" | "directory";
|
|
25
|
+
}
|
|
26
|
+
export interface ObsidianSearchMatch {
|
|
27
|
+
filename: string;
|
|
28
|
+
score: number;
|
|
29
|
+
matches: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface ObsidianCommand {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function loadTokens(): ObsidianTokens | null;
|
|
36
|
+
export declare function saveTokens(tokens: ObsidianTokens): void;
|
|
37
|
+
export declare function clearTokens(): void;
|
|
38
|
+
export declare class ObsidianConnector extends BaseConnector {
|
|
39
|
+
readonly providerName = "obsidian";
|
|
40
|
+
protected cachedTokens: ObsidianTokens | null;
|
|
41
|
+
protected getOAuthConfig(): null;
|
|
42
|
+
authenticate(): Promise<AuthContext>;
|
|
43
|
+
healthCheck(): Promise<{
|
|
44
|
+
ok: boolean;
|
|
45
|
+
error?: ConnectorError;
|
|
46
|
+
}>;
|
|
47
|
+
normalizeError(error: unknown): ConnectorError;
|
|
48
|
+
getStatus(): ConnectorStatus;
|
|
49
|
+
private baseUrl;
|
|
50
|
+
listVault(vaultPath?: string): Promise<ObsidianVaultEntry[]>;
|
|
51
|
+
readNote(notePath: string): Promise<string>;
|
|
52
|
+
writeNote(notePath: string, content: string, append?: boolean): Promise<void>;
|
|
53
|
+
appendToNote(notePath: string, content: string): Promise<void>;
|
|
54
|
+
deleteNote(notePath: string): Promise<void>;
|
|
55
|
+
searchVault(query: string): Promise<ObsidianSearchMatch[]>;
|
|
56
|
+
getActiveNote(): Promise<string>;
|
|
57
|
+
openNote(notePath: string): Promise<void>;
|
|
58
|
+
listCommands(): Promise<ObsidianCommand[]>;
|
|
59
|
+
executeCommand(commandId: string): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
export declare function getObsidianConnector(): ObsidianConnector;
|
|
62
|
+
export declare function resetObsidianConnector(): void;
|
|
63
|
+
export { loadTokens as isConnected };
|
|
64
|
+
export interface ConnectorHandlerResult {
|
|
65
|
+
status: number;
|
|
66
|
+
body: string;
|
|
67
|
+
contentType?: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* POST /connections/obsidian/connect { apiKey: "...", baseUrl?: "https://..." }
|
|
71
|
+
* Stores the API key and verifies it by calling GET /vault/.
|
|
72
|
+
*/
|
|
73
|
+
export declare function handleObsidianConnect(body: string): Promise<ConnectorHandlerResult>;
|
|
74
|
+
/**
|
|
75
|
+
* POST /connections/obsidian/test
|
|
76
|
+
* Verifies stored API key is still valid.
|
|
77
|
+
*/
|
|
78
|
+
export declare function handleObsidianTest(): Promise<ConnectorHandlerResult>;
|
|
79
|
+
/**
|
|
80
|
+
* DELETE /connections/obsidian
|
|
81
|
+
* Removes stored API key.
|
|
82
|
+
*/
|
|
83
|
+
export declare function handleObsidianDisconnect(): ConnectorHandlerResult;
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Obsidian connector — read/write notes via the Obsidian Local REST API plugin.
|
|
3
|
+
*
|
|
4
|
+
* Auth: API key (Bearer token) from plugin settings.
|
|
5
|
+
* - Env var: OBSIDIAN_API_KEY overrides stored key for CI/headless use.
|
|
6
|
+
* - Stored: getSecretJsonSync("obsidian") → ObsidianTokens
|
|
7
|
+
*
|
|
8
|
+
* Tools: listVault, readNote, writeNote, deleteNote, searchVault, appendToNote,
|
|
9
|
+
* getActiveNote, openNote, executeCommand, listCommands
|
|
10
|
+
*
|
|
11
|
+
* The plugin runs at https://127.0.0.1:27124 with a self-signed certificate.
|
|
12
|
+
* All fetch calls use an undici Agent with rejectUnauthorized: false.
|
|
13
|
+
*
|
|
14
|
+
* Extends BaseConnector for unified auth, retry, rate-limit, error handling.
|
|
15
|
+
*/
|
|
16
|
+
import { unlinkSync } from "node:fs";
|
|
17
|
+
import { homedir } from "node:os";
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
import { Agent, fetch as undiciFetch } from "undici";
|
|
20
|
+
import { BaseConnector, } from "./baseConnector.js";
|
|
21
|
+
import { getSecretJsonSync, storeSecretJsonSync } from "./tokenStorage.js";
|
|
22
|
+
const DEFAULT_BASE_URL = "https://127.0.0.1:27124";
|
|
23
|
+
// Reusable TLS agent that accepts the plugin's self-signed certificate.
|
|
24
|
+
const tlsAgent = new Agent({ connect: { rejectUnauthorized: false } });
|
|
25
|
+
// ------------------------------------------------------------------ token helpers
|
|
26
|
+
export function loadTokens() {
|
|
27
|
+
const envKey = process.env.OBSIDIAN_API_KEY;
|
|
28
|
+
if (envKey) {
|
|
29
|
+
return {
|
|
30
|
+
apiKey: envKey,
|
|
31
|
+
baseUrl: DEFAULT_BASE_URL,
|
|
32
|
+
connected_at: new Date().toISOString(),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return getSecretJsonSync("obsidian");
|
|
36
|
+
}
|
|
37
|
+
export function saveTokens(tokens) {
|
|
38
|
+
storeSecretJsonSync("obsidian", tokens);
|
|
39
|
+
}
|
|
40
|
+
export function clearTokens() {
|
|
41
|
+
try {
|
|
42
|
+
const p = path.join(homedir(), ".patchwork", "tokens", "obsidian.json");
|
|
43
|
+
unlinkSync(p);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
/* already gone */
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ------------------------------------------------------------------ connector
|
|
50
|
+
export class ObsidianConnector extends BaseConnector {
|
|
51
|
+
providerName = "obsidian";
|
|
52
|
+
cachedTokens = null;
|
|
53
|
+
getOAuthConfig() {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
async authenticate() {
|
|
57
|
+
const tokens = loadTokens();
|
|
58
|
+
if (!tokens) {
|
|
59
|
+
throw new Error("Obsidian not connected. Run: patchwork connect obsidian or set OBSIDIAN_API_KEY");
|
|
60
|
+
}
|
|
61
|
+
this.cachedTokens = tokens;
|
|
62
|
+
return { token: tokens.apiKey };
|
|
63
|
+
}
|
|
64
|
+
async healthCheck() {
|
|
65
|
+
try {
|
|
66
|
+
const result = await this.apiCall(async (token) => {
|
|
67
|
+
const tokens = this.cachedTokens ?? loadTokens();
|
|
68
|
+
const baseUrl = tokens?.baseUrl ?? DEFAULT_BASE_URL;
|
|
69
|
+
const res = await undiciFetch(`${baseUrl}/vault/`, {
|
|
70
|
+
dispatcher: tlsAgent,
|
|
71
|
+
headers: buildHeaders(token),
|
|
72
|
+
});
|
|
73
|
+
if (!res.ok)
|
|
74
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
75
|
+
status: res.status,
|
|
76
|
+
});
|
|
77
|
+
return res.json();
|
|
78
|
+
});
|
|
79
|
+
if ("error" in result)
|
|
80
|
+
return { ok: false, error: result.error };
|
|
81
|
+
return { ok: true };
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
return { ok: false, error: this.normalizeError(err) };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
normalizeError(error) {
|
|
88
|
+
if (error && typeof error === "object" && "status" in error) {
|
|
89
|
+
const status = error.status;
|
|
90
|
+
if (status === 401 || status === 403)
|
|
91
|
+
return {
|
|
92
|
+
code: "auth_expired",
|
|
93
|
+
message: "Obsidian API key rejected — check plugin settings",
|
|
94
|
+
retryable: false,
|
|
95
|
+
suggestedAction: "Reconnect: patchwork connect obsidian",
|
|
96
|
+
};
|
|
97
|
+
if (status === 404)
|
|
98
|
+
return {
|
|
99
|
+
code: "not_found",
|
|
100
|
+
message: "Obsidian note or path not found",
|
|
101
|
+
retryable: false,
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
code: "provider_error",
|
|
105
|
+
message: `Obsidian API error: HTTP ${status}`,
|
|
106
|
+
retryable: status >= 500,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (error instanceof Error) {
|
|
110
|
+
if (error.message.includes("ECONNREFUSED") ||
|
|
111
|
+
error.message.includes("ENOTFOUND")) {
|
|
112
|
+
return {
|
|
113
|
+
code: "network_error",
|
|
114
|
+
message: `Cannot reach Obsidian Local REST API: ${error.message}. Is the plugin running?`,
|
|
115
|
+
retryable: true,
|
|
116
|
+
suggestedAction: "Start Obsidian and enable the Local REST API plugin",
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
code: "provider_error",
|
|
122
|
+
message: error instanceof Error ? error.message : String(error),
|
|
123
|
+
retryable: false,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
getStatus() {
|
|
127
|
+
const tokens = loadTokens();
|
|
128
|
+
return {
|
|
129
|
+
id: "obsidian",
|
|
130
|
+
status: tokens ? "connected" : "disconnected",
|
|
131
|
+
lastSync: tokens?.connected_at,
|
|
132
|
+
workspace: tokens?.baseUrl,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
baseUrl() {
|
|
136
|
+
return (this.cachedTokens ?? loadTokens())?.baseUrl ?? DEFAULT_BASE_URL;
|
|
137
|
+
}
|
|
138
|
+
// ---------------------------------------------------------------- vault ops
|
|
139
|
+
async listVault(vaultPath) {
|
|
140
|
+
const result = await this.apiCall(async (token) => {
|
|
141
|
+
const encoded = vaultPath ? encodeURIComponent(vaultPath) : "";
|
|
142
|
+
const url = `${this.baseUrl()}/vault/${encoded ? `${encoded}/` : ""}`;
|
|
143
|
+
const res = await undiciFetch(url, {
|
|
144
|
+
dispatcher: tlsAgent,
|
|
145
|
+
headers: buildHeaders(token),
|
|
146
|
+
});
|
|
147
|
+
if (!res.ok)
|
|
148
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
149
|
+
status: res.status,
|
|
150
|
+
});
|
|
151
|
+
return res.json();
|
|
152
|
+
});
|
|
153
|
+
if ("error" in result)
|
|
154
|
+
throw new Error(result.error.message);
|
|
155
|
+
const raw = result.data;
|
|
156
|
+
return (raw.files ?? []).map((f) => ({
|
|
157
|
+
path: f,
|
|
158
|
+
type: f.endsWith("/") ? "directory" : "file",
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
async readNote(notePath) {
|
|
162
|
+
const result = await this.apiCall(async (token) => {
|
|
163
|
+
const res = await undiciFetch(`${this.baseUrl()}/vault/${encodeURIComponent(notePath)}`, {
|
|
164
|
+
dispatcher: tlsAgent,
|
|
165
|
+
headers: buildHeaders(token),
|
|
166
|
+
});
|
|
167
|
+
if (!res.ok)
|
|
168
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
169
|
+
status: res.status,
|
|
170
|
+
});
|
|
171
|
+
return res.text();
|
|
172
|
+
});
|
|
173
|
+
if ("error" in result)
|
|
174
|
+
throw new Error(result.error.message);
|
|
175
|
+
return result.data;
|
|
176
|
+
}
|
|
177
|
+
async writeNote(notePath, content, append = false) {
|
|
178
|
+
const result = await this.apiCall(async (token) => {
|
|
179
|
+
const method = append ? "POST" : "PUT";
|
|
180
|
+
const res = await undiciFetch(`${this.baseUrl()}/vault/${encodeURIComponent(notePath)}`, {
|
|
181
|
+
method,
|
|
182
|
+
dispatcher: tlsAgent,
|
|
183
|
+
headers: {
|
|
184
|
+
...buildHeaders(token),
|
|
185
|
+
"Content-Type": "text/markdown",
|
|
186
|
+
},
|
|
187
|
+
body: content,
|
|
188
|
+
});
|
|
189
|
+
if (!res.ok)
|
|
190
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
191
|
+
status: res.status,
|
|
192
|
+
});
|
|
193
|
+
return null;
|
|
194
|
+
});
|
|
195
|
+
if ("error" in result)
|
|
196
|
+
throw new Error(result.error.message);
|
|
197
|
+
}
|
|
198
|
+
async appendToNote(notePath, content) {
|
|
199
|
+
return this.writeNote(notePath, content, true);
|
|
200
|
+
}
|
|
201
|
+
async deleteNote(notePath) {
|
|
202
|
+
const result = await this.apiCall(async (token) => {
|
|
203
|
+
const res = await undiciFetch(`${this.baseUrl()}/vault/${encodeURIComponent(notePath)}`, {
|
|
204
|
+
method: "DELETE",
|
|
205
|
+
dispatcher: tlsAgent,
|
|
206
|
+
headers: buildHeaders(token),
|
|
207
|
+
});
|
|
208
|
+
if (!res.ok)
|
|
209
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
210
|
+
status: res.status,
|
|
211
|
+
});
|
|
212
|
+
return null;
|
|
213
|
+
});
|
|
214
|
+
if ("error" in result)
|
|
215
|
+
throw new Error(result.error.message);
|
|
216
|
+
}
|
|
217
|
+
async searchVault(query) {
|
|
218
|
+
const result = await this.apiCall(async (token) => {
|
|
219
|
+
const res = await undiciFetch(`${this.baseUrl()}/search/simple/?query=${encodeURIComponent(query)}`, {
|
|
220
|
+
method: "POST",
|
|
221
|
+
dispatcher: tlsAgent,
|
|
222
|
+
headers: buildHeaders(token),
|
|
223
|
+
});
|
|
224
|
+
if (!res.ok)
|
|
225
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
226
|
+
status: res.status,
|
|
227
|
+
});
|
|
228
|
+
return res.json();
|
|
229
|
+
});
|
|
230
|
+
if ("error" in result)
|
|
231
|
+
throw new Error(result.error.message);
|
|
232
|
+
return result.data;
|
|
233
|
+
}
|
|
234
|
+
async getActiveNote() {
|
|
235
|
+
const result = await this.apiCall(async (token) => {
|
|
236
|
+
const res = await undiciFetch(`${this.baseUrl()}/active/`, {
|
|
237
|
+
dispatcher: tlsAgent,
|
|
238
|
+
headers: buildHeaders(token),
|
|
239
|
+
});
|
|
240
|
+
if (!res.ok)
|
|
241
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
242
|
+
status: res.status,
|
|
243
|
+
});
|
|
244
|
+
return res.text();
|
|
245
|
+
});
|
|
246
|
+
if ("error" in result)
|
|
247
|
+
throw new Error(result.error.message);
|
|
248
|
+
return result.data;
|
|
249
|
+
}
|
|
250
|
+
async openNote(notePath) {
|
|
251
|
+
const result = await this.apiCall(async (token) => {
|
|
252
|
+
const res = await undiciFetch(`${this.baseUrl()}/open/${encodeURIComponent(notePath)}`, {
|
|
253
|
+
method: "POST",
|
|
254
|
+
dispatcher: tlsAgent,
|
|
255
|
+
headers: buildHeaders(token),
|
|
256
|
+
});
|
|
257
|
+
if (!res.ok)
|
|
258
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
259
|
+
status: res.status,
|
|
260
|
+
});
|
|
261
|
+
return null;
|
|
262
|
+
});
|
|
263
|
+
if ("error" in result)
|
|
264
|
+
throw new Error(result.error.message);
|
|
265
|
+
}
|
|
266
|
+
async listCommands() {
|
|
267
|
+
const result = await this.apiCall(async (token) => {
|
|
268
|
+
const res = await undiciFetch(`${this.baseUrl()}/commands/`, {
|
|
269
|
+
dispatcher: tlsAgent,
|
|
270
|
+
headers: buildHeaders(token),
|
|
271
|
+
});
|
|
272
|
+
if (!res.ok)
|
|
273
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
274
|
+
status: res.status,
|
|
275
|
+
});
|
|
276
|
+
return res.json();
|
|
277
|
+
});
|
|
278
|
+
if ("error" in result)
|
|
279
|
+
throw new Error(result.error.message);
|
|
280
|
+
return result.data.commands ?? [];
|
|
281
|
+
}
|
|
282
|
+
async executeCommand(commandId) {
|
|
283
|
+
const result = await this.apiCall(async (token) => {
|
|
284
|
+
const res = await undiciFetch(`${this.baseUrl()}/commands/${encodeURIComponent(commandId)}/execute`, {
|
|
285
|
+
method: "POST",
|
|
286
|
+
dispatcher: tlsAgent,
|
|
287
|
+
headers: buildHeaders(token),
|
|
288
|
+
});
|
|
289
|
+
if (!res.ok)
|
|
290
|
+
throw Object.assign(new Error(`HTTP ${res.status}`), {
|
|
291
|
+
status: res.status,
|
|
292
|
+
});
|
|
293
|
+
return null;
|
|
294
|
+
});
|
|
295
|
+
if ("error" in result)
|
|
296
|
+
throw new Error(result.error.message);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// ------------------------------------------------------------------ helpers
|
|
300
|
+
function buildHeaders(token) {
|
|
301
|
+
return {
|
|
302
|
+
Authorization: `Bearer ${token}`,
|
|
303
|
+
Accept: "application/json",
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
// ------------------------------------------------------------------ singleton
|
|
307
|
+
let _instance = null;
|
|
308
|
+
export function getObsidianConnector() {
|
|
309
|
+
if (!_instance)
|
|
310
|
+
_instance = new ObsidianConnector();
|
|
311
|
+
return _instance;
|
|
312
|
+
}
|
|
313
|
+
export function resetObsidianConnector() {
|
|
314
|
+
_instance = null;
|
|
315
|
+
}
|
|
316
|
+
// ------------------------------------------------------------------ convenience re-exports
|
|
317
|
+
export { loadTokens as isConnected };
|
|
318
|
+
/**
|
|
319
|
+
* POST /connections/obsidian/connect { apiKey: "...", baseUrl?: "https://..." }
|
|
320
|
+
* Stores the API key and verifies it by calling GET /vault/.
|
|
321
|
+
*/
|
|
322
|
+
export async function handleObsidianConnect(body) {
|
|
323
|
+
let apiKey;
|
|
324
|
+
let baseUrl = DEFAULT_BASE_URL;
|
|
325
|
+
try {
|
|
326
|
+
const parsed = JSON.parse(body);
|
|
327
|
+
if (typeof parsed.apiKey !== "string" || parsed.apiKey.trim() === "") {
|
|
328
|
+
return {
|
|
329
|
+
status: 400,
|
|
330
|
+
contentType: "application/json",
|
|
331
|
+
body: JSON.stringify({
|
|
332
|
+
ok: false,
|
|
333
|
+
error: "apiKey is required. Find it in Obsidian → Local REST API plugin settings.",
|
|
334
|
+
}),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
apiKey = parsed.apiKey.trim();
|
|
338
|
+
if (typeof parsed.baseUrl === "string" && parsed.baseUrl.trim() !== "") {
|
|
339
|
+
baseUrl = parsed.baseUrl.trim();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
return {
|
|
344
|
+
status: 400,
|
|
345
|
+
contentType: "application/json",
|
|
346
|
+
body: JSON.stringify({ ok: false, error: "Invalid JSON body" }),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
try {
|
|
350
|
+
const res = await undiciFetch(`${baseUrl}/vault/`, {
|
|
351
|
+
dispatcher: tlsAgent,
|
|
352
|
+
headers: {
|
|
353
|
+
Authorization: `Bearer ${apiKey}`,
|
|
354
|
+
Accept: "application/json",
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
if (!res.ok) {
|
|
358
|
+
return {
|
|
359
|
+
status: 401,
|
|
360
|
+
contentType: "application/json",
|
|
361
|
+
body: JSON.stringify({
|
|
362
|
+
ok: false,
|
|
363
|
+
error: "API key rejected by Obsidian plugin — check the key in plugin settings",
|
|
364
|
+
}),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
const tokens = {
|
|
368
|
+
apiKey,
|
|
369
|
+
baseUrl,
|
|
370
|
+
connected_at: new Date().toISOString(),
|
|
371
|
+
};
|
|
372
|
+
saveTokens(tokens);
|
|
373
|
+
resetObsidianConnector();
|
|
374
|
+
return {
|
|
375
|
+
status: 200,
|
|
376
|
+
contentType: "application/json",
|
|
377
|
+
body: JSON.stringify({
|
|
378
|
+
ok: true,
|
|
379
|
+
baseUrl,
|
|
380
|
+
connectedAt: tokens.connected_at,
|
|
381
|
+
}),
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
catch (err) {
|
|
385
|
+
return {
|
|
386
|
+
status: 500,
|
|
387
|
+
contentType: "application/json",
|
|
388
|
+
body: JSON.stringify({
|
|
389
|
+
ok: false,
|
|
390
|
+
error: err instanceof Error ? err.message : String(err),
|
|
391
|
+
}),
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* POST /connections/obsidian/test
|
|
397
|
+
* Verifies stored API key is still valid.
|
|
398
|
+
*/
|
|
399
|
+
export async function handleObsidianTest() {
|
|
400
|
+
const tokens = loadTokens();
|
|
401
|
+
if (!tokens) {
|
|
402
|
+
return {
|
|
403
|
+
status: 400,
|
|
404
|
+
contentType: "application/json",
|
|
405
|
+
body: JSON.stringify({ ok: false, error: "Obsidian not connected" }),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
try {
|
|
409
|
+
const connector = getObsidianConnector();
|
|
410
|
+
const check = await connector.healthCheck();
|
|
411
|
+
return {
|
|
412
|
+
status: check.ok ? 200 : 401,
|
|
413
|
+
contentType: "application/json",
|
|
414
|
+
body: JSON.stringify(check.ok ? { ok: true } : { ok: false, error: check.error?.message }),
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
catch (err) {
|
|
418
|
+
return {
|
|
419
|
+
status: 500,
|
|
420
|
+
contentType: "application/json",
|
|
421
|
+
body: JSON.stringify({
|
|
422
|
+
ok: false,
|
|
423
|
+
error: err instanceof Error ? err.message : String(err),
|
|
424
|
+
}),
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* DELETE /connections/obsidian
|
|
430
|
+
* Removes stored API key.
|
|
431
|
+
*/
|
|
432
|
+
export function handleObsidianDisconnect() {
|
|
433
|
+
clearTokens();
|
|
434
|
+
resetObsidianConnector();
|
|
435
|
+
return {
|
|
436
|
+
status: 200,
|
|
437
|
+
contentType: "application/json",
|
|
438
|
+
body: JSON.stringify({ ok: true }),
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
//# sourceMappingURL=obsidian.js.map
|