patchwork-os 0.2.0-alpha.2 → 0.2.0-alpha.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.bridge.md +6 -0
- package/README.md +40 -15
- package/deploy/bootstrap-vps.sh +184 -0
- package/dist/approvalHttp.d.ts +11 -2
- package/dist/approvalHttp.js +98 -10
- package/dist/approvalHttp.js.map +1 -1
- package/dist/approvalQueue.d.ts +12 -1
- package/dist/approvalQueue.js +25 -3
- package/dist/approvalQueue.js.map +1 -1
- package/dist/automation.d.ts +20 -0
- package/dist/automation.js +35 -0
- package/dist/automation.js.map +1 -1
- package/dist/bridge.js +145 -23
- package/dist/bridge.js.map +1 -1
- package/dist/bridgeToken.js +57 -19
- package/dist/bridgeToken.js.map +1 -1
- package/dist/claudeDriver.d.ts +3 -1
- package/dist/claudeDriver.js +48 -0
- package/dist/claudeDriver.js.map +1 -1
- package/dist/claudeOrchestrator.d.ts +1 -1
- package/dist/claudeOrchestrator.js +14 -8
- package/dist/claudeOrchestrator.js.map +1 -1
- package/dist/commands/launchd.d.ts +2 -0
- package/dist/commands/launchd.js +94 -0
- package/dist/commands/launchd.js.map +1 -0
- package/dist/commands/recipe.d.ts +256 -0
- package/dist/commands/recipe.js +1313 -0
- package/dist/commands/recipe.js.map +1 -0
- package/dist/config.d.ts +15 -2
- package/dist/config.js +94 -8
- package/dist/config.js.map +1 -1
- package/dist/connectors/baseConnector.d.ts +117 -0
- package/dist/connectors/baseConnector.js +213 -0
- package/dist/connectors/baseConnector.js.map +1 -0
- package/dist/connectors/confluence.d.ts +111 -0
- package/dist/connectors/confluence.js +406 -0
- package/dist/connectors/confluence.js.map +1 -0
- package/dist/connectors/fixtureLibrary.d.ts +21 -0
- package/dist/connectors/fixtureLibrary.js +70 -0
- package/dist/connectors/fixtureLibrary.js.map +1 -0
- package/dist/connectors/fixtureRecorder.d.ts +1 -0
- package/dist/connectors/fixtureRecorder.js +35 -0
- package/dist/connectors/fixtureRecorder.js.map +1 -0
- package/dist/connectors/github.d.ts +58 -8
- package/dist/connectors/github.js +312 -84
- package/dist/connectors/github.js.map +1 -1
- package/dist/connectors/gmail.d.ts +4 -1
- package/dist/connectors/gmail.js +93 -16
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleCalendar.d.ts +60 -0
- package/dist/connectors/googleCalendar.js +345 -0
- package/dist/connectors/googleCalendar.js.map +1 -0
- package/dist/connectors/jira.d.ts +98 -0
- package/dist/connectors/jira.js +379 -0
- package/dist/connectors/jira.js.map +1 -0
- package/dist/connectors/linear.d.ts +117 -0
- package/dist/connectors/linear.js +239 -0
- package/dist/connectors/linear.js.map +1 -0
- package/dist/connectors/mcpClient.d.ts +56 -0
- package/dist/connectors/mcpClient.js +189 -0
- package/dist/connectors/mcpClient.js.map +1 -0
- package/dist/connectors/mcpOAuth.d.ts +84 -0
- package/dist/connectors/mcpOAuth.js +389 -0
- package/dist/connectors/mcpOAuth.js.map +1 -0
- package/dist/connectors/mockConnector.d.ts +28 -0
- package/dist/connectors/mockConnector.js +81 -0
- package/dist/connectors/mockConnector.js.map +1 -0
- package/dist/connectors/notion.d.ts +143 -0
- package/dist/connectors/notion.js +424 -0
- package/dist/connectors/notion.js.map +1 -0
- package/dist/connectors/sentry.d.ts +43 -0
- package/dist/connectors/sentry.js +188 -0
- package/dist/connectors/sentry.js.map +1 -0
- package/dist/connectors/slack.d.ts +50 -0
- package/dist/connectors/slack.js +324 -0
- package/dist/connectors/slack.js.map +1 -0
- package/dist/connectors/tokenStorage.d.ts +35 -0
- package/dist/connectors/tokenStorage.js +394 -0
- package/dist/connectors/tokenStorage.js.map +1 -0
- package/dist/connectors/zendesk.d.ts +104 -0
- package/dist/connectors/zendesk.js +424 -0
- package/dist/connectors/zendesk.js.map +1 -0
- package/dist/drivers/claude/api.d.ts +11 -0
- package/dist/drivers/claude/api.js +54 -0
- package/dist/drivers/claude/api.js.map +1 -0
- package/dist/drivers/claude/envSanitizer.d.ts +7 -0
- package/dist/drivers/claude/envSanitizer.js +18 -0
- package/dist/drivers/claude/envSanitizer.js.map +1 -0
- package/dist/drivers/claude/streamParser.d.ts +38 -0
- package/dist/drivers/claude/streamParser.js +34 -0
- package/dist/drivers/claude/streamParser.js.map +1 -0
- package/dist/drivers/claude/subprocess.d.ts +19 -0
- package/dist/drivers/claude/subprocess.js +216 -0
- package/dist/drivers/claude/subprocess.js.map +1 -0
- package/dist/drivers/claude/subprocessSettings.d.ts +9 -0
- package/dist/drivers/claude/subprocessSettings.js +55 -0
- package/dist/drivers/claude/subprocessSettings.js.map +1 -0
- package/dist/drivers/gemini/index.d.ts +18 -0
- package/dist/drivers/gemini/index.js +210 -0
- package/dist/drivers/gemini/index.js.map +1 -0
- package/dist/drivers/grok/index.d.ts +11 -0
- package/dist/drivers/grok/index.js +22 -0
- package/dist/drivers/grok/index.js.map +1 -0
- package/dist/drivers/index.d.ts +23 -0
- package/dist/drivers/index.js +31 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/drivers/openai/index.d.ts +24 -0
- package/dist/drivers/openai/index.js +110 -0
- package/dist/drivers/openai/index.js.map +1 -0
- package/dist/drivers/types.d.ts +72 -0
- package/dist/drivers/types.js +30 -0
- package/dist/drivers/types.js.map +1 -0
- package/dist/featureFlags.d.ts +73 -0
- package/dist/featureFlags.js +203 -0
- package/dist/featureFlags.js.map +1 -0
- package/dist/fp/automationInterpreter.js +1 -0
- package/dist/fp/automationInterpreter.js.map +1 -1
- package/dist/fp/automationProgram.d.ts +1 -1
- package/dist/fp/automationProgram.js.map +1 -1
- package/dist/fp/policyParser.js +17 -0
- package/dist/fp/policyParser.js.map +1 -1
- package/dist/index.js +543 -37
- package/dist/index.js.map +1 -1
- package/dist/installGuard.d.ts +25 -0
- package/dist/installGuard.js +48 -0
- package/dist/installGuard.js.map +1 -0
- package/dist/oauth.d.ts +4 -1
- package/dist/oauth.js +50 -14
- package/dist/oauth.js.map +1 -1
- package/dist/patchworkConfig.d.ts +9 -0
- package/dist/patchworkConfig.js.map +1 -1
- package/dist/recipes/chainedRunner.d.ts +104 -0
- package/dist/recipes/chainedRunner.js +359 -0
- package/dist/recipes/chainedRunner.js.map +1 -0
- package/dist/recipes/dependencyGraph.d.ts +39 -0
- package/dist/recipes/dependencyGraph.js +199 -0
- package/dist/recipes/dependencyGraph.js.map +1 -0
- package/dist/recipes/legacyRecipeCompat.d.ts +1 -0
- package/dist/recipes/legacyRecipeCompat.js +97 -0
- package/dist/recipes/legacyRecipeCompat.js.map +1 -0
- package/dist/recipes/nestedRecipeStep.d.ts +58 -0
- package/dist/recipes/nestedRecipeStep.js +95 -0
- package/dist/recipes/nestedRecipeStep.js.map +1 -0
- package/dist/recipes/outputRegistry.d.ts +28 -0
- package/dist/recipes/outputRegistry.js +52 -0
- package/dist/recipes/outputRegistry.js.map +1 -0
- package/dist/recipes/scheduler.d.ts +23 -7
- package/dist/recipes/scheduler.js +135 -41
- package/dist/recipes/scheduler.js.map +1 -1
- package/dist/recipes/schemaGenerator.d.ts +28 -0
- package/dist/recipes/schemaGenerator.js +484 -0
- package/dist/recipes/schemaGenerator.js.map +1 -0
- package/dist/recipes/templateEngine.d.ts +62 -0
- package/dist/recipes/templateEngine.js +182 -0
- package/dist/recipes/templateEngine.js.map +1 -0
- package/dist/recipes/toolRegistry.d.ts +181 -0
- package/dist/recipes/toolRegistry.js +300 -0
- package/dist/recipes/toolRegistry.js.map +1 -0
- package/dist/recipes/tools/calendar.d.ts +6 -0
- package/dist/recipes/tools/calendar.js +61 -0
- package/dist/recipes/tools/calendar.js.map +1 -0
- package/dist/recipes/tools/confluence.d.ts +6 -0
- package/dist/recipes/tools/confluence.js +254 -0
- package/dist/recipes/tools/confluence.js.map +1 -0
- package/dist/recipes/tools/diagnostics.d.ts +6 -0
- package/dist/recipes/tools/diagnostics.js +36 -0
- package/dist/recipes/tools/diagnostics.js.map +1 -0
- package/dist/recipes/tools/file.d.ts +6 -0
- package/dist/recipes/tools/file.js +170 -0
- package/dist/recipes/tools/file.js.map +1 -0
- package/dist/recipes/tools/git.d.ts +6 -0
- package/dist/recipes/tools/git.js +63 -0
- package/dist/recipes/tools/git.js.map +1 -0
- package/dist/recipes/tools/github.d.ts +6 -0
- package/dist/recipes/tools/github.js +91 -0
- package/dist/recipes/tools/github.js.map +1 -0
- package/dist/recipes/tools/gmail.d.ts +6 -0
- package/dist/recipes/tools/gmail.js +210 -0
- package/dist/recipes/tools/gmail.js.map +1 -0
- package/dist/recipes/tools/index.d.ts +18 -0
- package/dist/recipes/tools/index.js +21 -0
- package/dist/recipes/tools/index.js.map +1 -0
- package/dist/recipes/tools/linear.d.ts +6 -0
- package/dist/recipes/tools/linear.js +83 -0
- package/dist/recipes/tools/linear.js.map +1 -0
- package/dist/recipes/tools/notion.d.ts +6 -0
- package/dist/recipes/tools/notion.js +278 -0
- package/dist/recipes/tools/notion.js.map +1 -0
- package/dist/recipes/tools/slack.d.ts +6 -0
- package/dist/recipes/tools/slack.js +72 -0
- package/dist/recipes/tools/slack.js.map +1 -0
- package/dist/recipes/tools/zendesk.d.ts +6 -0
- package/dist/recipes/tools/zendesk.js +245 -0
- package/dist/recipes/tools/zendesk.js.map +1 -0
- package/dist/recipes/yamlRunner.d.ts +79 -0
- package/dist/recipes/yamlRunner.js +612 -346
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +14 -1
- package/dist/recipesHttp.js +21 -4
- package/dist/recipesHttp.js.map +1 -1
- package/dist/riskTier.js +1 -0
- package/dist/riskTier.js.map +1 -1
- package/dist/runLog.d.ts +23 -0
- package/dist/runLog.js +56 -1
- package/dist/runLog.js.map +1 -1
- package/dist/server.d.ts +19 -1
- package/dist/server.js +682 -31
- package/dist/server.js.map +1 -1
- package/dist/streamableHttp.js +2 -0
- package/dist/streamableHttp.js.map +1 -1
- package/dist/tools/addLinearComment.d.ts +55 -0
- package/dist/tools/addLinearComment.js +72 -0
- package/dist/tools/addLinearComment.js.map +1 -0
- package/dist/tools/bridgeDoctor.js +2 -2
- package/dist/tools/bridgeDoctor.js.map +1 -1
- package/dist/tools/createLinearIssue.d.ts +84 -0
- package/dist/tools/createLinearIssue.js +146 -0
- package/dist/tools/createLinearIssue.js.map +1 -0
- package/dist/tools/ctxGetTaskContext.d.ts +4 -1
- package/dist/tools/ctxGetTaskContext.js +45 -2
- package/dist/tools/ctxGetTaskContext.js.map +1 -1
- package/dist/tools/fetchCalendarEvents.d.ts +94 -0
- package/dist/tools/fetchCalendarEvents.js +97 -0
- package/dist/tools/fetchCalendarEvents.js.map +1 -0
- package/dist/tools/fetchGithubIssue.d.ts +80 -0
- package/dist/tools/fetchGithubIssue.js +84 -0
- package/dist/tools/fetchGithubIssue.js.map +1 -0
- package/dist/tools/fetchGithubPR.d.ts +89 -0
- package/dist/tools/fetchGithubPR.js +96 -0
- package/dist/tools/fetchGithubPR.js.map +1 -0
- package/dist/tools/fetchLinearIssue.d.ts +112 -0
- package/dist/tools/fetchLinearIssue.js +129 -0
- package/dist/tools/fetchLinearIssue.js.map +1 -0
- package/dist/tools/fetchSentryIssue.d.ts +143 -0
- package/dist/tools/fetchSentryIssue.js +150 -0
- package/dist/tools/fetchSentryIssue.js.map +1 -0
- package/dist/tools/fetchSlackProfile.d.ts +43 -0
- package/dist/tools/fetchSlackProfile.js +46 -0
- package/dist/tools/fetchSlackProfile.js.map +1 -0
- package/dist/tools/getConnectorStatus.d.ts +58 -0
- package/dist/tools/getConnectorStatus.js +56 -0
- package/dist/tools/getConnectorStatus.js.map +1 -0
- package/dist/tools/github/actions.js +4 -2
- package/dist/tools/github/actions.js.map +1 -1
- package/dist/tools/github/composite.d.ts +339 -0
- package/dist/tools/github/composite.js +343 -0
- package/dist/tools/github/composite.js.map +1 -0
- package/dist/tools/github/index.d.ts +2 -1
- package/dist/tools/github/index.js +2 -1
- package/dist/tools/github/index.js.map +1 -1
- package/dist/tools/github/issues.js +8 -4
- package/dist/tools/github/issues.js.map +1 -1
- package/dist/tools/github/pr.d.ts +122 -0
- package/dist/tools/github/pr.js +195 -5
- package/dist/tools/github/pr.js.map +1 -1
- package/dist/tools/index.js +36 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/searchTools.js +1 -1
- package/dist/tools/searchTools.js.map +1 -1
- package/dist/tools/slackListChannels.d.ts +65 -0
- package/dist/tools/slackListChannels.js +70 -0
- package/dist/tools/slackListChannels.js.map +1 -0
- package/dist/tools/slackPostMessage.d.ts +57 -0
- package/dist/tools/slackPostMessage.js +77 -0
- package/dist/tools/slackPostMessage.js.map +1 -0
- package/dist/tools/updateLinearIssue.d.ts +89 -0
- package/dist/tools/updateLinearIssue.js +117 -0
- package/dist/tools/updateLinearIssue.js.map +1 -0
- package/dist/transport.d.ts +7 -1
- package/dist/transport.js +85 -11
- package/dist/transport.js.map +1 -1
- package/package.json +4 -2
- package/scripts/start-all.sh +56 -19
- package/templates/automation-policies/recipe-authoring.json +25 -0
- package/templates/automation-policy.example.json +6 -0
- package/templates/co.patchwork-os.bridge.plist +34 -0
- package/templates/recipes/ctx-loop-test.yaml +75 -0
- package/templates/recipes/lint-on-save.yaml +1 -2
- package/templates/recipes/morning-brief-slack.yaml +57 -0
- package/templates/recipes/morning-brief.yaml +21 -5
- package/templates/recipes/sentry-to-linear.yaml +77 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseConnector — shared foundation for all Patchwork OS connectors.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Unified authentication flow (token refresh, expiry handling)
|
|
6
|
+
* - Secure token storage via OS keychain/DPAPI/Secret Service
|
|
7
|
+
* - OAuth 2.0 refresh token flow
|
|
8
|
+
* - Rate limiting with exponential backoff
|
|
9
|
+
* - Error normalization to ConnectorError type
|
|
10
|
+
* - Health check endpoint
|
|
11
|
+
*
|
|
12
|
+
* All new connectors (Jira, Notion, PagerDuty, Drive, etc.) extend this base.
|
|
13
|
+
* Extracted to prevent "each connector reinvents auth" anti-pattern.
|
|
14
|
+
*/
|
|
15
|
+
export class BaseConnector {
|
|
16
|
+
auth = null;
|
|
17
|
+
rateLimit = {
|
|
18
|
+
remaining: 100,
|
|
19
|
+
resetAt: new Date(Date.now() + 60000),
|
|
20
|
+
backoffMs: 0,
|
|
21
|
+
};
|
|
22
|
+
oauthConfig = null;
|
|
23
|
+
/**
|
|
24
|
+
* Load stored tokens from secure storage.
|
|
25
|
+
* Call this in subclass constructor or connect method.
|
|
26
|
+
*/
|
|
27
|
+
async loadStoredTokens() {
|
|
28
|
+
const { getTokens } = await import("./tokenStorage.js");
|
|
29
|
+
const stored = await getTokens(this.providerName);
|
|
30
|
+
if (stored) {
|
|
31
|
+
this.auth = {
|
|
32
|
+
token: stored.accessToken,
|
|
33
|
+
refreshToken: stored.refreshToken,
|
|
34
|
+
expiresAt: stored.expiresAt ? new Date(stored.expiresAt) : undefined,
|
|
35
|
+
scopes: stored.scopes,
|
|
36
|
+
};
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Save current tokens to secure storage.
|
|
43
|
+
*/
|
|
44
|
+
async saveTokens() {
|
|
45
|
+
if (!this.auth)
|
|
46
|
+
return;
|
|
47
|
+
const { storeTokens } = await import("./tokenStorage.js");
|
|
48
|
+
await storeTokens(this.providerName, {
|
|
49
|
+
accessToken: this.auth.token,
|
|
50
|
+
refreshToken: this.auth.refreshToken,
|
|
51
|
+
expiresAt: this.auth.expiresAt?.toISOString(),
|
|
52
|
+
scopes: this.auth.scopes,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Clear stored tokens (logout/disconnect).
|
|
57
|
+
*/
|
|
58
|
+
async clearTokens() {
|
|
59
|
+
const { deleteTokens } = await import("./tokenStorage.js");
|
|
60
|
+
await deleteTokens(this.providerName);
|
|
61
|
+
this.auth = null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Perform OAuth 2.0 token refresh.
|
|
65
|
+
* Subclasses can override for provider-specific refresh flows.
|
|
66
|
+
*/
|
|
67
|
+
async refreshToken() {
|
|
68
|
+
if (!this.auth?.refreshToken)
|
|
69
|
+
return null;
|
|
70
|
+
const config = this.getOAuthConfig();
|
|
71
|
+
if (!config)
|
|
72
|
+
return null;
|
|
73
|
+
try {
|
|
74
|
+
const params = new URLSearchParams({
|
|
75
|
+
grant_type: "refresh_token",
|
|
76
|
+
refresh_token: this.auth.refreshToken,
|
|
77
|
+
client_id: config.clientId,
|
|
78
|
+
...(config.clientSecret ? { client_secret: config.clientSecret } : {}),
|
|
79
|
+
});
|
|
80
|
+
const response = await fetch(config.tokenEndpoint, {
|
|
81
|
+
method: "POST",
|
|
82
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
83
|
+
body: params.toString(),
|
|
84
|
+
});
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
throw new Error(`Token refresh failed: ${response.status}`);
|
|
87
|
+
}
|
|
88
|
+
const data = (await response.json());
|
|
89
|
+
const newAuth = {
|
|
90
|
+
token: data.access_token,
|
|
91
|
+
refreshToken: data.refresh_token ?? this.auth.refreshToken,
|
|
92
|
+
expiresAt: data.expires_in
|
|
93
|
+
? new Date(Date.now() + data.expires_in * 1000)
|
|
94
|
+
: undefined,
|
|
95
|
+
scopes: data.scope?.split(" ") ?? this.auth.scopes,
|
|
96
|
+
};
|
|
97
|
+
this.auth = newAuth;
|
|
98
|
+
await this.saveTokens();
|
|
99
|
+
return newAuth;
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
// Refresh failed - clear tokens to force re-auth
|
|
103
|
+
await this.clearTokens();
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Execute an authenticated API call with automatic token refresh
|
|
109
|
+
* and rate limit backoff.
|
|
110
|
+
*/
|
|
111
|
+
async apiCall(fn, options = {}) {
|
|
112
|
+
const { retries = 2, retryDelayMs = 1000 } = options;
|
|
113
|
+
// Ensure auth - try refresh first, then fall back to full auth
|
|
114
|
+
if (!this.auth || this.isTokenExpired()) {
|
|
115
|
+
// Try OAuth refresh if we have a refresh token
|
|
116
|
+
if (this.auth?.refreshToken) {
|
|
117
|
+
const refreshed = await this.refreshToken();
|
|
118
|
+
if (refreshed) {
|
|
119
|
+
this.auth = refreshed;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Refresh failed, fall back to full auth
|
|
123
|
+
try {
|
|
124
|
+
this.auth = await this.authenticate();
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
return { error: this.normalizeError(err) };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// No refresh token, do full auth
|
|
133
|
+
try {
|
|
134
|
+
this.auth = await this.authenticate();
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
return { error: this.normalizeError(err) };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Apply rate limit backoff
|
|
142
|
+
if (this.rateLimit.backoffMs > 0) {
|
|
143
|
+
await sleep(this.rateLimit.backoffMs);
|
|
144
|
+
}
|
|
145
|
+
// Execute with retry
|
|
146
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
147
|
+
try {
|
|
148
|
+
const result = await fn(this.auth?.token);
|
|
149
|
+
return { data: result };
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
const normalized = this.normalizeError(err);
|
|
153
|
+
// Don't retry non-retryable errors
|
|
154
|
+
if (!normalized.retryable || attempt === retries) {
|
|
155
|
+
return { error: normalized };
|
|
156
|
+
}
|
|
157
|
+
// Exponential backoff with jitter
|
|
158
|
+
const delay = retryDelayMs * 2 ** attempt + Math.random() * 500;
|
|
159
|
+
await sleep(delay);
|
|
160
|
+
// Token might have expired mid-call - try refresh first
|
|
161
|
+
if (normalized.code === "auth_expired") {
|
|
162
|
+
if (this.auth?.refreshToken) {
|
|
163
|
+
const refreshed = await this.refreshToken();
|
|
164
|
+
if (refreshed) {
|
|
165
|
+
this.auth = refreshed;
|
|
166
|
+
continue; // Retry with new token
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Refresh failed or no refresh token, try full auth
|
|
170
|
+
try {
|
|
171
|
+
this.auth = await this.authenticate();
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return { error: normalized };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Should not reach here, but TypeScript needs it
|
|
180
|
+
return {
|
|
181
|
+
error: {
|
|
182
|
+
code: "provider_error",
|
|
183
|
+
message: "Unexpected end of retry loop",
|
|
184
|
+
retryable: false,
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Update rate limit state from HTTP response headers.
|
|
190
|
+
* Subclass should call this after each API response.
|
|
191
|
+
*/
|
|
192
|
+
updateRateLimitFromHeaders(headers) {
|
|
193
|
+
if (headers["x-ratelimit-remaining"]) {
|
|
194
|
+
this.rateLimit.remaining = parseInt(headers["x-ratelimit-remaining"], 10);
|
|
195
|
+
}
|
|
196
|
+
if (headers["x-ratelimit-reset"]) {
|
|
197
|
+
this.rateLimit.resetAt = new Date(parseInt(headers["x-ratelimit-reset"], 10) * 1000);
|
|
198
|
+
}
|
|
199
|
+
if (headers["retry-after"]) {
|
|
200
|
+
this.rateLimit.backoffMs = parseInt(headers["retry-after"], 10) * 1000;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
isTokenExpired() {
|
|
204
|
+
if (!this.auth?.expiresAt)
|
|
205
|
+
return false;
|
|
206
|
+
// Refresh 5 minutes before actual expiry
|
|
207
|
+
return new Date(Date.now() + 5 * 60000) >= this.auth.expiresAt;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function sleep(ms) {
|
|
211
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=baseConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseConnector.js","sourceRoot":"","sources":["../../src/connectors/baseConnector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Confluence connector — read/write Confluence pages via Atlassian REST API v2.
|
|
3
|
+
*
|
|
4
|
+
* Auth: API token + email + instance URL (same credential shape as Jira).
|
|
5
|
+
* - Env vars: CONFLUENCE_API_TOKEN, CONFLUENCE_INSTANCE_URL, CONFLUENCE_EMAIL
|
|
6
|
+
* - Stored: getSecretJsonSync("confluence") → ConfluenceTokens
|
|
7
|
+
*
|
|
8
|
+
* Tools: getPage, search, createPage, appendToPage, listSpaces
|
|
9
|
+
*
|
|
10
|
+
* Extends BaseConnector for unified auth, retry, rate-limit, error handling.
|
|
11
|
+
*/
|
|
12
|
+
import { type AuthContext, BaseConnector, type ConnectorError, type ConnectorStatus } from "./baseConnector.js";
|
|
13
|
+
export interface ConfluenceTokens {
|
|
14
|
+
accessToken: string;
|
|
15
|
+
email: string;
|
|
16
|
+
instanceUrl: string;
|
|
17
|
+
connected_at: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ConfluencePage {
|
|
20
|
+
id: string;
|
|
21
|
+
title: string;
|
|
22
|
+
status: string;
|
|
23
|
+
spaceId: string;
|
|
24
|
+
parentId?: string;
|
|
25
|
+
version: {
|
|
26
|
+
number: number;
|
|
27
|
+
createdAt: string;
|
|
28
|
+
};
|
|
29
|
+
body?: {
|
|
30
|
+
storage?: {
|
|
31
|
+
value: string;
|
|
32
|
+
representation: "storage";
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
_links: {
|
|
36
|
+
webui: string;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export interface ConfluenceSpace {
|
|
40
|
+
id: string;
|
|
41
|
+
key: string;
|
|
42
|
+
name: string;
|
|
43
|
+
type: string;
|
|
44
|
+
status: string;
|
|
45
|
+
_links: {
|
|
46
|
+
webui: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export interface ConfluenceSearchResult {
|
|
50
|
+
results: Array<{
|
|
51
|
+
content: {
|
|
52
|
+
id: string;
|
|
53
|
+
type: string;
|
|
54
|
+
title: string;
|
|
55
|
+
_links: {
|
|
56
|
+
webui: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
excerpt: string;
|
|
60
|
+
url: string;
|
|
61
|
+
lastModified: string;
|
|
62
|
+
}>;
|
|
63
|
+
totalSize: number;
|
|
64
|
+
start: number;
|
|
65
|
+
limit: number;
|
|
66
|
+
}
|
|
67
|
+
export declare class ConfluenceConnector extends BaseConnector {
|
|
68
|
+
readonly providerName = "confluence";
|
|
69
|
+
private tokens;
|
|
70
|
+
protected getOAuthConfig(): null;
|
|
71
|
+
authenticate(): Promise<AuthContext>;
|
|
72
|
+
healthCheck(): Promise<{
|
|
73
|
+
ok: boolean;
|
|
74
|
+
error?: ConnectorError;
|
|
75
|
+
}>;
|
|
76
|
+
normalizeError(error: unknown): ConnectorError;
|
|
77
|
+
getStatus(): ConnectorStatus;
|
|
78
|
+
getPage(pageId: string, includeBody?: boolean): Promise<ConfluencePage | null>;
|
|
79
|
+
search(query: string, limit?: number): Promise<ConfluenceSearchResult>;
|
|
80
|
+
createPage(params: {
|
|
81
|
+
spaceId: string;
|
|
82
|
+
title: string;
|
|
83
|
+
body: string;
|
|
84
|
+
parentId?: string;
|
|
85
|
+
}): Promise<ConfluencePage>;
|
|
86
|
+
appendToPage(pageId: string, content: string): Promise<ConfluencePage>;
|
|
87
|
+
listSpaces(limit?: number): Promise<ConfluenceSpace[]>;
|
|
88
|
+
private buildHeaders;
|
|
89
|
+
}
|
|
90
|
+
export declare function loadTokens(): ConfluenceTokens | null;
|
|
91
|
+
export declare function saveTokens(tokens: ConfluenceTokens): void;
|
|
92
|
+
export declare function clearTokens(): void;
|
|
93
|
+
export declare function getConfluenceConnector(): ConfluenceConnector;
|
|
94
|
+
export { getConfluenceConnector as confluence };
|
|
95
|
+
export interface ConnectorHandlerResult {
|
|
96
|
+
status: number;
|
|
97
|
+
body: string;
|
|
98
|
+
contentType?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* POST /connections/confluence/connect { token, email, instanceUrl }
|
|
102
|
+
*/
|
|
103
|
+
export declare function handleConfluenceConnect(body: string): Promise<ConnectorHandlerResult>;
|
|
104
|
+
/**
|
|
105
|
+
* POST /connections/confluence/test
|
|
106
|
+
*/
|
|
107
|
+
export declare function handleConfluenceTest(): Promise<ConnectorHandlerResult>;
|
|
108
|
+
/**
|
|
109
|
+
* DELETE /connections/confluence
|
|
110
|
+
*/
|
|
111
|
+
export declare function handleConfluenceDisconnect(): ConnectorHandlerResult;
|