{"_id":"@cemoody/pi-crust-ext-todoist","_rev":"2-88661e6382d02feded38d5dd16930e0e","name":"@cemoody/pi-crust-ext-todoist","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@cemoody/pi-crust-ext-todoist","version":"0.1.0","keywords":["pi-crust","pi-crust-extension","pi-package","pi.dev","todoist","todo","tasks"],"author":{"name":"cemoody"},"license":"MIT","_id":"@cemoody/pi-crust-ext-todoist@0.1.0","maintainers":[{"name":"chrisemoodynpm","email":"chrisemoody@gmail.com"}],"homepage":"https://github.com/cemoody/pi-crust-ext-todoist#readme","bugs":{"url":"https://github.com/cemoody/pi-crust-ext-todoist/issues"},"pi":{"extensions":["./pi.mjs"]},"dist":{"shasum":"bc19e8e725f0c0f103467abbba3b72723d2020fd","tarball":"https://registry.npmjs.org/@cemoody/pi-crust-ext-todoist/-/pi-crust-ext-todoist-0.1.0.tgz","fileCount":9,"integrity":"sha512-xcK7a4ingf2Ln8POo6/VNGiQYSy5iWdDLiTRcvnvyTWLpYwkDXb47SZ+fgyxyFn/Zt6JKj/sROXgGkcD7EeGAA==","signatures":[{"sig":"MEYCIQCPLaXJJdBBI4sdEiYVXcZiOgePLFI8GWHH1YtY+bj7UQIhAN86zMz+Mo192zNXsXno+3j3zZjYoTCywWk/CWisXv26","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":70899},"main":"./server.mjs","type":"module","engines":{"node":">=22"},"exports":{".":"./server.mjs","./package.json":"./package.json"},"gitHead":"3afb95bbe8606a6184a53bb300f1ddbc892b61ed","piCrust":{"web":"./web.mjs","extension":"./server.mjs"},"scripts":{"test":"vitest run","test:watch":"vitest","prepublishOnly":"vitest run"},"_npmUser":{"name":"chrisemoodynpm","email":"chrisemoody@gmail.com"},"repository":{"url":"git+https://github.com/cemoody/pi-crust-ext-todoist.git","type":"git"},"_npmVersion":"10.9.7","description":"Interactive, mobile-friendly Todoist widget for pi-crust — the LLM drives your task list via tools while you edit/complete tasks inline in the sidebar.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^29.1.1","react":"^19.2.7","vitest":"^4.0.0","typebox":"^1.1.24","react-dom":"^19.2.7","@testing-library/dom":"^10.4.1","@testing-library/react":"^16.3.2"},"piRemoteControl":{"web":"./web.mjs","extension":"./server.mjs"},"peerDependencies":{"typebox":"*"},"_npmOperationalInternal":{"tmp":"tmp/pi-crust-ext-todoist_0.1.0_1781889388581_0.5917893221853829","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@cemoody/pi-crust-ext-todoist","version":"0.1.1","description":"Interactive, mobile-friendly Todoist widget for pi-crust — the LLM drives your task list via tools while you edit/complete tasks inline in the sidebar.","license":"MIT","author":{"name":"cemoody"},"type":"module","main":"./server.mjs","exports":{".":"./server.mjs","./package.json":"./package.json"},"engines":{"node":">=22"},"pi":{"extensions":["./pi.mjs"]},"piCrust":{"extension":"./server.mjs","web":"./web.mjs"},"piRemoteControl":{"extension":"./server.mjs","web":"./web.mjs"},"repository":{"type":"git","url":"git+https://github.com/cemoody/pi-crust-ext-todoist.git"},"homepage":"https://github.com/cemoody/pi-crust-ext-todoist#readme","bugs":{"url":"https://github.com/cemoody/pi-crust-ext-todoist/issues"},"keywords":["pi-crust","pi-crust-extension","pi-package","pi.dev","todoist","todo","tasks"],"scripts":{"test":"vitest run","test:watch":"vitest","prepublishOnly":"vitest run"},"peerDependencies":{"typebox":"*"},"devDependencies":{"@testing-library/dom":"^10.4.1","@testing-library/react":"^16.3.2","jsdom":"^29.1.1","react":"^19.2.7","react-dom":"^19.2.7","typebox":"^1.1.24","vitest":"^4.0.0"},"_id":"@cemoody/pi-crust-ext-todoist@0.1.1","gitHead":"df23eabbcbf25c9cd606ea3405ff053c96996777","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-iCEvgwxd5WXd2RCSLBviEzPVl0Yj+I//QVIV0N0Ize6+UHpZigOHxHuz+OSO2SnRehme+SSg6piS1rVkFdmngQ==","shasum":"c03ecfe13bb709c881181204d3c85cc2e133f438","tarball":"https://registry.npmjs.org/@cemoody/pi-crust-ext-todoist/-/pi-crust-ext-todoist-0.1.1.tgz","fileCount":9,"unpackedSize":72110,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD3W2BEyZGMErRKk7MmazUnOD4b3FpcCCwyrV8O/hqjvQIgGxO2NuA+gJ1lYy2WUXXBtlyiKtenImJ+JpUMwzCPDVk="}]},"_npmUser":{"name":"chrisemoodynpm","email":"chrisemoody@gmail.com"},"directories":{},"maintainers":[{"name":"chrisemoodynpm","email":"chrisemoody@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pi-crust-ext-todoist_0.1.1_1781889816400_0.7601411741326687"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-19T17:16:28.380Z","modified":"2026-06-19T17:23:36.673Z","0.1.0":"2026-06-19T17:16:28.729Z","0.1.1":"2026-06-19T17:23:36.552Z"},"bugs":{"url":"https://github.com/cemoody/pi-crust-ext-todoist/issues"},"author":{"name":"cemoody"},"license":"MIT","homepage":"https://github.com/cemoody/pi-crust-ext-todoist#readme","keywords":["pi-crust","pi-crust-extension","pi-package","pi.dev","todoist","todo","tasks"],"repository":{"type":"git","url":"git+https://github.com/cemoody/pi-crust-ext-todoist.git"},"description":"Interactive, mobile-friendly Todoist widget for pi-crust — the LLM drives your task list via tools while you edit/complete tasks inline in the sidebar.","maintainers":[{"name":"chrisemoodynpm","email":"chrisemoody@gmail.com"}],"readme":"# @cemoody/pi-crust-ext-todoist\n\nAn interactive, **mobile-friendly Todoist widget** for pi-crust. The LLM drives\nyour task list with tools; you edit, complete, and reschedule tasks inline in\nthe sidebar. Both surfaces operate on the **same Todoist account**, so changes\nthe agent makes show up immediately in the widget and vice-versa.\n\n> Without a `TODOIST_API_TOKEN` the extension runs against a fully-interactive\n> in-memory mock (create / edit / complete / reopen / delete all work) so you\n> can try it offline. Set the token to talk to your real account.\n\n## Three surfaces, one client\n\nThis package wires three pi-crust/pi entry points to a single shared Todoist\nREST client (`todoist-client.mjs`):\n\n| File                | Manifest key            | Role |\n|---------------------|-------------------------|------|\n| `pi.mjs`            | `pi.extensions`         | LLM-facing tools — the agent driving surface |\n| `server.mjs`        | `piCrust.extension`     | Registers the **Todoist** sidebar activity + `/api/ext/todoist/*` REST routes |\n| `web.mjs`           | `piCrust.web`           | The interactive React widget mounted in the sidebar |\n\nThe widget calls the server routes; the agent tools call Todoist directly.\nBoth go through the same client, so there's no state to keep in sync — Todoist\n(or the mock store) is the single source of truth.\n\n## The UI paradigm\n\nA deliberately **focused subset** of Todoist rather than a full clone — what you\nactually want inline in a session:\n\n- **Project chips** across the top scope the list (`All` + each project, with\n  live open-task counts). Horizontally scrollable on phones.\n- A **sticky quick-add bar** creates tasks into the active project (Inbox by\n  default). Enter or the **Add** button.\n- Each task row is a large tap target:\n  - a **round complete checkbox** colored by priority (P1 red → P4 grey) with a\n    satisfying strike-and-remove animation,\n  - the **title is tap-to-edit inline** (Enter saves, Esc cancels),\n  - a **due-date chip** (overdue = red, today = green, otherwise a friendly date),\n  - **project dot** (in the `All` view) and **@label** pills,\n  - row actions to **cycle priority** and **delete** (hover-revealed on desktop,\n    always visible on phones).\n- Every mutation is **optimistic** and reconciles against the server response.\n\nIt collapses to a single comfortable column with 44px+ tap targets under 640px,\nand reuses the host design tokens so it matches the rest of pi-crust.\n\n## Agent tools\n\n| Tool               | Description |\n|--------------------|-------------|\n| `todoist_list`     | List active tasks (by `projectId` or a Todoist `filter` query like `today`, `overdue`, `@work & p1`) |\n| `todoist_projects` | List projects with ids |\n| `todoist_add`      | Create a task (`content`, `dueString` natural language, `priority` 1–4, `labels`, `projectId`) |\n| `todoist_update`   | Edit a task (`content`, `dueString`, `clearDue`, `priority`, `labels`, `projectId`) |\n| `todoist_complete` | Complete (close) a task |\n| `todoist_reopen`   | Reopen a completed task |\n| `todoist_delete`   | Delete a task |\n\nPriority follows the Todoist REST convention: **4 = P1 (urgent)** … **1 = P4**.\n\n### Inline tool-call cards\n\nEvery agent tool call renders a compact Todoist summary **inline in the\nconversation timeline** (not just a line of text). The tools attach a\n`details.piRemoteControlArtifact` of **kind `markdown`** to their result;\npi-crust renders it natively in the timeline. We use markdown (not HTML) on\npurpose: HTML artifacts are wrapped in a bordered `figure` **and** a bordered,\n320px-min sandboxed `iframe`, which double-boxes a small task list, leaves dead\nwhitespace, and can't run scripts anyway. Markdown renders organically in a\nsingle box with the host's own typography.\n\nWhen the agent runs `todoist_list`, `todoist_add`, `todoist_complete`, or\n`todoist_update`, you see the affected list right in the chat — a just-added task\nis **bolded**, completed tasks are struck through, and a status line\n(`Added · Work`, `Completed · 3 still open`) heads the card.\n\n> The inline card is a **read-only snapshot**. pi-crust sandboxes artifact\n> iframes (`sandbox=\"\"`, no scripts), so inline items can't be tapped to mutate.\n> The interactive surface is the **sidebar panel**.\n\n### Editing in the sidebar (interactive)\n\nThe sidebar Todoist panel is where you work with tasks directly:\n\n- **Tap the round check** → completes the task (with strike animation).\n- **Tap the title** → inline text editor; Enter saves, Esc cancels.\n- **Tap the priority flag** → cycles P1→P4 (`todoist_update priority`).\n- **Tap the due chip** (or the faint `📅 Due` on undated tasks) → a natural-language\n  due editor (“tomorrow 9am”, “next monday”); clear it to remove the date.\n- **Quick-add** at the top; **trash** to delete.\n\nAll mutations are optimistic and proxied to the `/api/ext/todoist/*` routes.\n\n## Tests\n\nBuilt test-first (vitest + jsdom + Testing Library):\n\n```bash\nnpm test\n```\n\nCovers the inline-artifact builder (`test/artifact.test.mjs` — markdown shape,\nhighlight, status, due labels), the agent tools' artifact wiring\n(`test/pi-tools.test.mjs`), and the sidebar widget interactions\n(`test/widget.test.mjs` — complete, title edit, priority cycle, **due-date\nediting**, quick-add).\n\n## Connecting your account\n\nTwo ways to provide a Todoist personal API token (Todoist → Settings →\nIntegrations → Developer → API token):\n\n1. **In-app (recommended)** — open the Todoist panel and use the **Connect your\n   Todoist account** banner. The token is saved via `prc.storage` to\n   `…/todoist.json` and survives restarts. A **Disconnect** link clears it.\n2. **Env var** — set `TODOIST_API_TOKEN` (handy for headless/server/CI). \n\n**Token resolution precedence:** an in-app (stored) token wins; otherwise the\nenv var; otherwise the interactive in-memory **demo** store. The connection\nstatus endpoint returns only a masked hint (`…cdef`) — the raw token is never\nsent to the browser.\n\n| Env var             | Purpose |\n|---------------------|---------|\n| `TODOIST_API_TOKEN` | Optional fallback token. In-app token takes precedence; when neither is set the in-memory mock is used. |\n\nConfig routes: `GET /api/ext/todoist/config`, `POST /api/ext/todoist/token`\n`{token}`, `POST /api/ext/todoist/token/delete`. Full surface + edge cases:\n[`docs/SPEC-token-config.md`](docs/SPEC-token-config.md).\n\n## Publishing\n\nShips an allow-listed tarball (9 files; verify with `npm pack --dry-run`).\n`prepublishOnly` runs the test suite. To publish:\n\n```bash\nnpm version patch        # or minor/major\nnpm publish --access public\n# or: push a vX.Y.Z tag and let .github/workflows/publish.yml do it (needs NPM_TOKEN)\n```\n\nUntil published, install from a path or git URL:\n\n```bash\nPI_CRUST_EXTENSIONS=/path/to/pi-crust-ext-todoist npx pi-crust\n# or add the path/git url to packages[] in your pi-crust settings.json\n```\n\n## Install\n\nPi-crust discovers any installed package whose `package.json` carries a\n`piRemoteControl` / `piCrust` field; pi discovers the `pi.extensions` entry.\n\n```bash\nTODOIST_API_TOKEN=xxxx PI_CRUST_EXTENSIONS=/path/to/pi-crust-ext-todoist npx pi-crust\n```\n\n## REST surface (used by the widget)\n\n```\nGET  /api/ext/todoist/state?projectId=        -> { projects, tasks, live }\nPOST /api/ext/todoist/tasks                    { content, projectId? } -> { task }\nPOST /api/ext/todoist/tasks/:id/update         { content?, priority?, dueString?, ... } -> { task }\nPOST /api/ext/todoist/tasks/:id/close          -> { ok }\nPOST /api/ext/todoist/tasks/:id/reopen         -> { ok }\nPOST /api/ext/todoist/tasks/:id/delete         -> { ok }\n```\n\n## Preview\n\n`node preview/shoot.mjs` renders the widget against an in-memory mock and writes\n`preview/desktop.png` + `preview/mobile.png` (requires `playwright-core`).\n\n## License\n\nMIT.\n","readmeFilename":"README.md"}