Skip to content

Commit f30e3ba

Browse files
committed
More source --> connector cleanup
1 parent 285f9b5 commit f30e3ba

12 files changed

Lines changed: 46 additions & 65 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@plotday/twister": minor
3+
---
4+
5+
Removed: `addContacts()` from Plot tool public API (contacts are created implicitly through thread/note creation)
6+
Changed: `ContactAccess` enum now only has `Read``Write` removed from public API
7+
Added: `handleReplies` static property on Connector class (replaces Plot tool options for defaultMention)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@plotday/twister": patch
3+
---
4+
5+
Changed: Renamed `--source` CLI flag to `--connector` in `plot create` command to match SDK naming

connectors/AGENTS.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ import {
111111
type Channel,
112112
} from "@plotday/twister/tools/integrations";
113113
import { Network, type WebhookRequest } from "@plotday/twister/tools/network";
114-
import { ContactAccess, Plot } from "@plotday/twister/tools/plot";
115114
import { Tasks } from "@plotday/twister/tools/tasks";
116115

117116
type SyncState = {
@@ -126,6 +125,7 @@ export class MyConnector extends Connector<MyConnector> {
126125
static readonly PROVIDER = AuthProvider.Linear; // Use appropriate provider
127126
static readonly SCOPES = ["read", "write"];
128127
static readonly Options: SyncToolOptions;
128+
static readonly handleReplies = true; // Enable @-mentions on replies to synced threads
129129
declare readonly Options: SyncToolOptions;
130130

131131
// 2. Declare dependencies
@@ -143,7 +143,6 @@ export class MyConnector extends Connector<MyConnector> {
143143
network: build(Network, { urls: ["https://api.example.com/*"] }),
144144
callbacks: build(Callbacks),
145145
tasks: build(Tasks),
146-
plot: build(Plot, { contact: { access: ContactAccess.Write } }),
147146
};
148147
}
149148

@@ -798,20 +797,16 @@ async onNoteCreated(note: Note): Promise<void> {
798797

799798
### Default Mention on Replies
800799

801-
Connectors with bidirectional sync should set `thread.defaultMention: true` in their Plot tool options so replies to synced threads automatically mention the connector:
800+
Connectors with bidirectional sync should set `static readonly handleReplies = true` so replies to synced threads automatically mention the connector:
802801

803802
```typescript
804-
plot: build(Plot, {
805-
thread: {
806-
access: ThreadAccess.Create,
807-
defaultMention: true, // Replies to synced threads mention this connector by default
808-
updated: this.onThreadUpdated,
809-
},
810-
note: { created: this.onNoteCreated },
811-
}),
803+
export class MyConnector extends Connector<MyConnector> {
804+
static readonly handleReplies = true; // Replies to synced threads mention this connector by default
805+
// ...
806+
}
812807
```
813808

814-
Without this, users must manually toggle the connector's mention chip on each reply. Connectors that don't process replies (e.g., read-only calendar sync) should NOT set this flag.
809+
Without this, the connector cannot be @-mentioned at all. Connectors that don't process replies (e.g., read-only calendar sync) should NOT set this flag.
815810

816811
## Contacts Pattern
817812

@@ -837,10 +832,7 @@ const activity: NewActivityWithNotes = {
837832
};
838833
```
839834

840-
Declare `ContactAccess.Write` in build:
841-
```typescript
842-
plot: build(Plot, { contact: { access: ContactAccess.Write } }),
843-
```
835+
Contacts are created implicitly when saving threads/links via `integrations.saveLink()`no explicit `addContacts()` call or `ContactAccess.Write` permission is needed.
844836

845837
## Buffer Declaration
846838

@@ -875,7 +867,8 @@ After creating a new connector, add it to `pnpm-workspace.yaml` if not already c
875867
- [ ] Extend `Connector<YourConnector>`
876868
- [ ] Declare `static readonly PROVIDER`, `static readonly SCOPES`
877869
- [ ] Declare `static readonly Options: SyncToolOptions` and `declare readonly Options: SyncToolOptions`
878-
- [ ] Declare all dependencies in `build()`: Integrations, Network, Callbacks, Tasks, Plot
870+
- [ ] Declare all dependencies in `build()`: Integrations, Network, Callbacks, Tasks
871+
- [ ] Set `static readonly handleReplies = true` if the connector supports bidirectional sync
879872
- [ ] Implement `getChannels()`, `onChannelEnabled()`, `onChannelDisabled()`
880873
- [ ] Convert parent callbacks to tokens with `createFromParent()` — **never pass functions to `this.callback()`**
881874
- [ ] Store callback tokens with `this.set()`, retrieve with `this.get<Callback>()`

connectors/github/src/github.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
type Channel,
1818
} from "@plotday/twister/tools/integrations";
1919
import { Network, type WebhookRequest } from "@plotday/twister/tools/network";
20-
import { Plot } from "@plotday/twister/tools/plot";
2120
import { Tasks } from "@plotday/twister/tools/tasks";
2221
import {
2322
startPRBatchSync,
@@ -103,6 +102,7 @@ type GitHubRepo = {
103102
export class GitHub extends Connector<GitHub> {
104103
static readonly PROVIDER = AuthProvider.GitHub;
105104
static readonly SCOPES = ["repo"];
105+
static readonly handleReplies = true;
106106

107107
readonly provider = AuthProvider.GitHub;
108108
readonly scopes = GitHub.SCOPES;
@@ -153,10 +153,6 @@ export class GitHub extends Connector<GitHub> {
153153
integrations: build(Integrations),
154154
network: build(Network, { urls: ["https://api.github.com/*"] }),
155155
tasks: build(Tasks),
156-
plot: build(Plot, {
157-
thread: { defaultMention: true },
158-
note: { defaultMention: true },
159-
}),
160156
};
161157
}
162158

connectors/gmail/src/gmail.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
Integrations,
99
} from "@plotday/twister/tools/integrations";
1010
import { Network, type WebhookRequest } from "@plotday/twister/tools/network";
11-
import { Plot } from "@plotday/twister/tools/plot";
11+
1212

1313
import {
1414
GmailApi,
@@ -45,6 +45,7 @@ type MessageSyncOptions = {
4545
*/
4646
export class Gmail extends Connector<Gmail> {
4747
static readonly PROVIDER = AuthProvider.Google;
48+
static readonly handleReplies = true;
4849
static readonly SCOPES = [
4950
"https://www.googleapis.com/auth/gmail.readonly",
5051
"https://www.googleapis.com/auth/gmail.modify",
@@ -68,9 +69,6 @@ export class Gmail extends Connector<Gmail> {
6869
network: build(Network, {
6970
urls: ["https://gmail.googleapis.com/gmail/v1/*"],
7071
}),
71-
plot: build(Plot, {
72-
thread: { defaultMention: true },
73-
}),
7472
};
7573
}
7674

connectors/jira/src/jira.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
type Channel,
1818
} from "@plotday/twister/tools/integrations";
1919
import { Network, type WebhookRequest } from "@plotday/twister/tools/network";
20-
import { Plot } from "@plotday/twister/tools/plot";
2120
import { Tasks } from "@plotday/twister/tools/tasks";
2221

2322
type Project = {
@@ -47,6 +46,7 @@ type SyncState = {
4746
export class Jira extends Connector<Jira> {
4847
static readonly PROVIDER = AuthProvider.Atlassian;
4948
static readonly SCOPES = ["read:jira-work", "write:jira-work", "read:jira-user"];
49+
static readonly handleReplies = true;
5050

5151
readonly provider = AuthProvider.Atlassian;
5252
readonly scopes = Jira.SCOPES;
@@ -69,10 +69,6 @@ export class Jira extends Connector<Jira> {
6969
integrations: build(Integrations),
7070
network: build(Network, { urls: ["https://*.atlassian.net/*"] }),
7171
tasks: build(Tasks),
72-
plot: build(Plot, {
73-
thread: { defaultMention: true },
74-
note: { defaultMention: true },
75-
}),
7672
};
7773
}
7874

connectors/linear/src/linear.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import {
2525
type Channel,
2626
} from "@plotday/twister/tools/integrations";
2727
import { Network, type WebhookRequest } from "@plotday/twister/tools/network";
28-
import { Plot } from "@plotday/twister/tools/plot";
2928
import { Tasks } from "@plotday/twister/tools/tasks";
3029

3130
type Project = {
@@ -70,6 +69,7 @@ type ViewerInfo = {
7069
export class Linear extends Connector<Linear> {
7170
static readonly PROVIDER = AuthProvider.Linear;
7271
static readonly SCOPES = ["read", "write", "admin"];
72+
static readonly handleReplies = true;
7373

7474
readonly provider = AuthProvider.Linear;
7575
readonly scopes = Linear.SCOPES;
@@ -93,10 +93,6 @@ export class Linear extends Connector<Linear> {
9393
integrations: build(Integrations),
9494
network: build(Network, { urls: ["https://api.linear.app/*"] }),
9595
tasks: build(Tasks),
96-
plot: build(Plot, {
97-
thread: { defaultMention: true },
98-
note: { defaultMention: true },
99-
}),
10096
};
10197
}
10298

connectors/slack/src/slack.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
type Channel,
1111
} from "@plotday/twister/tools/integrations";
1212
import { Network, type WebhookRequest } from "@plotday/twister/tools/network";
13-
import { Plot } from "@plotday/twister/tools/plot";
13+
1414

1515
type MessageChannel = {
1616
id: string;
@@ -61,6 +61,7 @@ import {
6161
*/
6262
export class Slack extends Connector<Slack> {
6363
static readonly PROVIDER = AuthProvider.Slack;
64+
static readonly handleReplies = true;
6465
static readonly SCOPES = [
6566
"channels:history",
6667
"channels:read",
@@ -81,9 +82,6 @@ export class Slack extends Connector<Slack> {
8182
return {
8283
integrations: build(Integrations),
8384
network: build(Network, { urls: ["https://slack.com/api/*"] }),
84-
plot: build(Plot, {
85-
thread: { defaultMention: true },
86-
}),
8785
};
8886
}
8987

twister/cli/commands/create.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ interface CreateOptions {
1010
dir?: string;
1111
name?: string;
1212
displayName?: string;
13-
source?: boolean;
13+
connector?: boolean;
1414
}
1515

1616
export async function createCommand(options: CreateOptions) {
17-
const isSource = !!options.source;
18-
out.header(isSource ? "Create a new Plot connector" : "Create a new Plot twist");
17+
const isConnector = !!options.connector;
18+
out.header(isConnector ? "Create a new Plot connector" : "Create a new Plot twist");
1919

2020
let response: { name: string; displayName: string };
2121

@@ -96,7 +96,7 @@ export async function createCommand(options: CreateOptions) {
9696
const plotTwistId = crypto.randomUUID();
9797

9898
// Create package.json
99-
const packageName = isSource ? `@plotday/connector-${response.name}` : response.name;
99+
const packageName = isConnector ? `@plotday/connector-${response.name}` : response.name;
100100
const packageJson: any = {
101101
name: packageName,
102102
displayName: response.displayName || response.name,
@@ -130,7 +130,7 @@ export async function createCommand(options: CreateOptions) {
130130
JSON.stringify(tsconfigJson, null, 2) + "\n"
131131
);
132132

133-
const sourceTemplate = `import { Connector, type ToolBuilder } from "@plotday/twister";
133+
const connectorTemplate = `import { Connector, type ToolBuilder } from "@plotday/twister";
134134
import {
135135
AuthProvider,
136136
type AuthToken,
@@ -190,7 +190,7 @@ export default class MyTwist extends Twist<MyTwist> {
190190

191191
fs.writeFileSync(
192192
path.join(twistPath, "src", "index.ts"),
193-
isSource ? sourceTemplate : twistTemplate
193+
isConnector ? connectorTemplate : twistTemplate
194194
);
195195

196196
// Detect and use appropriate package manager

twister/cli/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ program
5555
.option("-d, --dir <directory>", "Directory to create the twist in")
5656
.option("-n, --name <name>", "Package name (kebab-case)")
5757
.option("--display-name <displayName>", "Display name for the twist")
58-
.option("--source", "Create a connector instead of a twist")
58+
.option("--connector", "Create a connector instead of a twist")
5959
.action(createCommand);
6060

6161
// Top-level lint command

0 commit comments

Comments
 (0)