Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ CopilotKit SDK telemetry collects usage metadata separately from conversation pe
| Slack | Managed Channels SDK declaration with workspace and user allowlists |
| Calls | WebRTC speech, delegated compute, bounded sessions, hangup, and timeline receipts |
| Background work | Scheduled server-side turns in their original conversation, with pause and retry controls |
| Goals and reminders | SQLite-backed responsibilities, editable progress and status, and one dismissible one-time reminder per goal |
| Browser | Separate read-only public-page service with page capture and navigation limits |
| Dot computers | Per-Dot browser profiles, files, shell, takeover, permissions, and action records through OpenBot |
| Connections | Per-Dot MCP servers, Composio connected apps, per-tool access, and owner approval for MCP write actions |
Expand All @@ -221,13 +222,13 @@ Local checks cover setup, persistence, permissions, SDK failure handling, and br

Automatic Learning routing and skill delivery are configured locally. Cloud schedules, eligible-thread counts, and published-skill delivery still need connected-service verification. Skills require review and publication in Intelligence; existing conversations without a container are not enrolled retroactively.

This is a single-owner starting point. Shared editing, invitations, file uploads, and interactive page embeds are not included. Schedules are recurring instructions, not a complete goal or event-trigger system. Specialist Dots have separate roles and conversations; multi-Dot group conversations and automatic delegation are further work.
This is a single-owner starting point. Shared editing, invitations, file uploads, and interactive page embeds are not included. Goals and their one-time reminders are managed in the workspace; due reminders appear there for the owner to dismiss, and do not send external notifications or trigger agent work. Recurring schedules remain a separate feature. Specialist Dots have separate roles and conversations; multi-Dot group conversations and automatic delegation are further work.

### Extending the template

- Add identity, Space membership, and shared page editing for multi-user deployments.
- Add file attachments and richer page content.
- Add event triggers and a persistent responsibility lifecycle.
- Add optional notification delivery for reminders with explicit provider setup and owner controls.
- Extend tools and approval flows for your own workflows.
- Add richer artifacts, connected-app context, and specialist coordination.

Expand Down
8 changes: 7 additions & 1 deletion docs/SETUP.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Running the template

OpenDots runs a React app and a Node server. The server stores pages, Space and Dot configuration, and thread bindings in SQLite and connects to your configured conversation, model, and messaging services.
OpenDots runs a React app and a Node server. The server stores pages, Space and Dot configuration, thread bindings, goals, and reminder state in SQLite and connects to your configured conversation, model, and messaging services.

## Local development

Expand Down Expand Up @@ -97,6 +97,12 @@ Use the conversation's save-to-page action to create a document from its saved t

Back up both storage layers: SQLite contains page content and thread bindings; the Intelligence project contains conversation history. The template does not include multi-user page sharing, realtime collaboration, file uploads, or arbitrary interactive embeds.

## Goals and reminders

Open **Goals & reminders** in the workspace to create responsibilities, add notes, track progress from 0–100%, and set a one-time reminder. Edit a goal to change its status (active, paused, completed, or cancelled), progress, or reminder time. When an active or paused goal's reminder becomes due, it is highlighted in the workspace; dismissing it is persisted. Changing or clearing the reminder resets its dismissed state.

Goals and reminder timestamps are stored in the configured SQLite database and survive server restarts. They are separate from recurring scheduled turns. Due reminders are only shown in the app while it is open; OpenDots does not send email, push, Slack, or other external notifications for them and does not start agent work when they become due.

## Browser tool

Parallel is selected by default (`WEB_SEARCH_PROVIDER=parallel`). Live research needs the model configuration, but no browser worker. An optional server-side `PARALLEL_API_KEY` enables authenticated usage and higher limits. The anonymous MCP endpoint is free for light use. Queries, selected URLs, research objectives and a stable session identifier go to Parallel. See [public-web research](../README.md#public-web-research) for data sharing, permissions and limitations.
Expand Down
39 changes: 30 additions & 9 deletions src/client/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
Plus,
Search,
Settings2,
Target,
Trash2,
X,
} from 'lucide-react';
Expand All @@ -46,6 +47,7 @@ import { ThreadList } from './ThreadList';
import { ResultPane } from './ResultPane';
import { TaskRow } from './TaskPresentation';
import { TaskActions } from './TaskActions';
import { GoalsPanel } from './GoalsPanel';
import { WorkspaceDialog, type Dialog } from './WorkspaceDialog';
import { submitComposerOnEnter } from './chat-composer';

Expand All @@ -62,9 +64,9 @@ export function App() {
const [workspace, setWorkspace] = useState<WorkspaceState>();
const [selectedDot, setSelectedDot] = useState('');
const [selectedThread, setSelectedThread] = useState<string>();
const [view, rawSetView] = useState<'chat' | 'tasks' | 'memories' | 'space'>(
'chat',
);
const [view, rawSetView] = useState<
'chat' | 'tasks' | 'goals' | 'memories' | 'space'
>('chat');
const dirtyPage = useRef(false);
const [spaceId, setSpaceId] = useState('');
const [pageId, setPageId] = useState<string>();
Expand Down Expand Up @@ -472,6 +474,17 @@ export function App() {
</div>
)}
<div className="sidebar-bottom">
<button
className={`nav-item ${view === 'goals' ? 'active' : ''}`}
onClick={() => {
setView('goals');
setMobile(false);
}}
>
<Target size={17} />
<span>Goals & reminders</span>
{state.goals.length > 0 && <small>{state.goals.length}</small>}
</button>
<button
className={`nav-item ${view === 'tasks' ? 'active' : ''}`}
onClick={() => {
Expand Down Expand Up @@ -539,9 +552,11 @@ export function App() {
? dot.name
: view === 'tasks'
? 'Activity'
: view === 'space'
? 'Pages'
: 'Memories'}
: view === 'goals'
? 'Goals & reminders'
: view === 'space'
? 'Pages'
: 'Memories'}
</strong>
</div>
<div className="top-actions">
Expand Down Expand Up @@ -775,12 +790,16 @@ export function App() {
<h1>
{view === 'memories'
? 'Memories'
: 'A little follow-through.'}
: view === 'goals'
? 'Goals & reminders'
: 'A little follow-through.'}
</h1>
<p>
{view === 'memories'
? 'Preferences you choose to share with your Dots.'
: 'Scheduled turns run on the server in their original conversation.'}
: view === 'goals'
? 'Keep responsibilities, progress, and one-time reminders in your workspace.'
: 'Scheduled turns run on the server in their original conversation.'}
</p>
</div>
{view === 'memories' && (
Expand All @@ -793,7 +812,9 @@ export function App() {
</button>
)}
</div>
{view === 'memories' ? (
{view === 'goals' ? (
<GoalsPanel goals={state.goals} mutate={mutate} />
) : view === 'memories' ? (
<>
<div className="memory-grid">
{state.memories.map((memory) => (
Expand Down
Loading