Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
57f3742
Activity --> Thread, Link --> Action
KrisBraun Feb 24, 2026
dd8a527
Separate scheduling from threads: new Schedule type, update tools
KrisBraun Feb 25, 2026
a70a120
Rename tools → sources: Sources save directly via integrations
KrisBraun Feb 25, 2026
118505b
Rename syncable → channel in sources/AGENTS.md and message-tasks twist
KrisBraun Feb 25, 2026
8d9cb26
Add ScheduleContact types to SDK
KrisBraun Feb 25, 2026
b34aed8
Remove RSVP tags (Attend/Skip/Undecided) from Tag enum
KrisBraun Feb 25, 2026
e67b0e6
Change ScheduleContact.contact from ActorId to Actor
KrisBraun Feb 25, 2026
3ef6326
Make ScheduleContact.role non-nullable
KrisBraun Feb 25, 2026
bb5084e
Use schedule contacts instead of RSVP tags, add links support
KrisBraun Feb 25, 2026
520335c
Update scripts for sources
KrisBraun Feb 26, 2026
30afad3
Remove deprecated twister functions and types
KrisBraun Feb 26, 2026
f442b2d
Link types
KrisBraun Feb 26, 2026
c3021b2
Clean up threads and tags
KrisBraun Feb 27, 2026
b6e6f50
Add lint to sources
KrisBraun Feb 27, 2026
c50958f
Add channelId to Link type and all sources for account-based priority…
KrisBraun Feb 27, 2026
4eecad3
Remove unnecessary common interfaces for sources
KrisBraun Feb 27, 2026
83a8f62
Redesign Source class to own identity and lifecycle
KrisBraun Feb 28, 2026
46fe8f1
Replace outdated changesets with accurate ones for threads/links/sche…
KrisBraun Feb 28, 2026
7ad8e06
Add dark mode icons
KrisBraun Mar 1, 2026
6e9dcf5
Stop publishing sources, update changesets for twister-only
KrisBraun Mar 4, 2026
a70e6f3
Add twist lifecycle hooks and link support to SDK
KrisBraun Mar 4, 2026
086acdd
Merge github-issues into github source, add Gmail thread read support
KrisBraun Mar 4, 2026
2602607
Update message-tasks twist to use new lifecycle hooks
KrisBraun Mar 4, 2026
76fc6fe
Update docs for source-owned lifecycle and link support
KrisBraun Mar 4, 2026
c42cc5a
Update lockfile
KrisBraun Mar 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .changeset/all-knives-build.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/bold-stars-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Changed: BREAKING — Refactor Source base class to own provider identity and channel lifecycle
5 changes: 5 additions & 0 deletions .changeset/brave-foxes-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Changed: BREAKING — Rename Activity to Thread and Link to Action throughout the SDK (types, methods, filters)
5 changes: 5 additions & 0 deletions .changeset/bright-trees-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Changed: BREAKING — Twist lifecycle hooks onThreadUpdated, onNoteCreated moved from Plot options to Twist base class methods; added onLinkCreated, onLinkUpdated, onLinkNoteCreated, onOptionsChanged
5 changes: 5 additions & 0 deletions .changeset/calm-waves-shine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Added: Schedule type with ScheduleContact for event scheduling, recurring events, and per-user schedules
3 changes: 2 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [
"@plotday/twist-*"
"@plotday/twist-*",
"@plotday/source-*"
]
}
5 changes: 5 additions & 0 deletions .changeset/cool-lakes-hum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Added: Source.onThreadRead() hook for writing back read/unread status to external services
5 changes: 5 additions & 0 deletions .changeset/deep-pens-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Changed: BREAKING — Removed deprecated IntegrationProviderConfig and IntegrationOptions types; added archiveLinks(filter) for bulk-archiving links
5 changes: 5 additions & 0 deletions .changeset/fresh-plants-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Added: Source base class for building service integrations with provider, scopes, and lifecycle management
13 changes: 0 additions & 13 deletions .changeset/full-ends-rescue.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/green-doors-open.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Added: LinkType config for sources and channelId on Link for account-based priority routing
5 changes: 5 additions & 0 deletions .changeset/kind-dogs-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Changed: BREAKING — Removed thread.updated and note.created callbacks from Plot options (use Twist.onThreadUpdated/onNoteCreated instead); added `link: true` option and `getLinks(filter?)` method for link processing
5 changes: 5 additions & 0 deletions .changeset/quiet-rivers-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Changed: BREAKING — Rename Syncable to Channel in Integrations tool, add saveLink() and saveContacts() methods
5 changes: 5 additions & 0 deletions .changeset/silver-moons-rise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Removed: BREAKING — Deprecated twister functions and types
5 changes: 5 additions & 0 deletions .changeset/swift-hawks-soar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Added: Package exports for ./source and ./schedule modules
5 changes: 5 additions & 0 deletions .changeset/tall-clouds-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Removed: BREAKING — Common interfaces (calendar, documents, messaging, projects, source-control) replaced by individual source implementations
5 changes: 5 additions & 0 deletions .changeset/warm-birds-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@plotday/twister": minor
---

Removed: BREAKING — RSVP tags (Attend, Skip, Undecided) from Tag enum, replaced by ScheduleContact
11 changes: 5 additions & 6 deletions .github/workflows/changeset-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,15 @@ jobs:
git fetch origin main
CHANGED_FILES=$(git diff --name-only origin/main...HEAD)

# Check if Twister or tools directories were modified
# Check if Twister was modified (sources are private and don't need changesets)
TWISTER_CHANGED=$(echo "$CHANGED_FILES" | grep -E '^twister/' || true)
TOOLS_CHANGED=$(echo "$CHANGED_FILES" | grep -E '^tools/' || true)

if [ -n "$TWISTER_CHANGED" ] || [ -n "$TOOLS_CHANGED" ]; then
if [ -n "$TWISTER_CHANGED" ]; then
echo "needs-changeset=true" >> $GITHUB_OUTPUT
echo "Twister or tools packages were modified"
echo "Twister package was modified"
else
echo "needs-changeset=false" >> $GITHUB_OUTPUT
echo "No Twister or tools changes detected"
echo "No Twister changes detected"
fi

- name: Check for changesets
Expand All @@ -55,7 +54,7 @@ jobs:
CHANGESET_COUNT=$(ls -1 .changeset/*.md 2>/dev/null | grep -v README.md | wc -l | tr -d ' ')

if [ "$CHANGESET_COUNT" -eq 0 ]; then
echo "❌ Error: Changes detected in Twister or tools packages, but no changeset found."
echo "❌ Error: Changes detected in Twister package, but no changeset found."
echo ""
echo "Please add a changeset by running:"
echo " pnpm changeset"
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,8 @@ jobs:
# Determine package directory
if [[ "$name" == "@plotday/twister" ]]; then
pkg_dir="twister"
elif [[ "$name" == @plotday/tool-* ]]; then
tool_name="${name#@plotday/tool-}"
pkg_dir="tools/$tool_name"
else
echo "Unknown package: $name"
echo "Skipping unknown package: $name"
continue
fi

Expand Down
39 changes: 14 additions & 25 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,52 @@
# Plot Development Guide for AI Assistants

This guide helps AI assistants build Plot tools and twists correctly.
This guide helps AI assistants build Plot sources and twists correctly.

## What Are You Building?

### Building a Tool (service integration)
### Building a Source (service integration)

Tools are reusable packages that connect to external services (Linear, Slack, Google Calendar, etc.). They implement a standard interface and are consumed by twists.
Sources are packages that connect to external services (Linear, Slack, Google Calendar, etc.). They extend Source and save data directly via `integrations.saveThread()`.

**Start here:** `tools/AGENTS.md` — Complete tool development guide with scaffold, patterns, and checklist.

**Choose your interface:**

| Interface | For | Import |
|-----------|-----|--------|
| `CalendarTool` | Calendar/scheduling | `@plotday/twister/common/calendar` |
| `ProjectTool` | Project/task management | `@plotday/twister/common/projects` |
| `MessagingTool` | Email and chat | `@plotday/twister/common/messaging` |
| `DocumentTool` | Document/file storage | `@plotday/twister/common/documents` |
**Start here:** `sources/AGENTS.md` — Complete source development guide with scaffold, patterns, and checklist.

### Building a Twist (orchestrator)

Twists are the entry point that users install. They declare which tools to use and implement domain logic (filtering, enrichment, two-way sync).
Twists are the entry point that users install. They declare which tools to use and implement domain logic.

**Start here:** `twister/cli/templates/AGENTS.template.md` — Twist implementation guide.

## Type Definitions

All types in `twister/src/` with full JSDoc:

- **Source base**: `twister/src/source.ts`
- **Tool base**: `twister/src/tool.ts`
- **Twist base**: `twister/src/twist.ts`
- **Built-in tools**: `twister/src/tools/*.ts`
- `callbacks.ts`, `store.ts`, `tasks.ts`, `plot.ts`, `ai.ts`, `network.ts`, `integrations.ts`, `twists.ts`
- **Common interfaces**: `twister/src/common/*.ts`
- `calendar.ts`, `messaging.ts`, `projects.ts`, `documents.ts`
- **Core types**: `twister/src/plot.ts`, `twister/src/tag.ts`

## Additional Resources

- **Full Documentation**: <https://twist.plot.day>
- **Building Tools Guide**: `twister/docs/BUILDING_TOOLS.md`
- **Building Sources Guide**: `sources/AGENTS.md`
- **Runtime Environment**: `twister/docs/RUNTIME.md`
- **Tools Guide**: `twister/docs/TOOLS_GUIDE.md`
- **Multi-User Auth**: `twister/docs/MULTI_USER_AUTH.md`
- **Sync Strategies**: `twister/docs/SYNC_STRATEGIES.md`
- **Working Tool Examples**: `tools/linear/`, `tools/google-calendar/`, `tools/slack/`, `tools/jira/`
- **Working Twist Examples**: `twists/calendar-sync/`, `twists/project-sync/`
- **Working Source Examples**: `sources/linear/`, `sources/google-calendar/`, `sources/slack/`, `sources/jira/`

## Common Pitfalls

1. **❌ Using instance variables for state** — Use `this.set()`/`this.get()` (state doesn't persist between executions)
2. **❌ Long-running operations without batching** — Break into chunks with `runTask()` (~1000 requests per execution)
3. **❌ Passing functions to `this.callback()`** — See `tools/AGENTS.md` for callback serialization pattern
4. **❌ Calling `plot.createActivity()` from a tool** — Tools build data, twists save it
5. **❌ Forgetting sync metadata** — Always inject `syncProvider` and `syncableId` into `activity.meta`
6. **❌ Not handling initial vs incremental sync** — `unread: false` for initial, omit for incremental
7. **❌ Missing localhost guard in webhooks** — Skip webhook registration when URL contains "localhost"
3. **❌ Passing functions to `this.callback()`** — See `sources/AGENTS.md` for callback serialization pattern
4. **❌ Forgetting sync metadata** — Always inject `syncProvider` and `channelId` into `thread.meta`
5. **❌ Not handling initial vs incremental sync** — Propagate `initialSync` flag from entry point (`onChannelEnabled` → `true`, webhook → `false`) through all batch callbacks. Set `unread: false` and `archived: false` for initial, omit for incremental
6. **❌ Missing localhost guard in webhooks** — Skip webhook registration when URL contains "localhost"
7. **❌ Stripping HTML tags locally** — Pass raw HTML with `contentType: "html"` for server-side markdown conversion

---

**Remember**: When in doubt, check the type definitions in `twister/src/` and study the working examples in `tools/`.
**Remember**: When in doubt, check the type definitions in `twister/src/` and study the working examples in `sources/`.
Loading